safe-sid 0.1.0

Safe borrowed/owned wrappers over a Windows security identifier (SID).
docs.rs failed to build safe-sid-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

safe-sid

Safe wrapper for working with SIDs from the Windows API.

Provides the borrowed/owned pair &Sid and SidBuf along with safe helper functions. Byte-compatible with the Windows SID struct. Defines equality and ordering traits so they can be compared and keyed on.

Depends on the windows crate by default, but this can be reduced down to just windows-core by turning off default features.

Usage

[dependencies]
safe-sid = "0.1"

Or for just the windows-core dependency:

[dependencies]
safe-sid = { version = "0.1", default-features = false }

Build a SID by hand

let admins = SidBuf::new([0, 0, 0, 0, 0, 5], &[32, 544]).unwrap();
assert_eq!(admins.to_string(), "S-1-5-32-544");

Build a well-known SID

let local_system = SidBuf::well_known(WinLocalSystemSid, None).unwrap();
assert_eq!(local_system.to_string(), "S-1-5-18");

Pass a SID to a Windows API

// Just an example, use Sid::to_string() normally 
fn sid_to_string(sid: &Sid) -> Result<String> {
    let mut hlocal_str = PSTR::null();
    unsafe {
        ConvertSidToStringSidA(sid.as_psid(), &mut hlocal_str)?;
        let string_sid = CStr::from_ptr(hlocal_str.0 as *const _).to_str().unwrap().to_owned();
        LocalFree(Some(HLOCAL(hlocal_str.0 as *mut _)));
        Ok(string_sid)
    }
}

Fill a SidBuf from a Windows API

Sometimes a SID comes from a Windows API that expects the caller to provide a buffer. You can unsafely acquire a mutable pointer, and are responsible for ensuring it is filled with a valid SID with a correctly matching length.

Note that even if the SID is malformed, dropping SidBuf will still be safe.

fn lookup_account_name(name: &CStr) -> Result<SidBuf> {
    let mut sid_use = SID_NAME_USE::default();
    let mut sid_len = 0u32;
    let mut domain_len = 0u32;

    unsafe {
        if let Err(e) = LookupAccountNameA(
            PCSTR::null(), PCSTR(name.as_ptr() as *const _), None, &mut sid_len,
            None, &mut domain_len, &mut sid_use,
        ) && e.code() != HRESULT::from_win32(ERROR_INSUFFICIENT_BUFFER.0)
        {
            return Err(e);
        }

        // Create the SidBuf with enough space to receive the SID
        let mut sid = SidBuf::with_capacity(sid_len as usize);
        let mut domain = vec![0u8; domain_len as usize];
        LookupAccountNameA(
            PCSTR::null(), PCSTR(name.as_ptr() as *const _), Some(PSID(sid.as_mut_ptr())), &mut sid_len,
            Some(PSTR(domain.as_mut_ptr())), &mut domain_len, &mut sid_use,
        )?;
        Ok(sid)
    }
}

License

Licensed under the ISC License.