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