@@ -3,17 +3,15 @@ use std::{
3
3
fs:: File ,
4
4
io:: { BufReader , Seek } ,
5
5
sync:: Arc ,
6
- time:: SystemTime ,
7
6
} ;
8
7
9
8
use 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 } ,
12
12
Error as TlsError ,
13
- OwnedTrustAnchor ,
14
13
RootCertStore ,
15
14
} ;
16
- use rustls_pemfile:: { certs, read_one, Item } ;
17
15
use tokio:: net:: TcpStream ;
18
16
use tokio_rustls:: TlsConnector ;
19
17
use webpki_roots:: TLS_SERVER_ROOTS ;
@@ -49,9 +47,11 @@ pub(super) async fn tls_connect(
49
47
tcp_stream : TcpStream ,
50
48
cfg : & TlsConfig ,
51
49
) -> 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 ( ) ;
55
55
56
56
let conn = cfg
57
57
. connector
@@ -66,110 +66,141 @@ pub(super) async fn tls_connect(
66
66
fn make_rustls_config ( cfg : TlsOptions ) -> Result < rustls:: ClientConfig > {
67
67
let mut store = RootCertStore :: empty ( ) ;
68
68
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 {
71
71
message : format ! (
72
- "Unable to parse PEM-encoded root certificate from {}" ,
72
+ "Unable to parse PEM-encoded root certificate from {}: {err} " ,
73
73
path. display( )
74
74
) ,
75
- }
76
- } ) ? ;
77
- store. add_parsable_certificates ( & ders) ;
75
+ } ) ?
76
+ . flatten ( ) ;
77
+ store. add_parsable_certificates ( ders) ;
78
78
} 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 ( ) ) ;
87
80
}
88
81
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
+
89
87
let mut config = if let Some ( path) = cfg. cert_key_file_path {
90
88
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
+ }
104
100
105
101
file. rewind ( ) ?;
106
102
let key = loop {
107
103
#[ cfg( feature = "cert-key-password" ) ]
108
104
if let Some ( key_pw) = cfg. tls_certificate_key_file_password . as_deref ( ) {
105
+ use rustls:: pki_types:: PrivatePkcs8KeyDer ;
109
106
use std:: io:: Read ;
110
107
let mut contents = vec ! [ ] ;
111
108
file. read_to_end ( & mut contents) ?;
112
- break rustls:: PrivateKey ( super :: pem:: decrypt_private_key ( & contents, key_pw) ?) ;
109
+ break PrivatePkcs8KeyDer :: from ( super :: pem:: decrypt_private_key (
110
+ & contents, key_pw,
111
+ ) ?)
112
+ . into ( ) ;
113
113
}
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,
116
+ Err ( err) => {
126
117
return Err ( ErrorKind :: InvalidTlsConfig {
127
118
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( ) ,
130
121
) ,
131
122
}
132
123
. into ( ) )
133
124
}
134
125
}
135
126
} ;
136
127
137
- ClientConfig :: builder ( )
138
- . with_safe_defaults ( )
139
- . with_root_certificates ( store)
128
+ config_builder
140
129
. with_client_auth_cert ( certs, key)
141
130
. map_err ( |error| ErrorKind :: InvalidTlsConfig {
142
131
message : error. to_string ( ) ,
143
132
} ) ?
144
133
} 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 ( )
149
135
} ;
150
136
151
137
if let Some ( true ) = cfg. allow_invalid_certificates {
152
138
// nosemgrep: rustls-dangerous
153
139
config // mongodb rating: No Fix Needed
154
140
. dangerous ( )
155
- . set_certificate_verifier ( Arc :: new ( NoCertVerifier { } ) ) ;
141
+ . set_certificate_verifier ( Arc :: new ( danger:: NoCertVerifier (
142
+ provider:: default_provider ( ) ,
143
+ ) ) ) ;
156
144
}
157
145
158
146
Ok ( config)
159
147
}
160
148
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
+ }
174
205
}
175
206
}
0 commit comments