@@ -9,15 +9,29 @@ use std::path::PathBuf;
99use std:: time:: Duration ;
1010use std:: time:: Instant ;
1111use windows_sys:: Win32 :: Foundation :: CloseHandle ;
12- use windows_sys:: Win32 :: Foundation :: LocalFree ;
1312use windows_sys:: Win32 :: Foundation :: ERROR_SUCCESS ;
1413use windows_sys:: Win32 :: Foundation :: HLOCAL ;
1514use windows_sys:: Win32 :: Foundation :: INVALID_HANDLE_VALUE ;
15+ use windows_sys:: Win32 :: Foundation :: LocalFree ;
16+ use windows_sys:: Win32 :: Security :: ACCESS_ALLOWED_ACE ;
17+ use windows_sys:: Win32 :: Security :: ACE_HEADER ;
18+ use windows_sys:: Win32 :: Security :: ACL ;
19+ use windows_sys:: Win32 :: Security :: ACL_SIZE_INFORMATION ;
20+ use windows_sys:: Win32 :: Security :: AclSizeInformation ;
1621use windows_sys:: Win32 :: Security :: Authorization :: GetNamedSecurityInfoW ;
1722use windows_sys:: Win32 :: Security :: Authorization :: GetSecurityInfo ;
23+ use windows_sys:: Win32 :: Security :: DACL_SECURITY_INFORMATION ;
24+ use windows_sys:: Win32 :: Security :: EqualSid ;
25+ use windows_sys:: Win32 :: Security :: GetAce ;
26+ use windows_sys:: Win32 :: Security :: GetAclInformation ;
27+ use windows_sys:: Win32 :: Security :: MapGenericMask ;
28+ use windows_sys:: Win32 :: Security :: GENERIC_MAPPING ;
1829use windows_sys:: Win32 :: Storage :: FileSystem :: CreateFileW ;
30+ use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_ALL_ACCESS ;
1931use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_APPEND_DATA ;
2032use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_FLAG_BACKUP_SEMANTICS ;
33+ use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_GENERIC_EXECUTE ;
34+ use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_GENERIC_READ ;
2135use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_GENERIC_WRITE ;
2236use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_SHARE_DELETE ;
2337use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_SHARE_READ ;
@@ -26,17 +40,6 @@ use windows_sys::Win32::Storage::FileSystem::FILE_WRITE_ATTRIBUTES;
2640use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_WRITE_DATA ;
2741use windows_sys:: Win32 :: Storage :: FileSystem :: FILE_WRITE_EA ;
2842use windows_sys:: Win32 :: Storage :: FileSystem :: OPEN_EXISTING ;
29- const GENERIC_ALL_MASK : u32 = 0x1000_0000 ;
30- const GENERIC_WRITE_MASK : u32 = 0x4000_0000 ;
31- use windows_sys:: Win32 :: Security :: AclSizeInformation ;
32- use windows_sys:: Win32 :: Security :: EqualSid ;
33- use windows_sys:: Win32 :: Security :: GetAce ;
34- use windows_sys:: Win32 :: Security :: GetAclInformation ;
35- use windows_sys:: Win32 :: Security :: ACCESS_ALLOWED_ACE ;
36- use windows_sys:: Win32 :: Security :: ACE_HEADER ;
37- use windows_sys:: Win32 :: Security :: ACL ;
38- use windows_sys:: Win32 :: Security :: ACL_SIZE_INFORMATION ;
39- use windows_sys:: Win32 :: Security :: DACL_SECURITY_INFORMATION ;
4043
4144// Preflight scan limits
4245const MAX_ITEMS_PER_DIR : i32 = 1000 ;
@@ -304,7 +307,7 @@ pub fn world_writable_warning_details(
304307 }
305308}
306309// Fast mask-based check: does the DACL contain any ACCESS_ALLOWED ACE for
307- // Everyone that includes generic or specific write bits? Skips inherit-only
310+ // Everyone that grants write after generic bits are expanded ? Skips inherit-only
308311// ACEs (do not apply to the current object).
309312unsafe fn dacl_quick_world_write_mask_allows ( p_dacl : * mut ACL , psid_world : * mut c_void ) -> bool {
310313 if p_dacl. is_null ( ) {
@@ -321,6 +324,12 @@ unsafe fn dacl_quick_world_write_mask_allows(p_dacl: *mut ACL, psid_world: *mut
321324 if ok == 0 {
322325 return false ;
323326 }
327+ let mapping = GENERIC_MAPPING {
328+ GenericRead : FILE_GENERIC_READ ,
329+ GenericWrite : FILE_GENERIC_WRITE ,
330+ GenericExecute : FILE_GENERIC_EXECUTE ,
331+ GenericAll : FILE_ALL_ACCESS ,
332+ } ;
324333 for i in 0 ..( info. AceCount as usize ) {
325334 let mut p_ace: * mut c_void = std:: ptr:: null_mut ( ) ;
326335 if GetAce ( p_dacl as * const ACL , i as u32 , & mut p_ace) == 0 {
@@ -337,19 +346,16 @@ unsafe fn dacl_quick_world_write_mask_allows(p_dacl: *mut ACL, psid_world: *mut
337346 let base = p_ace as usize ;
338347 let sid_ptr =
339348 ( base + std:: mem:: size_of :: < ACE_HEADER > ( ) + std:: mem:: size_of :: < u32 > ( ) ) as * mut c_void ; // skip header + mask
340- if EqualSid ( sid_ptr, psid_world) != 0 {
341- let ace = & * ( p_ace as * const ACCESS_ALLOWED_ACE ) ;
342- let mask = ace. Mask ;
343- let writey = FILE_GENERIC_WRITE
344- | FILE_WRITE_DATA
345- | FILE_APPEND_DATA
346- | FILE_WRITE_EA
347- | FILE_WRITE_ATTRIBUTES
348- | GENERIC_WRITE_MASK
349- | GENERIC_ALL_MASK ;
350- if ( mask & writey) != 0 {
351- return true ;
352- }
349+ if EqualSid ( sid_ptr, psid_world) == 0 {
350+ continue ;
351+ }
352+ let ace = & * ( p_ace as * const ACCESS_ALLOWED_ACE ) ;
353+ let mut mask = ace. Mask ;
354+ // Expand generic bits to concrete file rights before checking for write.
355+ MapGenericMask ( & mut mask, & mapping) ;
356+ let write_mask = FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES ;
357+ if ( mask & write_mask) != 0 {
358+ return true ;
353359 }
354360 }
355361 false
0 commit comments