Skip to content

Commit ded5555

Browse files
committed
See if checking for membership instead works (#386)
Inspired by this suggestion. microsoft/windows-rs#1697
1 parent 0dac74e commit ded5555

File tree

2 files changed

+42
-61
lines changed

2 files changed

+42
-61
lines changed

git-sec/Cargo.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ serde = { version = "1.0.114", optional = true, default-features = false, featur
2323
libc = "0.2.123"
2424

2525
[target.'cfg(windows)'.dependencies]
26-
windows = { version = "0.35.0", features = ["Win32_System_Threading", "Win32_Foundation", "Win32_Security", "Win32_Security_Authorization"] }
26+
windows = { version = "0.35.0", features = [ "alloc",
27+
"Win32_Foundation",
28+
"Win32_Security_Authorization",
29+
"Win32_Storage_FileSystem",
30+
"Win32_System_Memory",
31+
"Win32_System_Threading"
32+
] }
2733

2834
[dev-dependencies]
2935
tempfile = "3.3.0"

git-sec/src/lib.rs

+35-60
Original file line numberDiff line numberDiff line change
@@ -57,77 +57,52 @@ pub mod identity {
5757
}
5858

5959
pub fn is_path_owned_by_current_user(path: Cow<'_, Path>) -> std::io::Result<bool> {
60-
use windows::Win32::{
61-
Foundation::{CloseHandle, ERROR_SUCCESS, HANDLE, PSID},
62-
Security,
63-
Security::Authorization::SE_FILE_OBJECT,
64-
System::Threading,
60+
use windows::{
61+
core::{Error, PCWSTR},
62+
Win32::{
63+
Foundation::{BOOL, ERROR_SUCCESS, HANDLE, PSID},
64+
Security::{
65+
Authorization::{GetNamedSecurityInfoW, SE_FILE_OBJECT},
66+
CheckTokenMembershipEx, OWNER_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR,
67+
},
68+
System::Memory::LocalFree,
69+
},
6570
};
66-
let mut handle = HANDLE::default();
67-
let mut descriptor = Security::PSECURITY_DESCRIPTOR::default();
71+
6872
let mut err_msg = None;
6973
let mut is_owned = false;
7074

7175
#[allow(unsafe_code)]
7276
unsafe {
73-
Threading::OpenProcessToken(Threading::GetCurrentProcess(), Security::TOKEN_QUERY, &mut handle)
74-
.ok()
75-
.map_err(|_| err("Failed to open process token"))?;
76-
77-
let mut len = 0_u32;
78-
if !Security::GetTokenInformation(handle, Security::TokenUser, std::ptr::null_mut(), 0, &mut len)
79-
.as_bool()
80-
{
81-
let mut info_buf = Vec::<u8>::new();
82-
info_buf.reserve_exact(len as usize);
83-
if Security::GetTokenInformation(
84-
handle,
85-
Security::TokenUser,
86-
info_buf.as_mut_ptr() as *mut std::ffi::c_void,
87-
len,
88-
&mut len,
89-
)
90-
.as_bool()
91-
{
92-
// NOTE: we avoid to copy the sid or cache it in any way for now, even though it should be possible
93-
// with a custom allocation/vec/box and it's just very raw. Can the `windows` crate do better?
94-
// When/If yes, then let's improve this.
95-
// It should however be possible to create strings from SIDs, check this once more.
96-
let info: *const Security::TOKEN_USER = std::mem::transmute(info_buf.as_ptr());
97-
if Security::IsValidSid((*info).User.Sid).as_bool() {
98-
let wide_path = to_wide_path(&path);
99-
let mut path_sid = PSID::default();
100-
let res = Security::Authorization::GetNamedSecurityInfoW(
101-
windows::core::PCWSTR(wide_path.as_ptr()),
102-
SE_FILE_OBJECT,
103-
Security::OWNER_SECURITY_INFORMATION | Security::DACL_SECURITY_INFORMATION,
104-
&mut path_sid as *mut _,
105-
std::ptr::null_mut(),
106-
std::ptr::null_mut(),
107-
std::ptr::null_mut(),
108-
&mut descriptor as *mut _,
109-
);
110-
111-
if res == ERROR_SUCCESS.0 && Security::IsValidSid(path_sid).as_bool() {
112-
is_owned = Security::EqualSid(path_sid, (*info).User.Sid).as_bool();
113-
dbg!(is_owned, path.as_ref());
114-
} else {
115-
err_msg = format!("couldn't get owner for path or it wasn't valid: {}", res).into();
116-
}
117-
} else {
118-
err_msg = String::from("owner id of current process wasn't set or valid").into();
119-
}
77+
let mut psid = PSID::default();
78+
let mut pdescriptor = PSECURITY_DESCRIPTOR::default();
79+
let wpath = to_wide_path(&path);
80+
81+
let result = GetNamedSecurityInfoW(
82+
PCWSTR(wpath.as_ptr()),
83+
SE_FILE_OBJECT,
84+
OWNER_SECURITY_INFORMATION,
85+
&mut psid,
86+
std::ptr::null_mut(),
87+
std::ptr::null_mut(),
88+
std::ptr::null_mut(),
89+
&mut pdescriptor,
90+
);
91+
92+
if result == ERROR_SUCCESS.0 {
93+
let mut is_member = BOOL(0);
94+
if CheckTokenMembershipEx(HANDLE::default(), psid, 0, &mut is_member).as_bool() {
95+
is_owned = is_member.as_bool();
12096
} else {
121-
err_msg = String::from("Could not get information about the token user").into();
97+
err_msg = String::from("Could not check token membership").into();
12298
}
12399
} else {
124-
err_msg = String::from("Could not get token information for length of token user").into();
125-
}
126-
CloseHandle(handle);
127-
if !descriptor.is_invalid() {
128-
windows::core::heap_free(descriptor.0);
100+
err_msg = format!("Could not get security information for path with err: {}", result).into();
129101
}
102+
103+
LocalFree(pdescriptor.0 as isize);
130104
}
105+
131106
err_msg.map(|msg| Err(err(msg))).unwrap_or(Ok(is_owned))
132107
}
133108

0 commit comments

Comments
 (0)