summaryrefslogtreecommitdiff
path: root/ext/tls/lib.rs
diff options
context:
space:
mode:
authorBartek Iwańczuk <biwanczuk@gmail.com>2024-06-13 21:41:26 +0100
committerGitHub <noreply@github.com>2024-06-13 22:41:26 +0200
commitfb31eaa9ca59f6daaee0210d5cd206185c7041b9 (patch)
tree0c4ebc81ed7b44b683f31281accc47d451d09718 /ext/tls/lib.rs
parent518e4d3b3a93838e0f2dbcc4d3b79f8f395db563 (diff)
chore: upgrade to reqwest 0.12.4 and rustls 0.22 (#24056)
This commit updates Deno to use `reqwest` at 0.12.4 and `rustls` at 0.22. Other related crates were updated as well to match versions accepted by `reqwest` and `rustls`. Note: we are not using the latest available `rustls` yet, but this upgrade was non-trivial already, so a bump to 0.23 for `rustls` will be done in a separate commit. Closes #23370 --------- Signed-off-by: Ryan Dahl <ry@tinyclouds.org> Signed-off-by: Bartek Iwańczuk <biwanczuk@gmail.com> Co-authored-by: Ryan Dahl <ry@tinyclouds.org> Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com>
Diffstat (limited to 'ext/tls/lib.rs')
-rw-r--r--ext/tls/lib.rs201
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() {