structured_cms/attribute_certificate/
service.rs1use super::{end, sequence, tag};
9use crate::attribute::Attribute;
10use crate::signer::required;
11use crate::{Error, ErrorCode, Result};
12use core::fmt;
13use structured_asn1::memory::{OwnedVec, Work};
14use structured_asn1::{Element, Encoding, Oid, ScopedReader, Tag, universal};
15use structured_pkix::general_name::{self, GeneralName};
16
17const FIELD: &str = "attributeCertificate.svceAuthInfo";
18const SERVICE: &str = "attributeCertificate.svceAuthInfo.service";
19const IDENT: &str = "attributeCertificate.svceAuthInfo.ident";
20const AUTH: &str = "attributeCertificate.svceAuthInfo.authInfo";
21
22pub const AUTHENTICATION_INFO: Oid<'static> = Oid::from_bytes(&[43, 6, 1, 5, 5, 7, 10, 1]);
24pub const ACCESS_IDENTITY: Oid<'static> = Oid::from_bytes(&[43, 6, 1, 5, 5, 7, 10, 2]);
26
27#[derive(Clone, Copy)]
29enum Syntax {
30 Authentication,
31 Access,
32}
33
34pub struct SvceAuthInfo<'a> {
38 element: Element<'a>,
39 service_element: Element<'a>,
40 service: GeneralName<'a>,
41 ident_element: Element<'a>,
42 ident: GeneralName<'a>,
43 auth_info: Option<Element<'a>>,
44}
45
46impl fmt::Debug for SvceAuthInfo<'_> {
47 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
48 formatter
51 .debug_struct("SvceAuthInfo")
52 .field("element", &self.element.span())
53 .field("service", &self.service_element.span())
54 .field("ident", &self.ident_element.span())
55 .field("auth_info", &self.auth_info.map(Element::span))
56 .finish()
57 }
58}
59
60impl<'a> SvceAuthInfo<'a> {
61 pub fn read(parent: &mut ScopedReader<'a, '_>) -> Result<Self> {
64 let element = required(parent, FIELD)?;
65 let reading = Self::read_element(parent, &element)?;
66 end(parent, FIELD)?;
67 Ok(reading)
68 }
69
70 pub fn read_element(parent: &ScopedReader<'a, '_>, element: &Element<'a>) -> Result<Self> {
73 Self::read_fields(parent, element, Syntax::Authentication)
74 }
75
76 fn read_fields(
77 parent: &ScopedReader<'a, '_>,
78 element: &Element<'a>,
79 syntax: Syntax,
80 ) -> Result<Self> {
81 let mut der = parent
82 .reread(element, Encoding::Der)
83 .map_err(|e| Error::encoding(e, FIELD))?;
84 let element = required(&mut der, FIELD)?;
85 tag(&element, sequence(), FIELD)?;
86 end(&der, FIELD)?;
87 let mut inside = der.enter(&element).map_err(|e| Error::encoding(e, FIELD))?;
88 let service_element = required(&mut inside, SERVICE)?;
89 let ident_element = required(&mut inside, IDENT)?;
90 let auth_info = inside
91 .next_element()
92 .map_err(|e| Error::encoding(e, AUTH))?;
93 if let Some(auth) = auth_info {
94 tag(&auth, Tag::primitive(universal::OCTET_STRING), AUTH)?;
95 if matches!(syntax, Syntax::Access) {
99 return Err(Error::schema(
100 ErrorCode::AttributeSyntax,
101 AUTH,
102 auth.span().start,
103 ));
104 }
105 }
106 end(&inside, FIELD)?;
107 let service =
108 general_name::read(&inside, &service_element, SERVICE).map_err(Error::pkix)?;
109 let ident = general_name::read(&inside, &ident_element, IDENT).map_err(Error::pkix)?;
110 Ok(Self {
111 element,
112 service_element,
113 service,
114 ident_element,
115 ident,
116 auth_info,
117 })
118 }
119
120 pub fn read_attribute<W: Work>(attribute: &Attribute<'a>, work: &W) -> Result<OwnedVec<Self>> {
126 let execution = attribute.query_in(work);
127 execution
130 .charge_work(17)
131 .map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
132 let syntax = if attribute.kind() == AUTHENTICATION_INFO {
133 Syntax::Authentication
134 } else if attribute.kind() == ACCESS_IDENTITY {
135 Syntax::Access
136 } else {
137 return Err(Error::schema(
138 ErrorCode::UnexpectedContentType,
139 FIELD,
140 attribute.span().start,
141 ));
142 };
143 if attribute.values().is_empty() {
147 return Err(Error::schema(
148 ErrorCode::AttributeCardinality,
149 FIELD,
150 attribute.span().start,
151 ));
152 }
153 let mut values = execution.vector();
154 values
155 .try_reserve_exact(attribute.values().len())
156 .map_err(|e| Error::resource(e, FIELD, attribute.span().start))?;
157 for index in 0..attribute.values().len() {
158 let mut reader = attribute
159 .value_reader_scoped(index, &execution, FIELD)?
160 .ok_or_else(|| {
161 Error::schema(
162 ErrorCode::AttributeCardinality,
163 FIELD,
164 attribute.span().start,
165 )
166 })?;
167 let element = required(&mut reader, FIELD)?;
168 let value = Self::read_fields(&reader, &element, syntax)?;
169 end(&reader, FIELD)?;
170 values
171 .try_push(value)
172 .map_err(|e| Error::resource(e, FIELD, element.span().start))?;
173 }
174 Ok(values.into_owned())
175 }
176
177 #[must_use]
179 pub fn element(&self) -> Element<'a> {
180 self.element
181 }
182 #[must_use]
184 pub fn service(&self) -> &GeneralName<'a> {
185 &self.service
186 }
187 #[must_use]
189 pub fn service_element(&self) -> Element<'a> {
190 self.service_element
191 }
192 #[must_use]
194 pub fn ident(&self) -> &GeneralName<'a> {
195 &self.ident
196 }
197 #[must_use]
199 pub fn ident_element(&self) -> Element<'a> {
200 self.ident_element
201 }
202 #[must_use]
205 pub fn auth_info(&self) -> Option<&'a [u8]> {
206 self.auth_info.map(Element::contents)
207 }
208 #[must_use]
210 pub fn auth_info_element(&self) -> Option<Element<'a>> {
211 self.auth_info
212 }
213}