windows_permissions/structures/
trustee.rs1use crate::constants::TrusteeForm;
2use crate::utilities;
3use crate::wrappers;
4use crate::Sid;
5use std::ffi::OsStr;
6use std::fmt;
7use std::marker::PhantomData;
8use std::ptr::NonNull;
9use winapi::ctypes::c_void;
10use winapi::um::accctrl::TRUSTEE_W;
11
12#[repr(C)]
17pub struct Trustee<'s> {
18 inner: TRUSTEE_W,
19 _phantom: PhantomData<TrusteeSubject<'s>>,
20}
21
22#[derive(Debug)]
24pub enum TrusteeSubject<'s> {
25 Name(&'s [u16]),
29
30 Sid(&'s Sid),
32
33 ObjectsAndSid(*const c_void),
35
36 ObjectsAndName(*const c_void),
38
39 Bad,
41}
42
43impl<'s> Trustee<'s> {
44 pub fn as_ptr(&self) -> *const TRUSTEE_W {
46 &self.inner
47 }
48
49 pub fn as_mut_ptr(&mut self) -> *mut TRUSTEE_W {
51 &mut self.inner
52 }
53
54 pub unsafe fn allocate() -> Self {
61 Self {
62 inner: std::mem::zeroed(),
63 _phantom: PhantomData,
64 }
65 }
66
67 pub fn get_subject(&self) -> TrusteeSubject<'s> {
76 let form = wrappers::GetTrusteeForm(&self)
77 .unwrap_or_else(|f| panic!("Trustee had unrecognized form: {:x}", f));
78
79 let ptr = self.inner.ptstrName as *mut _;
80
81 match form {
82 TrusteeForm::TRUSTEE_IS_SID => {
83 let ptr =
84 NonNull::new(ptr).expect("Null SID pointer on Trustee with TRUSTEE_IS_SID");
85
86 unsafe { TrusteeSubject::Sid(&*ptr.as_ptr()) }
87 }
88 TrusteeForm::TRUSTEE_IS_NAME => {
89 let ptr =
90 NonNull::new(ptr).expect("Null name pointer on Trustee with TRUSTEE_IS_NAME");
91
92 unsafe {
93 let nul_pos = utilities::search_buffer(&0x00, ptr.as_ptr() as *const u16);
94 TrusteeSubject::Name(std::slice::from_raw_parts(
95 ptr.as_ptr() as *const u16,
96 nul_pos + 1,
97 ))
98 }
99 }
100 TrusteeForm::TRUSTEE_IS_OBJECTS_AND_SID => {
101 TrusteeSubject::ObjectsAndSid(ptr as *const _)
102 }
103 TrusteeForm::TRUSTEE_IS_OBJECTS_AND_NAME => {
104 TrusteeSubject::ObjectsAndName(ptr as *const _)
105 }
106 TrusteeForm::TRUSTEE_BAD_FORM => TrusteeSubject::Bad,
107 }
108 }
109}
110
111impl<'s> From<&'s Sid> for Trustee<'s> {
112 fn from(sid: &'s Sid) -> Self {
113 wrappers::BuildTrusteeWithSid(sid)
114 }
115}
116
117impl From<&OsStr> for Trustee<'static> {
118 fn from(name: &OsStr) -> Self {
119 wrappers::BuildTrusteeWithNameOsStr(name)
120 }
121}
122
123impl<'s> fmt::Debug for Trustee<'s> {
124 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
125 fmt.debug_map().finish()
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 const TRUSTEE_NAMES: &[&'static str] = &["test_name", r"domain\username", "a_unicode_char: 💩"];
134
135 #[test]
136 fn create_and_retrieve_sid_trustee() {
137 use std::ops::Deref;
138
139 for (sid, _, _) in Sid::test_sids() {
140 let trustee: Trustee = sid.as_ref().into();
141
142 match trustee.get_subject() {
143 TrusteeSubject::Sid(s) => assert_eq!(s, sid.deref()),
144 _ => panic!("Expected to get back a TrusteeSubject::Sid"),
145 }
146 }
147 }
148
149 #[test]
150 fn create_and_retrieve_name_trustee() {
151 for name in TRUSTEE_NAMES {
152 let trustee: Trustee = OsStr::new(name).into();
153 let buffer = utilities::buf_from_os(OsStr::new(name));
154
155 match trustee.get_subject() {
156 TrusteeSubject::Name(n) => assert_eq!(n, buffer.as_slice()),
157 _ => panic!("Expected to get back a TrusteeSubject::Name"),
158 }
159
160 assert_eq!(wrappers::GetTrusteeName(&trustee), **name);
161 }
162 }
163}