diff options
Diffstat (limited to 'ext/tls/lib.rs')
-rw-r--r-- | ext/tls/lib.rs | 201 |
1 files changed, 107 insertions, 94 deletions
diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index 5122264bf..c4d548ccf 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -1,7 +1,9 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - pub use deno_native_certs; pub use rustls; +use rustls::pki_types::CertificateDer; +use rustls::pki_types::PrivateKeyDer; +use rustls::pki_types::ServerName; pub use rustls_pemfile; pub use rustls_tokio_stream::*; pub use webpki; @@ -11,14 +13,14 @@ use deno_core::anyhow::anyhow; use deno_core::error::custom_error; use deno_core::error::AnyError; -use rustls::client::HandshakeSignatureValid; -use rustls::client::ServerCertVerified; -use rustls::client::ServerCertVerifier; -use rustls::client::WebPkiVerifier; +use rustls::client::danger::HandshakeSignatureValid; +use rustls::client::danger::ServerCertVerified; +use rustls::client::danger::ServerCertVerifier; +use rustls::client::WebPkiServerVerifier; use rustls::ClientConfig; use rustls::DigitallySignedStruct; use rustls::Error; -use rustls::ServerName; +use rustls::RootCertStore; use rustls_pemfile::certs; use rustls_pemfile::ec_private_keys; use rustls_pemfile::pkcs8_private_keys; @@ -27,16 +29,12 @@ use serde::Deserialize; use std::io::BufRead; use std::io::BufReader; use std::io::Cursor; +use std::net::IpAddr; use std::sync::Arc; -use std::time::SystemTime; mod tls_key; pub use tls_key::*; -pub type Certificate = rustls::Certificate; -pub type PrivateKey = rustls::PrivateKey; -pub type RootCertStore = rustls::RootCertStore; - /// Lazily resolves the root cert store. /// /// This was done because the root cert store is not needed in all cases @@ -48,56 +46,59 @@ pub trait RootCertStoreProvider: Send + Sync { // This extension has no runtime apis, it only exports some shared native functions. deno_core::extension!(deno_tls); -struct DefaultSignatureVerification; +#[derive(Debug)] +pub struct NoCertificateVerification { + pub ic_allowlist: Vec<String>, + default_verifier: Arc<WebPkiServerVerifier>, +} -impl ServerCertVerifier for DefaultSignatureVerification { - fn verify_server_cert( - &self, - _end_entity: &Certificate, - _intermediates: &[Certificate], - _server_name: &ServerName, - _scts: &mut dyn Iterator<Item = &[u8]>, - _ocsp_response: &[u8], - _now: SystemTime, - ) -> Result<ServerCertVerified, Error> { - Err(Error::General("Should not be used".to_string())) +impl NoCertificateVerification { + pub fn new(ic_allowlist: Vec<String>) -> Self { + Self { + ic_allowlist, + default_verifier: WebPkiServerVerifier::builder( + create_default_root_cert_store().into(), + ) + .build() + .unwrap(), + } } } -pub struct NoCertificateVerification(pub Vec<String>); - impl ServerCertVerifier for NoCertificateVerification { + fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> { + self.default_verifier.supported_verify_schemes() + } + fn verify_server_cert( &self, - end_entity: &Certificate, - intermediates: &[Certificate], - server_name: &ServerName, - scts: &mut dyn Iterator<Item = &[u8]>, + end_entity: &rustls::pki_types::CertificateDer<'_>, + intermediates: &[rustls::pki_types::CertificateDer<'_>], + server_name: &rustls::pki_types::ServerName<'_>, ocsp_response: &[u8], - now: SystemTime, + now: rustls::pki_types::UnixTime, ) -> Result<ServerCertVerified, Error> { - if self.0.is_empty() { + if self.ic_allowlist.is_empty() { return Ok(ServerCertVerified::assertion()); } let dns_name_or_ip_address = match server_name { ServerName::DnsName(dns_name) => dns_name.as_ref().to_owned(), - ServerName::IpAddress(ip_address) => ip_address.to_string(), + ServerName::IpAddress(ip_address) => { + Into::<IpAddr>::into(*ip_address).to_string() + } _ => { // NOTE(bartlomieju): `ServerName` is a non-exhaustive enum // so we have this catch all errors here. return Err(Error::General("Unknown `ServerName` variant".to_string())); } }; - if self.0.contains(&dns_name_or_ip_address) { + if self.ic_allowlist.contains(&dns_name_or_ip_address) { Ok(ServerCertVerified::assertion()) } else { - let root_store = create_default_root_cert_store(); - let verifier = WebPkiVerifier::new(root_store, None); - verifier.verify_server_cert( + self.default_verifier.verify_server_cert( end_entity, intermediates, server_name, - scts, ocsp_response, now, ) @@ -107,28 +108,32 @@ impl ServerCertVerifier for NoCertificateVerification { fn verify_tls12_signature( &self, message: &[u8], - cert: &rustls::Certificate, + cert: &rustls::pki_types::CertificateDer, dss: &DigitallySignedStruct, ) -> Result<HandshakeSignatureValid, Error> { - if self.0.is_empty() { + if self.ic_allowlist.is_empty() { return Ok(HandshakeSignatureValid::assertion()); } filter_invalid_encoding_err( - DefaultSignatureVerification.verify_tls12_signature(message, cert, dss), + self + .default_verifier + .verify_tls12_signature(message, cert, dss), ) } fn verify_tls13_signature( &self, message: &[u8], - cert: &rustls::Certificate, + cert: &rustls::pki_types::CertificateDer, dss: &DigitallySignedStruct, ) -> Result<HandshakeSignatureValid, Error> { - if self.0.is_empty() { + if self.ic_allowlist.is_empty() { return Ok(HandshakeSignatureValid::assertion()); } filter_invalid_encoding_err( - DefaultSignatureVerification.verify_tls13_signature(message, cert, dss), + self + .default_verifier + .verify_tls13_signature(message, cert, dss), ) } } @@ -149,17 +154,10 @@ pub struct BasicAuth { } 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_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map( - |ta| { - rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - }, - )); + let root_cert_store = rustls::RootCertStore { + roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(), + }; + debug_assert!(!root_cert_store.is_empty()); root_cert_store } @@ -183,10 +181,10 @@ pub fn create_client_config( ) -> Result<ClientConfig, AnyError> { if let Some(ic_allowlist) = unsafely_ignore_certificate_errors { let client_config = ClientConfig::builder() - .with_safe_defaults() - .with_custom_certificate_verifier(Arc::new(NoCertificateVerification( - ic_allowlist, - ))); + .dangerous() + .with_custom_certificate_verifier(Arc::new( + NoCertificateVerification::new(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 @@ -194,7 +192,7 @@ pub fn create_client_config( // or client cert". let mut client = match maybe_cert_chain_and_key { TlsKeys::Static(TlsKey(cert_chain, private_key)) => client_config - .with_client_auth_cert(cert_chain, private_key) + .with_client_auth_cert(cert_chain, private_key.clone_key()) .expect("invalid client key or certificate"), TlsKeys::Null => client_config.with_no_client_auth(), TlsKeys::Resolver(_) => unimplemented!(), @@ -204,33 +202,33 @@ pub fn create_client_config( return Ok(client); } - 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 - )); - } + 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. + for r in rustls_pemfile::certs(reader) { + match r { + Ok(cert) => { + root_cert_store.add(cert)?; + } + Err(e) => { + return Err(anyhow!( + "Unable to add pem file to certificate store: {}", + e + )); } } - root_cert_store - }); + } + } + + let client_config = + ClientConfig::builder().with_root_certificates(root_cert_store); let mut client = match maybe_cert_chain_and_key { TlsKeys::Static(TlsKey(cert_chain, private_key)) => client_config - .with_client_auth_cert(cert_chain, private_key) + .with_client_auth_cert(cert_chain, private_key.clone_key()) .expect("invalid client key or certificate"), TlsKeys::Null => client_config.with_no_client_auth(), TlsKeys::Resolver(_) => unimplemented!(), @@ -257,15 +255,17 @@ fn add_alpn(client: &mut ClientConfig, socket_use: SocketUse) { pub fn load_certs( reader: &mut dyn BufRead, -) -> Result<Vec<Certificate>, AnyError> { - let certs = certs(reader) +) -> Result<Vec<CertificateDer<'static>>, AnyError> { + let certs: Result<Vec<_>, _> = certs(reader).collect(); + + let certs = certs .map_err(|_| custom_error("InvalidData", "Unable to decode certificate"))?; if certs.is_empty() { return Err(cert_not_found_err()); } - Ok(certs.into_iter().map(rustls::Certificate).collect()) + Ok(certs) } fn key_decode_err() -> AnyError { @@ -281,21 +281,32 @@ fn cert_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.into_iter().map(rustls::PrivateKey).collect()) +fn load_rsa_keys( + mut bytes: &[u8], +) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> { + let keys: Result<Vec<_>, _> = rsa_private_keys(&mut bytes).collect(); + let keys = keys.map_err(|_| key_decode_err())?; + Ok(keys.into_iter().map(PrivateKeyDer::Pkcs1).collect()) } /// Starts with -----BEGIN EC PRIVATE KEY----- -fn load_ec_keys(mut bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { - let keys = ec_private_keys(&mut bytes).map_err(|_| key_decode_err())?; - Ok(keys.into_iter().map(rustls::PrivateKey).collect()) +fn load_ec_keys( + mut bytes: &[u8], +) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> { + let keys: Result<Vec<_>, std::io::Error> = + ec_private_keys(&mut bytes).collect(); + let keys2 = keys.map_err(|_| key_decode_err())?; + Ok(keys2.into_iter().map(PrivateKeyDer::Sec1).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.into_iter().map(rustls::PrivateKey).collect()) +fn load_pkcs8_keys( + mut bytes: &[u8], +) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> { + let keys: Result<Vec<_>, std::io::Error> = + pkcs8_private_keys(&mut bytes).collect(); + let keys2 = keys.map_err(|_| key_decode_err())?; + Ok(keys2.into_iter().map(PrivateKeyDer::Pkcs8).collect()) } fn filter_invalid_encoding_err( @@ -309,7 +320,9 @@ fn filter_invalid_encoding_err( } } -pub fn load_private_keys(bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { +pub fn load_private_keys( + bytes: &[u8], +) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> { let mut keys = load_rsa_keys(bytes)?; if keys.is_empty() { |