use std::error::Error;
use log::{trace,error};
use crate::enums::{secdesc::LdapSid, regex::IS_SID_RE1};
pub fn is_sid(input: &str) -> Result<bool, Box<dyn Error>> {
Ok(IS_SID_RE1.is_match(input))
}
pub fn sid_maker(sid: LdapSid, domain: &str) -> String {
trace!("sid_maker before: {:?}",&sid);
let sub = sid.sub_authority.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("-");
let result = format!("S-{}-{}-{}", sid.revision, sid.identifier_authority.value[5], sub);
let final_sid = {
if result.len() <= 16 {
format!("{}-{}", domain.to_uppercase(), result.to_owned())
} else {
result
}
};
trace!("sid_maker value: {}",final_sid);
if final_sid.contains("S-0-0"){
error!("SID contains null bytes!\n[INPUT: {:?}]\n[OUTPUT: {}]", &sid, final_sid);
}
final_sid
}
pub fn objectsid_to_vec8(sid: &str) -> Vec<u8>
{
sid.as_bytes().iter().map(|x| *x).collect::<Vec<u8>>()
}
pub fn _decode_guid(raw_guid: &[u8]) -> String
{
let raw_guid = raw_guid.iter().map(|x| x & 0xFF).collect::<Vec<u8>>();
let rev = | x: &[u8] | -> Vec<u8> { x.iter().map(|i| *i).rev().collect::<Vec<u8>>()};
let str_guid = format!(
"{}-{}-{}-{}-{}",
&hex_push(&raw_guid[0..4]),
&hex_push(&rev(&raw_guid[4..6])),
&hex_push(&rev(&raw_guid[6..8])),
&hex_push(&raw_guid[8..10]),
&hex_push(&raw_guid[10..16]),
);
str_guid
}
pub fn hex_push(blob: &[u8]) -> String {
blob.iter().map(|x| format!("{:X}", x)).collect::<String>()
}
pub fn bin_to_string(raw_guid: &[u8]) -> String
{
let raw_guid = raw_guid.iter().map(|x| x & 0xFF).collect::<Vec<u8>>();
let rev = | x: &[u8] | -> Vec<u8> { x.iter().map(|i| *i).collect::<Vec<u8>>()};
let str_guid = format!(
"{}-{}-{}-{}-{}",
&hex_push(&raw_guid[12..16]),
&hex_push(&raw_guid[10..12]),
&hex_push(&raw_guid[8..10]),
&hex_push(&rev(&raw_guid[6..8])),
&hex_push(&rev(&raw_guid[0..6]))
);
str_guid
}
pub fn decode_guid_le(raw_guid: &[u8]) -> String {
let str_guid = format!(
"{:02X}{:02X}{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
raw_guid[3], raw_guid[2], raw_guid[1], raw_guid[0], raw_guid[5], raw_guid[4], raw_guid[7], raw_guid[6], raw_guid[8], raw_guid[9], raw_guid[10], raw_guid[11], raw_guid[12], raw_guid[13], raw_guid[14], raw_guid[15] );
str_guid
}
#[cfg(test)]
mod tests {
use super::*;
use crate::enums::secdesc::{LdapSid, LdapSidIdentifiedAuthority};
fn make_sid(sub_authority: Vec<u32>) -> LdapSid {
LdapSid {
revision: 1,
sub_authority_count: sub_authority.len() as u8,
identifier_authority: LdapSidIdentifiedAuthority {
value: vec![0, 0, 0, 0, 0, 5],
},
sub_authority,
}
}
#[test]
fn sid_maker_keeps_long_sid_without_domain_prefix() {
let sid = make_sid(vec![21, 123456789, 1234567890, 500]);
assert_eq!(
sid_maker(sid, "domain.local"),
"S-1-5-21-123456789-1234567890-500"
);
}
#[test]
fn sid_maker_prefixes_short_sid_with_domain() {
let sid = make_sid(vec![500]);
assert_eq!(sid_maker(sid, "domain.local"), "DOMAIN.LOCAL-S-1-5-500");
}
#[test]
fn decode_guid_le_converts_little_endian_fields() {
let raw = [
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
];
assert_eq!(
decode_guid_le(&raw),
"33221100-5544-7766-8899-AABBCCDDEEFF"
);
}
#[test]
fn is_sid_accepts_valid_sid_and_rejects_invalid_input() {
assert!(is_sid("S-1-5-21-123456789-500").unwrap());
assert!(!is_sid("S-1-4-21-123456789").unwrap());
assert!(!is_sid("not-a-sid").unwrap());
}
#[test]
fn hex_push_returns_uppercase_hex_without_padding() {
assert_eq!(hex_push(&[0x0F, 0xA0]), "FA0");
}
}