Skip to content

Commit

Permalink
Refactor AuthorityInfoAccess to keep items in order
Browse files Browse the repository at this point in the history
  • Loading branch information
chifflier committed Jul 27, 2021
1 parent 3b76c78 commit 070b9cf
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 19 deletions.
75 changes: 62 additions & 13 deletions src/extensions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,50 @@ impl<'a> FromDer<'a> for NSCertType {

#[derive(Clone, Debug, PartialEq)]
pub struct AuthorityInfoAccess<'a> {
pub accessdescs: HashMap<Oid<'a>, Vec<GeneralName<'a>>>,
pub accessdescs: Vec<AccessDescription<'a>>,
}

impl<'a> AuthorityInfoAccess<'a> {
/// Returns a `HashMap` mapping `Oid` to the list of references to `GeneralNames`
///
/// If several names match the same `Oid`, they are merged in the same entry.
pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&GeneralName<'a>>> {
// create the hashmap and merge entries with same OID
let mut m: HashMap<Oid, Vec<&GeneralName>> = HashMap::new();
for desc in &self.accessdescs {
let AccessDescription {
access_method: oid,
access_location: gn,
} = desc;
if let Some(general_names) = m.get_mut(&oid) {
general_names.push(gn);
} else {
m.insert(oid.clone(), vec![gn]);
}
}
m
}

/// Returns a `HashMap` mapping `Oid` to the list of `GeneralNames` (consuming the input)
///
/// If several names match the same `Oid`, they are merged in the same entry.
pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<GeneralName<'a>>> {
let mut aia_list = self.accessdescs;
// create the hashmap and merge entries with same OID
let mut m: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
for desc in aia_list.drain(..) {
let AccessDescription {
access_method: oid,
access_location: gn,
} = desc;
if let Some(general_names) = m.get_mut(&oid) {
general_names.push(gn);
} else {
m.insert(oid, vec![gn]);
}
}
m
}
}

impl<'a> FromDer<'a> for AuthorityInfoAccess<'a> {
Expand All @@ -413,6 +456,21 @@ impl<'a> FromDer<'a> for AuthorityInfoAccess<'a> {
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct AccessDescription<'a> {
pub access_method: Oid<'a>,
pub access_location: GeneralName<'a>,
}

impl<'a> AccessDescription<'a> {
pub const fn new(access_method: Oid<'a>, access_location: GeneralName<'a>) -> Self {
AccessDescription {
access_method,
access_location,
}
}
}

#[derive(Clone, Debug, PartialEq)]
pub struct InhibitAnyPolicy {
pub skip_certs: u32,
Expand Down Expand Up @@ -916,25 +974,16 @@ pub(crate) mod parser {
pub(super) fn parse_authorityinfoaccess(
i: &[u8],
) -> IResult<&[u8], AuthorityInfoAccess, BerError> {
fn parse_aia(i: &[u8]) -> IResult<&[u8], (Oid, GeneralName), BerError> {
fn parse_aia(i: &[u8]) -> IResult<&[u8], AccessDescription, BerError> {
parse_der_sequence_defined_g(|content, _| {
// Read first element, an oid.
let (gn, oid) = map_res(parse_der_oid, |x: DerObject| x.as_oid_val())(content)?;
// Parse second element
let (rest, gn) = parse_generalname(gn)?;
Ok((rest, (oid, gn)))
Ok((rest, AccessDescription::new(oid, gn)))
})(i)
}
let (ret, mut aia_list) = parse_der_sequence_of_v(parse_aia)(i)?;
// create the hashmap and merge entries with same OID
let mut accessdescs: HashMap<Oid, Vec<GeneralName>> = HashMap::new();
for (oid, gn) in aia_list.drain(..) {
if let Some(general_names) = accessdescs.get_mut(&oid) {
general_names.push(gn);
} else {
accessdescs.insert(oid, vec![gn]);
}
}
let (ret, accessdescs) = parse_der_sequence_of_v(parse_aia)(i)?;
Ok((ret, AuthorityInfoAccess { accessdescs }))
}

Expand Down
15 changes: 9 additions & 6 deletions tests/readcert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,15 +328,18 @@ fn test_duplicate_authority_info_access() {
.unwrap();
let mut accessdescs = HashMap::new();
let ca_issuers = vec![
GeneralName::URI("http://cdp1.pca.dfn.de/dfn-ca-global-g2/pub/cacert/cacert.crt"),
GeneralName::URI("http://cdp2.pca.dfn.de/dfn-ca-global-g2/pub/cacert/cacert.crt"),
&GeneralName::URI("http://cdp1.pca.dfn.de/dfn-ca-global-g2/pub/cacert/cacert.crt"),
&GeneralName::URI("http://cdp2.pca.dfn.de/dfn-ca-global-g2/pub/cacert/cacert.crt"),
];
let ocsp = vec![GeneralName::URI("http://ocsp.pca.dfn.de/OCSP-Server/OCSP")];
let ocsp = vec![&GeneralName::URI("http://ocsp.pca.dfn.de/OCSP-Server/OCSP")];
accessdescs.insert(OID_PKIX_ACCESS_DESCRIPTOR_CA_ISSUERS, ca_issuers);
accessdescs.insert(OID_PKIX_ACCESS_DESCRIPTOR_OCSP, ocsp);
let expected_aia =
ParsedExtension::AuthorityInfoAccess(AuthorityInfoAccess { accessdescs });
assert_eq!(*extension.parsed_extension(), expected_aia);
if let ParsedExtension::AuthorityInfoAccess(aia) = extension.parsed_extension() {
let h = aia.as_hashmap();
assert_eq!(h, accessdescs);
} else {
panic!("Wrong extension type parsed");
}
}
err => panic!("x509 parsing failed: {:?}", err),
}
Expand Down

0 comments on commit 070b9cf

Please sign in to comment.