diff options
Diffstat (limited to 'cli/ops')
-rw-r--r-- | cli/ops/io.rs | 8 | ||||
-rw-r--r-- | cli/ops/net.rs | 10 | ||||
-rw-r--r-- | cli/ops/tls.rs | 80 |
3 files changed, 89 insertions, 9 deletions
diff --git a/cli/ops/io.rs b/cli/ops/io.rs index e045eddfb..9c228ffad 100644 --- a/cli/ops/io.rs +++ b/cli/ops/io.rs @@ -157,7 +157,7 @@ impl StreamResourceHolder { pub enum StreamResource { Stdin(tokio::io::Stdin, TTYMetadata), FsFile(Option<(tokio::fs::File, FileMetadata)>), - TcpStream(tokio::net::TcpStream), + TcpStream(Option<tokio::net::TcpStream>), #[cfg(not(windows))] UnixStream(tokio::net::UnixStream), ServerTlsStream(Box<ServerTlsStream<TcpStream>>), @@ -195,7 +195,7 @@ impl DenoAsyncRead for StreamResource { FsFile(Some((f, _))) => f, FsFile(None) => return Poll::Ready(Err(OpError::resource_unavailable())), Stdin(f, _) => f, - TcpStream(f) => f, + TcpStream(Some(f)) => f, #[cfg(not(windows))] UnixStream(f) => f, ClientTlsStream(f) => f, @@ -297,7 +297,7 @@ impl DenoAsyncWrite for StreamResource { let f: &mut dyn UnpinAsyncWrite = match self { FsFile(Some((f, _))) => f, FsFile(None) => return Poll::Pending, - TcpStream(f) => f, + TcpStream(Some(f)) => f, #[cfg(not(windows))] UnixStream(f) => f, ClientTlsStream(f) => f, @@ -315,7 +315,7 @@ impl DenoAsyncWrite for StreamResource { let f: &mut dyn UnpinAsyncWrite = match self { FsFile(Some((f, _))) => f, FsFile(None) => return Poll::Pending, - TcpStream(f) => f, + TcpStream(Some(f)) => f, #[cfg(not(windows))] UnixStream(f) => f, ClientTlsStream(f) => f, diff --git a/cli/ops/net.rs b/cli/ops/net.rs index 2636a2c2d..101fc5130 100644 --- a/cli/ops/net.rs +++ b/cli/ops/net.rs @@ -81,9 +81,9 @@ fn accept_tcp( let mut state = state_.borrow_mut(); let rid = state.resource_table.add( "tcpStream", - Box::new(StreamResourceHolder::new(StreamResource::TcpStream( + Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some( tcp_stream, - ))), + )))), ); Ok(json!({ "rid": rid, @@ -280,9 +280,9 @@ fn op_connect( let mut state = state_.borrow_mut(); let rid = state.resource_table.add( "tcpStream", - Box::new(StreamResourceHolder::new(StreamResource::TcpStream( + Box::new(StreamResourceHolder::new(StreamResource::TcpStream(Some( tcp_stream, - ))), + )))), ); Ok(json!({ "rid": rid, @@ -367,7 +367,7 @@ fn op_shutdown( .get_mut::<StreamResourceHolder>(rid) .ok_or_else(OpError::bad_resource_id)?; match resource_holder.resource { - StreamResource::TcpStream(ref mut stream) => { + StreamResource::TcpStream(Some(ref mut stream)) => { TcpStream::shutdown(stream, shutdown_mode).map_err(OpError::from)?; } #[cfg(unix)] diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs index 60338f7fc..dca2d8012 100644 --- a/cli/ops/tls.rs +++ b/cli/ops/tls.rs @@ -28,6 +28,7 @@ use tokio_rustls::{ use webpki::DNSNameRef; pub fn init(i: &mut Isolate, s: &State) { + i.register_op("op_start_tls", s.stateful_json_op(op_start_tls)); i.register_op("op_connect_tls", s.stateful_json_op(op_connect_tls)); i.register_op("op_listen_tls", s.stateful_json_op(op_listen_tls)); i.register_op("op_accept_tls", s.stateful_json_op(op_accept_tls)); @@ -42,6 +43,85 @@ struct ConnectTLSArgs { cert_file: Option<String>, } +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +struct StartTLSArgs { + rid: u32, + cert_file: Option<String>, + hostname: String, +} + +pub fn op_start_tls( + state: &State, + args: Value, + _zero_copy: Option<ZeroCopyBuf>, +) -> Result<JsonOp, OpError> { + let args: StartTLSArgs = serde_json::from_value(args)?; + let rid = args.rid as u32; + let cert_file = args.cert_file.clone(); + let state_ = state.clone(); + + let mut domain = args.hostname; + if domain.is_empty() { + domain.push_str("localhost"); + } + + let op = async move { + let mut state = state_.borrow_mut(); + + let mut resource_holder = + match state.resource_table.remove::<StreamResourceHolder>(rid) { + Some(resource) => *resource, + None => return Err(OpError::bad_resource_id()), + }; + + if let StreamResource::TcpStream(ref mut tcp_stream) = + resource_holder.resource + { + let tcp_stream = tcp_stream.take().unwrap(); + let local_addr = tcp_stream.local_addr()?; + let remote_addr = tcp_stream.peer_addr()?; + let mut config = ClientConfig::new(); + config + .root_store + .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); + if let Some(path) = cert_file { + let key_file = File::open(path)?; + let reader = &mut BufReader::new(key_file); + config.root_store.add_pem_file(reader).unwrap(); + } + + let tls_connector = TlsConnector::from(Arc::new(config)); + let dnsname = + DNSNameRef::try_from_ascii_str(&domain).expect("Invalid DNS lookup"); + let tls_stream = tls_connector.connect(dnsname, tcp_stream).await?; + + let rid = state.resource_table.add( + "clientTlsStream", + Box::new(StreamResourceHolder::new(StreamResource::ClientTlsStream( + Box::new(tls_stream), + ))), + ); + Ok(json!({ + "rid": rid, + "localAddr": { + "hostname": local_addr.ip().to_string(), + "port": local_addr.port(), + "transport": "tcp", + }, + "remoteAddr": { + "hostname": remote_addr.ip().to_string(), + "port": remote_addr.port(), + "transport": "tcp", + } + })) + } else { + Err(OpError::bad_resource_id()) + } + }; + Ok(JsonOp::Async(op.boxed_local())) +} + pub fn op_connect_tls( state: &State, args: Value, |