Skip to content

Commit

Permalink
Allow limiting the number of provider ASNs in ASPA decoding.
Browse files Browse the repository at this point in the history
  • Loading branch information
partim committed Dec 30, 2024
1 parent 01024d5 commit 767a6e7
Showing 1 changed file with 62 additions and 6 deletions.
68 changes: 62 additions & 6 deletions src/repository/aspa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,29 @@ pub struct Aspa {
impl Aspa {
pub fn decode<S: IntoSource>(
source: S,
strict: bool
strict: bool,
) -> Result<Self, DecodeError<<S::Source as Source>::Error>> {
Self::_decode(source, strict, None)
}

pub fn decode_with_limit<S: IntoSource>(
source: S,
strict: bool,
provider_limit: usize,
) -> Result<Self, DecodeError<<S::Source as Source>::Error>> {
Self::_decode(source, strict, Some(provider_limit))
}

fn _decode<S: IntoSource>(
source: S,
strict: bool,
provider_limit: Option<usize>,
) -> Result<Self, DecodeError<<S::Source as Source>::Error>> {
let signed = SignedObject::decode_if_type(
source, &oid::CT_ASPA, strict
)?;
let content = signed.decode_content(|cons| {
AsProviderAttestation::take_from(cons)
AsProviderAttestation::take_from(cons, provider_limit)
}).map_err(DecodeError::convert)?;
Ok(Aspa { signed, content })
}
Expand Down Expand Up @@ -118,15 +134,16 @@ pub struct AsProviderAttestation {

impl AsProviderAttestation {
fn take_from<S: decode::Source>(
cons: &mut decode::Constructed<S>
cons: &mut decode::Constructed<S>,
provider_limit: Option<usize>,
) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(|cons| {
// version [0] EXPLICIT INTEGER DEFAULT 0
// must be 1!
cons.take_constructed_if(Tag::CTX_0, |c| c.skip_u8_if(1))?;
let customer_as = Asn::take_from(cons)?;
let provider_as_set = ProviderAsSet::take_from(
cons, customer_as
cons, customer_as, provider_limit,
)?;

Ok(AsProviderAttestation {
Expand Down Expand Up @@ -221,13 +238,24 @@ impl ProviderAsSet {
fn take_from<S: decode::Source>(
cons: &mut decode::Constructed<S>,
customer_as: Asn,
mut provider_limit: Option<usize>,
) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(|cons| {
cons.capture(|cons| {
let mut last: Option<Asn> = None;
while let Some(asn) = Asn::take_opt_from(
cons
)? {
if let Some(limit) = provider_limit {
match limit.checked_sub(1) {
Some(new) => provider_limit = Some(new),
None => {
return Err(cons.content_err(
"too many provider ASNs"
))
}
}
}
if asn == customer_as {
return Err(cons.content_err(
"customer AS in provider AS set"
Expand Down Expand Up @@ -391,7 +419,7 @@ mod test {
include_bytes!(
"../../test-data/repository/aspa-content.der"
).as_ref(),
AsProviderAttestation::take_from
|cons| AsProviderAttestation::take_from(cons, None)
).unwrap();
assert_eq!(content.customer_as(), 15562.into());
assert_eq!(
Expand All @@ -409,10 +437,38 @@ mod test {
include_bytes!(
"../../test-data/repository/aspa-content-draft-13.der"
).as_ref(),
AsProviderAttestation::take_from
|cons| AsProviderAttestation::take_from(cons, None)
).is_err()
)
}

#[test]
fn decode_content_with_limit() {
assert!(
Mode::Der.decode(
include_bytes!(
"../../test-data/repository/aspa-content.der"
).as_ref(),
|cons| AsProviderAttestation::take_from(cons, Some(5))
).is_ok()
);
assert!(
Mode::Der.decode(
include_bytes!(
"../../test-data/repository/aspa-content.der"
).as_ref(),
|cons| AsProviderAttestation::take_from(cons, Some(4))
).is_ok()
);
assert!(
Mode::Der.decode(
include_bytes!(
"../../test-data/repository/aspa-content.der"
).as_ref(),
|cons| AsProviderAttestation::take_from(cons, Some(3))
).is_err()
);
}
}

#[cfg(all(test, feature = "softkeys"))]
Expand Down

0 comments on commit 767a6e7

Please sign in to comment.