summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksei Kosyrev <albnnc@gmail.com>2022-05-18 14:32:12 +0300
committerGitHub <noreply@github.com>2022-05-18 13:32:12 +0200
commit037466e9cdec913d0f146532fde28b26093267f1 (patch)
treec30c4aea060be94e3fcbc24b6723327e4b84379c
parent4d8261070095e49de68ca21ac3b564887039bd24 (diff)
fix(ext/tls): ability to ignore IP-address certificate errors (#14610)
-rw-r--r--Cargo.lock4
-rw-r--r--cli/tests/integration/mod.rs6
-rw-r--r--cli/tests/testdata/ip_address_unsafe_ssl.ts2
-rw-r--r--cli/tests/testdata/ip_address_unsafe_ssl.ts.out2
-rw-r--r--cli/tests/unit/tls_test.ts11
-rw-r--r--ext/tls/lib.rs98
6 files changed, 93 insertions, 30 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 2f81d70e6..916b2fcb9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3373,9 +3373,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.20.4"
+version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921"
+checksum = "a024a432ae760ab3bff924ad91ce1cfa52cb57ed16e1ef32d0d249cfee1a6c13"
dependencies = [
"log",
"ring",
diff --git a/cli/tests/integration/mod.rs b/cli/tests/integration/mod.rs
index 7acd92661..7de441874 100644
--- a/cli/tests/integration/mod.rs
+++ b/cli/tests/integration/mod.rs
@@ -523,6 +523,12 @@ itest!(deno_land_unsafe_ssl {
output: "deno_land_unsafe_ssl.ts.out",
});
+itest!(ip_address_unsafe_ssl {
+ args:
+ "run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=1.1.1.1 ip_address_unsafe_ssl.ts",
+ output: "ip_address_unsafe_ssl.ts.out",
+});
+
itest!(localhost_unsafe_ssl {
args:
"run --quiet --reload --allow-net --unsafely-ignore-certificate-errors=deno.land cafile_url_imports.ts",
diff --git a/cli/tests/testdata/ip_address_unsafe_ssl.ts b/cli/tests/testdata/ip_address_unsafe_ssl.ts
new file mode 100644
index 000000000..a3268888f
--- /dev/null
+++ b/cli/tests/testdata/ip_address_unsafe_ssl.ts
@@ -0,0 +1,2 @@
+const r = await fetch("https://1.1.1.1");
+console.log(r.status);
diff --git a/cli/tests/testdata/ip_address_unsafe_ssl.ts.out b/cli/tests/testdata/ip_address_unsafe_ssl.ts.out
new file mode 100644
index 000000000..d4ebb2617
--- /dev/null
+++ b/cli/tests/testdata/ip_address_unsafe_ssl.ts.out
@@ -0,0 +1,2 @@
+DANGER: TLS certificate validation is disabled for: 1.1.1.1
+200
diff --git a/cli/tests/unit/tls_test.ts b/cli/tests/unit/tls_test.ts
index 07ffcd487..05eced64e 100644
--- a/cli/tests/unit/tls_test.ts
+++ b/cli/tests/unit/tls_test.ts
@@ -36,18 +36,9 @@ Deno.test({ permissions: { net: false } }, async function connectTLSNoPerm() {
Deno.test(
{ permissions: { read: true, net: true } },
async function connectTLSInvalidHost() {
- const listener = await Deno.listenTls({
- hostname: "localhost",
- port: 3567,
- certFile: "cli/tests/testdata/tls/localhost.crt",
- keyFile: "cli/tests/testdata/tls/localhost.key",
- });
-
await assertRejects(async () => {
- await Deno.connectTls({ hostname: "127.0.0.1", port: 3567 });
+ await Deno.connectTls({ hostname: "256.0.0.0", port: 3567 });
}, TypeError);
-
- listener.close();
},
);
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)?;