From 43904af6bf7c0497f5e5659533cb31e1a116acca Mon Sep 17 00:00:00 2001 From: Kotauskas Date: Tue, 2 Apr 2024 15:49:16 +0300 Subject: [PATCH] Make SD test work in CI..? --- Cargo.toml | 1 + .../local_socket_security_descriptor.rs | 108 +++++++++++------- 2 files changed, 66 insertions(+), 43 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 724e5da..8878c56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ windows-sys = { version = "0.52.0", features = [ "Win32_System_Threading", "Win32_System_Memory", "Win32_System_SystemServices", + "Win32_System_LibraryLoader", ] } recvmsg = "1.0.0" widestring = "1.0.2" diff --git a/tests/os/windows/local_socket_security_descriptor.rs b/tests/os/windows/local_socket_security_descriptor.rs index fc6a699..9a7f2af 100644 --- a/tests/os/windows/local_socket_security_descriptor.rs +++ b/tests/os/windows/local_socket_security_descriptor.rs @@ -5,16 +5,17 @@ use crate::{ BorrowedSecurityDescriptor, LocalBox, SecurityDescriptor, }, tests::util::*, - TryClone, + OrErrno, TryClone, }; -use std::{io, os::windows::prelude::*, ptr, sync::Arc}; +use std::{ffi::OsString, fs::File, io, mem::MaybeUninit, os::windows::prelude::*, ptr, sync::Arc}; use widestring::{U16CStr, U16Str}; use windows_sys::Win32::{ - Foundation::STATUS_SUCCESS, + Foundation::{MAX_PATH, STATUS_SUCCESS}, Security::{ Authorization::{GetSecurityInfo, SE_KERNEL_OBJECT, SE_OBJECT_TYPE}, DACL_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION, OWNER_SECURITY_INFORMATION, }, + System::LibraryLoader::GetModuleFileNameW, }; const SECINFO: u32 = @@ -45,39 +46,18 @@ fn get_sd(handle: BorrowedHandle<'_>, ot: SE_OBJECT_TYPE) -> TestResult TestResult { - get_sd( - unsafe { BorrowedHandle::borrow_raw(-1 as _) }, - SE_KERNEL_OBJECT, - ) - .opname("get_process_sd()") +fn count_opening_parentheses(s: &U16Str) -> u32 { + let mut cpa = 0; + for c in s.as_slice().iter().copied() { + if c == '(' as u16 { + cpa += 1; + } + } + cpa } -#[test] -fn local_socket_security_descriptor() -> TestResult { - let sd = get_process_sd()?; - let (name, listener) = - listen_and_pick_name(&mut namegen_local_socket(make_id!(), false), |nm| { - ListenerOptions::new() - .name(nm.borrow()) - .security_descriptor(sd.try_clone()?) - .create_sync() - })?; - let _ = Stream::connect(Arc::try_unwrap(name).unwrap()).opname("client connect")?; - - let listener_handle = OwnedHandle::from(listener); - let listener_sd = - get_sd(listener_handle.as_handle(), SE_KERNEL_OBJECT).opname("get listener SD")?; - - sd.serialize(SECINFO, |old_s| { - listener_sd.serialize(SECINFO, |new_s| { - let start = ensure_equal_non_acl_part(old_s, new_s)?; - ensure_equal_number_of_opening_parentheses(&old_s[start..], &new_s[start..])?; - TestResult::Ok(()) - }) - }) - .opname("serialize")???; - +fn ensure_equal_number_of_opening_parentheses(a: &U16Str, b: &U16Str) -> TestResult { + ensure_eq!(count_opening_parentheses(a), count_opening_parentheses(b)); Ok(()) } @@ -99,17 +79,59 @@ fn ensure_equal_non_acl_part(a: &U16CStr, b: &U16CStr) -> TestResult { Ok(idx) } -fn count_opening_parentheses(s: &U16Str) -> u32 { - let mut cpa = 0; - for c in s.as_slice().iter().copied() { - if c == '(' as u16 { - cpa += 1; - } +fn get_self_exe(obuf: &mut [MaybeUninit]) -> io::Result<&U16CStr> { + if obuf.is_empty() { + return Ok(Default::default()); } - cpa + let base = obuf.as_mut_ptr().cast(); + let cap = obuf.len().try_into().unwrap_or(u32::MAX); + unsafe { GetModuleFileNameW(0, base, cap) != 0 } + .true_val_or_errno(()) + .and_then(|()| unsafe { + U16CStr::from_ptr_truncate(base.cast_const(), cap as usize).map_err(io::Error::other) + }) } -fn ensure_equal_number_of_opening_parentheses(a: &U16Str, b: &U16Str) -> TestResult { - ensure_eq!(count_opening_parentheses(a), count_opening_parentheses(b)); +#[test] +fn local_socket_security_descriptor() -> TestResult { + let sd = { + let mut pathbuf = [MaybeUninit::uninit(); MAX_PATH as _]; + let path: OsString = get_self_exe(&mut pathbuf) + .opname("query of path to own executable")? + .into(); + let file = File::open(path).opname("own executable open")?; + get_sd(file.as_handle(), SE_KERNEL_OBJECT) + .opname("query of own executable's security descriptor")? + }; + + let (name, listener) = + listen_and_pick_name(&mut namegen_local_socket(make_id!(), false), |nm| { + ListenerOptions::new() + .name(nm.borrow()) + .security_descriptor(sd.try_clone()?) + .create_sync() + })?; + let _ = Stream::connect(Arc::try_unwrap(name).unwrap()).opname("client connect")?; + + let listener_handle = OwnedHandle::from(listener); + let listener_sd = + get_sd(listener_handle.as_handle(), SE_KERNEL_OBJECT).opname("get listener SD")?; + + sd.serialize(SECINFO, |old_s| { + listener_sd.serialize(SECINFO, |new_s| { + eprintln!( + "\ +SDDL of the running executable\t: {} +SDDL of the local socket listener\t: {}", + old_s.display(), + new_s.display() + ); + let start = ensure_equal_non_acl_part(old_s, new_s)?; + ensure_equal_number_of_opening_parentheses(&old_s[start..], &new_s[start..])?; + TestResult::Ok(()) + }) + }) + .opname("serialize and check")???; + Ok(()) }