mirror of
https://github.com/git/git.git
synced 2026-01-09 17:46:37 +00: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;
|
HANDLE token;
|
||||||
DWORD len = 0;
|
DWORD len = 0;
|
||||||
PSID result = NULL;
|
TOKEN_ELEVATION_TYPE elevationType;
|
||||||
|
DWORD size;
|
||||||
|
|
||||||
|
*sid = NULL;
|
||||||
|
*linked_token = NULL;
|
||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
|
||||||
return NULL;
|
return;
|
||||||
|
|
||||||
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
|
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
|
||||||
TOKEN_USER *info = xmalloc((size_t)len);
|
TOKEN_USER *info = xmalloc((size_t)len);
|
||||||
if (GetTokenInformation(token, TokenUser, info, len, &len)) {
|
if (GetTokenInformation(token, TokenUser, info, len, &len)) {
|
||||||
len = GetLengthSid(info->User.Sid);
|
len = GetLengthSid(info->User.Sid);
|
||||||
result = xmalloc(len);
|
*sid = xmalloc(len);
|
||||||
if (!CopySid(len, result, info->User.Sid)) {
|
if (!CopySid(len, *sid, info->User.Sid)) {
|
||||||
error(_("failed to copy SID (%ld)"),
|
error(_("failed to copy SID (%ld)"),
|
||||||
GetLastError());
|
GetLastError());
|
||||||
FREE_AND_NULL(result);
|
FREE_AND_NULL(*sid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE_AND_NULL(info);
|
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)
|
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)) {
|
else if (sid && IsValidSid(sid)) {
|
||||||
/* Now, verify that the SID matches the current user's */
|
/* Now, verify that the SID matches the current user's */
|
||||||
static PSID current_user_sid;
|
static PSID current_user_sid;
|
||||||
|
static HANDLE linked_token;
|
||||||
BOOL is_member;
|
BOOL is_member;
|
||||||
|
|
||||||
if (!current_user_sid)
|
if (!current_user_sid)
|
||||||
current_user_sid = get_current_user_sid();
|
get_current_user_sid(¤t_user_sid, &linked_token);
|
||||||
|
|
||||||
if (current_user_sid &&
|
if (current_user_sid &&
|
||||||
IsValidSid(current_user_sid) &&
|
IsValidSid(current_user_sid) &&
|
||||||
EqualSid(sid, current_user_sid))
|
EqualSid(sid, current_user_sid))
|
||||||
result = 1;
|
result = 1;
|
||||||
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
|
else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
|
||||||
CheckTokenMembership(NULL, sid, &is_member) &&
|
((CheckTokenMembership(NULL, sid, &is_member) &&
|
||||||
is_member)
|
is_member) ||
|
||||||
|
(linked_token &&
|
||||||
|
CheckTokenMembership(linked_token, sid, &is_member) &&
|
||||||
|
is_member)))
|
||||||
/*
|
/*
|
||||||
* If owned by the Administrators group, and the
|
* If owned by the Administrators group, and the
|
||||||
* current user is an administrator, we consider that
|
* current user is an administrator, we consider that
|
||||||
|
|||||||
Reference in New Issue
Block a user