diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2024-06-19 15:09:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-19 16:09:17 +0200 |
commit | b94707af7df757db13f24b7b70dbd7956d1e1e1c (patch) | |
tree | 5e2ce944f66f4fda8b0982b68e7e422c2960753a /ext/tls | |
parent | f4eead61ebd0af203784134c0a8b6339874531b5 (diff) |
Revert "chore: upgrade to reqwest 0.12.4 and rustls 0.22 (#24056)" (#24262)
This reverts commit fb31eaa9ca59f6daaee0210d5cd206185c7041b9.
Reverting because users reported spurious errors when downloading
dependencies - https://github.com/denoland/deno/issues/24260.
Closes https://github.com/denoland/deno/issues/24260
Diffstat (limited to 'ext/tls')
-rw-r--r-- | ext/tls/Cargo.toml | 4 | ||||
-rw-r--r-- | ext/tls/lib.rs | 201 | ||||
-rw-r--r-- | ext/tls/testdata/README | 4 | ||||
-rw-r--r-- | ext/tls/testdata/example1_cert.der | bin | 929 -> 0 bytes | |||
-rw-r--r-- | ext/tls/testdata/example1_prikey.der | bin | 1190 -> 0 bytes | |||
-rw-r--r-- | ext/tls/testdata/example2_cert.der | bin | 929 -> 0 bytes | |||
-rw-r--r-- | ext/tls/testdata/example2_prikey.der | bin | 1191 -> 0 bytes | |||
-rw-r--r-- | ext/tls/tls_key.rs | 46 |
8 files changed, 114 insertions, 141 deletions
diff --git a/ext/tls/Cargo.toml b/ext/tls/Cargo.toml index e9f432848..65c407d1c 100644 --- a/ext/tls/Cargo.toml +++ b/ext/tls/Cargo.toml @@ -15,8 +15,8 @@ path = "lib.rs" [dependencies] deno_core.workspace = true -deno_native_certs = "0.3.0" -rustls.workspace = true +deno_native_certs = "0.2.0" +rustls = { workspace = true, features = ["dangerous_configuration"] } rustls-pemfile.workspace = true rustls-tokio-stream.workspace = true rustls-webpki.workspace = true diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index c4d548ccf..5122264bf 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -1,9 +1,7 @@ // 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; @@ -13,14 +11,14 @@ use deno_core::anyhow::anyhow; use deno_core::error::custom_error; use deno_core::error::AnyError; -use rustls::client::danger::HandshakeSignatureValid; -use rustls::client::danger::ServerCertVerified; -use rustls::client::danger::ServerCertVerifier; -use rustls::client::WebPkiServerVerifier; +use rustls::client::HandshakeSignatureValid; +use rustls::client::ServerCertVerified; +use rustls::client::ServerCertVerifier; +use rustls::client::WebPkiVerifier; use rustls::ClientConfig; use rustls::DigitallySignedStruct; use rustls::Error; -use rustls::RootCertStore; +use rustls::ServerName; use rustls_pemfile::certs; use rustls_pemfile::ec_private_keys; use rustls_pemfile::pkcs8_private_keys; @@ -29,12 +27,16 @@ 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 @@ -46,59 +48,56 @@ pub trait RootCertStoreProvider: Send + Sync { // This extension has no runtime apis, it only exports some shared native functions. deno_core::extension!(deno_tls); -#[derive(Debug)] -pub struct NoCertificateVerification { - pub ic_allowlist: Vec<String>, - default_verifier: Arc<WebPkiServerVerifier>, -} +struct DefaultSignatureVerification; -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(), - } +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 ServerCertVerifier for NoCertificateVerification { - fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> { - self.default_verifier.supported_verify_schemes() - } +pub struct NoCertificateVerification(pub Vec<String>); +impl ServerCertVerifier for NoCertificateVerification { fn verify_server_cert( &self, - end_entity: &rustls::pki_types::CertificateDer<'_>, - intermediates: &[rustls::pki_types::CertificateDer<'_>], - server_name: &rustls::pki_types::ServerName<'_>, + end_entity: &Certificate, + intermediates: &[Certificate], + server_name: &ServerName, + scts: &mut dyn Iterator<Item = &[u8]>, ocsp_response: &[u8], - now: rustls::pki_types::UnixTime, + now: SystemTime, ) -> Result<ServerCertVerified, Error> { - if self.ic_allowlist.is_empty() { + if self.0.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) => { - Into::<IpAddr>::into(*ip_address).to_string() - } + ServerName::IpAddress(ip_address) => 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.ic_allowlist.contains(&dns_name_or_ip_address) { + if self.0.contains(&dns_name_or_ip_address) { Ok(ServerCertVerified::assertion()) } else { - self.default_verifier.verify_server_cert( + 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, ) @@ -108,32 +107,28 @@ impl ServerCertVerifier for NoCertificateVerification { fn verify_tls12_signature( &self, message: &[u8], - cert: &rustls::pki_types::CertificateDer, + cert: &rustls::Certificate, dss: &DigitallySignedStruct, ) -> Result<HandshakeSignatureValid, Error> { - if self.ic_allowlist.is_empty() { + if self.0.is_empty() { return Ok(HandshakeSignatureValid::assertion()); } filter_invalid_encoding_err( - self - .default_verifier - .verify_tls12_signature(message, cert, dss), + DefaultSignatureVerification.verify_tls12_signature(message, cert, dss), ) } fn verify_tls13_signature( &self, message: &[u8], - cert: &rustls::pki_types::CertificateDer, + cert: &rustls::Certificate, dss: &DigitallySignedStruct, ) -> Result<HandshakeSignatureValid, Error> { - if self.ic_allowlist.is_empty() { + if self.0.is_empty() { return Ok(HandshakeSignatureValid::assertion()); } filter_invalid_encoding_err( - self - .default_verifier - .verify_tls13_signature(message, cert, dss), + DefaultSignatureVerification.verify_tls13_signature(message, cert, dss), ) } } @@ -154,10 +149,17 @@ pub struct BasicAuth { } pub fn create_default_root_cert_store() -> RootCertStore { - let root_cert_store = rustls::RootCertStore { - roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(), - }; - debug_assert!(!root_cert_store.is_empty()); + 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, + ) + }, + )); root_cert_store } @@ -181,10 +183,10 @@ pub fn create_client_config( ) -> Result<ClientConfig, AnyError> { if let Some(ic_allowlist) = unsafely_ignore_certificate_errors { let client_config = ClientConfig::builder() - .dangerous() - .with_custom_certificate_verifier(Arc::new( - NoCertificateVerification::new(ic_allowlist), - )); + .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 @@ -192,7 +194,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.clone_key()) + .with_client_auth_cert(cert_chain, private_key) .expect("invalid client key or certificate"), TlsKeys::Null => client_config.with_no_client_auth(), TlsKeys::Resolver(_) => unimplemented!(), @@ -202,33 +204,33 @@ pub fn create_client_config( return Ok(client); } - 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 - )); + 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 client_config = - ClientConfig::builder().with_root_certificates(root_cert_store); + 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.clone_key()) + .with_client_auth_cert(cert_chain, private_key) .expect("invalid client key or certificate"), TlsKeys::Null => client_config.with_no_client_auth(), TlsKeys::Resolver(_) => unimplemented!(), @@ -255,17 +257,15 @@ fn add_alpn(client: &mut ClientConfig, socket_use: SocketUse) { pub fn load_certs( reader: &mut dyn BufRead, -) -> Result<Vec<CertificateDer<'static>>, AnyError> { - let certs: Result<Vec<_>, _> = certs(reader).collect(); - - let certs = certs +) -> Result<Vec<Certificate>, AnyError> { + let certs = certs(reader) .map_err(|_| custom_error("InvalidData", "Unable to decode certificate"))?; if certs.is_empty() { return Err(cert_not_found_err()); } - Ok(certs) + Ok(certs.into_iter().map(rustls::Certificate).collect()) } fn key_decode_err() -> AnyError { @@ -281,32 +281,21 @@ fn cert_not_found_err() -> AnyError { } /// Starts with -----BEGIN RSA PRIVATE KEY----- -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()) +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()) } /// Starts with -----BEGIN EC PRIVATE KEY----- -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()) +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()) } /// Starts with -----BEGIN PRIVATE KEY----- -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 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 filter_invalid_encoding_err( @@ -320,9 +309,7 @@ fn filter_invalid_encoding_err( } } -pub fn load_private_keys( - bytes: &[u8], -) -> Result<Vec<PrivateKeyDer<'static>>, AnyError> { +pub fn load_private_keys(bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { let mut keys = load_rsa_keys(bytes)?; if keys.is_empty() { diff --git a/ext/tls/testdata/README b/ext/tls/testdata/README deleted file mode 100644 index 12046561c..000000000 --- a/ext/tls/testdata/README +++ /dev/null @@ -1,4 +0,0 @@ - -openssl req -x509 -newkey rsa:2048 -nodes -keyout example2_prikey.pem -out example2_cert.der -subj "/C=US/ST=State/L=Locality/O=Organization/CN=example2.com" -outform der - -openssl pkey -in example2_prikey.pem -out example2_prikey.der -outform der diff --git a/ext/tls/testdata/example1_cert.der b/ext/tls/testdata/example1_cert.der Binary files differdeleted file mode 100644 index fb1b2e64b..000000000 --- a/ext/tls/testdata/example1_cert.der +++ /dev/null diff --git a/ext/tls/testdata/example1_prikey.der b/ext/tls/testdata/example1_prikey.der Binary files differdeleted file mode 100644 index 1cf7ef1d2..000000000 --- a/ext/tls/testdata/example1_prikey.der +++ /dev/null diff --git a/ext/tls/testdata/example2_cert.der b/ext/tls/testdata/example2_cert.der Binary files differdeleted file mode 100644 index 4428f3f6b..000000000 --- a/ext/tls/testdata/example2_cert.der +++ /dev/null diff --git a/ext/tls/testdata/example2_prikey.der b/ext/tls/testdata/example2_prikey.der Binary files differdeleted file mode 100644 index 8bdef8df3..000000000 --- a/ext/tls/testdata/example2_prikey.der +++ /dev/null diff --git a/ext/tls/tls_key.rs b/ext/tls/tls_key.rs index 1e60e7cf0..18064a91a 100644 --- a/ext/tls/tls_key.rs +++ b/ext/tls/tls_key.rs @@ -11,6 +11,8 @@ //! key lookup can handle closing one end of the pair, in which case they will just //! attempt to clean up the associated resources. +use crate::Certificate; +use crate::PrivateKey; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::futures::future::poll_fn; @@ -30,21 +32,12 @@ use std::sync::Arc; use tokio::sync::broadcast; use tokio::sync::mpsc; use tokio::sync::oneshot; -use webpki::types::CertificateDer; -use webpki::types::PrivateKeyDer; type ErrorType = Rc<AnyError>; /// A TLS certificate/private key pair. -/// see https://docs.rs/rustls-pki-types/latest/rustls_pki_types/#cloning-private-keys -#[derive(Debug, PartialEq, Eq)] -pub struct TlsKey(pub Vec<CertificateDer<'static>>, pub PrivateKeyDer<'static>); - -impl Clone for TlsKey { - fn clone(&self) -> Self { - Self(self.0.clone(), self.1.clone_key()) - } -} +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TlsKey(pub Vec<Certificate>, pub PrivateKey); #[derive(Clone, Debug, Default)] pub enum TlsKeys { @@ -116,8 +109,9 @@ impl TlsKeyResolver { let key = self.resolve(sni).await?; let mut tls_config = ServerConfig::builder() + .with_safe_defaults() .with_no_client_auth() - .with_single_cert(key.0, key.1.clone_key())?; + .with_single_cert(key.0, key.1)?; tls_config.alpn_protocols = alpn; Ok(tls_config.into()) } @@ -257,18 +251,14 @@ impl TlsKeyLookup { pub mod tests { use super::*; use deno_core::unsync::spawn; + use rustls::Certificate; + use rustls::PrivateKey; fn tls_key_for_test(sni: &str) -> TlsKey { - let manifest_dir = - std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()); - let sni = sni.replace(".com", ""); - let cert_file = manifest_dir.join(format!("testdata/{}_cert.der", sni)); - let prikey_file = manifest_dir.join(format!("testdata/{}_prikey.der", sni)); - let cert = std::fs::read(cert_file).unwrap(); - let prikey = std::fs::read(prikey_file).unwrap(); - let cert = CertificateDer::from(cert); - let prikey = PrivateKeyDer::try_from(prikey).unwrap(); - TlsKey(vec![cert], prikey) + TlsKey( + vec![Certificate(format!("{sni}-cert").into_bytes())], + PrivateKey(format!("{sni}-key").into_bytes()), + ) } #[tokio::test] @@ -280,8 +270,8 @@ pub mod tests { } }); - let key = resolver.resolve("example1.com".to_owned()).await.unwrap(); - assert_eq!(tls_key_for_test("example1.com"), key); + let key = resolver.resolve("example.com".to_owned()).await.unwrap(); + assert_eq!(tls_key_for_test("example.com"), key); drop(resolver); task.await.unwrap(); @@ -296,13 +286,13 @@ pub mod tests { } }); - let f1 = resolver.resolve("example1.com".to_owned()); - let f2 = resolver.resolve("example1.com".to_owned()); + let f1 = resolver.resolve("example.com".to_owned()); + let f2 = resolver.resolve("example.com".to_owned()); let key = f1.await.unwrap(); - assert_eq!(tls_key_for_test("example1.com"), key); + assert_eq!(tls_key_for_test("example.com"), key); let key = f2.await.unwrap(); - assert_eq!(tls_key_for_test("example1.com"), key); + assert_eq!(tls_key_for_test("example.com"), key); drop(resolver); task.await.unwrap(); |