diff options
Diffstat (limited to 'extensions/net')
-rw-r--r-- | extensions/net/Cargo.toml | 4 | ||||
-rw-r--r-- | extensions/net/lib.rs | 12 | ||||
-rw-r--r-- | extensions/net/ops_tls.rs | 128 |
3 files changed, 53 insertions, 91 deletions
diff --git a/extensions/net/Cargo.toml b/extensions/net/Cargo.toml index d774acf88..58363fd2e 100644 --- a/extensions/net/Cargo.toml +++ b/extensions/net/Cargo.toml @@ -15,13 +15,11 @@ path = "lib.rs" [dependencies] deno_core = { version = "0.95.0", path = "../../core" } +deno_tls = { version = "0.1.0", path = "../tls" } lazy_static = "1.4.0" log = "0.4.14" -rustls = "0.19.0" serde = { version = "1.0.126", features = ["derive"] } tokio = { version = "1.8.1", features = ["full"] } trust-dns-proto = "0.20.3" trust-dns-resolver = { version = "0.20.3", features = ["tokio-runtime", "serde-config"] } -webpki = "0.21.4" -webpki-roots = "0.21.1" diff --git a/extensions/net/lib.rs b/extensions/net/lib.rs index 11d0b4493..6b0b728b1 100644 --- a/extensions/net/lib.rs +++ b/extensions/net/lib.rs @@ -11,6 +11,7 @@ use deno_core::error::AnyError; use deno_core::include_js_files; use deno_core::Extension; use deno_core::OpState; +use deno_tls::rustls::RootCertStore; use std::cell::RefCell; use std::path::Path; use std::path::PathBuf; @@ -90,20 +91,17 @@ pub fn get_unstable_declaration() -> PathBuf { #[derive(Clone)] pub struct DefaultTlsOptions { - pub ca_data: Option<Vec<u8>>, + pub root_cert_store: Option<RootCertStore>, } pub fn init<P: NetPermissions + 'static>( - ca_data: Option<Vec<u8>>, + root_cert_store: Option<RootCertStore>, unstable: bool, ) -> Extension { let mut ops_to_register = vec![]; ops_to_register.extend(io::init()); ops_to_register.extend(ops::init::<P>()); ops_to_register.extend(ops_tls::init::<P>()); - - let default_tls_options = DefaultTlsOptions { ca_data }; - Extension::builder() .js(include_js_files!( prefix "deno:extensions/net", @@ -113,7 +111,9 @@ pub fn init<P: NetPermissions + 'static>( )) .ops(ops_to_register) .state(move |state| { - state.put(default_tls_options.clone()); + state.put(DefaultTlsOptions { + root_cert_store: root_cert_store.clone(), + }); state.put(UnstableChecker { unstable }); Ok(()) }) diff --git a/extensions/net/ops_tls.rs b/extensions/net/ops_tls.rs index a082f7f62..124da2f03 100644 --- a/extensions/net/ops_tls.rs +++ b/extensions/net/ops_tls.rs @@ -1,8 +1,5 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -pub use rustls; -pub use webpki; - use crate::io::TcpStreamResource; use crate::io::TlsStreamResource; use crate::ops::IpAddr; @@ -38,30 +35,29 @@ use deno_core::OpState; use deno_core::RcRef; use deno_core::Resource; use deno_core::ResourceId; +use deno_tls::create_client_config; +use deno_tls::rustls::internal::pemfile::certs; +use deno_tls::rustls::internal::pemfile::pkcs8_private_keys; +use deno_tls::rustls::internal::pemfile::rsa_private_keys; +use deno_tls::rustls::Certificate; +use deno_tls::rustls::ClientConfig; +use deno_tls::rustls::ClientSession; +use deno_tls::rustls::NoClientAuth; +use deno_tls::rustls::PrivateKey; +use deno_tls::rustls::ServerConfig; +use deno_tls::rustls::ServerSession; +use deno_tls::rustls::Session; +use deno_tls::webpki::DNSNameRef; use io::Error; use io::Read; use io::Write; -use rustls::internal::pemfile::certs; -use rustls::internal::pemfile::pkcs8_private_keys; -use rustls::internal::pemfile::rsa_private_keys; -use rustls::Certificate; -use rustls::ClientConfig; -use rustls::ClientSession; -use rustls::NoClientAuth; -use rustls::PrivateKey; -use rustls::ServerConfig; -use rustls::ServerSession; -use rustls::Session; -use rustls::StoresClientSessions; use serde::Deserialize; use std::borrow::Cow; use std::cell::RefCell; -use std::collections::HashMap; use std::convert::From; use std::fs::File; use std::io; use std::io::BufReader; -use std::io::Cursor; use std::io::ErrorKind; use std::ops::Deref; use std::ops::DerefMut; @@ -76,32 +72,6 @@ use tokio::io::ReadBuf; use tokio::net::TcpListener; use tokio::net::TcpStream; use tokio::task::spawn_local; -use webpki::DNSNameRef; - -lazy_static::lazy_static! { - static ref CLIENT_SESSION_MEMORY_CACHE: Arc<ClientSessionMemoryCache> = - Arc::new(ClientSessionMemoryCache::default()); -} - -#[derive(Default)] -struct ClientSessionMemoryCache(Mutex<HashMap<Vec<u8>, Vec<u8>>>); - -impl StoresClientSessions for ClientSessionMemoryCache { - fn get(&self, key: &[u8]) -> Option<Vec<u8>> { - self.0.lock().get(key).cloned() - } - - fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool { - let mut sessions = self.0.lock(); - // TODO(bnoordhuis) Evict sessions LRU-style instead of arbitrarily. - while sessions.len() >= 1024 { - let key = sessions.keys().next().unwrap().clone(); - sessions.remove(&key); - } - sessions.insert(key, value); - true - } -} #[derive(Debug)] enum TlsSession { @@ -703,8 +673,6 @@ where n => n, }; let cert_file = args.cert_file.as_deref(); - - let default_tls_options; { super::check_unstable2(&state, "Deno.startTls"); let mut s = state.borrow_mut(); @@ -713,12 +681,28 @@ where if let Some(path) = cert_file { permissions.check_read(Path::new(path))?; } - default_tls_options = s.borrow::<DefaultTlsOptions>().clone(); } + let ca_data = match cert_file { + Some(path) => { + let mut buf = Vec::new(); + File::open(path)?.read_to_end(&mut buf)?; + Some(buf) + } + _ => None, + }; + let hostname_dns = DNSNameRef::try_from_ascii_str(hostname) .map_err(|_| invalid_hostname(hostname))?; + // TODO(@justinmchase): Ideally the certificate store is created once + // and not cloned. The store should be wrapped in Arc<T> to reduce + // copying memory unnecessarily. + let root_cert_store = state + .borrow() + .borrow::<DefaultTlsOptions>() + .root_cert_store + .clone(); let resource_rc = state .borrow_mut() .resource_table @@ -732,22 +716,7 @@ where let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - let mut tls_config = ClientConfig::new(); - tls_config.set_persistence(CLIENT_SESSION_MEMORY_CACHE.clone()); - tls_config - .root_store - .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); - if let Some(ca_data) = default_tls_options.ca_data { - let reader = &mut Cursor::new(ca_data); - tls_config.root_store.add_pem_file(reader).unwrap(); - }; - if let Some(path) = cert_file { - let key_file = File::open(path)?; - let reader = &mut BufReader::new(key_file); - tls_config.root_store.add_pem_file(reader).unwrap(); - } - let tls_config = Arc::new(tls_config); - + let tls_config = Arc::new(create_client_config(root_cert_store, ca_data)?); let tls_stream = TlsStream::new_client_side(tcp_stream, &tls_config, hostname_dns); @@ -786,8 +755,6 @@ where }; let port = args.port; let cert_file = args.cert_file.as_deref(); - - let default_tls_options; { let mut s = state.borrow_mut(); let permissions = s.borrow_mut::<NP>(); @@ -795,9 +762,22 @@ where if let Some(path) = cert_file { permissions.check_read(Path::new(path))?; } - default_tls_options = s.borrow::<DefaultTlsOptions>().clone(); } + let ca_data = match cert_file { + Some(path) => { + let mut buf = Vec::new(); + File::open(path)?.read_to_end(&mut buf)?; + Some(buf) + } + _ => None, + }; + + let root_cert_store = state + .borrow() + .borrow::<DefaultTlsOptions>() + .root_cert_store + .clone(); let hostname_dns = DNSNameRef::try_from_ascii_str(hostname) .map_err(|_| invalid_hostname(hostname))?; @@ -808,23 +788,7 @@ where let tcp_stream = TcpStream::connect(connect_addr).await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - - let mut tls_config = ClientConfig::new(); - tls_config.set_persistence(CLIENT_SESSION_MEMORY_CACHE.clone()); - tls_config - .root_store - .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); - if let Some(ca_data) = default_tls_options.ca_data { - let reader = &mut Cursor::new(ca_data); - tls_config.root_store.add_pem_file(reader).unwrap(); - }; - if let Some(path) = cert_file { - let key_file = File::open(path)?; - let reader = &mut BufReader::new(key_file); - tls_config.root_store.add_pem_file(reader).unwrap(); - } - let tls_config = Arc::new(tls_config); - + let tls_config = Arc::new(create_client_config(root_cert_store, ca_data)?); let tls_stream = TlsStream::new_client_side(tcp_stream, &tls_config, hostname_dns); |