@@ -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,146 @@ 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
+ . map_err ( |e| ErrorKind :: InvalidTlsConfig {
85
+ message : format ! (
86
+ "built-in provider should support default protocol versions: {}" ,
87
+ e
88
+ ) ,
89
+ } ) ?
90
+ . with_root_certificates ( store) ;
91
+
89
92
let mut config = if let Some ( path) = cfg. cert_key_file_path {
90
93
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
- } ;
94
+ let mut certs = vec ! [ ] ;
95
+
96
+ for cert in CertificateDer :: pem_reader_iter ( & mut file) {
97
+ let cert = cert. map_err ( |error| ErrorKind :: InvalidTlsConfig {
98
+ message : format ! (
99
+ "Unable to parse PEM-encoded client certificate from {}: {error}" ,
100
+ path. display( ) ,
101
+ ) ,
102
+ } ) ?;
103
+ certs. push ( cert) ;
104
+ }
104
105
105
106
file. rewind ( ) ?;
106
- let key = loop {
107
+ let key = ' key : {
107
108
#[ cfg( feature = "cert-key-password" ) ]
108
109
if let Some ( key_pw) = cfg. tls_certificate_key_file_password . as_deref ( ) {
110
+ use rustls:: pki_types:: PrivatePkcs8KeyDer ;
109
111
use std:: io:: Read ;
110
112
let mut contents = vec ! [ ] ;
111
113
file. read_to_end ( & mut contents) ?;
112
- break rustls:: PrivateKey ( super :: pem:: decrypt_private_key ( & contents, key_pw) ?) ;
114
+ break ' key PrivatePkcs8KeyDer :: from ( super :: pem:: decrypt_private_key (
115
+ & contents, key_pw,
116
+ ) ?)
117
+ . into ( ) ;
113
118
}
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 ( _) => {
119
+ match PrivateKeyDer :: from_pem_reader ( & mut file) {
120
+ Ok ( key) => break ' key key,
121
+ Err ( err) => {
126
122
return Err ( ErrorKind :: InvalidTlsConfig {
127
123
message : format ! (
128
- "Unable to parse PEM-encoded item from {}" ,
129
- path. display( )
124
+ "Unable to parse PEM-encoded item from {}: {err} " ,
125
+ path. display( ) ,
130
126
) ,
131
127
}
132
128
. into ( ) )
133
129
}
134
130
}
135
131
} ;
136
132
137
- ClientConfig :: builder ( )
138
- . with_safe_defaults ( )
139
- . with_root_certificates ( store)
133
+ config_builder
140
134
. with_client_auth_cert ( certs, key)
141
135
. map_err ( |error| ErrorKind :: InvalidTlsConfig {
142
136
message : error. to_string ( ) ,
143
137
} ) ?
144
138
} else {
145
- ClientConfig :: builder ( )
146
- . with_safe_defaults ( )
147
- . with_root_certificates ( store)
148
- . with_no_client_auth ( )
139
+ config_builder. with_no_client_auth ( )
149
140
} ;
150
141
151
142
if let Some ( true ) = cfg. allow_invalid_certificates {
152
143
// nosemgrep: rustls-dangerous
153
144
config // mongodb rating: No Fix Needed
154
145
. dangerous ( )
155
- . set_certificate_verifier ( Arc :: new ( NoCertVerifier { } ) ) ;
146
+ . set_certificate_verifier ( Arc :: new ( danger:: NoCertVerifier (
147
+ provider:: default_provider ( ) ,
148
+ ) ) ) ;
156
149
}
157
150
158
151
Ok ( config)
159
152
}
160
153
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 ( ) )
154
+ mod danger {
155
+ use super :: * ;
156
+ use rustls:: {
157
+ client:: danger:: { HandshakeSignatureValid , ServerCertVerified , ServerCertVerifier } ,
158
+ crypto:: { verify_tls12_signature, verify_tls13_signature, CryptoProvider } ,
159
+ pki_types:: UnixTime ,
160
+ DigitallySignedStruct ,
161
+ SignatureScheme ,
162
+ } ;
163
+
164
+ #[ derive( Debug ) ]
165
+ pub ( super ) struct NoCertVerifier ( pub ( super ) CryptoProvider ) ;
166
+
167
+ impl ServerCertVerifier for NoCertVerifier {
168
+ fn verify_server_cert (
169
+ & self ,
170
+ _end_entity : & CertificateDer < ' _ > ,
171
+ _intermediates : & [ CertificateDer < ' _ > ] ,
172
+ _server_name : & ServerName < ' _ > ,
173
+ _ocsp : & [ u8 ] ,
174
+ _now : UnixTime ,
175
+ ) -> std:: result:: Result < ServerCertVerified , TlsError > {
176
+ Ok ( ServerCertVerified :: assertion ( ) )
177
+ }
178
+
179
+ fn verify_tls12_signature (
180
+ & self ,
181
+ message : & [ u8 ] ,
182
+ cert : & CertificateDer < ' _ > ,
183
+ dss : & DigitallySignedStruct ,
184
+ ) -> std:: result:: Result < HandshakeSignatureValid , TlsError > {
185
+ verify_tls12_signature (
186
+ message,
187
+ cert,
188
+ dss,
189
+ & self . 0 . signature_verification_algorithms ,
190
+ )
191
+ }
192
+
193
+ fn verify_tls13_signature (
194
+ & self ,
195
+ message : & [ u8 ] ,
196
+ cert : & CertificateDer < ' _ > ,
197
+ dss : & DigitallySignedStruct ,
198
+ ) -> std:: result:: Result < HandshakeSignatureValid , TlsError > {
199
+ verify_tls13_signature (
200
+ message,
201
+ cert,
202
+ dss,
203
+ & self . 0 . signature_verification_algorithms ,
204
+ )
205
+ }
206
+
207
+ fn supported_verify_schemes ( & self ) -> Vec < SignatureScheme > {
208
+ self . 0 . signature_verification_algorithms . supported_schemes ( )
209
+ }
174
210
}
175
211
}
0 commit comments