Skip to content

Commit 2608f2e

Browse files
committed
fixup! Windows: add support for a Windows-wide configuration
Let's refactor the `validate_system_file_ownership()` a bit, not only to clarify what is done, but also to prepare for maybe adding a slighty more expensive check: it is possible that the file `C:\ProgramData\Git\config` is owned by the local administrator (who has a different SID than the `Administrators` group). Signed-off-by: Johannes Schindelin <[email protected]>
1 parent de7827b commit 2608f2e

File tree

1 file changed

+56
-48
lines changed

1 file changed

+56
-48
lines changed

compat/mingw.c

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3299,6 +3299,40 @@ int uname(struct utsname *buf)
32993299
return 0;
33003300
}
33013301

3302+
/*
3303+
* Determines whether the SID refers to an administrator or the current user.
3304+
*
3305+
* For convenience, the `info` parameter allows avoiding multiple calls to
3306+
* `OpenProcessToken()` if this function is called more than once. The initial
3307+
* value of `*info` is expected to be `NULL`, and it needs to be released via
3308+
* `free()` after the last call to this function.
3309+
*
3310+
* Returns 0 if the SID indicates a dubious owner of system files, otherwise 1.
3311+
*/
3312+
static int is_valid_system_file_owner(PSID sid, TOKEN_USER **info)
3313+
{
3314+
HANDLE token;
3315+
DWORD len;
3316+
3317+
if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) ||
3318+
IsWellKnownSid(sid, WinLocalSystemSid))
3319+
return 1;
3320+
3321+
/* Obtain current user's SID */
3322+
if (!*info &&
3323+
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
3324+
if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
3325+
*info = xmalloc((size_t)len);
3326+
if (!GetTokenInformation(token, TokenUser, *info, len,
3327+
&len))
3328+
FREE_AND_NULL(*info);
3329+
}
3330+
CloseHandle(token);
3331+
}
3332+
3333+
return *info && EqualSid(sid, (*info)->User.Sid) ? 1 : 0;
3334+
}
3335+
33023336
/*
33033337
* Verify that the file in question is owned by an administrator or system
33043338
* account, or at least by the current user.
@@ -3309,11 +3343,10 @@ int uname(struct utsname *buf)
33093343
static int validate_system_file_ownership(const char *path)
33103344
{
33113345
WCHAR wpath[MAX_LONG_PATH];
3312-
PSID owner_sid = NULL;
3346+
PSID owner_sid = NULL, problem_sid = NULL;
33133347
PSECURITY_DESCRIPTOR descriptor = NULL;
3314-
HANDLE token;
33153348
TOKEN_USER* info = NULL;
3316-
DWORD err, len;
3349+
DWORD err;
33173350
int ret;
33183351

33193352
if (xutftowcs_long_path(wpath, path) < 0)
@@ -3325,63 +3358,37 @@ static int validate_system_file_ownership(const char *path)
33253358
&owner_sid, NULL, NULL, NULL, &descriptor);
33263359

33273360
/* if the file does not exist, it does not have a valid owner */
3328-
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
3361+
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
33293362
ret = 0;
3330-
owner_sid = NULL;
3331-
goto finish_validation;
3332-
}
3333-
3334-
if (err != ERROR_SUCCESS) {
3363+
else if (err != ERROR_SUCCESS)
33353364
ret = error(_("failed to validate '%s' (%ld)"), path, err);
3336-
owner_sid = NULL;
3337-
goto finish_validation;
3338-
}
3339-
3340-
if (!IsValidSid(owner_sid)) {
3365+
else if (!IsValidSid(owner_sid))
33413366
ret = error(_("invalid owner: '%s'"), path);
3342-
goto finish_validation;
3343-
}
3344-
3345-
if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
3346-
IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
3367+
else if (is_valid_system_file_owner(owner_sid, &info))
33473368
ret = 1;
3348-
goto finish_validation;
3349-
}
3350-
3351-
/* Obtain current user's SID */
3352-
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) &&
3353-
!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
3354-
info = xmalloc((size_t)len);
3355-
if (!GetTokenInformation(token, TokenUser, info, len, &len))
3356-
FREE_AND_NULL(info);
3357-
}
3358-
3359-
if (!info)
3360-
ret = 0;
33613369
else {
3362-
ret = EqualSid(owner_sid, info->User.Sid) ? 1 : 0;
3363-
free(info);
3370+
ret = 0;
3371+
problem_sid = owner_sid;
33643372
}
33653373

3366-
finish_validation:
3367-
if (!ret && owner_sid) {
3374+
if (!ret && problem_sid) {
33683375
#define MAX_NAME_OR_DOMAIN 256
3369-
wchar_t owner_name[MAX_NAME_OR_DOMAIN];
3370-
wchar_t owner_domain[MAX_NAME_OR_DOMAIN];
3376+
wchar_t name[MAX_NAME_OR_DOMAIN];
3377+
wchar_t domain[MAX_NAME_OR_DOMAIN];
33713378
wchar_t *p = NULL;
33723379
DWORD size = MAX_NAME_OR_DOMAIN;
33733380
SID_NAME_USE type;
3374-
char name[3 * MAX_NAME_OR_DOMAIN + 1];
3381+
char utf[3 * MAX_NAME_OR_DOMAIN + 1];
33753382

3376-
if (!LookupAccountSidW(NULL, owner_sid, owner_name, &size,
3377-
owner_domain, &size, &type) ||
3378-
xwcstoutf(name, owner_name, ARRAY_SIZE(name)) < 0) {
3379-
if (!ConvertSidToStringSidW(owner_sid, &p))
3380-
strlcpy(name, "(unknown)", ARRAY_SIZE(name));
3383+
if (!LookupAccountSidW(NULL, problem_sid, name, &size,
3384+
domain, &size, &type) ||
3385+
xwcstoutf(utf, name, ARRAY_SIZE(utf)) < 0) {
3386+
if (!ConvertSidToStringSidW(problem_sid, &p))
3387+
strlcpy(utf, "(unknown)", ARRAY_SIZE(utf));
33813388
else {
3382-
if (xwcstoutf(name, p, ARRAY_SIZE(name)) < 0)
3383-
strlcpy(name, "(some user)",
3384-
ARRAY_SIZE(name));
3389+
if (xwcstoutf(utf, p, ARRAY_SIZE(utf)) < 0)
3390+
strlcpy(utf, "(some user)",
3391+
ARRAY_SIZE(utf));
33853392
LocalFree(p);
33863393
}
33873394
}
@@ -3390,11 +3397,12 @@ static int validate_system_file_ownership(const char *path)
33903397
"For security reasons, it is therefore ignored.\n"
33913398
"To fix this, please transfer ownership to an "
33923399
"admininstrator."),
3393-
path, name);
3400+
path, utf);
33943401
}
33953402

33963403
if (descriptor)
33973404
LocalFree(descriptor);
3405+
free(info);
33983406

33993407
return ret;
34003408
}

0 commit comments

Comments
 (0)