|
1 | 1 | #include "../git-compat-util.h"
|
2 | 2 | #include "win32.h"
|
| 3 | +#include <aclapi.h> |
3 | 4 | #include <conio.h>
|
4 | 5 | #include <wchar.h>
|
5 | 6 | #include "../strbuf.h"
|
@@ -2601,6 +2602,92 @@ static void setup_windows_environment(void)
|
2601 | 2602 | }
|
2602 | 2603 | }
|
2603 | 2604 |
|
| 2605 | +static PSID get_current_user_sid(void) |
| 2606 | +{ |
| 2607 | + HANDLE token; |
| 2608 | + DWORD len = 0; |
| 2609 | + PSID result = NULL; |
| 2610 | + |
| 2611 | + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) |
| 2612 | + return NULL; |
| 2613 | + |
| 2614 | + if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) { |
| 2615 | + TOKEN_USER *info = xmalloc((size_t)len); |
| 2616 | + if (GetTokenInformation(token, TokenUser, info, len, &len)) { |
| 2617 | + len = GetLengthSid(info->User.Sid); |
| 2618 | + result = xmalloc(len); |
| 2619 | + if (!CopySid(len, result, info->User.Sid)) { |
| 2620 | + error(_("failed to copy SID (%ld)"), |
| 2621 | + GetLastError()); |
| 2622 | + FREE_AND_NULL(result); |
| 2623 | + } |
| 2624 | + } |
| 2625 | + FREE_AND_NULL(info); |
| 2626 | + } |
| 2627 | + CloseHandle(token); |
| 2628 | + |
| 2629 | + return result; |
| 2630 | +} |
| 2631 | + |
| 2632 | +int is_path_owned_by_current_sid(const char *path) |
| 2633 | +{ |
| 2634 | + WCHAR wpath[MAX_PATH]; |
| 2635 | + PSID sid = NULL; |
| 2636 | + PSECURITY_DESCRIPTOR descriptor = NULL; |
| 2637 | + DWORD err; |
| 2638 | + |
| 2639 | + static wchar_t home[MAX_PATH]; |
| 2640 | + |
| 2641 | + int result = 0; |
| 2642 | + |
| 2643 | + if (xutftowcs_path(wpath, path) < 0) |
| 2644 | + return 0; |
| 2645 | + |
| 2646 | + /* |
| 2647 | + * On Windows, the home directory is owned by the administrator, but for |
| 2648 | + * all practical purposes, it belongs to the user. Do pretend that it is |
| 2649 | + * owned by the user. |
| 2650 | + */ |
| 2651 | + if (!*home) { |
| 2652 | + DWORD size = ARRAY_SIZE(home); |
| 2653 | + DWORD len = GetEnvironmentVariableW(L"HOME", home, size); |
| 2654 | + if (!len || len > size) |
| 2655 | + wcscpy(home, L"::N/A::"); |
| 2656 | + } |
| 2657 | + if (!wcsicmp(wpath, home)) |
| 2658 | + return 1; |
| 2659 | + |
| 2660 | + /* Get the owner SID */ |
| 2661 | + err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT, |
| 2662 | + OWNER_SECURITY_INFORMATION | |
| 2663 | + DACL_SECURITY_INFORMATION, |
| 2664 | + &sid, NULL, NULL, NULL, &descriptor); |
| 2665 | + |
| 2666 | + if (err != ERROR_SUCCESS) |
| 2667 | + error(_("failed to get owner for '%s' (%ld)"), path, err); |
| 2668 | + else if (sid && IsValidSid(sid)) { |
| 2669 | + /* Now, verify that the SID matches the current user's */ |
| 2670 | + static PSID current_user_sid; |
| 2671 | + |
| 2672 | + if (!current_user_sid) |
| 2673 | + current_user_sid = get_current_user_sid(); |
| 2674 | + |
| 2675 | + if (current_user_sid && |
| 2676 | + IsValidSid(current_user_sid) && |
| 2677 | + EqualSid(sid, current_user_sid)) |
| 2678 | + result = 1; |
| 2679 | + } |
| 2680 | + |
| 2681 | + /* |
| 2682 | + * We can release the security descriptor struct only now because `sid` |
| 2683 | + * actually points into this struct. |
| 2684 | + */ |
| 2685 | + if (descriptor) |
| 2686 | + LocalFree(descriptor); |
| 2687 | + |
| 2688 | + return result; |
| 2689 | +} |
| 2690 | + |
2604 | 2691 | int is_valid_win32_path(const char *path, int allow_literal_nul)
|
2605 | 2692 | {
|
2606 | 2693 | const char *p = path;
|
|
0 commit comments