windows_permissions/structures/
sd.rs1use crate::constants::SecurityInformation;
2use crate::{wrappers, Acl, LocalBox, Sid};
3use std::ffi::OsString;
4use std::fmt;
5use std::io;
6use std::str::FromStr;
7
8#[repr(C)]
15pub struct SecurityDescriptor {
16 _opaque: [u8; 0],
17}
18
19impl Drop for SecurityDescriptor {
20 fn drop(&mut self) {
21 unreachable!("SecurityDescriptor should only be borrowed, not owned")
22 }
23}
24
25impl SecurityDescriptor {
26 pub fn as_sddl(&self) -> io::Result<OsString> {
34 wrappers::ConvertSecurityDescriptorToStringSecurityDescriptor(
35 self,
36 SecurityInformation::all(),
37 )
38 }
39
40 pub fn owner(&self) -> Option<&Sid> {
53 wrappers::GetSecurityDescriptorOwner(self)
54 .expect("Valid SecurityDescriptor failed to get owner")
55 }
56
57 pub fn group(&self) -> Option<&Sid> {
70 wrappers::GetSecurityDescriptorGroup(self)
71 .expect("Valid SecurityDescriptor failed to get group")
72 }
73
74 pub fn dacl(&self) -> Option<&Acl> {
76 wrappers::GetSecurityDescriptorDacl(self)
77 .expect("Valid SecurityDescriptor failed to get dacl")
78 }
79
80 pub fn sacl(&self) -> Option<&Acl> {
82 wrappers::GetSecurityDescriptorSacl(self)
83 .expect("Valid SecurityDescriptor failed to get sacl")
84 }
85}
86
87impl fmt::Debug for SecurityDescriptor {
88 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
89 fmt.debug_map()
90 .entry(&"owner", &self.owner())
91 .entry(&"group", &self.group())
92 .entry(&"sddl", &self.as_sddl().unwrap())
93 .finish()
94 }
95}
96
97impl FromStr for LocalBox<SecurityDescriptor> {
98 type Err = io::Error;
99
100 fn from_str(s: &str) -> Result<Self, Self::Err> {
101 wrappers::ConvertStringSecurityDescriptorToSecurityDescriptor(s)
102 }
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108 use crate::LocalBox;
109 use std::ffi::OsStr;
110 use std::ops::Deref;
111
112 static SDDL_TEST_CASES: &[(&str, &str, &str)] = &[
113 ("", "", ""),
114 ("O:AOG:SY", "AO", "SY"),
115 ("O:SU", "SU", ""),
116 ("G:SI", "", "SI"),
117 ("O:AOG:SYD:S:", "AO", "SY"),
118 ];
119
120 fn assert_option_eq(lhs: Option<&Sid>, rhs: Option<&LocalBox<Sid>>) {
121 match (lhs, rhs) {
122 (None, None) => (),
123 (Some(_), None) => panic!("Assertion failed: {:?} == {:?}", lhs, rhs),
124 (None, Some(_)) => panic!("Assertion failed: {:?} == {:?}", lhs, rhs),
125 (Some(l), Some(r)) => assert_eq!(l, r.deref()),
126 }
127 }
128
129 fn sddl_test_cases(
130 ) -> impl Iterator<Item = (String, Option<LocalBox<Sid>>, Option<LocalBox<Sid>>)> {
131 let parse_if_there = |s: &str| {
132 if s.is_empty() {
133 None
134 } else {
135 Some(s.parse().unwrap())
136 }
137 };
138
139 SDDL_TEST_CASES.iter().map(move |(sddl, own, grp)| {
140 (sddl.to_string(), parse_if_there(own), parse_if_there(grp))
141 })
142 }
143
144 #[test]
145 fn sddl_get_sids() -> io::Result<()> {
146 for (sddl, owner, group) in sddl_test_cases() {
147 let sd: LocalBox<SecurityDescriptor> = sddl.parse()?;
148
149 assert_option_eq(sd.owner(), owner.as_ref());
150 assert_option_eq(sd.group(), group.as_ref());
151 }
152
153 Ok(())
154 }
155
156 #[test]
157 fn sddl_round_trip() -> io::Result<()> {
158 for (sddl, _, _) in sddl_test_cases() {
159 let sd: LocalBox<SecurityDescriptor> = sddl.parse()?;
160 let sddl2 = sd.as_sddl()?;
161
162 assert_eq!(OsStr::new(&sddl), &sddl2);
163 }
164
165 Ok(())
166 }
167
168 #[test]
169 fn sddl_missing_acls() -> io::Result<()> {
170 let sd: LocalBox<SecurityDescriptor> = "O:LAG:AO".parse()?;
171 assert!(sd.dacl().is_none());
172 assert!(sd.sacl().is_none());
173
174 let sd: LocalBox<SecurityDescriptor> = "O:LAG:AOD:".parse()?;
175 assert!(sd.dacl().is_some());
176 assert!(sd.sacl().is_none());
177
178 let sd: LocalBox<SecurityDescriptor> = "O:LAG:AOS:".parse()?;
179 assert!(sd.dacl().is_none());
180 assert!(sd.sacl().is_some());
181
182 let sd: LocalBox<SecurityDescriptor> = "O:LAG:AOD:S:".parse()?;
183 assert!(sd.dacl().is_some());
184 assert!(sd.sacl().is_some());
185
186 Ok(())
187 }
188}