diff options
Diffstat (limited to 'extensions/net/ops_tls.rs')
-rw-r--r-- | extensions/net/ops_tls.rs | 78 |
1 files changed, 60 insertions, 18 deletions
diff --git a/extensions/net/ops_tls.rs b/extensions/net/ops_tls.rs index 124da2f03..7c4563390 100644 --- a/extensions/net/ops_tls.rs +++ b/extensions/net/ops_tls.rs @@ -14,6 +14,7 @@ use deno_core::error::bad_resource_id; 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::futures::future::poll_fn; use deno_core::futures::ready; @@ -57,6 +58,7 @@ use std::cell::RefCell; use std::convert::From; use std::fs::File; use std::io; +use std::io::BufRead; use std::io::BufReader; use std::io::ErrorKind; use std::ops::Deref; @@ -649,6 +651,8 @@ pub struct ConnectTlsArgs { hostname: String, port: u16, cert_file: Option<String>, + cert_chain: Option<String>, + private_key: Option<String>, } #[derive(Deserialize)] @@ -717,6 +721,7 @@ where let remote_addr = tcp_stream.peer_addr()?; 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); @@ -755,6 +760,14 @@ where }; let port = args.port; let cert_file = args.cert_file.as_deref(); + + if args.cert_chain.is_some() { + super::check_unstable2(&state, "ConnectTlsOptions.certChain"); + } + if args.private_key.is_some() { + super::check_unstable2(&state, "ConnectTlsOptions.privateKey"); + } + { let mut s = state.borrow_mut(); let permissions = s.borrow_mut::<NP>(); @@ -788,7 +801,28 @@ where let tcp_stream = TcpStream::connect(connect_addr).await?; let local_addr = tcp_stream.local_addr()?; let remote_addr = tcp_stream.peer_addr()?; - let tls_config = Arc::new(create_client_config(root_cert_store, ca_data)?); + + let mut tls_config = create_client_config(root_cert_store, ca_data)?; + + if args.cert_chain.is_some() || args.private_key.is_some() { + let cert_chain = args + .cert_chain + .ok_or_else(|| type_error("No certificate chain provided"))?; + let private_key = args + .private_key + .ok_or_else(|| type_error("No private key provided"))?; + + // The `remove` is safe because load_private_keys checks that there is at least one key. + let private_key = load_private_keys(private_key.as_bytes())?.remove(0); + + tls_config.set_single_client_cert( + load_certs(&mut cert_chain.as_bytes())?, + private_key, + )?; + } + + let tls_config = Arc::new(tls_config); + let tls_stream = TlsStream::new_client_side(tcp_stream, &tls_config, hostname_dns); @@ -812,10 +846,7 @@ where }) } -fn load_certs(path: &str) -> Result<Vec<Certificate>, AnyError> { - let cert_file = File::open(path)?; - let reader = &mut BufReader::new(cert_file); - +fn load_certs(reader: &mut dyn BufRead) -> Result<Vec<Certificate>, AnyError> { let certs = certs(reader) .map_err(|_| custom_error("InvalidData", "Unable to decode certificate"))?; @@ -827,6 +858,12 @@ fn load_certs(path: &str) -> Result<Vec<Certificate>, AnyError> { Ok(certs) } +fn load_certs_from_file(path: &str) -> Result<Vec<Certificate>, AnyError> { + let cert_file = File::open(path)?; + let reader = &mut BufReader::new(cert_file); + load_certs(reader) +} + fn key_decode_err() -> AnyError { custom_error("InvalidData", "Unable to decode key") } @@ -836,27 +873,22 @@ fn key_not_found_err() -> AnyError { } /// Starts with -----BEGIN RSA PRIVATE KEY----- -fn load_rsa_keys(path: &str) -> Result<Vec<PrivateKey>, AnyError> { - let key_file = File::open(path)?; - let reader = &mut BufReader::new(key_file); - let keys = rsa_private_keys(reader).map_err(|_| key_decode_err())?; +fn load_rsa_keys(mut bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { + let keys = rsa_private_keys(&mut bytes).map_err(|_| key_decode_err())?; Ok(keys) } /// Starts with -----BEGIN PRIVATE KEY----- -fn load_pkcs8_keys(path: &str) -> Result<Vec<PrivateKey>, AnyError> { - let key_file = File::open(path)?; - let reader = &mut BufReader::new(key_file); - let keys = pkcs8_private_keys(reader).map_err(|_| key_decode_err())?; +fn load_pkcs8_keys(mut bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { + let keys = pkcs8_private_keys(&mut bytes).map_err(|_| key_decode_err())?; Ok(keys) } -fn load_keys(path: &str) -> Result<Vec<PrivateKey>, AnyError> { - let path = path.to_string(); - let mut keys = load_rsa_keys(&path)?; +fn load_private_keys(bytes: &[u8]) -> Result<Vec<PrivateKey>, AnyError> { + let mut keys = load_rsa_keys(bytes)?; if keys.is_empty() { - keys = load_pkcs8_keys(&path)?; + keys = load_pkcs8_keys(bytes)?; } if keys.is_empty() { @@ -866,6 +898,13 @@ fn load_keys(path: &str) -> Result<Vec<PrivateKey>, AnyError> { Ok(keys) } +fn load_private_keys_from_file( + path: &str, +) -> Result<Vec<PrivateKey>, AnyError> { + let key_bytes = std::fs::read(path)?; + load_private_keys(&key_bytes) +} + pub struct TlsListenerResource { tcp_listener: AsyncRefCell<TcpListener>, tls_config: Arc<ServerConfig>, @@ -921,7 +960,10 @@ where alpn_protocols.into_iter().map(|s| s.into_bytes()).collect(); } tls_config - .set_single_cert(load_certs(cert_file)?, load_keys(key_file)?.remove(0)) + .set_single_cert( + load_certs_from_file(cert_file)?, + load_private_keys_from_file(key_file)?.remove(0), + ) .expect("invalid key or certificate"); let bind_addr = resolve_addr_sync(hostname, port)? |