1 //! Name-related definitions as defined in X.501 (and updated by RFC 5280).
2 
3 use crate::attr::AttributeTypeAndValue;
4 use alloc::vec::Vec;
5 use core::{fmt, str::FromStr};
6 use der::{asn1::SetOfVec, Encode};
7 
8 /// X.501 Name as defined in [RFC 5280 Section 4.1.2.4]. X.501 Name is used to represent distinguished names.
9 ///
10 /// ```text
11 /// Name ::= CHOICE { rdnSequence  RDNSequence }
12 /// ```
13 ///
14 /// [RFC 5280 Section 4.1.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.4
15 pub type Name = RdnSequence;
16 
17 /// X.501 RDNSequence as defined in [RFC 5280 Section 4.1.2.4].
18 ///
19 /// ```text
20 /// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
21 /// ```
22 ///
23 /// [RFC 5280 Section 4.1.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.4
24 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
25 #[derive(Clone, Debug, Default, PartialEq, Eq)]
26 pub struct RdnSequence(pub Vec<RelativeDistinguishedName>);
27 
28 impl RdnSequence {
29     /// Converts an `RDNSequence` string into an encoded `RDNSequence`.
30     #[deprecated(since = "0.2.1", note = "use RdnSequence::from_str(...)?.to_der()")]
encode_from_string(s: &str) -> Result<Vec<u8>, der::Error>31     pub fn encode_from_string(s: &str) -> Result<Vec<u8>, der::Error> {
32         Self::from_str(s)?.to_der()
33     }
34 
35     /// Is this [`RdnSequence`] empty?
is_empty(&self) -> bool36     pub fn is_empty(&self) -> bool {
37         self.0.is_empty()
38     }
39 }
40 
41 /// Parse an [`RdnSequence`] string.
42 ///
43 /// Follows the rules in [RFC 4514].
44 ///
45 /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514
46 impl FromStr for RdnSequence {
47     type Err = der::Error;
48 
from_str(s: &str) -> der::Result<Self>49     fn from_str(s: &str) -> der::Result<Self> {
50         let mut parts = split(s, b',')
51             .map(RelativeDistinguishedName::from_str)
52             .collect::<der::Result<Vec<_>>>()?;
53         parts.reverse();
54         Ok(Self(parts))
55     }
56 }
57 
58 /// Serializes the structure according to the rules in [RFC 4514].
59 ///
60 /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514
61 impl fmt::Display for RdnSequence {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result62     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63         // As per RFC 4514 Section 2.1, the elements are reversed
64         for (i, atv) in self.0.iter().rev().enumerate() {
65             match i {
66                 0 => write!(f, "{}", atv)?,
67                 _ => write!(f, ",{}", atv)?,
68             }
69         }
70 
71         Ok(())
72     }
73 }
74 
75 impl_newtype!(RdnSequence, Vec<RelativeDistinguishedName>);
76 
77 /// Find the indices of all non-escaped separators.
find(s: &str, b: u8) -> impl '_ + Iterator<Item = usize>78 fn find(s: &str, b: u8) -> impl '_ + Iterator<Item = usize> {
79     (0..s.len())
80         .filter(move |i| s.as_bytes()[*i] == b)
81         .filter(|i| {
82             let x = i
83                 .checked_sub(2)
84                 .map(|i| s.as_bytes()[i])
85                 .unwrap_or_default();
86 
87             let y = i
88                 .checked_sub(1)
89                 .map(|i| s.as_bytes()[i])
90                 .unwrap_or_default();
91 
92             y != b'\\' || x == b'\\'
93         })
94 }
95 
96 /// Split a string at all non-escaped separators.
split(s: &str, b: u8) -> impl '_ + Iterator<Item = &'_ str>97 fn split(s: &str, b: u8) -> impl '_ + Iterator<Item = &'_ str> {
98     let mut prev = 0;
99     find(s, b).chain([s.len()].into_iter()).map(move |i| {
100         let x = &s[prev..i];
101         prev = i + 1;
102         x
103     })
104 }
105 
106 /// X.501 DistinguishedName as defined in [RFC 5280 Section 4.1.2.4].
107 ///
108 /// ```text
109 /// DistinguishedName ::=   RDNSequence
110 /// ```
111 ///
112 /// [RFC 5280 Section 4.1.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.4
113 pub type DistinguishedName = RdnSequence;
114 
115 /// RelativeDistinguishedName as defined in [RFC 5280 Section 4.1.2.4].
116 ///
117 /// ```text
118 /// RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
119 /// ```
120 ///
121 /// Note that we follow the more common definition above. This technically
122 /// differs from the definition in X.501, which is:
123 ///
124 /// ```text
125 /// RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndDistinguishedValue
126 ///
127 /// AttributeTypeAndDistinguishedValue ::= SEQUENCE {
128 ///     type ATTRIBUTE.&id ({SupportedAttributes}),
129 ///     value ATTRIBUTE.&Type({SupportedAttributes}{@type}),
130 ///     primaryDistinguished BOOLEAN DEFAULT TRUE,
131 ///     valuesWithContext SET SIZE (1..MAX) OF SEQUENCE {
132 ///         distingAttrValue [0] ATTRIBUTE.&Type ({SupportedAttributes}{@type}) OPTIONAL,
133 ///         contextList SET SIZE (1..MAX) OF Context
134 ///     } OPTIONAL
135 /// }
136 /// ```
137 ///
138 /// [RFC 5280 Section 4.1.2.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.4
139 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
140 #[derive(Clone, Debug, Default, PartialEq, Eq)]
141 pub struct RelativeDistinguishedName(pub SetOfVec<AttributeTypeAndValue>);
142 
143 impl RelativeDistinguishedName {
144     /// Converts an RelativeDistinguishedName string into an encoded RelativeDistinguishedName
145     #[deprecated(
146         since = "0.2.1",
147         note = "use RelativeDistinguishedName::from_str(...)?.to_der()"
148     )]
encode_from_string(s: &str) -> Result<Vec<u8>, der::Error>149     pub fn encode_from_string(s: &str) -> Result<Vec<u8>, der::Error> {
150         Self::from_str(s)?.to_der()
151     }
152 }
153 
154 /// Parse a [`RelativeDistinguishedName`] string.
155 ///
156 /// This function follows the rules in [RFC 4514].
157 ///
158 /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514
159 impl FromStr for RelativeDistinguishedName {
160     type Err = der::Error;
161 
from_str(s: &str) -> der::Result<Self>162     fn from_str(s: &str) -> der::Result<Self> {
163         split(s, b'+')
164             .map(AttributeTypeAndValue::from_str)
165             .collect::<der::Result<Vec<_>>>()?
166             .try_into()
167             .map(Self)
168     }
169 }
170 
171 impl TryFrom<Vec<AttributeTypeAndValue>> for RelativeDistinguishedName {
172     type Error = der::Error;
173 
try_from(vec: Vec<AttributeTypeAndValue>) -> der::Result<RelativeDistinguishedName>174     fn try_from(vec: Vec<AttributeTypeAndValue>) -> der::Result<RelativeDistinguishedName> {
175         Ok(RelativeDistinguishedName(SetOfVec::try_from(vec)?))
176     }
177 }
178 
179 /// Serializes the structure according to the rules in [RFC 4514].
180 ///
181 /// [RFC 4514]: https://datatracker.ietf.org/doc/html/rfc4514
182 impl fmt::Display for RelativeDistinguishedName {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result183     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184         for (i, atv) in self.0.iter().enumerate() {
185             match i {
186                 0 => write!(f, "{}", atv)?,
187                 _ => write!(f, "+{}", atv)?,
188             }
189         }
190 
191         Ok(())
192     }
193 }
194 
195 impl_newtype!(RelativeDistinguishedName, SetOfVec<AttributeTypeAndValue>);
196