@@ -3,17 +3,15 @@ use std::{
33 fs:: File ,
44 io:: { BufReader , Seek } ,
55 sync:: Arc ,
6- time:: SystemTime ,
76} ;
87
98use rustls:: {
10- client:: { ClientConfig , ServerCertVerified , ServerCertVerifier , ServerName } ,
11- Certificate ,
9+ client:: ClientConfig ,
10+ crypto:: ring as provider,
11+ pki_types:: { pem:: PemObject , CertificateDer , PrivateKeyDer , ServerName } ,
1212 Error as TlsError ,
13- OwnedTrustAnchor ,
1413 RootCertStore ,
1514} ;
16- use rustls_pemfile:: { certs, read_one, Item } ;
1715use tokio:: net:: TcpStream ;
1816use tokio_rustls:: TlsConnector ;
1917use webpki_roots:: TLS_SERVER_ROOTS ;
@@ -49,9 +47,11 @@ pub(super) async fn tls_connect(
4947 tcp_stream : TcpStream ,
5048 cfg : & TlsConfig ,
5149) -> Result < TlsStream > {
52- let name = ServerName :: try_from ( host) . map_err ( |e| ErrorKind :: DnsResolve {
53- message : format ! ( "could not resolve {:?}: {}" , host, e) ,
54- } ) ?;
50+ let name = ServerName :: try_from ( host)
51+ . map_err ( |e| ErrorKind :: DnsResolve {
52+ message : format ! ( "could not resolve {:?}: {}" , host, e) ,
53+ } ) ?
54+ . to_owned ( ) ;
5555
5656 let conn = cfg
5757 . connector
@@ -66,110 +66,141 @@ pub(super) async fn tls_connect(
6666fn make_rustls_config ( cfg : TlsOptions ) -> Result < rustls:: ClientConfig > {
6767 let mut store = RootCertStore :: empty ( ) ;
6868 if let Some ( path) = cfg. ca_file_path {
69- let ders = certs ( & mut BufReader :: new ( File :: open ( & path) ? ) ) . map_err ( |_| {
70- ErrorKind :: InvalidTlsConfig {
69+ let ders = CertificateDer :: pem_file_iter ( & path)
70+ . map_err ( |err| ErrorKind :: InvalidTlsConfig {
7171 message : format ! (
72- "Unable to parse PEM-encoded root certificate from {}" ,
72+ "Unable to parse PEM-encoded root certificate from {}: {err} " ,
7373 path. display( )
7474 ) ,
75- }
76- } ) ? ;
77- store. add_parsable_certificates ( & ders) ;
75+ } ) ?
76+ . flatten ( ) ;
77+ store. add_parsable_certificates ( ders) ;
7878 } else {
79- let trust_anchors = TLS_SERVER_ROOTS . iter ( ) . map ( |ta| {
80- OwnedTrustAnchor :: from_subject_spki_name_constraints (
81- ta. subject ,
82- ta. spki ,
83- ta. name_constraints ,
84- )
85- } ) ;
86- store. add_trust_anchors ( trust_anchors) ;
79+ store. extend ( TLS_SERVER_ROOTS . iter ( ) . cloned ( ) ) ;
8780 }
8881
82+ let config_builder = ClientConfig :: builder_with_provider ( provider:: default_provider ( ) . into ( ) )
83+ . with_safe_default_protocol_versions ( )
84+ . expect ( "built-in provider should support default protocol versions" )
85+ . with_root_certificates ( store) ;
86+
8987 let mut config = if let Some ( path) = cfg. cert_key_file_path {
9088 let mut file = BufReader :: new ( File :: open ( & path) ?) ;
91- let certs = match certs ( & mut file) {
92- Ok ( certs) => certs. into_iter ( ) . map ( Certificate ) . collect ( ) ,
93- Err ( error) => {
94- return Err ( ErrorKind :: InvalidTlsConfig {
95- message : format ! (
96- "Unable to parse PEM-encoded client certificate from {}: {}" ,
97- path. display( ) ,
98- error,
99- ) ,
100- }
101- . into ( ) )
102- }
103- } ;
89+ let mut certs = vec ! [ ] ;
90+
91+ for cert in CertificateDer :: pem_reader_iter ( & mut file) {
92+ let cert = cert. map_err ( |error| ErrorKind :: InvalidTlsConfig {
93+ message : format ! (
94+ "Unable to parse PEM-encoded client certificate from {}: {error}" ,
95+ path. display( ) ,
96+ ) ,
97+ } ) ?;
98+ certs. push ( cert) ;
99+ }
104100
105101 file. rewind ( ) ?;
106- let key = loop {
102+ let key = ' key : {
107103 #[ cfg( feature = "cert-key-password" ) ]
108104 if let Some ( key_pw) = cfg. tls_certificate_key_file_password . as_deref ( ) {
105+ use rustls:: pki_types:: PrivatePkcs8KeyDer ;
109106 use std:: io:: Read ;
110107 let mut contents = vec ! [ ] ;
111108 file. read_to_end ( & mut contents) ?;
112- break rustls:: PrivateKey ( super :: pem:: decrypt_private_key ( & contents, key_pw) ?) ;
109+ break ' key PrivatePkcs8KeyDer :: from ( super :: pem:: decrypt_private_key (
110+ & contents, key_pw,
111+ ) ?)
112+ . into ( ) ;
113113 }
114- match read_one ( & mut file) {
115- Ok ( Some ( Item :: PKCS8Key ( bytes) ) ) | Ok ( Some ( Item :: RSAKey ( bytes) ) ) => {
116- break rustls:: PrivateKey ( bytes)
117- }
118- Ok ( Some ( _) ) => continue ,
119- Ok ( None ) => {
120- return Err ( ErrorKind :: InvalidTlsConfig {
121- message : format ! ( "No PEM-encoded keys in {}" , path. display( ) ) ,
122- }
123- . into ( ) )
124- }
125- Err ( _) => {
114+ match PrivateKeyDer :: from_pem_reader ( & mut file) {
115+ Ok ( key) => break ' key key,
116+ Err ( err) => {
126117 return Err ( ErrorKind :: InvalidTlsConfig {
127118 message : format ! (
128- "Unable to parse PEM-encoded item from {}" ,
129- path. display( )
119+ "Unable to parse PEM-encoded item from {}: {err} " ,
120+ path. display( ) ,
130121 ) ,
131122 }
132123 . into ( ) )
133124 }
134125 }
135126 } ;
136127
137- ClientConfig :: builder ( )
138- . with_safe_defaults ( )
139- . with_root_certificates ( store)
128+ config_builder
140129 . with_client_auth_cert ( certs, key)
141130 . map_err ( |error| ErrorKind :: InvalidTlsConfig {
142131 message : error. to_string ( ) ,
143132 } ) ?
144133 } else {
145- ClientConfig :: builder ( )
146- . with_safe_defaults ( )
147- . with_root_certificates ( store)
148- . with_no_client_auth ( )
134+ config_builder. with_no_client_auth ( )
149135 } ;
150136
151137 if let Some ( true ) = cfg. allow_invalid_certificates {
152138 // nosemgrep: rustls-dangerous
153139 config // mongodb rating: No Fix Needed
154140 . dangerous ( )
155- . set_certificate_verifier ( Arc :: new ( NoCertVerifier { } ) ) ;
141+ . set_certificate_verifier ( Arc :: new ( danger:: NoCertVerifier (
142+ provider:: default_provider ( ) ,
143+ ) ) ) ;
156144 }
157145
158146 Ok ( config)
159147}
160148
161- struct NoCertVerifier { }
162-
163- impl ServerCertVerifier for NoCertVerifier {
164- fn verify_server_cert (
165- & self ,
166- _: & Certificate ,
167- _: & [ Certificate ] ,
168- _: & ServerName ,
169- _: & mut dyn Iterator < Item = & [ u8 ] > ,
170- _: & [ u8 ] ,
171- _: SystemTime ,
172- ) -> std:: result:: Result < ServerCertVerified , TlsError > {
173- Ok ( ServerCertVerified :: assertion ( ) )
149+ mod danger {
150+ use super :: * ;
151+ use rustls:: {
152+ client:: danger:: { HandshakeSignatureValid , ServerCertVerified , ServerCertVerifier } ,
153+ crypto:: { verify_tls12_signature, verify_tls13_signature, CryptoProvider } ,
154+ pki_types:: UnixTime ,
155+ DigitallySignedStruct ,
156+ SignatureScheme ,
157+ } ;
158+
159+ #[ derive( Debug ) ]
160+ pub ( super ) struct NoCertVerifier ( pub ( super ) CryptoProvider ) ;
161+
162+ impl ServerCertVerifier for NoCertVerifier {
163+ fn verify_server_cert (
164+ & self ,
165+ _end_entity : & CertificateDer < ' _ > ,
166+ _intermediates : & [ CertificateDer < ' _ > ] ,
167+ _server_name : & ServerName < ' _ > ,
168+ _ocsp : & [ u8 ] ,
169+ _now : UnixTime ,
170+ ) -> std:: result:: Result < ServerCertVerified , TlsError > {
171+ Ok ( ServerCertVerified :: assertion ( ) )
172+ }
173+
174+ fn verify_tls12_signature (
175+ & self ,
176+ message : & [ u8 ] ,
177+ cert : & CertificateDer < ' _ > ,
178+ dss : & DigitallySignedStruct ,
179+ ) -> std:: result:: Result < HandshakeSignatureValid , TlsError > {
180+ verify_tls12_signature (
181+ message,
182+ cert,
183+ dss,
184+ & self . 0 . signature_verification_algorithms ,
185+ )
186+ }
187+
188+ fn verify_tls13_signature (
189+ & self ,
190+ message : & [ u8 ] ,
191+ cert : & CertificateDer < ' _ > ,
192+ dss : & DigitallySignedStruct ,
193+ ) -> std:: result:: Result < HandshakeSignatureValid , TlsError > {
194+ verify_tls13_signature (
195+ message,
196+ cert,
197+ dss,
198+ & self . 0 . signature_verification_algorithms ,
199+ )
200+ }
201+
202+ fn supported_verify_schemes ( & self ) -> Vec < SignatureScheme > {
203+ self . 0 . signature_verification_algorithms . supported_schemes ( )
204+ }
174205 }
175206}
0 commit comments