Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: stabilize Deno.startTls #12581

Merged
merged 2 commits into from
Oct 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions cli/dts/lib.deno.unstable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1093,45 +1093,6 @@ declare namespace Deno {
*/
export function connectTls(options: ConnectTlsOptions): Promise<TlsConn>;

export interface StartTlsOptions {
/** A literal IP address or host name that can be resolved to an IP address.
* If not specified, defaults to `127.0.0.1`. */
hostname?: string;
/**
* @deprecated This option is deprecated and will be removed in a future
* release.
*
* Server certificate file.
*/
certFile?: string;
/** A list of root certificates that will be used in addition to the
* default root certificates to verify the peer's certificate.
*
* Must be in PEM format. */
caCerts?: string[];
}

/** **UNSTABLE**: new API, yet to be vetted.
*
* Start TLS handshake from an existing connection using
* an optional cert file, hostname (default is "127.0.0.1"). Specifying CA
* certs is optional. By default the configured root certificates are used.
* Using this function requires that the other end of the connection is
* prepared for TLS handshake.
*
* ```ts
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
* const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
* const tlsConn = await Deno.startTls(conn, { caCerts: [caCert], hostname: "localhost" });
* ```
*
* Requires `allow-net` permission.
*/
export function startTls(
conn: Conn,
options?: StartTlsOptions,
): Promise<TlsConn>;

export interface ListenTlsOptions {
/** **UNSTABLE**: new API, yet to be vetted.
*
Expand Down
19 changes: 1 addition & 18 deletions cli/tests/unit/tls_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,23 +1105,6 @@ unitTest(
},
);

unitTest(
{ permissions: { read: true, net: true } },
async function startTLSCertFile() {
const plainConn = await Deno.connect({
hostname: "localhost",
port: 4557,
});
const conn = await Deno.startTls(plainConn, {
hostname: "localhost",
certFile: "cli/tests/testdata/tls/RootCA.pem",
});
const result = decoder.decode(await readAll(conn));
assertEquals(result, "PASS");
conn.close();
},
);

unitTest(
{ permissions: { read: true, net: true } },
async function tlsHandshakeSuccess() {
Expand Down Expand Up @@ -1235,7 +1218,7 @@ unitTest(
const tcpConn = await Deno.connect({ hostname, port });
const tlsConn = await Deno.startTls(tcpConn, {
hostname: "foo.land",
certFile: "cli/tests/testdata/tls/RootCA.crt",
caCerts: [Deno.readTextFileSync("cli/tests/testdata/tls/RootCA.pem")],
lucacasonato marked this conversation as resolved.
Show resolved Hide resolved
});
// Handshake fails because hostname doesn't match the certificate.
await assertRejects(
Expand Down
30 changes: 30 additions & 0 deletions ext/net/lib.deno_net.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,36 @@ declare namespace Deno {
*/
export function connectTls(options: ConnectTlsOptions): Promise<TlsConn>;

export interface StartTlsOptions {
/** A literal IP address or host name that can be resolved to an IP address.
* If not specified, defaults to `127.0.0.1`. */
hostname?: string;
/** A list of root certificates that will be used in addition to the
* default root certificates to verify the peer's certificate.
*
* Must be in PEM format. */
caCerts?: string[];
}

/** Start TLS handshake from an existing connection using an optional list of
* CA certificates, and hostname (default is "127.0.0.1"). Specifying CA certs
* is optional. By default the configured root certificates are used. Using
* this function requires that the other end of the connection is prepared for
* a TLS handshake.
*
* ```ts
* const conn = await Deno.connect({ port: 80, hostname: "127.0.0.1" });
* const caCert = await Deno.readTextFile("./certs/my_custom_root_CA.pem");
* const tlsConn = await Deno.startTls(conn, { caCerts: [caCert], hostname: "localhost" });
* ```
*
* Requires `allow-net` permission.
*/
export function startTls(
conn: Conn,
options?: StartTlsOptions,
): Promise<TlsConn>;

/** Shutdown socket send operations.
*
* Matches behavior of POSIX shutdown(3).
Expand Down
15 changes: 2 additions & 13 deletions ext/net/ops_tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,6 @@ pub struct ConnectTlsArgs {
#[serde(rename_all = "camelCase")]
struct StartTlsArgs {
rid: ResourceId,
cert_file: Option<String>,
ca_certs: Vec<String>,
hostname: String,
}
Expand All @@ -794,29 +793,19 @@ where
"" => "localhost",
n => n,
};
let cert_file = args.cert_file.as_deref();

{
super::check_unstable2(&state, "Deno.startTls");
let mut s = state.borrow_mut();
let permissions = s.borrow_mut::<NP>();
permissions.check_net(&(hostname, Some(0)))?;
if let Some(path) = cert_file {
permissions.check_read(Path::new(path))?;
}
}

let mut ca_certs = args
let ca_certs = args
.ca_certs
.into_iter()
.map(|s| s.into_bytes())
.collect::<Vec<_>>();

if let Some(path) = cert_file {
let mut buf = Vec::new();
File::open(path)?.read_to_end(&mut buf)?;
ca_certs.push(buf);
};

let hostname_dns = DNSNameRef::try_from_ascii_str(hostname)
.map_err(|_| invalid_hostname(hostname))?;

Expand Down
2 changes: 1 addition & 1 deletion runtime/js/90_deno_ns.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
listen: __bootstrap.net.listen,
connectTls: __bootstrap.tls.connectTls,
listenTls: __bootstrap.tls.listenTls,
startTls: __bootstrap.tls.startTls,
shutdown: __bootstrap.net.shutdown,
fstatSync: __bootstrap.fs.fstatSync,
fstat: __bootstrap.fs.fstat,
Expand Down Expand Up @@ -125,7 +126,6 @@
listen: __bootstrap.netUnstable.listen,
connect: __bootstrap.netUnstable.connect,
listenDatagram: __bootstrap.netUnstable.listenDatagram,
startTls: __bootstrap.tls.startTls,
umask: __bootstrap.fs.umask,
futime: __bootstrap.fs.futime,
futimeSync: __bootstrap.fs.futimeSync,
Expand Down