diff options
author | Ron Yorston <rmy@pobox.com> | 2023-01-16 11:03:30 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2023-01-16 11:03:30 +0000 |
commit | 88965fe20a26e17247e6ffc10692fe202d77f1fa (patch) | |
tree | 16109de1bf8fb14d04c3c5f4176ec20c77ea7f6d | |
parent | 857b0732b9268c049e94bb3220fbb078f662ab02 (diff) | |
download | busybox-w32-88965fe20a26e17247e6ffc10692fe202d77f1fa.tar.gz busybox-w32-88965fe20a26e17247e6ffc10692fe202d77f1fa.tar.bz2 busybox-w32-88965fe20a26e17247e6ffc10692fe202d77f1fa.zip |
win32: use ACL check to clarify write permission
On Microsoft Windows a user's home directory doesn't belong to
them: it actually belongs to the 'system' user. stat(2) was
only using ownership to determine write permissions, so it seemed
that the user was unable to write to their own home directory.
Use a call to AccessCheck() to determine if files can be accessed
due to an entry in their ACL. User home directories and a few other
files (e.g. C:/Users/Public) now have the correct write permission.
This feature is enabled by FEATURE_EXTRA_FILE_DATA.
Costs 220-256 bytes.
(GitHub issue #280)
-rw-r--r-- | win32/mingw.c | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index a2a736d52..bfc1531fb 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -494,11 +494,13 @@ static int has_exec_format(const char *name) | |||
494 | } | 494 | } |
495 | 495 | ||
496 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | 496 | #if ENABLE_FEATURE_EXTRA_FILE_DATA |
497 | static uid_t file_owner(HANDLE fh) | 497 | static uid_t file_owner(HANDLE fh, struct mingw_stat *buf) |
498 | { | 498 | { |
499 | PSID pSidOwner; | 499 | PSID pSidOwner; |
500 | PACL pDACL; | ||
500 | PSECURITY_DESCRIPTOR pSD; | 501 | PSECURITY_DESCRIPTOR pSD; |
501 | static PTOKEN_USER user = NULL; | 502 | static PTOKEN_USER user = NULL; |
503 | static HANDLE impersonate = INVALID_HANDLE_VALUE; | ||
502 | static int initialised = 0; | 504 | static int initialised = 0; |
503 | uid_t uid = 0; | 505 | uid_t uid = 0; |
504 | DWORD *ptr; | 506 | DWORD *ptr; |
@@ -519,13 +521,16 @@ static uid_t file_owner(HANDLE fh) | |||
519 | DWORD ret = 0; | 521 | DWORD ret = 0; |
520 | 522 | ||
521 | initialised = 1; | 523 | initialised = 1; |
522 | if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { | 524 | if (OpenProcessToken(GetCurrentProcess(), |
525 | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_DUPLICATE | | ||
526 | STANDARD_RIGHTS_READ, &token)) { | ||
523 | GetTokenInformation(token, TokenUser, NULL, 0, &ret); | 527 | GetTokenInformation(token, TokenUser, NULL, 0, &ret); |
524 | if (ret <= 0 || (user=malloc(ret)) == NULL || | 528 | if (ret <= 0 || (user=malloc(ret)) == NULL || |
525 | !GetTokenInformation(token, TokenUser, user, ret, &ret)) { | 529 | !GetTokenInformation(token, TokenUser, user, ret, &ret)) { |
526 | free(user); | 530 | free(user); |
527 | user = NULL; | 531 | user = NULL; |
528 | } | 532 | } |
533 | DuplicateToken(token, SecurityImpersonation, &impersonate); | ||
529 | CloseHandle(token); | 534 | CloseHandle(token); |
530 | } | 535 | } |
531 | } | 536 | } |
@@ -534,8 +539,10 @@ static uid_t file_owner(HANDLE fh) | |||
534 | return DEFAULT_UID; | 539 | return DEFAULT_UID; |
535 | 540 | ||
536 | /* get SID of file's owner */ | 541 | /* get SID of file's owner */ |
537 | if (GetSecurityInfo(fh, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, | 542 | if (GetSecurityInfo(fh, SE_FILE_OBJECT, |
538 | &pSidOwner, NULL, NULL, NULL, &pSD) != ERROR_SUCCESS) | 543 | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | |
544 | DACL_SECURITY_INFORMATION, | ||
545 | &pSidOwner, NULL, &pDACL, NULL, &pSD) != ERROR_SUCCESS) | ||
539 | return 0; | 546 | return 0; |
540 | 547 | ||
541 | if (EqualSid(pSidOwner, user->User.Sid)) { | 548 | if (EqualSid(pSidOwner, user->User.Sid)) { |
@@ -548,33 +555,28 @@ static uid_t file_owner(HANDLE fh) | |||
548 | if (ptr[6] >= 500 && ptr[6] < DEFAULT_UID) | 555 | if (ptr[6] >= 500 && ptr[6] < DEFAULT_UID) |
549 | uid = (uid_t)ptr[6]; | 556 | uid = (uid_t)ptr[6]; |
550 | } | 557 | } |
551 | LocalFree(pSD); | ||
552 | return uid; | ||
553 | 558 | ||
554 | #if 0 | 559 | if (uid != DEFAULT_UID && impersonate != INVALID_HANDLE_VALUE) { |
555 | /* this is how it would be done properly using the API */ | 560 | static GENERIC_MAPPING mapping = { |
556 | { | 561 | FILE_GENERIC_READ, FILE_GENERIC_WRITE, |
557 | PSID_IDENTIFIER_AUTHORITY auth; | 562 | FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS |
558 | unsigned char *count; | ||
559 | PDWORD subauth; | ||
560 | unsigned char nt_auth[] = { | ||
561 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x05 | ||
562 | }; | 563 | }; |
563 | 564 | PRIVILEGE_SET privileges; | |
564 | if (IsValidSid(pSidOwner) ) { | 565 | DWORD grantedAccess; |
565 | auth = GetSidIdentifierAuthority(pSidOwner); | 566 | DWORD privilegesLength = sizeof(privileges); |
566 | count = GetSidSubAuthorityCount(pSidOwner); | 567 | DWORD genericAccessRights = MAXIMUM_ALLOWED; |
567 | subauth = GetSidSubAuthority(pSidOwner, 0); | 568 | BOOL result; |
568 | if (memcmp(auth, nt_auth, sizeof(nt_auth)) == 0 && | 569 | |
569 | *count == 5 && *subauth == 21) { | 570 | if (AccessCheck(pSD, impersonate, genericAccessRights, |
570 | subauth = GetSidSubAuthority(pSidOwner, 4); | 571 | &mapping, &privileges, &privilegesLength, |
571 | if (*subauth >= 500 && *subauth < DEFAULT_UID) | 572 | &grantedAccess, &result)) { |
572 | uid = (uid_t)*subauth; | 573 | if (result && (grantedAccess & 0x1200af) == 0x1200af) { |
574 | buf->st_mode |= (buf->st_mode & S_IRWXU) >> 6; | ||
573 | } | 575 | } |
574 | } | 576 | } |
575 | return uid; | ||
576 | } | 577 | } |
577 | #endif | 578 | LocalFree(pSD); |
579 | return uid; | ||
578 | } | 580 | } |
579 | #endif | 581 | #endif |
580 | 582 | ||
@@ -711,7 +713,8 @@ static int do_lstat(int follow, const char *file_name, struct mingw_stat *buf) | |||
711 | count_subdirs(file_name) : | 713 | count_subdirs(file_name) : |
712 | hdata.nNumberOfLinks; | 714 | hdata.nNumberOfLinks; |
713 | } | 715 | } |
714 | buf->st_uid = buf->st_gid = file_owner(fh); | 716 | |
717 | buf->st_uid = buf->st_gid = file_owner(fh, buf); | ||
715 | CloseHandle(fh); | 718 | CloseHandle(fh); |
716 | } | 719 | } |
717 | else { | 720 | else { |