0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-02-08 07:16:56 -05:00

fix(ext/node): implement X509Certificate#checkHost (#27821)

Fixes https://github.com/denoland/deno/issues/27619
This commit is contained in:
Divy Srivastava 2025-01-27 16:33:03 +05:30 committed by Bartek Iwańczuk
parent 2b27d342d8
commit 6fe2341897
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
4 changed files with 83 additions and 2 deletions

View file

@ -301,6 +301,7 @@ deno_core::extension!(deno_node,
ops::crypto::x509::op_node_x509_parse,
ops::crypto::x509::op_node_x509_ca,
ops::crypto::x509::op_node_x509_check_email,
ops::crypto::x509::op_node_x509_check_host,
ops::crypto::x509::op_node_x509_fingerprint,
ops::crypto::x509::op_node_x509_fingerprint256,
ops::crypto::x509::op_node_x509_fingerprint512,

View file

@ -130,6 +130,43 @@ pub fn op_node_x509_check_email(
false
}
#[op2(fast)]
pub fn op_node_x509_check_host(
#[cppgc] cert: &Certificate,
#[string] host: &str,
) -> bool {
let cert = cert.inner.get().deref();
let subject = cert.subject();
if subject
.iter_common_name()
.any(|e| e.as_str().unwrap_or("") == host)
{
return true;
}
let subject_alt = cert
.extensions()
.iter()
.find(|e| e.oid == x509_parser::oid_registry::OID_X509_EXT_SUBJECT_ALT_NAME)
.and_then(|e| match e.parsed_extension() {
extensions::ParsedExtension::SubjectAlternativeName(s) => Some(s),
_ => None,
});
if let Some(subject_alt) = subject_alt {
for name in &subject_alt.general_names {
if let extensions::GeneralName::DNSName(n) = name {
if *n == host {
return true;
}
}
}
}
false
}
#[op2]
#[string]
pub fn op_node_x509_fingerprint(#[cppgc] cert: &Certificate) -> Option<String> {

View file

@ -7,6 +7,7 @@
import {
op_node_x509_ca,
op_node_x509_check_email,
op_node_x509_check_host,
op_node_x509_fingerprint,
op_node_x509_fingerprint256,
op_node_x509_fingerprint512,
@ -90,8 +91,11 @@ export class X509Certificate {
}
}
checkHost(_name: string, _options?: X509CheckOptions): string | undefined {
notImplemented("crypto.X509Certificate.prototype.checkHost");
checkHost(name: string, _options?: X509CheckOptions): string | undefined {
validateString(name, "name");
if (op_node_x509_check_host(this.#handle, name)) {
return name;
}
}
checkIP(_ip: string): string | undefined {

View file

@ -12,6 +12,7 @@ import {
generateKeyPairSync,
KeyObject,
randomBytes,
X509Certificate,
} from "node:crypto";
import { promisify } from "node:util";
import { Buffer } from "node:buffer";
@ -716,3 +717,41 @@ Deno.test("RSA export private JWK", function () {
assertEquals((privateKey as any).kty, "RSA");
assertEquals((privateKey as any).n, (publicKey as any).n);
});
Deno.test("X509Certificate checkHost", function () {
const der = Buffer.from(
"308203e8308202d0a0030201020214147d36c1c2f74206de9fab5f2226d78adb00a42630" +
"0d06092a864886f70d01010b0500307a310b3009060355040613025553310b3009060355" +
"04080c024341310b300906035504070c025346310f300d060355040a0c064a6f79656e74" +
"3110300e060355040b0c074e6f64652e6a73310c300a06035504030c036361313120301e" +
"06092a864886f70d010901161172794074696e79636c6f7564732e6f72673020170d3232" +
"303930333231343033375a180f32323936303631373231343033375a307d310b30090603" +
"55040613025553310b300906035504080c024341310b300906035504070c025346310f30" +
"0d060355040a0c064a6f79656e743110300e060355040b0c074e6f64652e6a73310f300d" +
"06035504030c066167656e74313120301e06092a864886f70d010901161172794074696e" +
"79636c6f7564732e6f726730820122300d06092a864886f70d01010105000382010f0030" +
"82010a0282010100d456320afb20d3827093dc2c4284ed04dfbabd56e1ddae529e28b790" +
"cd4256db273349f3735ffd337c7a6363ecca5a27b7f73dc7089a96c6d886db0c62388f1c" +
"dd6a963afcd599d5800e587a11f908960f84ed50ba25a28303ecda6e684fbe7baedc9ce8" +
"801327b1697af25097cee3f175e400984c0db6a8eb87be03b4cf94774ba56fffc8c63c68" +
"d6adeb60abbe69a7b14ab6a6b9e7baa89b5adab8eb07897c07f6d4fa3d660dff574107d2" +
"8e8f63467a788624c574197693e959cea1362ffae1bba10c8c0d88840abfef103631b2e8" +
"f5c39b5548a7ea57e8a39f89291813f45a76c448033a2b7ed8403f4baa147cf35e2d2554" +
"aa65ce49695797095bf4dc6b0203010001a361305f305d06082b06010505070101045130" +
"4f302306082b060105050730018617687474703a2f2f6f6373702e6e6f64656a732e6f72" +
"672f302806082b06010505073002861c687474703a2f2f63612e6e6f64656a732e6f7267" +
"2f63612e63657274300d06092a864886f70d01010b05000382010100c3349810632ccb7d" +
"a585de3ed51e34ed154f0f7215608cf2701c00eda444dc2427072c8aca4da6472c1d9e68" +
"f177f99a90a8b5dbf3884586d61cb1c14ea7016c8d38b70d1b46b42947db30edc1e9961e" +
"d46c0f0e35da427bfbe52900771817e733b371adf19e12137235141a34347db0dfc05579" +
"8b1f269f3bdf5e30ce35d1339d56bb3c570de9096215433047f87ca42447b44e7e6b5d0e" +
"48f7894ab186f85b6b1a74561b520952fea888617f32f582afce1111581cd63efcc68986" +
"00d248bb684dedb9c3d6710c38de9e9bc21f9c3394b729d5f707d64ea890603e5989f8fa" +
"59c19ad1a00732e7adc851b89487cc00799dde068aa64b3b8fd976e8bc113ef2",
"hex",
);
const cert = new X509Certificate(der);
assertEquals(cert.checkHost("www.google.com"), undefined);
assertEquals(cert.checkHost("agent1"), "agent1");
});