summaryrefslogtreecommitdiff
path: root/ext/tls
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2024-06-19 15:09:17 +0100
committerGitHub <noreply@github.com>2024-06-19 16:09:17 +0200
commitb94707af7df757db13f24b7b70dbd7956d1e1e1c (patch)
tree5e2ce944f66f4fda8b0982b68e7e422c2960753a /ext/tls
parentf4eead61ebd0af203784134c0a8b6339874531b5 (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.toml4
-rw-r--r--ext/tls/lib.rs201
-rw-r--r--ext/tls/testdata/README4
-rw-r--r--ext/tls/testdata/example1_cert.derbin929 -> 0 bytes
-rw-r--r--ext/tls/testdata/example1_prikey.derbin1190 -> 0 bytes
-rw-r--r--ext/tls/testdata/example2_cert.derbin929 -> 0 bytes
-rw-r--r--ext/tls/testdata/example2_prikey.derbin1191 -> 0 bytes
-rw-r--r--ext/tls/tls_key.rs46
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
deleted file mode 100644
index fb1b2e64b..000000000
--- a/ext/tls/testdata/example1_cert.der
+++ /dev/null
Binary files differ
diff --git a/ext/tls/testdata/example1_prikey.der b/ext/tls/testdata/example1_prikey.der
deleted file mode 100644
index 1cf7ef1d2..000000000
--- a/ext/tls/testdata/example1_prikey.der
+++ /dev/null
Binary files differ
diff --git a/ext/tls/testdata/example2_cert.der b/ext/tls/testdata/example2_cert.der
deleted file mode 100644
index 4428f3f6b..000000000
--- a/ext/tls/testdata/example2_cert.der
+++ /dev/null
Binary files differ
diff --git a/ext/tls/testdata/example2_prikey.der b/ext/tls/testdata/example2_prikey.der
deleted file mode 100644
index 8bdef8df3..000000000
--- a/ext/tls/testdata/example2_prikey.der
+++ /dev/null
Binary files differ
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();