From 684377c92c88877d97c522bcc4cd6a4175277dfb Mon Sep 17 00:00:00 2001 From: Matt Mastracci Date: Thu, 9 May 2024 10:54:47 -0600 Subject: refactor(ext/tls): Implement required functionality for later SNI support (#23686) Precursor to #23236 This implements the SNI features, but uses private symbols to avoid exposing the functionality at this time. Note that to properly test this feature, we need to add a way for `connectTls` to specify a hostname. This is something that should be pushed into that API at a later time as well. ```ts Deno.test( { permissions: { net: true, read: true } }, async function listenResolver() { let sniRequests = []; const listener = Deno.listenTls({ hostname: "localhost", port: 0, [resolverSymbol]: (sni: string) => { sniRequests.push(sni); return { cert, key, }; }, }); { const conn = await Deno.connectTls({ hostname: "localhost", [serverNameSymbol]: "server-1", port: listener.addr.port, }); const [_handshake, serverConn] = await Promise.all([ conn.handshake(), listener.accept(), ]); conn.close(); serverConn.close(); } { const conn = await Deno.connectTls({ hostname: "localhost", [serverNameSymbol]: "server-2", port: listener.addr.port, }); const [_handshake, serverConn] = await Promise.all([ conn.handshake(), listener.accept(), ]); conn.close(); serverConn.close(); } assertEquals(sniRequests, ["server-1", "server-2"]); listener.close(); }, ); ``` --------- Signed-off-by: Matt Mastracci --- ext/tls/lib.rs | 47 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) (limited to 'ext/tls/lib.rs') diff --git a/ext/tls/lib.rs b/ext/tls/lib.rs index 7e68971e2..5122264bf 100644 --- a/ext/tls/lib.rs +++ b/ext/tls/lib.rs @@ -30,6 +30,9 @@ use std::io::Cursor; 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; @@ -175,7 +178,7 @@ pub fn create_client_config( root_cert_store: Option, ca_certs: Vec>, unsafely_ignore_certificate_errors: Option>, - maybe_cert_chain_and_key: Option, + maybe_cert_chain_and_key: TlsKeys, socket_use: SocketUse, ) -> Result { if let Some(ic_allowlist) = unsafely_ignore_certificate_errors { @@ -189,14 +192,13 @@ pub fn create_client_config( // However it's not really feasible to deduplicate it as the `client_config` instances // are not type-compatible - one wants "client cert", the other wants "transparency policy // or client cert". - let mut client = - if let Some(TlsKey(cert_chain, private_key)) = maybe_cert_chain_and_key { - client_config - .with_client_auth_cert(cert_chain, private_key) - .expect("invalid client key or certificate") - } else { - client_config.with_no_client_auth() - }; + 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) + .expect("invalid client key or certificate"), + TlsKeys::Null => client_config.with_no_client_auth(), + TlsKeys::Resolver(_) => unimplemented!(), + }; add_alpn(&mut client, socket_use); return Ok(client); @@ -226,14 +228,13 @@ pub fn create_client_config( root_cert_store }); - let mut client = - if let Some(TlsKey(cert_chain, private_key)) = maybe_cert_chain_and_key { - client_config - .with_client_auth_cert(cert_chain, private_key) - .expect("invalid client key or certificate") - } else { - client_config.with_no_client_auth() - }; + 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) + .expect("invalid client key or certificate"), + TlsKeys::Null => client_config.with_no_client_auth(), + TlsKeys::Resolver(_) => unimplemented!(), + }; add_alpn(&mut client, socket_use); Ok(client) @@ -325,15 +326,3 @@ pub fn load_private_keys(bytes: &[u8]) -> Result, AnyError> { Ok(keys) } - -/// A loaded key. -// FUTURE(mmastrac): add resolver enum value to support dynamic SNI -pub enum TlsKeys { - // TODO(mmastrac): We need Option<&T> for cppgc -- this is a workaround - Null, - Static(TlsKey), -} - -/// A TLS certificate/private key pair. -#[derive(Clone, Debug)] -pub struct TlsKey(pub Vec, pub PrivateKey); -- cgit v1.2.3