diff options
Diffstat (limited to 'ext/net/ops_tls.rs')
-rw-r--r-- | ext/net/ops_tls.rs | 142 |
1 files changed, 79 insertions, 63 deletions
diff --git a/ext/net/ops_tls.rs b/ext/net/ops_tls.rs index e83173e90..874f795f2 100644 --- a/ext/net/ops_tls.rs +++ b/ext/net/ops_tls.rs @@ -12,9 +12,9 @@ use deno_core::error::bad_resource; use deno_core::error::custom_error; use deno_core::error::generic_error; use deno_core::error::invalid_hostname; -use deno_core::error::type_error; use deno_core::error::AnyError; use deno_core::op2; +use deno_core::v8; use deno_core::AsyncRefCell; use deno_core::AsyncResult; use deno_core::CancelHandle; @@ -31,7 +31,8 @@ use deno_tls::rustls::PrivateKey; use deno_tls::rustls::ServerConfig; use deno_tls::rustls::ServerName; use deno_tls::SocketUse; -use io::Read; +use deno_tls::TlsKey; +use deno_tls::TlsKeys; use rustls_tokio_stream::TlsStreamRead; use rustls_tokio_stream::TlsStreamWrite; use serde::Deserialize; @@ -43,9 +44,9 @@ use std::cell::RefCell; use std::convert::From; use std::convert::TryFrom; use std::fs::File; -use std::io; use std::io::BufReader; use std::io::ErrorKind; +use std::io::Read; use std::num::NonZeroUsize; use std::path::Path; use std::rc::Rc; @@ -145,8 +146,6 @@ impl Resource for TlsStreamResource { pub struct ConnectTlsArgs { cert_file: Option<String>, ca_certs: Vec<String>, - cert: Option<String>, - key: Option<String>, alpn_protocols: Option<Vec<String>>, } @@ -160,6 +159,59 @@ pub struct StartTlsArgs { } #[op2] +pub fn op_tls_key_null<'s>( + scope: &mut v8::HandleScope<'s>, +) -> Result<v8::Local<'s, v8::Object>, AnyError> { + Ok(deno_core::cppgc::make_cppgc_object(scope, TlsKeys::Null)) +} + +#[op2] +pub fn op_tls_key_static<'s>( + scope: &mut v8::HandleScope<'s>, + #[string] cert: String, + #[string] key: String, +) -> Result<v8::Local<'s, v8::Object>, AnyError> { + let cert = load_certs(&mut BufReader::new(cert.as_bytes()))?; + let key = load_private_keys(key.as_bytes())? + .into_iter() + .next() + .unwrap(); + Ok(deno_core::cppgc::make_cppgc_object( + scope, + TlsKeys::Static(TlsKey(cert, key)), + )) +} + +/// Legacy op -- will be removed in Deno 2.0. +#[op2] +pub fn op_tls_key_static_from_file<'s, NP>( + state: &mut OpState, + scope: &mut v8::HandleScope<'s>, + #[string] api: String, + #[string] cert_file: String, + #[string] key_file: String, +) -> Result<v8::Local<'s, v8::Object>, AnyError> +where + NP: NetPermissions + 'static, +{ + { + let permissions = state.borrow_mut::<NP>(); + permissions.check_read(Path::new(&cert_file), &api)?; + permissions.check_read(Path::new(&key_file), &api)?; + } + + let cert = load_certs_from_file(&cert_file)?; + let key = load_private_keys_from_file(&key_file)? + .into_iter() + .next() + .unwrap(); + Ok(deno_core::cppgc::make_cppgc_object( + scope, + TlsKeys::Static(TlsKey(cert, key)), + )) +} + +#[op2] #[serde] pub fn op_tls_start<NP>( state: Rc<RefCell<OpState>>, @@ -251,6 +303,7 @@ pub async fn op_net_connect_tls<NP>( state: Rc<RefCell<OpState>>, #[serde] addr: IpAddr, #[serde] args: ConnectTlsArgs, + #[cppgc] key_pair: &TlsKeys, ) -> Result<(ResourceId, IpAddr, IpAddr), AnyError> where NP: NetPermissions + 'static, @@ -297,18 +350,10 @@ where let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - let cert_and_key = if args.cert.is_some() || args.key.is_some() { - let cert = args - .cert - .ok_or_else(|| type_error("No certificate chain provided"))?; - let key = args - .key - .ok_or_else(|| type_error("No private key provided"))?; - Some((cert, key)) - } else { - None + let cert_and_key = match key_pair { + TlsKeys::Null => None, + TlsKeys::Static(key) => Some(key.clone()), }; - let mut tls_config = create_client_config( root_cert_store, ca_certs, @@ -373,12 +418,6 @@ impl Resource for TlsListenerResource { #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct ListenTlsArgs { - cert: Option<String>, - // TODO(kt3k): Remove this option at v2.0. - cert_file: Option<String>, - key: Option<String>, - // TODO(kt3k): Remove this option at v2.0. - key_file: Option<String>, alpn_protocols: Option<Vec<String>>, reuse_port: bool, } @@ -389,6 +428,7 @@ pub fn op_net_listen_tls<NP>( state: &mut OpState, #[serde] addr: IpAddr, #[serde] args: ListenTlsArgs, + #[cppgc] keys: &TlsKeys, ) -> Result<(ResourceId, IpAddr), AnyError> where NP: NetPermissions + 'static, @@ -397,54 +437,30 @@ where super::check_unstable(state, "Deno.listenTls({ reusePort: true })"); } - let cert_file = args.cert_file.as_deref(); - let key_file = args.key_file.as_deref(); - let cert = args.cert.as_deref(); - let key = args.key.as_deref(); - { let permissions = state.borrow_mut::<NP>(); permissions .check_net(&(&addr.hostname, Some(addr.port)), "Deno.listenTls()")?; - if let Some(path) = cert_file { - permissions.check_read(Path::new(path), "Deno.listenTls()")?; - } - if let Some(path) = key_file { - permissions.check_read(Path::new(path), "Deno.listenTls()")?; - } } - let cert_chain = if cert_file.is_some() && cert.is_some() { - return Err(generic_error("Both cert and certFile is specified. You can specify either one of them.")); - } else if let Some(path) = cert_file { - load_certs_from_file(path)? - } else if let Some(cert) = cert { - load_certs(&mut BufReader::new(cert.as_bytes()))? - } else { - return Err(generic_error("`cert` is not specified.")); - }; - let key_der = if key_file.is_some() && key.is_some() { - return Err(generic_error( - "Both key and keyFile is specified. You can specify either one of them.", - )); - } else if let Some(path) = key_file { - load_private_keys_from_file(path)?.remove(0) - } else if let Some(key) = key { - load_private_keys(key.as_bytes())?.remove(0) - } else { - return Err(generic_error("`key` is not specified.")); - }; - - let mut tls_config = ServerConfig::builder() + let tls_config = ServerConfig::builder() .with_safe_defaults() - .with_no_client_auth() - .with_single_cert(cert_chain, key_der) - .map_err(|e| { - custom_error( - "InvalidData", - format!("Error creating TLS certificate: {:?}", e), - ) - })?; + .with_no_client_auth(); + + let mut tls_config = match keys { + TlsKeys::Null => { + unreachable!() + } + TlsKeys::Static(TlsKey(cert, key)) => { + tls_config.with_single_cert(cert.clone(), key.clone()) + } + } + .map_err(|e| { + custom_error( + "InvalidData", + format!("Error creating TLS certificate: {:?}", e), + ) + })?; if let Some(alpn_protocols) = args.alpn_protocols { tls_config.alpn_protocols = |