diff options
author | Aleksei Kosyrev <albnnc@gmail.com> | 2022-05-18 14:32:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-18 13:32:12 +0200 |
commit | 037466e9cdec913d0f146532fde28b26093267f1 (patch) | |
tree | c30c4aea060be94e3fcbc24b6723327e4b84379c /ext/tls/lib.rs | |
parent | 4d8261070095e49de68ca21ac3b564887039bd24 (diff) |
fix(ext/tls): ability to ignore IP-address certificate errors (#14610)
Diffstat (limited to 'ext/tls/lib.rs')
-rw-r--r-- | ext/tls/lib.rs | 98 |
1 files changed, 80 insertions, 18 deletions
diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index 66545ec7d..42ea5b05d 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -12,10 +12,12 @@ use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::Extension; +use rustls::client::HandshakeSignatureValid; use rustls::client::ServerCertVerified; use rustls::client::ServerCertVerifier; use rustls::client::StoresClientSessions; use rustls::client::WebPkiVerifier; +use rustls::internal::msgs::handshake::DigitallySignedStruct; use rustls::Certificate; use rustls::ClientConfig; use rustls::Error; @@ -38,6 +40,22 @@ pub fn init() -> Extension { Extension::builder().build() } +struct DefaultSignatureVerification; + +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())) + } +} + pub struct NoCertificateVerification(pub Vec<String>); impl ServerCertVerifier for NoCertificateVerification { @@ -50,28 +68,61 @@ impl ServerCertVerifier for NoCertificateVerification { 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, - ) + 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) => 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) { + Ok(ServerCertVerified::assertion()) } else { - // NOTE(bartlomieju): `ServerName` is a non-exhaustive enum - // so we have this catch all error here. - Err(Error::General("Unknown `ServerName` variant".to_string())) + 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, + ) } } + + fn verify_tls12_signature( + &self, + message: &[u8], + cert: &rustls::Certificate, + dss: &DigitallySignedStruct, + ) -> Result<HandshakeSignatureValid, Error> { + if self.0.is_empty() { + return Ok(HandshakeSignatureValid::assertion()); + } + filter_invalid_encoding_err( + DefaultSignatureVerification.verify_tls12_signature(message, cert, dss), + ) + } + + fn verify_tls13_signature( + &self, + message: &[u8], + cert: &rustls::Certificate, + dss: &DigitallySignedStruct, + ) -> Result<HandshakeSignatureValid, Error> { + if self.0.is_empty() { + return Ok(HandshakeSignatureValid::assertion()); + } + filter_invalid_encoding_err( + DefaultSignatureVerification.verify_tls13_signature(message, cert, dss), + ) + } } #[derive(Deserialize, Default, Debug, Clone)] @@ -233,6 +284,17 @@ fn load_pkcs8_keys(mut bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { Ok(keys.into_iter().map(PrivateKey).collect()) } +fn filter_invalid_encoding_err( + to_be_filtered: Result<HandshakeSignatureValid, Error>, +) -> Result<HandshakeSignatureValid, Error> { + match to_be_filtered { + Err(Error::InvalidCertificateEncoding) => { + Ok(HandshakeSignatureValid::assertion()) + } + res => res, + } +} + pub fn load_private_keys(bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { let mut keys = load_rsa_keys(bytes)?; |