structured_cms/attribute_certificate/
controls.rs1use super::{end, sequence, tag};
9use crate::signer::required;
10use crate::{Error, ErrorCode, Result};
11use structured_asn1::memory::{OwnedVec, Work};
12use structured_asn1::{Element, Encoding, Integer, Oid, Parser, ScopedReader, Tag, universal};
13use structured_pkix::Extension;
14
15const FIELD: &str = "attributeCertificate.aaControls";
16pub const IDENTIFIER: Oid<'static> = Oid::from_bytes(&[43, 6, 1, 5, 5, 7, 1, 6]);
18
19#[derive(Debug)]
22pub struct AaControls<'a> {
23 parser: &'a Parser,
24 pub element: Element<'a>,
26 pub path_length: Option<Integer<'a>>,
28 pub path_length_element: Option<Element<'a>>,
30 pub permitted_element: Option<Element<'a>>,
32 pub permitted: OwnedVec<Oid<'a>>,
34 pub excluded_element: Option<Element<'a>>,
36 pub excluded: OwnedVec<Oid<'a>>,
38 pub unspecified_element: Option<Element<'a>>,
40 pub permit_unspecified: bool,
42}
43
44impl<'a> AaControls<'a> {
45 pub fn read(parent: &mut ScopedReader<'a, '_>) -> Result<Self> {
47 let element = required(parent, FIELD)?;
48 let result = Self::read_element(parent, &element)?;
49 end(parent, FIELD)?;
50 Ok(result)
51 }
52
53 pub fn read_element(parent: &ScopedReader<'a, '_>, element: &Element<'a>) -> Result<Self> {
55 let mut der = parent
56 .reread(element, Encoding::Der)
57 .map_err(|e| Error::encoding(e, FIELD))?;
58 let element = required(&mut der, FIELD)?;
59 tag(&element, sequence(), FIELD)?;
60 end(&der, FIELD)?;
61 let mut inside = der.enter(&element).map_err(|e| Error::encoding(e, FIELD))?;
62 let mut next = inside
63 .next_element()
64 .map_err(|e| Error::encoding(e, FIELD))?;
65 let path_length_element = super::optional(
66 &mut inside,
67 &mut next,
68 Tag::primitive(universal::INTEGER),
69 FIELD,
70 )?;
71 let path_length = path_length_element
72 .map(|encoded| {
73 let number = inside
74 .integer(&encoded)
75 .map_err(|e| Error::encoding(e, FIELD))?;
76 if number.is_negative() {
77 return Err(Error::schema(
78 ErrorCode::MalformedValue,
79 FIELD,
80 encoded.span().start,
81 ));
82 }
83 Ok(number)
84 })
85 .transpose()?;
86 let permitted_element =
87 super::optional(&mut inside, &mut next, Tag::context(true, 0), FIELD)?;
88 let excluded_element =
89 super::optional(&mut inside, &mut next, Tag::context(true, 1), FIELD)?;
90 let unspecified_element = super::optional(
91 &mut inside,
92 &mut next,
93 Tag::primitive(universal::BOOLEAN),
94 FIELD,
95 )?;
96 super::no_pending(next, FIELD)?;
97 let permit_unspecified = match unspecified_element {
98 Some(encoded) => {
99 let value = inside
100 .boolean(&encoded)
101 .map_err(|e| Error::encoding(e, FIELD))?;
102 if value {
105 return Err(Error::schema(
106 ErrorCode::DefaultWritten,
107 FIELD,
108 encoded.span().start,
109 ));
110 }
111 false
112 }
113 None => true,
114 };
115 let permitted = identifiers(&inside, permitted_element)?;
116 let excluded = identifiers(&inside, excluded_element)?;
117 Ok(Self {
118 parser: parent.parser(),
119 element,
120 path_length,
121 path_length_element,
122 permitted_element,
123 permitted,
124 excluded_element,
125 excluded,
126 unspecified_element,
127 permit_unspecified,
128 })
129 }
130
131 pub fn read_extension<W: Work>(extension: &Extension<'a>, work: &W) -> Result<Self> {
134 let execution = work.execution_for(extension.parser());
135 execution
136 .charge_work(9)
137 .map_err(|e| Error::resource(e, FIELD, extension.span().start))?;
138 if extension.kind() != IDENTIFIER {
139 return Err(Error::schema(
140 ErrorCode::UnexpectedContentType,
141 FIELD,
142 extension.span().start,
143 ));
144 }
145 let mut reader = extension
146 .reader_scoped(&execution)
147 .map_err(|e| Error::encoding(e, FIELD))?;
148 Self::read(&mut reader)
149 }
150
151 pub fn allows<W: Work>(&self, kind: Oid<'_>, work: &W) -> Result<bool> {
155 let execution = work.execution_for(self.parser);
156 execution
157 .charge_work(1)
158 .map_err(|e| Error::resource(e, FIELD, self.element.span().start))?;
159 for (list, answer) in [(&self.excluded, false), (&self.permitted, true)] {
163 for identifier in list {
164 let amount = identifier.as_bytes().len().min(kind.as_bytes().len()) as u64 + 1;
165 execution
166 .charge_work(amount)
167 .map_err(|e| Error::resource(e, FIELD, self.element.span().start))?;
168 if *identifier == kind {
169 return Ok(answer);
170 }
171 }
172 }
173 Ok(self.permit_unspecified)
174 }
175
176 pub fn permits_distance<W: Work>(&self, distance: u64, work: &W) -> Result<bool> {
180 let execution = work.execution_for(self.parser);
181 execution
182 .charge_work(10)
183 .map_err(|e| Error::resource(e, FIELD, self.element.span().start))?;
184 Ok(match self.path_length {
185 None => true,
186 Some(number) => match number.as_u64() {
187 Some(bound) => distance <= bound,
188 None => true,
189 },
190 })
191 }
192}
193
194fn identifiers<'a>(
195 parent: &ScopedReader<'a, '_>,
196 element: Option<Element<'a>>,
197) -> Result<OwnedVec<Oid<'a>>> {
198 let execution = parent.execution();
199 let mut result = execution.vector();
200 if let Some(encoded) = element {
201 let mut inside = parent
202 .enter(&encoded)
203 .map_err(|e| Error::encoding(e, FIELD))?;
204 while let Some(value) = inside
205 .next_element()
206 .map_err(|e| Error::encoding(e, FIELD))?
207 {
208 tag(&value, Tag::primitive(universal::OID), FIELD)?;
209 result
210 .try_reserve(1)
211 .map_err(|e| Error::resource(e, FIELD, value.span().start))?;
212 let identifier = inside.oid(&value).map_err(|e| Error::encoding(e, FIELD))?;
213 result
214 .try_push(identifier)
215 .map_err(|e| Error::resource(e, FIELD, value.span().start))?;
216 }
217 }
218 Ok(result.into_owned())
219}