@@ -63,9 +63,9 @@ mod impl_ {
6363#[ cfg( windows) ]
6464mod impl_ {
6565 use std:: {
66- io,
66+ io, mem ,
6767 mem:: MaybeUninit ,
68- os:: windows:: io:: { FromRawHandle as _, OwnedHandle } ,
68+ os:: windows:: io:: { AsRawHandle as _ , FromRawHandle as _, OwnedHandle } ,
6969 path:: Path ,
7070 ptr,
7171 } ;
@@ -80,14 +80,46 @@ mod impl_ {
8080 } } ;
8181 }
8282
83+ fn token_information ( token : windows_sys:: Win32 :: Foundation :: HANDLE , class : i32 ) -> io:: Result < Vec < u8 > > {
84+ use windows_sys:: Win32 :: {
85+ Foundation :: { GetLastError , ERROR_INSUFFICIENT_BUFFER } ,
86+ Security :: GetTokenInformation ,
87+ } ;
88+
89+ #[ allow( unsafe_code) ]
90+ unsafe {
91+ let mut buffer_size = 36 ;
92+ let mut heap_buf = vec ! [ 0 ; 36 ] ;
93+
94+ loop {
95+ if GetTokenInformation (
96+ token,
97+ class,
98+ heap_buf. as_mut_ptr ( ) . cast ( ) ,
99+ heap_buf. len ( ) as _ ,
100+ & mut buffer_size,
101+ ) != 0
102+ {
103+ return Ok ( heap_buf) ;
104+ }
105+
106+ if GetLastError ( ) != ERROR_INSUFFICIENT_BUFFER {
107+ error ! ( "Couldn't acquire token information" ) ;
108+ }
109+
110+ heap_buf. resize ( buffer_size as _ , 0 ) ;
111+ }
112+ }
113+ }
114+
83115 pub fn is_path_owned_by_current_user ( path : & Path ) -> io:: Result < bool > {
84116 use windows_sys:: Win32 :: {
85- Foundation :: { GetLastError , LocalFree , ERROR_INSUFFICIENT_BUFFER , ERROR_INVALID_FUNCTION , ERROR_SUCCESS } ,
117+ Foundation :: { LocalFree , ERROR_INVALID_FUNCTION , ERROR_SUCCESS } ,
86118 Security :: {
87119 Authorization :: { GetNamedSecurityInfoW , SE_FILE_OBJECT } ,
88- CheckTokenMembership , EqualSid , GetTokenInformation , IsWellKnownSid , TokenOwner ,
89- WinBuiltinAdministratorsSid , OWNER_SECURITY_INFORMATION , PSECURITY_DESCRIPTOR , TOKEN_OWNER ,
90- TOKEN_QUERY ,
120+ CheckTokenMembership , EqualSid , IsWellKnownSid , TokenElevationType , TokenElevationTypeLimited ,
121+ TokenLinkedToken , TokenUser , WinBuiltinAdministratorsSid , OWNER_SECURITY_INFORMATION ,
122+ PSECURITY_DESCRIPTOR , TOKEN_ELEVATION_TYPE , TOKEN_LINKED_TOKEN , TOKEN_QUERY , TOKEN_USER ,
91123 } ,
92124 System :: Threading :: { GetCurrentProcess , GetCurrentThread , OpenProcessToken , OpenThreadToken } ,
93125 } ;
@@ -169,46 +201,48 @@ mod impl_ {
169201
170202 let _owned_token = OwnedHandle :: from_raw_handle ( token as _ ) ;
171203
172- let buf = ' token_buf: {
173- let mut buffer_size = 36 ;
174- let mut heap_buf = vec ! [ 0 ; 36 ] ;
175-
176- loop {
177- if GetTokenInformation (
178- token,
179- TokenOwner ,
180- heap_buf. as_mut_ptr ( ) . cast ( ) ,
181- heap_buf. len ( ) as _ ,
182- & mut buffer_size,
183- ) != 0
184- {
185- break ' token_buf heap_buf;
186- }
204+ let user_info = token_information ( token, TokenUser ) ?;
205+ let token_user = ( * user_info. as_ptr ( ) . cast :: < TOKEN_USER > ( ) ) . User . Sid ;
187206
188- if GetLastError ( ) != ERROR_INSUFFICIENT_BUFFER {
189- error ! ( "Couldn't acquire token ownership" ) ;
190- }
207+ if EqualSid ( folder_owner , token_user ) != 0 {
208+ return Ok ( true ) ;
209+ }
191210
192- heap_buf. resize ( buffer_size as _ , 0 ) ;
193- }
194- } ;
211+ // Admin-group owned folders are considered owned by the current user, if they are in the admin group.
212+ if IsWellKnownSid ( folder_owner, WinBuiltinAdministratorsSid ) == 0 {
213+ return Ok ( false ) ;
214+ }
195215
196- let token_owner = ( * buf. as_ptr ( ) . cast :: < TOKEN_OWNER > ( ) ) . Owner ;
216+ let mut is_member = 0 ;
217+ if CheckTokenMembership ( std:: ptr:: null_mut ( ) , folder_owner, & mut is_member) == 0 {
218+ error ! ( "Couldn't check if user is an administrator" ) ;
219+ }
197220
198- // If the current user is the owner of the parent folder then they also
199- // own this file
200- if EqualSid ( folder_owner, token_owner) != 0 {
221+ if is_member != 0 {
201222 return Ok ( true ) ;
202223 }
203224
204- // Admin-group owned folders are considered owned by the current user, if they are in the admin group
205- if IsWellKnownSid ( token_owner, WinBuiltinAdministratorsSid ) == 0 {
225+ let mut elevation_type = TokenElevationTypeLimited ;
226+ let mut elevation_type_size = 0 ;
227+ if windows_sys:: Win32 :: Security :: GetTokenInformation (
228+ token,
229+ TokenElevationType ,
230+ ( & mut elevation_type as * mut TOKEN_ELEVATION_TYPE ) . cast ( ) ,
231+ mem:: size_of :: < TOKEN_ELEVATION_TYPE > ( ) as u32 ,
232+ & mut elevation_type_size,
233+ ) == 0
234+ || elevation_type != TokenElevationTypeLimited
235+ {
206236 return Ok ( false ) ;
207237 }
208238
239+ let linked_token_info = token_information ( token, TokenLinkedToken ) ?;
240+ let linked_token = ( * linked_token_info. as_ptr ( ) . cast :: < TOKEN_LINKED_TOKEN > ( ) ) . LinkedToken ;
241+ let linked_token = OwnedHandle :: from_raw_handle ( linked_token as _ ) ;
242+
209243 let mut is_member = 0 ;
210- if CheckTokenMembership ( std :: ptr :: null_mut ( ) , token_owner , & mut is_member) == 0 {
211- error ! ( "Couldn't check if user is an administrator" ) ;
244+ if CheckTokenMembership ( linked_token . as_raw_handle ( ) as _ , folder_owner , & mut is_member) == 0 {
245+ error ! ( "Couldn't check if elevated user is an administrator" ) ;
212246 }
213247
214248 Ok ( is_member != 0 )
0 commit comments