Skip to content

Commit 84023cb

Browse files
committed
Use strict ownership semantics on windows as well (#386)
Thanks microsoft/windows-rs#1697 (comment) for figuring this out.
1 parent 2705679 commit 84023cb

File tree

1 file changed

+52
-15
lines changed

1 file changed

+52
-15
lines changed

git-sec/src/identity.rs

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,48 +49,85 @@ mod impl_ {
4949

5050
pub fn is_path_owned_by_current_user(path: impl AsRef<Path>) -> std::io::Result<bool> {
5151
use windows::{
52-
core::PCWSTR,
52+
core::{Error, PCWSTR},
5353
Win32::{
54-
Foundation::{BOOL, ERROR_SUCCESS, HANDLE, PSID},
54+
Foundation::{ERROR_SUCCESS, HANDLE, PSID},
5555
Security::{
5656
Authorization::{GetNamedSecurityInfoW, SE_FILE_OBJECT},
57-
CheckTokenMembershipEx, OWNER_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR,
57+
EqualSid, GetTokenInformation, TokenOwner, OWNER_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR,
58+
TOKEN_OWNER, TOKEN_QUERY,
59+
},
60+
System::{
61+
Memory::LocalFree,
62+
Threading::{GetCurrentProcess, OpenProcessToken},
5863
},
59-
System::Memory::LocalFree,
6064
},
6165
};
6266

6367
let mut err_msg = None;
6468
let mut is_owned = false;
69+
let path = path.as_ref();
6570

6671
#[allow(unsafe_code)]
6772
unsafe {
68-
let mut psid = PSID::default();
73+
let mut folder_owner = PSID::default();
6974
let mut pdescriptor = PSECURITY_DESCRIPTOR::default();
70-
let wpath = to_wide_path(&path);
71-
7275
let result = GetNamedSecurityInfoW(
73-
PCWSTR(wpath.as_ptr()),
76+
PCWSTR(to_wide_path(path).as_ptr()),
7477
SE_FILE_OBJECT,
7578
OWNER_SECURITY_INFORMATION,
76-
&mut psid,
79+
&mut folder_owner,
7780
std::ptr::null_mut(),
7881
std::ptr::null_mut(),
7982
std::ptr::null_mut(),
8083
&mut pdescriptor,
8184
);
8285

86+
// Workaround for https://github.com/microsoft/win32metadata/issues/884
8387
if result == ERROR_SUCCESS.0 {
84-
let mut is_member = BOOL(0);
85-
if CheckTokenMembershipEx(HANDLE::default(), psid, 0, &mut is_member).as_bool() {
86-
is_owned = is_member.as_bool();
88+
let mut token = HANDLE::default();
89+
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token).ok()?;
90+
91+
let mut buffer_size = 0;
92+
let mut buffer = Vec::<u8>::new();
93+
GetTokenInformation(token, TokenOwner, std::ptr::null_mut(), 0, &mut buffer_size);
94+
if buffer_size != 0 {
95+
buffer.resize(buffer_size as usize, 0);
96+
if GetTokenInformation(
97+
token,
98+
TokenOwner,
99+
buffer.as_mut_ptr() as _,
100+
buffer_size,
101+
&mut buffer_size,
102+
)
103+
.as_bool()
104+
{
105+
let token_owner = buffer.as_ptr() as *const TOKEN_OWNER;
106+
let token_owner = (*token_owner).Owner;
107+
108+
is_owned = EqualSid(folder_owner, token_owner).as_bool();
109+
} else {
110+
err_msg = format!(
111+
"Couldn't get actual token information for current process with err: {}",
112+
Error::from_win32()
113+
)
114+
.into();
115+
}
87116
} else {
88-
err_msg = String::from("Could not check token membership").into();
117+
err_msg = format!(
118+
"Couldn't get token information size info for current process with err: {}",
119+
Error::from_win32()
120+
)
121+
.into();
89122
}
90123
} else {
91-
err_msg = format!("Could not get security information for path with err: {}", result).into();
124+
err_msg = format!(
125+
"Couldn't get security information for path '{}' with err {}",
126+
path.display(),
127+
Error::from_win32()
128+
)
129+
.into();
92130
}
93-
94131
LocalFree(pdescriptor.0 as isize);
95132
}
96133

0 commit comments

Comments
 (0)