mirror of
https://github.com/git/git.git
synced 2025-12-12 20:36:24 +01:00
mingw: special-case administrators even more
The check for dubious ownership has one particular quirk on Windows: if running as an administrator, files owned by the Administrators _group_ are considered owned by the user. The rationale for that is: When running in elevated mode, Git creates files that aren't owned by the individual user but by the Administrators group. There is yet another quirk, though: The check I introduced to determine whether the current user is an administrator uses the `CheckTokenMembership()` function with the current process token. And that check only succeeds when running in elevated mode! Let's be a bit more lenient here and look harder whether the current user is an administrator. We do this by looking for a so-called "linked token". That token exists when administrators run in non-elevated mode, and can be used to create a new process in elevated mode. And feeding _that_ token to the `CheckTokenMembership()` function succeeds! Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
683c54c999
commit
03a4e46d12
@@ -2826,31 +2826,44 @@ static void setup_windows_environment(void)
|
||||
}
|
||||
}
|
||||
|
||||
static PSID get_current_user_sid(void)
|
||||
static void get_current_user_sid(PSID *sid, HANDLE *linked_token)
|
||||
{
|
||||
HANDLE token;
|
||||
DWORD len = 0;
|
||||
PSID result = NULL;
|
||||
TOKEN_ELEVATION_TYPE elevationType;
|
||||
DWORD size;
|
||||
|
||||
*sid = NULL;
|
||||
*linked_token = NULL;
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
|
||||
TOKEN_USER *info = xmalloc((size_t)len);
|
||||
if (GetTokenInformation(token, TokenUser, info, len, &len)) {
|
||||
len = GetLengthSid(info->User.Sid);
|
||||
result = xmalloc(len);
|
||||
if (!CopySid(len, result, info->User.Sid)) {
|
||||
*sid = xmalloc(len);
|
||||
if (!CopySid(len, *sid, info->User.Sid)) {
|
||||
error(_("failed to copy SID (%ld)"),
|
||||
GetLastError());
|
||||
FREE_AND_NULL(result);
|
||||
FREE_AND_NULL(*sid);
|
||||
}
|
||||
}
|
||||
FREE_AND_NULL(info);
|
||||
}
|
||||
CloseHandle(token);
|
||||
|
||||
return result;
|
||||
if (GetTokenInformation(token, TokenElevationType, &elevationType, sizeof(elevationType), &size) &&
|
||||
elevationType == TokenElevationTypeLimited) {
|
||||
/*
|
||||
* The current process is run by a member of the Administrators
|
||||
* group, but is not running elevated.
|
||||
*/
|
||||
if (!GetTokenInformation(token, TokenLinkedToken, linked_token, sizeof(*linked_token), &size))
|
||||
linked_token = NULL; /* there is no linked token */
|
||||
}
|
||||
|
||||
CloseHandle(token);
|
||||
}
|
||||
|
||||
static BOOL user_sid_to_user_name(PSID sid, LPSTR *str)
|
||||
@@ -2931,18 +2944,22 @@ int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
|
||||
else if (sid && IsValidSid(sid)) {
|
||||
/* Now, verify that the SID matches the current user's */
|
||||
static PSID current_user_sid;
|
||||
static HANDLE linked_token;
|
||||
BOOL is_member;
|
||||
|
||||
if (!current_user_sid)
|
||||
current_user_sid = get_current_user_sid();
|
||||
get_current_user_sid(¤t_user_sid, &linked_token);
|
||||
|
||||
if (current_user_sid &&
|
||||
IsValidSid(current_user_sid) &&
|
||||
EqualSid(sid, current_user_sid))
|
||||
result = 1;
|
||||
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
|
||||
CheckTokenMembership(NULL, sid, &is_member) &&
|
||||
is_member)
|
||||
((CheckTokenMembership(NULL, sid, &is_member) &&
|
||||
is_member) ||
|
||||
(linked_token &&
|
||||
CheckTokenMembership(linked_token, sid, &is_member) &&
|
||||
is_member)))
|
||||
/*
|
||||
* If owned by the Administrators group, and the
|
||||
* current user is an administrator, we consider that
|
||||
|
||||
Reference in New Issue
Block a user