1#![forbid(unsafe_code)]
2
3#[cfg(test)]
4mod tests;
5mod maybe_heap;
6
7use byteorder::{BigEndian, ByteOrder};
8use nom::{
9 branch::alt,
10 bytes::complete::{tag, take},
11 character::complete::{digit1, hex_digit1},
12 combinator::{map_res, recognize},
13 multi::{many0, many_m_n},
14 number::complete::le_u32,
15 Finish, IResult,
16};
17#[cfg(feature = "serde")]
18use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
19use std::{
20 fmt::{Debug, Display, Write}, hash::Hash, str::FromStr
21};
22use thiserror::Error;
23use const_for::const_for;
24use maybe_heap::MaybeHeap;
25
26fn use_parse_str<T>(parser_result: IResult<&str, T>) -> Result<T, SecurityIdentifierError> {
27 let (remainder, value) = parser_result.finish()?;
28 if !remainder.is_empty() {
29 Err(SecurityIdentifierError::UnexpectedContent(remainder.to_owned()))
30 } else {
31 Ok(value)
32 }
33}
34
35#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
43pub struct IdentifierAuthority([u8; 6]);
44
45impl IdentifierAuthority {
46 fn parse_str(input: &str) -> IResult<&str, Self> {
47 let mut identifier_authority = [0u8; 6];
48 let (input, _) = tag("-")(input)?;
49 let (input, value) = alt((hex_u64, dec_u64))(input)?;
50 BigEndian::write_u48(&mut identifier_authority, value);
51 Ok((input, Self(identifier_authority)))
52 }
53}
54
55impl From<u32> for IdentifierAuthority {
56 fn from(value: u32) -> Self {
57 let mut identifier_authority = [0u8; 6];
58 BigEndian::write_u48(&mut identifier_authority, value as u64);
59 Self(identifier_authority)
60 }
61}
62
63impl From<IdentifierAuthority> for u64 {
64 fn from(value: IdentifierAuthority) -> Self {
65 BigEndian::read_u48(&value.0)
66 }
67}
68
69impl Display for IdentifierAuthority {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 if self.0[0] == 0x00 && self.0[1] == 0x00 {
72 f.write_fmt(format_args!("{}", BigEndian::read_u32(&self.0[2..6])))?;
73 } else {
74 f.write_fmt(format_args!("{:#X}", BigEndian::read_u48(&self.0)))?;
75 }
76 Ok(())
77 }
78}
79
80impl FromStr for IdentifierAuthority {
81 type Err = SecurityIdentifierError;
82
83 fn from_str(input: &str) -> Result<Self, Self::Err> {
84 use_parse_str(Self::parse_str(input))
85 }
86}
87
88const COMMON_SIZE: usize = 6;
89
90#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
92pub struct SecurityIdentifier {
93 identifier_authority: IdentifierAuthority,
94 sub_authority: MaybeHeap<COMMON_SIZE>,
95}
96
97impl SecurityIdentifier {
98 pub fn new(identifier_authority: impl Into<IdentifierAuthority>, sub_authority: &[u32]) -> Self {
106 if sub_authority.len() > 256 {
107 panic!("SIDs do not support more than 256 sub-authorities. An attempt was made to construct a SID with {} sub-authorities", sub_authority.len())
108 }
109 Self {
110 identifier_authority: identifier_authority.into(),
111 sub_authority: sub_authority.to_vec().into(),
112 }
113 }
114
115 pub const fn new_const<const N: usize>(identifier_authority: u64, sub_authority: [u32; N]) -> Self {
123 let mut stack_sub_authorities = [0u32; COMMON_SIZE];
124 assert!(N <= COMMON_SIZE);
125 const_for!(i in 0..COMMON_SIZE => {
126 if N > i {
127 stack_sub_authorities[i] = sub_authority[i];
128 }
129 });
130 Self {
131 identifier_authority: IdentifierAuthority([
132 (identifier_authority >> 40) as u8,
133 (identifier_authority >> 32) as u8,
134 (identifier_authority >> 24) as u8,
135 (identifier_authority >> 16) as u8,
136 (identifier_authority >> 8) as u8,
137 identifier_authority as u8
138 ]),
139 sub_authority: MaybeHeap::Stack(stack_sub_authorities, N),
140 }
141 }
142
143 pub fn from_bytes(input: &[u8]) -> Result<Self, SecurityIdentifierError> {
147 let (remainder, sid) = parse_sid_bytes(input).finish()?;
148 if !remainder.is_empty() {
149 Err(SecurityIdentifierError::UnexpectedContent(format!("{:?}", remainder)))
150 } else {
151 Ok(sid)
152 }
153 }
154
155 pub fn to_bytes(&self) -> Vec<u8> {
157 let mut result = Vec::with_capacity(8 + (self.sub_authority.as_slice().len() * 4));
158 result.push(1);
159 result.push(self.sub_authority.as_slice().len() as u8);
160 for byte in self.identifier_authority.0 {
161 result.push(byte)
162 }
163 for sub_authority in self.sub_authority.as_slice() {
164 for byte in sub_authority.to_le_bytes() {
165 result.push(byte);
166 }
167 }
168 result
169 }
170
171 pub fn to_ldap_predicate(&self) -> String {
173 let bytes = self.to_bytes();
174 let mut predicate = String::with_capacity(12 + (bytes.len() * 3));
176 let _ = write!(predicate, "(objectSID=");
177 for byte in bytes {
178 let _ = write!(predicate, "\\{:02x}", byte);
179 }
180 let _ = write!(predicate, ")");
181 predicate
182 }
183
184 pub fn get_resource_identifier(&self) -> Option<&u32> {
186 self.sub_authority.as_slice().last()
187 }
188
189 pub fn get_identifier_authority(&self) -> &IdentifierAuthority {
191 &self.identifier_authority
192 }
193
194 pub fn get_identifier_sub_authority(&self) -> &[u32] {
196 self.sub_authority.as_slice()
197 }
198
199 fn parse_str(input: &str) -> IResult<&str, Self> {
200 let (input, _) = tag::<_, _, nom::error::Error<_>>("S-1")(input)?;
201
202 let (input, identifier_authority) = IdentifierAuthority::parse_str(input)?;
203 let (input, sub_authority) = many0(sid_segment)(input)?;
204
205 Ok((
206 input,
207 Self {
208 identifier_authority,
209 sub_authority : sub_authority.into(),
210 },
211 ))
212 }
213}
214
215impl Display for SecurityIdentifier {
216 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
217 f.write_fmt(format_args!("S-1-{}", self.identifier_authority))?;
218 for sub_authority in self.sub_authority.as_slice() {
219 f.write_fmt(format_args!("-{}", sub_authority))?;
220 }
221 Ok(())
222 }
223}
224
225impl FromStr for SecurityIdentifier {
226 type Err = SecurityIdentifierError;
227
228 fn from_str(input: &str) -> Result<Self, Self::Err> {
229 use_parse_str(Self::parse_str(input))
230 }
231}
232
233#[cfg(feature = "serde")]
234impl<'de> Deserialize<'de> for SecurityIdentifier {
235 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
236 where
237 D: Deserializer<'de>,
238 {
239 SecurityIdentifier::from_str(&String::deserialize(deserializer)?).map_err(|err| D::Error::custom(err.to_string()))
240 }
241}
242
243#[cfg(feature = "serde")]
244impl Serialize for SecurityIdentifier {
245 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
246 where
247 S: Serializer,
248 {
249 self.to_string().serialize(serializer)
250 }
251}
252
253fn dec_u64(input: &str) -> IResult<&str, u64> {
254 map_res(recognize(digit1), str::parse)(input)
255}
256
257fn hex_u64(input: &str) -> IResult<&str, u64> {
258 let (input, _) = tag("0x")(input)?;
259 map_res(recognize(hex_digit1), |x| u64::from_str_radix(x, 16))(input)
260}
261
262fn dec_u32(input: &str) -> IResult<&str, u32> {
263 map_res(recognize(digit1), str::parse)(input)
264}
265
266fn hex_u32(input: &str) -> IResult<&str, u32> {
267 let (input, _) = tag("0x")(input)?;
268 map_res(recognize(hex_digit1), |x| u32::from_str_radix(x, 16))(input)
269}
270
271fn sid_segment(input: &str) -> IResult<&str, u32> {
272 let (input, _) = tag("-")(input)?;
273 let (input, value) = alt((hex_u32, dec_u32))(input)?;
274 Ok((input, value))
275}
276
277fn parse_sid_bytes(input: &[u8]) -> IResult<&[u8], SecurityIdentifier> {
278 let (input, _) = tag([1])(input)?;
279
280 let (input, sub_authority_count) = nom::number::complete::u8(input)?;
281 let (input, identifier_authority) = take(6usize)(input)?;
282 let (input, sub_authority) = many_m_n(sub_authority_count as usize, sub_authority_count as usize, le_u32)(input)?;
283
284 Ok((
285 input,
286 SecurityIdentifier {
287 identifier_authority: IdentifierAuthority(identifier_authority.try_into().unwrap()),
288 sub_authority: sub_authority.into(),
289 },
290 ))
291}
292
293#[derive(Error, Debug)]
295pub enum SecurityIdentifierError {
296 #[error("bad revision")]
298 BadRevision,
299
300 #[error("parsing error: {0}")]
302 ParseError(String),
303
304 #[error("unexpected content: {0}")]
306 UnexpectedContent(String),
307}
308
309impl<E> From<nom::error::Error<E>> for SecurityIdentifierError
310where
311 E: Debug,
312{
313 fn from(value: nom::error::Error<E>) -> Self {
314 Self::ParseError(format!("{:?}: {:?}", value.code, value.input))
315 }
316}