mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
parent
3c7057d583
commit
9a43a2b495
4 changed files with 185 additions and 19 deletions
|
@ -51,21 +51,49 @@ async function connectTls({
|
|||
caCerts = [],
|
||||
certChain = undefined,
|
||||
privateKey = undefined,
|
||||
cert = undefined,
|
||||
key = undefined,
|
||||
alpnProtocols = undefined,
|
||||
}) {
|
||||
if (certFile !== undefined) {
|
||||
internals.warnOnDeprecatedApi(
|
||||
"Deno.ConnectTlsOptions.certFile",
|
||||
new Error().stack,
|
||||
"Pass the cert file contents to the `Deno.ConnectTlsOptions.certChain` option instead.",
|
||||
"Pass the cert file contents to the `Deno.ConnectTlsOptions.cert` option instead.",
|
||||
);
|
||||
}
|
||||
if (certChain !== undefined) {
|
||||
internals.warnOnDeprecatedApi(
|
||||
"Deno.ConnectTlsOptions.certChain",
|
||||
new Error().stack,
|
||||
"Use the `Deno.ConnectTlsOptions.cert` option instead.",
|
||||
);
|
||||
}
|
||||
if (privateKey !== undefined) {
|
||||
internals.warnOnDeprecatedApi(
|
||||
"Deno.ConnectTlsOptions.privateKey",
|
||||
new Error().stack,
|
||||
"Use the `Deno.ConnectTlsOptions.key` option instead.",
|
||||
);
|
||||
}
|
||||
if (transport !== "tcp") {
|
||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||
}
|
||||
if (certChain !== undefined && cert !== undefined) {
|
||||
throw new TypeError(
|
||||
"Cannot specify both `certChain` and `cert`",
|
||||
);
|
||||
}
|
||||
if (privateKey !== undefined && key !== undefined) {
|
||||
throw new TypeError(
|
||||
"Cannot specify both `privateKey` and `key`",
|
||||
);
|
||||
}
|
||||
cert ??= certChain;
|
||||
key ??= privateKey;
|
||||
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tls(
|
||||
{ hostname, port },
|
||||
{ certFile, caCerts, certChain, privateKey, alpnProtocols },
|
||||
{ certFile, caCerts, cert, key, alpnProtocols },
|
||||
);
|
||||
localAddr.transport = "tcp";
|
||||
remoteAddr.transport = "tcp";
|
||||
|
|
20
ext/net/lib.deno_net.d.ts
vendored
20
ext/net/lib.deno_net.d.ts
vendored
|
@ -348,10 +348,26 @@ declare namespace Deno {
|
|||
* TLS handshake.
|
||||
*/
|
||||
alpnProtocols?: string[];
|
||||
/** PEM formatted client certificate chain. */
|
||||
/**
|
||||
* PEM formatted client certificate chain.
|
||||
*
|
||||
* @deprecated This will be removed in Deno 2.0. See the
|
||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||
* for migration instructions.
|
||||
*/
|
||||
certChain?: string;
|
||||
/** PEM formatted (RSA or PKCS8) private key of client certificate. */
|
||||
/**
|
||||
* PEM formatted (RSA or PKCS8) private key of client certificate.
|
||||
*
|
||||
* @deprecated This will be removed in Deno 2.0. See the
|
||||
* {@link https://docs.deno.com/runtime/manual/advanced/migrate_deprecations | Deno 1.x to 2.x Migration Guide}
|
||||
* for migration instructions.
|
||||
*/
|
||||
privateKey?: string;
|
||||
/** Server private key in PEM format. */
|
||||
key?: string;
|
||||
/** Cert chain in PEM format. */
|
||||
cert?: string;
|
||||
}
|
||||
|
||||
/** Establishes a secure connection over TLS (transport layer security) using
|
||||
|
|
|
@ -145,8 +145,8 @@ impl Resource for TlsStreamResource {
|
|||
pub struct ConnectTlsArgs {
|
||||
cert_file: Option<String>,
|
||||
ca_certs: Vec<String>,
|
||||
cert_chain: Option<String>,
|
||||
private_key: Option<String>,
|
||||
cert: Option<String>,
|
||||
key: Option<String>,
|
||||
alpn_protocols: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
|
@ -297,24 +297,23 @@ where
|
|||
let local_addr = tcp_stream.local_addr()?;
|
||||
let remote_addr = tcp_stream.peer_addr()?;
|
||||
|
||||
let cert_chain_and_key =
|
||||
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"))?;
|
||||
Some((cert_chain, private_key))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let cert_and_key = if args.cert.is_some() || args.key.is_some() {
|
||||
let cert = args
|
||||
.cert
|
||||
.ok_or_else(|| type_error("No certificate chain provided"))?;
|
||||
let key = args
|
||||
.key
|
||||
.ok_or_else(|| type_error("No private key provided"))?;
|
||||
Some((cert, key))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut tls_config = create_client_config(
|
||||
root_cert_store,
|
||||
ca_certs,
|
||||
unsafely_ignore_certificate_errors,
|
||||
cert_chain_and_key,
|
||||
cert_and_key,
|
||||
SocketUse::GeneralSsl,
|
||||
)?;
|
||||
|
||||
|
|
|
@ -1174,6 +1174,22 @@ Deno.test(
|
|||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTLSBadCertKey(): Promise<void> {
|
||||
await assertRejects(async () => {
|
||||
await Deno.connectTls({
|
||||
hostname: "deno.land",
|
||||
port: 443,
|
||||
cert: "bad data",
|
||||
key: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.key",
|
||||
),
|
||||
});
|
||||
}, Deno.errors.InvalidData);
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTLSBadPrivateKey(): Promise<void> {
|
||||
|
@ -1190,6 +1206,22 @@ Deno.test(
|
|||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTLSBadKey(): Promise<void> {
|
||||
await assertRejects(async () => {
|
||||
await Deno.connectTls({
|
||||
hostname: "deno.land",
|
||||
port: 443,
|
||||
cert: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
key: "bad data",
|
||||
});
|
||||
}, Deno.errors.InvalidData);
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTLSNotPrivateKey(): Promise<void> {
|
||||
|
@ -1206,6 +1238,22 @@ Deno.test(
|
|||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTLSNotKey(): Promise<void> {
|
||||
await assertRejects(async () => {
|
||||
await Deno.connectTls({
|
||||
hostname: "deno.land",
|
||||
port: 443,
|
||||
cert: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
key: "",
|
||||
});
|
||||
}, Deno.errors.InvalidData);
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectWithClientCert() {
|
||||
|
@ -1231,6 +1279,81 @@ Deno.test(
|
|||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectWithCert() {
|
||||
// The test_server running on port 4552 responds with 'PASS' if client
|
||||
// authentication was successful. Try it by running test_server and
|
||||
// curl --key cli/tests/testdata/tls/localhost.key \
|
||||
// --cert cli/tests/testdata/tls/localhost.crt \
|
||||
// --cacert cli/tests/testdata/tls/RootCA.crt https://localhost:4552/
|
||||
const conn = await Deno.connectTls({
|
||||
hostname: "localhost",
|
||||
port: 4552,
|
||||
cert: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
key: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.key",
|
||||
),
|
||||
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
|
||||
});
|
||||
const result = decoder.decode(await readAll(conn));
|
||||
assertEquals(result, "PASS");
|
||||
conn.close();
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTlsConflictingCertOptions(): Promise<void> {
|
||||
await assertRejects(
|
||||
async () => {
|
||||
await Deno.connectTls({
|
||||
hostname: "deno.land",
|
||||
port: 443,
|
||||
cert: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
certChain: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
key: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.key",
|
||||
),
|
||||
});
|
||||
},
|
||||
TypeError,
|
||||
"Cannot specify both `certChain` and `cert`",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTlsConflictingKeyOptions(): Promise<void> {
|
||||
await assertRejects(
|
||||
async () => {
|
||||
await Deno.connectTls({
|
||||
hostname: "deno.land",
|
||||
port: 443,
|
||||
cert: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
privateKey: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.crt",
|
||||
),
|
||||
key: await Deno.readTextFile(
|
||||
"tests/testdata/tls/localhost.key",
|
||||
),
|
||||
});
|
||||
},
|
||||
TypeError,
|
||||
"Cannot specify both `privateKey` and `key`",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, net: true } },
|
||||
async function connectTLSCaCerts() {
|
||||
|
|
Loading…
Reference in a new issue