summaryrefslogtreecommitdiff
path: root/extensions/net/ops_tls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/net/ops_tls.rs')
-rw-r--r--extensions/net/ops_tls.rs78
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)?