mirror of
https://github.com/usestrix/firewall.git
synced 2026-11-09 18:08:49 -10:00
schannel's revocation check, which cargo enables, fails closed on a leaf without a reachable CRL. The CA gains cRLSign, which rcgen needs to sign one, and leaves carry a distribution point when the platform serves it. Co-authored-by: Ian Graham Martinez <[email protected]>
53 lines
2.0 KiB
Rust
53 lines
2.0 KiB
Rust
use firewall::mitm;
|
|
use rcgen::KeyPair;
|
|
|
|
fn signer() -> KeyPair {
|
|
KeyPair::generate().expect("generate a key")
|
|
}
|
|
|
|
/// The name constraint is what scopes a machine-wide trust anchor, and only if critical.
|
|
#[test]
|
|
fn minted_ca_is_name_constrained() {
|
|
let hosts = ["registry.npmjs.org", "pypi.org"];
|
|
let ca = mitm::CertificateAuthority::generate(&hosts, &signer()).expect("mint a ca");
|
|
|
|
let der = ca.crt.to_der().expect("re-encode the certificate");
|
|
// SEQUENCE { OID 2.5.29.30, BOOLEAN TRUE, ... }
|
|
let critical_name_constraints = [0x06, 0x03, 0x55, 0x1d, 0x1e, 0x01, 0x01, 0xff];
|
|
assert!(der.windows(8).any(|w| w == critical_name_constraints));
|
|
|
|
for host in hosts {
|
|
assert!(der.windows(host.len()).any(|w| w == host.as_bytes()), "{host} missing");
|
|
}
|
|
}
|
|
|
|
/// A stored CA must survive a restart, but never be reused for a different host set.
|
|
#[test]
|
|
fn stored_ca_round_trips_and_rejects_a_changed_host_set() {
|
|
let hosts = ["registry.npmjs.org", "pypi.org"];
|
|
let signer = signer();
|
|
let ca = mitm::CertificateAuthority::generate(&hosts, &signer);
|
|
let blob = ca.expect("mint a ca").to_blob(&hosts);
|
|
|
|
let restored = mitm::CertificateAuthority::from_blob(&blob, &hosts, &signer);
|
|
assert_eq!(restored.expect("restore the ca").to_blob(&hosts), blob);
|
|
assert!(mitm::CertificateAuthority::from_blob(&blob, &["npmjs.org"], &signer).is_none());
|
|
}
|
|
|
|
/// Leaves signed by a different key would not verify against the stored certificate.
|
|
#[test]
|
|
fn stored_ca_is_rejected_when_the_signing_key_changed() {
|
|
let hosts = ["registry.npmjs.org", "pypi.org"];
|
|
let ca = mitm::CertificateAuthority::generate(&hosts, &signer());
|
|
let blob = ca.expect("mint a ca").to_blob(&hosts);
|
|
|
|
assert!(mitm::CertificateAuthority::from_blob(&blob, &hosts, &signer()).is_none());
|
|
}
|
|
|
|
/// rcgen signs a CRL only for a CA with cRLSign, and schannel wants one for every leaf.
|
|
#[test]
|
|
fn ca_signs_an_empty_crl() {
|
|
let crl = mitm::crl(&["registry.npmjs.org", "pypi.org"], &signer()).expect("sign a crl");
|
|
assert_eq!(crl[0], 0x30, "a DER SEQUENCE");
|
|
}
|