summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/integration/run_tests.rs10
-rw-r--r--cli/tests/tls.out1
-rw-r--r--cli/tests/tls_connecttls.js67
-rw-r--r--cli/tests/tls_starttls.js65
-rw-r--r--extensions/net/lib.rs13
-rw-r--r--extensions/net/ops_tls.rs14
-rw-r--r--runtime/build.rs2
-rw-r--r--runtime/web_worker.rs5
-rw-r--r--runtime/worker.rs2
9 files changed, 175 insertions, 4 deletions
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index 88b7f5928..4ca0616f7 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -1785,3 +1785,13 @@ mod permissions {
exit_code: 1,
});
}
+
+itest!(tls_starttls {
+ args: "run --quiet --reload --allow-net --allow-read --unstable --cert tls/RootCA.pem tls_starttls.js",
+ output: "tls.out",
+});
+
+itest!(tls_connecttls {
+ args: "run --quiet --reload --allow-net --allow-read --cert tls/RootCA.pem tls_connecttls.js",
+ output: "tls.out",
+});
diff --git a/cli/tests/tls.out b/cli/tests/tls.out
new file mode 100644
index 000000000..c8e8a135c
--- /dev/null
+++ b/cli/tests/tls.out
@@ -0,0 +1 @@
+DONE
diff --git a/cli/tests/tls_connecttls.js b/cli/tests/tls_connecttls.js
new file mode 100644
index 000000000..1ef6b99ee
--- /dev/null
+++ b/cli/tests/tls_connecttls.js
@@ -0,0 +1,67 @@
+import { deferred } from "../../test_util/std/async/deferred.ts";
+import { assert, assertEquals } from "../../test_util/std/testing/asserts.ts";
+import { BufReader, BufWriter } from "../../test_util/std/io/bufio.ts";
+import { TextProtoReader } from "../../test_util/std/textproto/mod.ts";
+
+const encoder = new TextEncoder();
+const decoder = new TextDecoder();
+
+const resolvable = deferred();
+const hostname = "localhost";
+const port = 3505;
+
+const listener = Deno.listenTls({
+ hostname,
+ port,
+ certFile: "./tls/localhost.crt",
+ keyFile: "./tls/localhost.key",
+});
+
+const response = encoder.encode(
+ "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
+);
+
+listener.accept().then(
+ async (conn) => {
+ assert(conn.remoteAddr != null);
+ assert(conn.localAddr != null);
+ await conn.write(response);
+ // TODO(bartlomieju): this might be a bug
+ setTimeout(() => {
+ conn.close();
+ resolvable.resolve();
+ }, 0);
+ },
+);
+
+const conn = await Deno.connectTls({
+ hostname,
+ port,
+});
+assert(conn.rid > 0);
+const w = new BufWriter(conn);
+const r = new BufReader(conn);
+const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`;
+const writeResult = await w.write(encoder.encode(body));
+assertEquals(body.length, writeResult);
+await w.flush();
+const tpr = new TextProtoReader(r);
+const statusLine = await tpr.readLine();
+assert(statusLine !== null, `line must be read: ${String(statusLine)}`);
+const m = statusLine.match(/^(.+?) (.+?) (.+?)$/);
+assert(m !== null, "must be matched");
+const [_, proto, status, ok] = m;
+assertEquals(proto, "HTTP/1.1");
+assertEquals(status, "200");
+assertEquals(ok, "OK");
+const headers = await tpr.readMIMEHeader();
+assert(headers !== null);
+const contentLength = parseInt(headers.get("content-length"));
+const bodyBuf = new Uint8Array(contentLength);
+await r.readFull(bodyBuf);
+assertEquals(decoder.decode(bodyBuf), "Hello World\n");
+conn.close();
+listener.close();
+await resolvable;
+
+console.log("DONE");
diff --git a/cli/tests/tls_starttls.js b/cli/tests/tls_starttls.js
new file mode 100644
index 000000000..652ba869f
--- /dev/null
+++ b/cli/tests/tls_starttls.js
@@ -0,0 +1,65 @@
+import { deferred } from "../../test_util/std/async/deferred.ts";
+import { assert, assertEquals } from "../../test_util/std/testing/asserts.ts";
+import { BufReader, BufWriter } from "../../test_util/std/io/bufio.ts";
+import { TextProtoReader } from "../../test_util/std/textproto/mod.ts";
+
+const encoder = new TextEncoder();
+const decoder = new TextDecoder();
+
+const resolvable = deferred();
+const hostname = "localhost";
+const port = 3504;
+
+const listener = Deno.listenTls({
+ hostname,
+ port,
+ certFile: "./tls/localhost.crt",
+ keyFile: "./tls/localhost.key",
+});
+
+const response = encoder.encode(
+ "HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
+);
+
+listener.accept().then(
+ async (conn) => {
+ assert(conn.remoteAddr != null);
+ assert(conn.localAddr != null);
+ await conn.write(response);
+ // TODO(bartlomieju): this might be a bug
+ setTimeout(() => {
+ conn.close();
+ resolvable.resolve();
+ }, 0);
+ },
+);
+
+let conn = await Deno.connect({ hostname, port });
+conn = await Deno.startTls(conn, { hostname });
+assert(conn.rid > 0);
+const w = new BufWriter(conn);
+const r = new BufReader(conn);
+const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`;
+const writeResult = await w.write(encoder.encode(body));
+assertEquals(body.length, writeResult);
+await w.flush();
+const tpr = new TextProtoReader(r);
+const statusLine = await tpr.readLine();
+assert(statusLine !== null, `line must be read: ${String(statusLine)}`);
+const m = statusLine.match(/^(.+?) (.+?) (.+?)$/);
+assert(m !== null, "must be matched");
+const [_, proto, status, ok] = m;
+assertEquals(proto, "HTTP/1.1");
+assertEquals(status, "200");
+assertEquals(ok, "OK");
+const headers = await tpr.readMIMEHeader();
+assert(headers !== null);
+const contentLength = parseInt(headers.get("content-length"));
+const bodyBuf = new Uint8Array(contentLength);
+await r.readFull(bodyBuf);
+assertEquals(decoder.decode(bodyBuf), "Hello World\n");
+conn.close();
+listener.close();
+await resolvable;
+
+console.log("DONE");
diff --git a/extensions/net/lib.rs b/extensions/net/lib.rs
index f3281a2fb..11d0b4493 100644
--- a/extensions/net/lib.rs
+++ b/extensions/net/lib.rs
@@ -88,12 +88,22 @@ pub fn get_unstable_declaration() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("lib.deno_net.unstable.d.ts")
}
-pub fn init<P: NetPermissions + 'static>(unstable: bool) -> Extension {
+#[derive(Clone)]
+pub struct DefaultTlsOptions {
+ pub ca_data: Option<Vec<u8>>,
+}
+
+pub fn init<P: NetPermissions + 'static>(
+ ca_data: Option<Vec<u8>>,
+ 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",
@@ -103,6 +113,7 @@ pub fn init<P: NetPermissions + 'static>(unstable: bool) -> Extension {
))
.ops(ops_to_register)
.state(move |state| {
+ state.put(default_tls_options.clone());
state.put(UnstableChecker { unstable });
Ok(())
})
diff --git a/extensions/net/ops_tls.rs b/extensions/net/ops_tls.rs
index 092c74a69..a082f7f62 100644
--- a/extensions/net/ops_tls.rs
+++ b/extensions/net/ops_tls.rs
@@ -10,6 +10,7 @@ use crate::ops::OpAddr;
use crate::ops::OpConn;
use crate::resolve_addr::resolve_addr;
use crate::resolve_addr::resolve_addr_sync;
+use crate::DefaultTlsOptions;
use crate::NetPermissions;
use deno_core::error::bad_resource;
use deno_core::error::bad_resource_id;
@@ -60,6 +61,7 @@ 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;
@@ -702,6 +704,7 @@ where
};
let cert_file = args.cert_file.as_deref();
+ let default_tls_options;
{
super::check_unstable2(&state, "Deno.startTls");
let mut s = state.borrow_mut();
@@ -710,6 +713,7 @@ where
if let Some(path) = cert_file {
permissions.check_read(Path::new(path))?;
}
+ default_tls_options = s.borrow::<DefaultTlsOptions>().clone();
}
let hostname_dns = DNSNameRef::try_from_ascii_str(hostname)
@@ -733,6 +737,10 @@ where
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);
@@ -779,6 +787,7 @@ 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>();
@@ -786,6 +795,7 @@ where
if let Some(path) = cert_file {
permissions.check_read(Path::new(path))?;
}
+ default_tls_options = s.borrow::<DefaultTlsOptions>().clone();
}
let hostname_dns = DNSNameRef::try_from_ascii_str(hostname)
@@ -804,6 +814,10 @@ where
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);
diff --git a/runtime/build.rs b/runtime/build.rs
index 8c5772c67..0d1cf3bce 100644
--- a/runtime/build.rs
+++ b/runtime/build.rs
@@ -59,7 +59,7 @@ fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) {
deno_broadcast_channel::InMemoryBroadcastChannel::default(),
false, // No --unstable.
),
- deno_net::init::<deno_net::NoNetPermissions>(false), // No --unstable.
+ deno_net::init::<deno_net::NoNetPermissions>(None, false), // No --unstable.
deno_http::init(),
];
diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs
index acafb086b..bcbf71692 100644
--- a/runtime/web_worker.rs
+++ b/runtime/web_worker.rs
@@ -332,7 +332,10 @@ impl WebWorker {
vec![
ops::fs_events::init(),
ops::fs::init(),
- deno_net::init::<Permissions>(options.unstable),
+ deno_net::init::<Permissions>(
+ options.ca_data.clone(),
+ options.unstable,
+ ),
ops::os::init(),
ops::permissions::init(),
ops::plugin::init(),
diff --git a/runtime/worker.rs b/runtime/worker.rs
index 41e63914d..18ba348ff 100644
--- a/runtime/worker.rs
+++ b/runtime/worker.rs
@@ -123,7 +123,7 @@ impl MainWorker {
ops::fs::init(),
ops::io::init(),
ops::io::init_stdio(),
- deno_net::init::<Permissions>(options.unstable),
+ deno_net::init::<Permissions>(options.ca_data.clone(), options.unstable),
ops::os::init(),
ops::permissions::init(),
ops::plugin::init(),