x509_parser/extensions/
policymappings.rs

1use crate::error::{X509Error, X509Result};
2use asn1_rs::{DerSequence, Error, FromDer, Oid};
3use nom::{Err, IResult};
4use std::collections::HashMap;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct PolicyMappings<'a> {
8    pub mappings: Vec<PolicyMapping<'a>>,
9}
10
11impl<'a> FromDer<'a, X509Error> for PolicyMappings<'a> {
12    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
13        parse_policymappings(i).map_err(Err::convert)
14    }
15}
16
17impl<'a> PolicyMappings<'a> {
18    /// Returns a `HashMap` mapping `Oid` to the list of references to `Oid`
19    ///
20    /// If several names match the same `Oid`, they are merged in the same entry.
21    pub fn as_hashmap(&self) -> HashMap<Oid<'a>, Vec<&Oid<'a>>> {
22        // create the hashmap and merge entries with same OID
23        let mut m: HashMap<Oid, Vec<&_>> = HashMap::new();
24        for desc in &self.mappings {
25            let PolicyMapping {
26                issuer_domain_policy: left,
27                subject_domain_policy: right,
28            } = desc;
29            if let Some(l) = m.get_mut(left) {
30                l.push(right);
31            } else {
32                m.insert(left.clone(), vec![right]);
33            }
34        }
35        m
36    }
37
38    /// Returns a `HashMap` mapping `Oid` to the list of `Oid` (consuming the input)
39    ///
40    /// If several names match the same `Oid`, they are merged in the same entry.
41    pub fn into_hashmap(self) -> HashMap<Oid<'a>, Vec<Oid<'a>>> {
42        let mut l = self.mappings;
43        // create the hashmap and merge entries with same OID
44        let mut m: HashMap<Oid, Vec<_>> = HashMap::new();
45        for mapping in l.drain(..) {
46            let PolicyMapping {
47                issuer_domain_policy: left,
48                subject_domain_policy: right,
49            } = mapping;
50            if let Some(general_names) = m.get_mut(&left) {
51                general_names.push(right);
52            } else {
53                m.insert(left, vec![right]);
54            }
55        }
56        m
57    }
58}
59
60#[derive(Clone, Debug, PartialEq, Eq, DerSequence)]
61pub struct PolicyMapping<'a> {
62    pub issuer_domain_policy: Oid<'a>,
63    pub subject_domain_policy: Oid<'a>,
64}
65
66impl<'a> PolicyMapping<'a> {
67    pub const fn new(issuer_domain_policy: Oid<'a>, subject_domain_policy: Oid<'a>) -> Self {
68        PolicyMapping {
69            issuer_domain_policy,
70            subject_domain_policy,
71        }
72    }
73}
74
75// PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
76//  issuerDomainPolicy      CertPolicyId,
77//  subjectDomainPolicy     CertPolicyId }
78pub(crate) fn parse_policymappings(i: &[u8]) -> IResult<&[u8], PolicyMappings, Error> {
79    let (ret, pairs) = <Vec<PolicyMapping>>::from_der(i)?;
80    // let mut mappings: HashMap<Oid, Vec<Oid>> = HashMap::new();
81    let mappings = pairs;
82    // let mut mappings = Vec::new();
83    // for pair in pairs.iter() {
84    //     // XXX this should go to Validate
85    //     // if left.bytes() == oid!(raw 2.5.29.32.0) || right.bytes() == oid!(raw 2.5.29.32.0) {
86    //     //     // mapping to or from anyPolicy is not allowed
87    //     //     return Err(Err::Failure(BerError::InvalidTag));
88    //     // }
89    //     mappings.push(PolicyMapping::new(left, right));
90    // }
91    Ok((ret, PolicyMappings { mappings }))
92}