run tree from tal pass

This commit is contained in:
2026-02-10 12:09:59 +08:00
parent afc31c02ab
commit 6e135b9d7a
38 changed files with 1667 additions and 1313 deletions

View File

@@ -51,17 +51,13 @@ pub enum CaPathError {
#[error("certificate not valid at validation_time (RFC 5280 §4.1.2.5; RFC 5280 §6.1)")]
CertificateNotValidAtTime,
#[error(
"child CA KeyUsage extension missing (RFC 6487 §4.8.4; RFC 5280 §4.2.1.3)"
)]
#[error("child CA KeyUsage extension missing (RFC 6487 §4.8.4; RFC 5280 §4.2.1.3)")]
KeyUsageMissing,
#[error("child CA KeyUsage criticality must be critical (RFC 6487 §4.8.4; RFC 5280 §4.2.1.3)")]
KeyUsageNotCritical,
#[error(
"child CA KeyUsage must have only keyCertSign and cRLSign set (RFC 6487 §4.8.4)"
)]
#[error("child CA KeyUsage must have only keyCertSign and cRLSign set (RFC 6487 §4.8.4)")]
KeyUsageInvalidBits,
#[error(
@@ -370,7 +366,8 @@ fn resolve_child_ip_resources(
}
IpAddressChoice::AddressesOrRanges(items) => {
// Subset check against parent union for that AFI.
let parent_set = ip_resources_single_afi(parent, fam.afi, parent_by_afi.get(&fam.afi));
let parent_set =
ip_resources_single_afi(parent, fam.afi, parent_by_afi.get(&fam.afi));
if !ip_family_items_subset(items, &parent_set) {
return Err(CaPathError::ResourcesNotSubset);
}
@@ -382,7 +379,9 @@ fn resolve_child_ip_resources(
}
}
Ok(Some(IpResourceSet { families: out_families }))
Ok(Some(IpResourceSet {
families: out_families,
}))
}
fn resolve_child_as_resources(
@@ -403,7 +402,11 @@ fn resolve_child_as_resources(
let asnum = match child_as.asnum.as_ref() {
None => None,
Some(AsIdentifierChoice::Inherit) => parent.asnum.clone().ok_or(CaPathError::InheritWithoutParentResources).map(Some)?,
Some(AsIdentifierChoice::Inherit) => parent
.asnum
.clone()
.ok_or(CaPathError::InheritWithoutParentResources)
.map(Some)?,
Some(_) => {
if !as_choice_subset(child_as.asnum.as_ref(), parent.asnum.as_ref()) {
return Err(CaPathError::ResourcesNotSubset);
@@ -414,7 +417,11 @@ fn resolve_child_as_resources(
let rdi = match child_as.rdi.as_ref() {
None => None,
Some(AsIdentifierChoice::Inherit) => parent.rdi.clone().ok_or(CaPathError::InheritWithoutParentResources).map(Some)?,
Some(AsIdentifierChoice::Inherit) => parent
.rdi
.clone()
.ok_or(CaPathError::InheritWithoutParentResources)
.map(Some)?,
Some(_) => {
if !as_choice_subset(child_as.rdi.as_ref(), parent.rdi.as_ref()) {
return Err(CaPathError::ResourcesNotSubset);
@@ -426,10 +433,10 @@ fn resolve_child_as_resources(
Ok(Some(AsResourceSet { asnum, rdi }))
}
fn as_choice_subset(
child: Option<&AsIdentifierChoice>,
parent: Option<&AsIdentifierChoice>,
) -> bool {
fn as_choice_subset(
child: Option<&AsIdentifierChoice>,
parent: Option<&AsIdentifierChoice>,
) -> bool {
let Some(child) = child else {
return true;
};
@@ -508,9 +515,17 @@ enum AfiKey {
fn ip_resources_by_afi_items(
set: &IpResourceSet,
) -> Result<std::collections::BTreeMap<crate::data_model::rc::Afi, Vec<crate::data_model::rc::IpAddressOrRange>>, CaPathError> {
let mut m: std::collections::BTreeMap<crate::data_model::rc::Afi, Vec<crate::data_model::rc::IpAddressOrRange>> =
std::collections::BTreeMap::new();
) -> Result<
std::collections::BTreeMap<
crate::data_model::rc::Afi,
Vec<crate::data_model::rc::IpAddressOrRange>,
>,
CaPathError,
> {
let mut m: std::collections::BTreeMap<
crate::data_model::rc::Afi,
Vec<crate::data_model::rc::IpAddressOrRange>,
> = std::collections::BTreeMap::new();
for fam in &set.families {
match &fam.choice {
IpAddressChoice::Inherit => return Err(CaPathError::InheritWithoutParentResources),
@@ -555,8 +570,12 @@ fn ip_family_items_subset(
let mut child_intervals: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
for item in child_items {
match item {
crate::data_model::rc::IpAddressOrRange::Prefix(p) => child_intervals.push(prefix_to_range(p)),
crate::data_model::rc::IpAddressOrRange::Range(r) => child_intervals.push((r.min.clone(), r.max.clone())),
crate::data_model::rc::IpAddressOrRange::Prefix(p) => {
child_intervals.push(prefix_to_range(p))
}
crate::data_model::rc::IpAddressOrRange::Range(r) => {
child_intervals.push((r.min.clone(), r.max.clone()))
}
}
}
child_intervals.sort_by(|(a, _), (b, _)| a.cmp(b));
@@ -673,7 +692,9 @@ mod tests {
use crate::data_model::rc::{
Afi, AsIdentifierChoice, AsResourceSet, IpAddressChoice, IpAddressFamily, IpResourceSet,
};
use crate::data_model::rc::{RcExtensions, ResourceCertKind, ResourceCertificate, RpkixTbsCertificate};
use crate::data_model::rc::{
RcExtensions, ResourceCertKind, ResourceCertificate, RpkixTbsCertificate,
};
use der_parser::num_bigint::BigUint;
use url::Url;
@@ -882,11 +903,9 @@ mod tests {
Some(vec!["rsync://example.test/issuer.cer"]),
None,
);
let err = validate_child_crldp_contains_issuer_crl_uri(
&child,
"rsync://example.test/issuer.crl",
)
.unwrap_err();
let err =
validate_child_crldp_contains_issuer_crl_uri(&child, "rsync://example.test/issuer.crl")
.unwrap_err();
assert!(matches!(err, CaPathError::ChildCrlDpMissing), "{err}");
let child = dummy_cert(
@@ -898,15 +917,10 @@ mod tests {
Some(vec!["rsync://example.test/issuer.cer"]),
Some(vec!["rsync://example.test/other.crl"]),
);
let err = validate_child_crldp_contains_issuer_crl_uri(
&child,
"rsync://example.test/issuer.crl",
)
.unwrap_err();
assert!(
matches!(err, CaPathError::ChildCrlDpUriMismatch),
"{err}"
);
let err =
validate_child_crldp_contains_issuer_crl_uri(&child, "rsync://example.test/issuer.crl")
.unwrap_err();
assert!(matches!(err, CaPathError::ChildCrlDpUriMismatch), "{err}");
// Cover child AKI missing.
let child_missing_aki = dummy_cert(