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
use crate::constants::TrusteeForm;
use crate::utilities;
use crate::wrappers;
use crate::Sid;
use std::ffi::OsStr;
use std::fmt;
use std::marker::PhantomData;
use std::ptr::NonNull;
use winapi::ctypes::c_void;
use winapi::um::accctrl::TRUSTEE_W;
#[repr(C)]
pub struct Trustee<'s> {
    inner: TRUSTEE_W,
    _phantom: PhantomData<TrusteeSubject<'s>>,
}
#[derive(Debug)]
pub enum TrusteeSubject<'s> {
    
    
    
    Name(&'s [u16]),
    
    Sid(&'s Sid),
    
    ObjectsAndSid(*const c_void),
    
    ObjectsAndName(*const c_void),
    
    Bad,
}
impl<'s> Trustee<'s> {
    
    pub fn as_ptr(&self) -> *const TRUSTEE_W {
        &self.inner
    }
    
    pub fn as_mut_ptr(&mut self) -> *mut TRUSTEE_W {
        &mut self.inner
    }
    
    pub unsafe fn allocate() -> Self {
        Self {
            inner: std::mem::zeroed(),
            _phantom: PhantomData,
        }
    }
    
    
    
    
    
    
    
    
    pub fn get_subject(&self) -> TrusteeSubject<'s> {
        let form = wrappers::GetTrusteeForm(&self)
            .unwrap_or_else(|f| panic!("Trustee had unrecognized form: {:x}", f));
        let ptr = self.inner.ptstrName as *mut _;
        match form {
            TrusteeForm::TRUSTEE_IS_SID => {
                let ptr =
                    NonNull::new(ptr).expect("Null SID pointer on Trustee with TRUSTEE_IS_SID");
                unsafe { TrusteeSubject::Sid(&*ptr.as_ptr()) }
            }
            TrusteeForm::TRUSTEE_IS_NAME => {
                let ptr =
                    NonNull::new(ptr).expect("Null name pointer on Trustee with TRUSTEE_IS_NAME");
                unsafe {
                    let nul_pos = utilities::search_buffer(&0x00, ptr.as_ptr() as *const u16);
                    TrusteeSubject::Name(std::slice::from_raw_parts(
                        ptr.as_ptr() as *const u16,
                        nul_pos + 1,
                    ))
                }
            }
            TrusteeForm::TRUSTEE_IS_OBJECTS_AND_SID => {
                TrusteeSubject::ObjectsAndSid(ptr as *const _)
            }
            TrusteeForm::TRUSTEE_IS_OBJECTS_AND_NAME => {
                TrusteeSubject::ObjectsAndName(ptr as *const _)
            }
            TrusteeForm::TRUSTEE_BAD_FORM => TrusteeSubject::Bad,
        }
    }
}
impl<'s> From<&'s Sid> for Trustee<'s> {
    fn from(sid: &'s Sid) -> Self {
        wrappers::BuildTrusteeWithSid(sid)
    }
}
impl From<&OsStr> for Trustee<'static> {
    fn from(name: &OsStr) -> Self {
        wrappers::BuildTrusteeWithNameOsStr(name)
    }
}
impl<'s> fmt::Debug for Trustee<'s> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_map().finish()
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    const TRUSTEE_NAMES: &[&'static str] = &["test_name", r"domain\username", "a_unicode_char: 💩"];
    #[test]
    fn create_and_retrieve_sid_trustee() {
        use std::ops::Deref;
        for (sid, _, _) in Sid::test_sids() {
            let trustee: Trustee = sid.as_ref().into();
            match trustee.get_subject() {
                TrusteeSubject::Sid(s) => assert_eq!(s, sid.deref()),
                _ => panic!("Expected to get back a TrusteeSubject::Sid"),
            }
        }
    }
    #[test]
    fn create_and_retrieve_name_trustee() {
        for name in TRUSTEE_NAMES {
            let trustee: Trustee = OsStr::new(name).into();
            let buffer = utilities::buf_from_os(OsStr::new(name));
            match trustee.get_subject() {
                TrusteeSubject::Name(n) => assert_eq!(n, buffer.as_slice()),
                _ => panic!("Expected to get back a TrusteeSubject::Name"),
            }
        }
    }
}