/rust/registry/src/index.crates.io-1949cf8c6b5b557f/x509-parser-0.16.0/src/cri_attributes.rs
Line | Count | Source |
1 | | use crate::{ |
2 | | error::{X509Error, X509Result}, |
3 | | extensions::X509Extension, |
4 | | }; |
5 | | |
6 | | use asn1_rs::{Error, FromDer, Header, Oid, Sequence, Tag}; |
7 | | use nom::combinator::{all_consuming, complete}; |
8 | | use nom::multi::many0; |
9 | | use nom::Err; |
10 | | use oid_registry::*; |
11 | | use std::collections::HashMap; |
12 | | |
13 | | /// Attributes for Certification Request |
14 | | #[derive(Clone, Debug, PartialEq)] |
15 | | pub struct X509CriAttribute<'a> { |
16 | | pub oid: Oid<'a>, |
17 | | pub value: &'a [u8], |
18 | | pub(crate) parsed_attribute: ParsedCriAttribute<'a>, |
19 | | } |
20 | | |
21 | | impl<'a> FromDer<'a, X509Error> for X509CriAttribute<'a> { |
22 | 0 | fn from_der(i: &'a [u8]) -> X509Result<X509CriAttribute> { |
23 | 0 | Sequence::from_ber_and_then(i, |i| { |
24 | 0 | let (i, oid) = Oid::from_der(i)?; |
25 | 0 | let value_start = i; |
26 | 0 | let (i, hdr) = Header::from_der(i)?; |
27 | 0 | if hdr.tag() != Tag::Set { |
28 | 0 | return Err(Err::Error(Error::BerTypeError)); |
29 | 0 | }; |
30 | | |
31 | 0 | let (i, parsed_attribute) = crate::cri_attributes::parser::parse_attribute(i, &oid) |
32 | 0 | .map_err(|_| Err::Error(Error::BerValueError))?; |
33 | 0 | let attribute = X509CriAttribute { |
34 | 0 | oid, |
35 | 0 | value: &value_start[..value_start.len() - i.len()], |
36 | 0 | parsed_attribute, |
37 | 0 | }; |
38 | 0 | Ok((i, attribute)) |
39 | 0 | }) |
40 | 0 | .map_err(|_| X509Error::InvalidAttributes.into()) |
41 | 0 | } |
42 | | } |
43 | | |
44 | | impl<'a> X509CriAttribute<'a> { |
45 | | /// Return the attribute type or `UnsupportedAttribute` if the attribute is unknown. |
46 | | #[inline] |
47 | 0 | pub fn parsed_attribute(&self) -> &ParsedCriAttribute<'a> { |
48 | 0 | &self.parsed_attribute |
49 | 0 | } |
50 | | } |
51 | | |
52 | | /// Section 3.1 of rfc 5272 |
53 | | #[derive(Clone, Debug, PartialEq)] |
54 | | pub struct ExtensionRequest<'a> { |
55 | | pub extensions: Vec<X509Extension<'a>>, |
56 | | } |
57 | | |
58 | | impl<'a> FromDer<'a, X509Error> for ExtensionRequest<'a> { |
59 | 0 | fn from_der(i: &'a [u8]) -> X509Result<'a, Self> { |
60 | 0 | parser::parse_extension_request(i).map_err(Err::convert) |
61 | 0 | } |
62 | | } |
63 | | |
64 | | #[derive(Clone, Debug, Eq, PartialEq)] |
65 | | pub struct ChallengePassword(pub String); |
66 | | |
67 | | /// Attributes for Certification Request |
68 | | #[derive(Clone, Debug, PartialEq)] |
69 | | pub enum ParsedCriAttribute<'a> { |
70 | | ChallengePassword(ChallengePassword), |
71 | | ExtensionRequest(ExtensionRequest<'a>), |
72 | | UnsupportedAttribute, |
73 | | } |
74 | | |
75 | | pub(crate) mod parser { |
76 | | use crate::cri_attributes::*; |
77 | | use der_parser::der::{ |
78 | | parse_der_bmpstring, parse_der_printablestring, parse_der_t61string, |
79 | | parse_der_universalstring, parse_der_utf8string, |
80 | | }; |
81 | | use lazy_static::lazy_static; |
82 | | use nom::branch::alt; |
83 | | use nom::combinator::map; |
84 | | |
85 | | type AttrParser = fn(&[u8]) -> X509Result<ParsedCriAttribute>; |
86 | | |
87 | | lazy_static! { |
88 | | static ref ATTRIBUTE_PARSERS: HashMap<Oid<'static>, AttrParser> = { |
89 | | macro_rules! add { |
90 | | ($m:ident, $oid:ident, $p:ident) => { |
91 | | $m.insert($oid, $p as AttrParser); |
92 | | }; |
93 | | } |
94 | | |
95 | | let mut m = HashMap::new(); |
96 | | add!(m, OID_PKCS9_EXTENSION_REQUEST, parse_extension_request_attr); |
97 | | add!( |
98 | | m, |
99 | | OID_PKCS9_CHALLENGE_PASSWORD, |
100 | | parse_challenge_password_attr |
101 | | ); |
102 | | m |
103 | | }; |
104 | | } |
105 | | |
106 | | // look into the parser map if the extension is known, and parse it |
107 | | // otherwise, leave it as UnsupportedExtension |
108 | 0 | pub(crate) fn parse_attribute<'a>( |
109 | 0 | i: &'a [u8], |
110 | 0 | oid: &Oid, |
111 | 0 | ) -> X509Result<'a, ParsedCriAttribute<'a>> { |
112 | 0 | if let Some(parser) = ATTRIBUTE_PARSERS.get(oid) { |
113 | 0 | parser(i) |
114 | | } else { |
115 | 0 | Ok((i, ParsedCriAttribute::UnsupportedAttribute)) |
116 | | } |
117 | 0 | } |
118 | | |
119 | 0 | pub(super) fn parse_extension_request(i: &[u8]) -> X509Result<ExtensionRequest> { |
120 | 0 | crate::extensions::parse_extension_sequence(i) |
121 | 0 | .map(|(i, extensions)| (i, ExtensionRequest { extensions })) |
122 | 0 | } |
123 | | |
124 | 0 | fn parse_extension_request_attr(i: &[u8]) -> X509Result<ParsedCriAttribute> { |
125 | 0 | map( |
126 | 0 | parse_extension_request, |
127 | 0 | ParsedCriAttribute::ExtensionRequest, |
128 | 0 | )(i) |
129 | 0 | } |
130 | | |
131 | | // RFC 2985, 5.4.1 Challenge password |
132 | | // challengePassword ATTRIBUTE ::= { |
133 | | // WITH SYNTAX DirectoryString {pkcs-9-ub-challengePassword} |
134 | | // EQUALITY MATCHING RULE caseExactMatch |
135 | | // SINGLE VALUE TRUE |
136 | | // ID pkcs-9-at-challengePassword |
137 | | // } |
138 | | // RFC 5280, 4.1.2.4. Issuer |
139 | | // DirectoryString ::= CHOICE { |
140 | | // teletexString TeletexString (SIZE (1..MAX)), |
141 | | // printableString PrintableString (SIZE (1..MAX)), |
142 | | // universalString UniversalString (SIZE (1..MAX)), |
143 | | // utf8String UTF8String (SIZE (1..MAX)), |
144 | | // bmpString BMPString (SIZE (1..MAX)) |
145 | | // } |
146 | 0 | pub(super) fn parse_challenge_password(i: &[u8]) -> X509Result<ChallengePassword> { |
147 | 0 | let (rem, obj) = match alt(( |
148 | 0 | parse_der_utf8string, |
149 | 0 | parse_der_printablestring, |
150 | 0 | parse_der_universalstring, |
151 | 0 | parse_der_bmpstring, |
152 | 0 | parse_der_t61string, // == teletexString |
153 | 0 | ))(i) |
154 | | { |
155 | 0 | Ok((rem, obj)) => (rem, obj), |
156 | 0 | Err(_) => return Err(Err::Error(X509Error::InvalidAttributes)), |
157 | | }; |
158 | 0 | match obj.content.as_str() { |
159 | 0 | Ok(s) => Ok((rem, ChallengePassword(s.to_string()))), |
160 | 0 | Err(_) => Err(Err::Error(X509Error::InvalidAttributes)), |
161 | | } |
162 | 0 | } |
163 | | |
164 | 0 | fn parse_challenge_password_attr(i: &[u8]) -> X509Result<ParsedCriAttribute> { |
165 | 0 | map( |
166 | 0 | parse_challenge_password, |
167 | 0 | ParsedCriAttribute::ChallengePassword, |
168 | 0 | )(i) |
169 | 0 | } |
170 | | } |
171 | | |
172 | 0 | pub(crate) fn parse_cri_attributes(i: &[u8]) -> X509Result<Vec<X509CriAttribute>> { |
173 | 0 | let (i, hdr) = Header::from_der(i).map_err(|_| Err::Error(X509Error::InvalidAttributes))?; |
174 | 0 | if hdr.is_contextspecific() && hdr.tag().0 == 0 { |
175 | 0 | all_consuming(many0(complete(X509CriAttribute::from_der)))(i) |
176 | | } else { |
177 | 0 | Err(Err::Error(X509Error::InvalidAttributes)) |
178 | | } |
179 | 0 | } |