1
1
use crate :: vm:: { builtins:: PyModule , PyRef , VirtualMachine } ;
2
+ use openssl_probe:: ProbeResult ;
2
3
3
4
pub ( crate ) fn make_module ( vm : & VirtualMachine ) -> PyRef < PyModule > {
4
- // if openssl is vendored, it doesn't know the locations of system certificates
5
- #[ cfg( feature = "ssl-vendor" ) ]
6
- if let None | Some ( "0" ) = option_env ! ( "OPENSSL_NO_VENDOR" ) {
7
- // TODO: use openssl_probe::probe() instead
8
- unsafe { openssl_probe:: init_openssl_env_vars ( ) } ;
9
- }
10
- openssl:: init ( ) ;
5
+ // if openssl is vendored, it doesn't know the locations
6
+ // of system certificates - cache the probe result now.
7
+ #[ cfg( openssl_vendored) ]
8
+ LazyLock :: force ( & PROBE ) ;
11
9
_ssl:: make_module ( vm)
12
10
}
13
11
12
+ // define our own copy of ProbeResult so we can handle the vendor case
13
+ // easily, without having to have a bunch of cfgs
14
+ cfg_if:: cfg_if! {
15
+ if #[ cfg( openssl_vendored) ] {
16
+ use std:: sync:: LazyLock ;
17
+ static PROBE : LazyLock <ProbeResult > = LazyLock :: new( openssl_probe:: probe) ;
18
+ fn probe( ) -> & ' static ProbeResult { & PROBE }
19
+ } else {
20
+ fn probe( ) -> & ' static ProbeResult {
21
+ & ProbeResult { cert_file: None , cert_dir: None }
22
+ }
23
+ }
24
+ }
25
+
14
26
#[ allow( non_upper_case_globals) ]
15
27
#[ pymodule( with( ossl101, windows) ) ]
16
28
mod _ssl {
17
- use super :: bio;
29
+ use super :: { bio, probe } ;
18
30
use crate :: {
19
31
common:: {
20
32
ascii,
@@ -46,10 +58,12 @@ mod _ssl {
46
58
x509:: { self , X509Ref , X509 } ,
47
59
} ;
48
60
use openssl_sys as sys;
61
+ use rustpython_vm:: ospath:: OsPath ;
49
62
use std:: {
50
63
ffi:: CStr ,
51
64
fmt,
52
65
io:: { Read , Write } ,
66
+ path:: Path ,
53
67
time:: Instant ,
54
68
} ;
55
69
@@ -355,21 +369,43 @@ mod _ssl {
355
369
. ok_or_else ( || vm. new_value_error ( format ! ( "unknown NID {nid}" ) ) )
356
370
}
357
371
358
- #[ pyfunction]
359
- fn get_default_verify_paths ( ) -> ( String , String , String , String ) {
360
- macro_rules! convert {
361
- ( $f: ident) => {
362
- CStr :: from_ptr( sys:: $f( ) ) . to_string_lossy( ) . into_owned( )
363
- } ;
364
- }
365
- unsafe {
366
- (
367
- convert ! ( X509_get_default_cert_file_env ) ,
368
- convert ! ( X509_get_default_cert_file ) ,
369
- convert ! ( X509_get_default_cert_dir_env ) ,
370
- convert ! ( X509_get_default_cert_dir ) ,
371
- )
372
+ fn get_cert_file_dir ( ) -> ( & ' static Path , & ' static Path ) {
373
+ let probe = probe ( ) ;
374
+ // on windows, these should be utf8 strings
375
+ fn path_from_bytes ( c : & CStr ) -> & Path {
376
+ #[ cfg( unix) ]
377
+ {
378
+ use std:: os:: unix:: ffi:: OsStrExt ;
379
+ std:: ffi:: OsStr :: from_bytes ( c. to_bytes ( ) ) . as_ref ( )
380
+ }
381
+ #[ cfg( windows) ]
382
+ {
383
+ c. to_str ( ) . unwrap ( ) . as_ref ( )
384
+ }
372
385
}
386
+ let cert_file = probe. cert_file . as_deref ( ) . unwrap_or_else ( || {
387
+ path_from_bytes ( unsafe { CStr :: from_ptr ( sys:: X509_get_default_cert_file ( ) ) } )
388
+ } ) ;
389
+ let cert_dir = probe. cert_dir . as_deref ( ) . unwrap_or_else ( || {
390
+ path_from_bytes ( unsafe { CStr :: from_ptr ( sys:: X509_get_default_cert_dir ( ) ) } )
391
+ } ) ;
392
+ ( cert_file, cert_dir)
393
+ }
394
+
395
+ #[ pyfunction]
396
+ fn get_default_verify_paths (
397
+ vm : & VirtualMachine ,
398
+ ) -> PyResult < ( & ' static str , PyObjectRef , & ' static str , PyObjectRef ) > {
399
+ let cert_file_env = unsafe { CStr :: from_ptr ( sys:: X509_get_default_cert_file_env ( ) ) }
400
+ . to_str ( )
401
+ . unwrap ( ) ;
402
+ let cert_dir_env = unsafe { CStr :: from_ptr ( sys:: X509_get_default_cert_dir_env ( ) ) }
403
+ . to_str ( )
404
+ . unwrap ( ) ;
405
+ let ( cert_file, cert_dir) = get_cert_file_dir ( ) ;
406
+ let cert_file = OsPath :: new_str ( cert_file) . filename ( vm) ?;
407
+ let cert_dir = OsPath :: new_str ( cert_dir) . filename ( vm) ?;
408
+ Ok ( ( cert_file_env, cert_file, cert_dir_env, cert_dir) )
373
409
}
374
410
375
411
#[ pyfunction( name = "RAND_status" ) ]
@@ -591,9 +627,18 @@ mod _ssl {
591
627
592
628
#[ pymethod]
593
629
fn set_default_verify_paths ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
594
- self . builder ( )
595
- . set_default_verify_paths ( )
596
- . map_err ( |e| convert_openssl_error ( vm, e) )
630
+ cfg_if:: cfg_if! {
631
+ if #[ cfg( openssl_vendored) ] {
632
+ let ( cert_file, cert_dir) = get_cert_file_dir( ) ;
633
+ self . builder( )
634
+ . load_verify_locations( Some ( cert_file) , Some ( cert_dir) )
635
+ . map_err( |e| convert_openssl_error( vm, e) )
636
+ } else {
637
+ self . builder( )
638
+ . set_default_verify_paths( )
639
+ . map_err( |e| convert_openssl_error( vm, e) )
640
+ }
641
+ }
597
642
}
598
643
599
644
#[ pymethod]
@@ -640,6 +685,12 @@ mod _ssl {
640
685
vm. new_type_error ( "cafile, capath and cadata cannot be all omitted" . to_owned ( ) )
641
686
) ;
642
687
}
688
+ if let Some ( cafile) = & args. cafile {
689
+ cafile. ensure_no_nul ( vm) ?
690
+ }
691
+ if let Some ( capath) = & args. capath {
692
+ capath. ensure_no_nul ( vm) ?
693
+ }
643
694
644
695
#[ cold]
645
696
fn invalid_cadata ( vm : & VirtualMachine ) -> PyBaseExceptionRef {
@@ -648,6 +699,8 @@ mod _ssl {
648
699
)
649
700
}
650
701
702
+ let mut ctx = self . builder ( ) ;
703
+
651
704
// validate cadata type and load cadata
652
705
if let Some ( cadata) = args. cadata {
653
706
let certs = match cadata {
@@ -660,7 +713,6 @@ mod _ssl {
660
713
Either :: B ( b) => b. with_ref ( x509_stack_from_der) ,
661
714
} ;
662
715
let certs = certs. map_err ( |e| convert_openssl_error ( vm, e) ) ?;
663
- let mut ctx = self . builder ( ) ;
664
716
let store = ctx. cert_store_mut ( ) ;
665
717
for cert in certs {
666
718
store
@@ -670,29 +722,11 @@ mod _ssl {
670
722
}
671
723
672
724
if args. cafile . is_some ( ) || args. capath . is_some ( ) {
673
- let cafile = args. cafile . map ( |s| s. to_cstring ( vm) ) . transpose ( ) ?;
674
- let capath = args. capath . map ( |s| s. to_cstring ( vm) ) . transpose ( ) ?;
675
- let ret = unsafe {
676
- let ctx = self . ctx . write ( ) ;
677
- sys:: SSL_CTX_load_verify_locations (
678
- ctx. as_ptr ( ) ,
679
- cafile
680
- . as_ref ( )
681
- . map_or_else ( std:: ptr:: null, |cs| cs. as_ptr ( ) ) ,
682
- capath
683
- . as_ref ( )
684
- . map_or_else ( std:: ptr:: null, |cs| cs. as_ptr ( ) ) ,
685
- )
686
- } ;
687
- if ret != 1 {
688
- let errno = crate :: common:: os:: last_posix_errno ( ) ;
689
- let err = if errno != 0 {
690
- crate :: vm:: stdlib:: os:: errno_err ( vm)
691
- } else {
692
- convert_openssl_error ( vm, ErrorStack :: get ( ) )
693
- } ;
694
- return Err ( err) ;
695
- }
725
+ ctx. load_verify_locations (
726
+ args. cafile . as_ref ( ) . map ( |s| s. as_str ( ) . as_ref ( ) ) ,
727
+ args. capath . as_ref ( ) . map ( |s| s. as_str ( ) . as_ref ( ) ) ,
728
+ )
729
+ . map_err ( |e| convert_openssl_error ( vm, e) ) ?;
696
730
}
697
731
698
732
Ok ( ( ) )
0 commit comments