diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2021-12-06 18:48:11 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-07 00:48:11 +0100 |
commit | a2f1357fe81fe212451567cc433c0e6b4a85edc5 (patch) | |
tree | 1e4267d9f6e6bb3ddbdf030b4d6d1c547a33b6be /ext/tls/lib.rs | |
parent | b91e6fd02f61ea34881226bc4b202e38ed75123e (diff) |
chore: upgrade to rustls 0.20 (#12488)
Co-authored-by: Bartek IwaĆczuk <biwanczuk@gmail.com>
Co-authored-by: Bert Belder <bertbelder@gmail.com>
Diffstat (limited to 'ext/tls/lib.rs')
-rw-r--r-- | ext/tls/lib.rs | 189 |
1 files changed, 112 insertions, 77 deletions
diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index 68bd2fcc1..bcaf0f1be 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -2,6 +2,7 @@ pub use rustls; pub use rustls_native_certs; +pub use rustls_pemfile; pub use webpki; pub use webpki_roots; @@ -11,27 +12,26 @@ use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::Extension; -use rustls::internal::msgs::handshake::DigitallySignedStruct; -use rustls::internal::pemfile::certs; -use rustls::internal::pemfile::pkcs8_private_keys; -use rustls::internal::pemfile::rsa_private_keys; +use rustls::client::ServerCertVerified; +use rustls::client::ServerCertVerifier; +use rustls::client::StoresClientSessions; +use rustls::client::WebPkiVerifier; use rustls::Certificate; use rustls::ClientConfig; -use rustls::HandshakeSignatureValid; +use rustls::Error; use rustls::PrivateKey; use rustls::RootCertStore; -use rustls::ServerCertVerified; -use rustls::ServerCertVerifier; -use rustls::StoresClientSessions; -use rustls::TLSError; -use rustls::WebPKIVerifier; +use rustls::ServerName; +use rustls_pemfile::certs; +use rustls_pemfile::pkcs8_private_keys; +use rustls_pemfile::rsa_private_keys; use serde::Deserialize; use std::collections::HashMap; use std::io::BufRead; use std::io::BufReader; use std::io::Cursor; use std::sync::Arc; -use webpki::DNSNameRef; +use std::time::SystemTime; /// This extension has no runtime apis, it only exports some shared native functions. pub fn init() -> Extension { @@ -43,42 +43,35 @@ pub struct NoCertificateVerification(pub Vec<String>); impl ServerCertVerifier for NoCertificateVerification { fn verify_server_cert( &self, - roots: &RootCertStore, - presented_certs: &[Certificate], - dns_name_ref: DNSNameRef<'_>, - ocsp: &[u8], - ) -> Result<ServerCertVerified, TLSError> { - let dns_name: &str = dns_name_ref.into(); - let dns_name: String = dns_name.to_owned(); - if self.0.is_empty() || self.0.contains(&dns_name) { - Ok(ServerCertVerified::assertion()) + end_entity: &Certificate, + intermediates: &[Certificate], + server_name: &ServerName, + scts: &mut dyn Iterator<Item = &[u8]>, + ocsp_response: &[u8], + now: SystemTime, + ) -> Result<ServerCertVerified, Error> { + if let ServerName::DnsName(dns_name) = server_name { + let dns_name = dns_name.as_ref().to_owned(); + if self.0.is_empty() || self.0.contains(&dns_name) { + Ok(ServerCertVerified::assertion()) + } else { + let root_store = create_default_root_cert_store(); + let verifier = WebPkiVerifier::new(root_store, None); + verifier.verify_server_cert( + end_entity, + intermediates, + server_name, + scts, + ocsp_response, + now, + ) + } } else { - WebPKIVerifier::new().verify_server_cert( - roots, - presented_certs, - dns_name_ref, - ocsp, - ) + // NOTE(bartlomieju): `ServerName` is a non-exhaustive enum + // so we have this catch all error here. + Err(Error::General("Unknown `ServerName` variant".to_string())) } } - - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &Certificate, - _dss: &DigitallySignedStruct, - ) -> Result<HandshakeSignatureValid, TLSError> { - Ok(HandshakeSignatureValid::assertion()) - } - - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &Certificate, - _dss: &DigitallySignedStruct, - ) -> Result<HandshakeSignatureValid, TLSError> { - Ok(HandshakeSignatureValid::assertion()) - } } #[derive(Deserialize, Default, Debug, Clone)] @@ -124,7 +117,15 @@ impl StoresClientSessions for ClientSessionMemoryCache { pub fn create_default_root_cert_store() -> RootCertStore { let mut root_cert_store = RootCertStore::empty(); // TODO(@justinmchase): Consider also loading the system keychain here - root_cert_store.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + root_cert_store.add_server_trust_anchors( + webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { + rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( + ta.subject, + ta.spki, + ta.name_constraints, + ) + }), + ); root_cert_store } @@ -134,39 +135,73 @@ pub fn create_client_config( unsafely_ignore_certificate_errors: Option<Vec<String>>, client_cert_chain_and_key: Option<(String, String)>, ) -> Result<ClientConfig, AnyError> { - let mut tls_config = ClientConfig::new(); - tls_config.set_persistence(CLIENT_SESSION_MEMORY_CACHE.clone()); - tls_config.root_store = - root_cert_store.unwrap_or_else(create_default_root_cert_store); - - // If custom certs are specified, add them to the store - for cert in ca_certs { - let reader = &mut BufReader::new(Cursor::new(cert)); - // This function does not return specific errors, if it fails give a generic message. - if let Err(()) = tls_config.root_store.add_pem_file(reader) { - return Err(anyhow!("Unable to add pem file to certificate store")); - } - } + let maybe_cert_chain_and_key = + if let Some((cert_chain, private_key)) = client_cert_chain_and_key { + // The `remove` is safe because load_private_keys checks that there is at least one key. + let private_key = load_private_keys(private_key.as_bytes())?.remove(0); + let cert_chain = load_certs(&mut cert_chain.as_bytes())?; + Some((cert_chain, private_key)) + } else { + None + }; if let Some(ic_allowlist) = unsafely_ignore_certificate_errors { - tls_config.dangerous().set_certificate_verifier(Arc::new( - NoCertificateVerification(ic_allowlist), - )); - } - - if let Some((cert_chain, private_key)) = client_cert_chain_and_key { - // The `remove` is safe because load_private_keys checks that there is at least one key. - let private_key = load_private_keys(private_key.as_bytes())?.remove(0); - - tls_config - .set_single_client_cert( - load_certs(&mut cert_chain.as_bytes())?, - private_key, - ) - .expect("invalid client key or certificate"); + let client_config = ClientConfig::builder() + .with_safe_defaults() + .with_custom_certificate_verifier(Arc::new(NoCertificateVerification( + ic_allowlist, + ))); + + // NOTE(bartlomieju): this if/else is duplicated at the end of the body of this function. + // However it's not really feasible to deduplicate it as the `client_config` instances + // are not type-compatible - one wants "client cert", the other wants "transparency policy + // or client cert". + let client = + if let Some((cert_chain, private_key)) = maybe_cert_chain_and_key { + client_config + .with_single_cert(cert_chain, private_key) + .expect("invalid client key or certificate") + } else { + client_config.with_no_client_auth() + }; + + return Ok(client); } - Ok(tls_config) + let client_config = ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates({ + let mut root_cert_store = + root_cert_store.unwrap_or_else(create_default_root_cert_store); + // If custom certs are specified, add them to the store + for cert in ca_certs { + let reader = &mut BufReader::new(Cursor::new(cert)); + // This function does not return specific errors, if it fails give a generic message. + match rustls_pemfile::certs(reader) { + Ok(certs) => { + root_cert_store.add_parsable_certificates(&certs); + } + Err(e) => { + return Err(anyhow!( + "Unable to add pem file to certificate store: {}", + e + )); + } + } + } + root_cert_store + }); + + let client = if let Some((cert_chain, private_key)) = maybe_cert_chain_and_key + { + client_config + .with_single_cert(cert_chain, private_key) + .expect("invalid client key or certificate") + } else { + client_config.with_no_client_auth() + }; + + Ok(client) } pub fn load_certs( @@ -180,7 +215,7 @@ pub fn load_certs( return Err(e); } - Ok(certs) + Ok(certs.into_iter().map(Certificate).collect()) } fn key_decode_err() -> AnyError { @@ -194,13 +229,13 @@ fn key_not_found_err() -> AnyError { /// Starts with -----BEGIN RSA PRIVATE KEY----- fn load_rsa_keys(mut bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { let keys = rsa_private_keys(&mut bytes).map_err(|_| key_decode_err())?; - Ok(keys) + Ok(keys.into_iter().map(PrivateKey).collect()) } /// Starts with -----BEGIN PRIVATE KEY----- fn load_pkcs8_keys(mut bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { let keys = pkcs8_private_keys(&mut bytes).map_err(|_| key_decode_err())?; - Ok(keys) + Ok(keys.into_iter().map(PrivateKey).collect()) } pub fn load_private_keys(bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { |