diff options
author | Johannes Schindelin <johannes.schindelin@gmx.de> | 2019-06-19 12:59:27 +0200 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2019-08-13 17:56:06 +0100 |
commit | cb1439c9d32c059ee93216637a6d155306f76ab3 (patch) | |
tree | 76f15274fb66652dba8d29f5aad0c6c456b84e56 /src/path.c | |
parent | 5774b2b13468aa3c2e7e604dd348357f6842c56a (diff) | |
download | libgit2-cb1439c9d32c059ee93216637a6d155306f76ab3.tar.gz |
config: validate ownership of C:\ProgramData\Git\config before using it
When the VirtualStore feature is in effect, it is safe to let random
users write into C:\ProgramData because other users won't see those
files. This seemed to be the case when we introduced support for
C:\ProgramData\Git\config.
However, when that feature is not in effect (which seems to be the case
in newer Windows 10 versions), we'd rather not use those files unless
they come from a trusted source, such as an administrator.
This change imitates the strategy chosen by PowerShell's native OpenSSH
port to Windows regarding host key files: if a system file is owned
neither by an administrator, a system account, or the current user, it
is ignored.
Diffstat (limited to 'src/path.c')
-rw-r--r-- | src/path.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/path.c b/src/path.c index 41232c2f6..150e09eb6 100644 --- a/src/path.c +++ b/src/path.c @@ -14,6 +14,7 @@ #include "win32/w32_buffer.h" #include "win32/w32_util.h" #include "win32/version.h" +#include <AclAPI.h> #else #include <dirent.h> #endif @@ -1946,3 +1947,79 @@ done: git_buf_dispose(&path); return supported; } + +int git_path_validate_system_file_ownership(const char *path) +{ +#ifndef GIT_WIN32 + GIT_UNUSED(path); + return GIT_OK; +#else + git_win32_path buf; + PSID owner_sid; + PSECURITY_DESCRIPTOR descriptor = NULL; + HANDLE token; + TOKEN_USER *info = NULL; + DWORD err, len; + int ret; + + if (git_win32_path_from_utf8(buf, path) < 0) + return -1; + + err = GetNamedSecurityInfoW(buf, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION, + &owner_sid, NULL, NULL, NULL, &descriptor); + + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) { + ret = GIT_ENOTFOUND; + goto cleanup; + } + + if (err != ERROR_SUCCESS) { + git_error_set(GIT_ERROR_OS, "failed to get security information"); + ret = GIT_ERROR; + goto cleanup; + } + + if (!IsValidSid(owner_sid)) { + git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is unknown"); + ret = GIT_ERROR; + goto cleanup; + } + + if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) || + IsWellKnownSid(owner_sid, WinLocalSystemSid)) { + ret = GIT_OK; + goto cleanup; + } + + /* Obtain current user's SID */ + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) && + !GetTokenInformation(token, TokenUser, NULL, 0, &len)) { + info = git__malloc(len); + GIT_ERROR_CHECK_ALLOC(info); + if (!GetTokenInformation(token, TokenUser, info, len, &len)) { + git__free(info); + info = NULL; + } + } + + /* + * If the file is owned by the same account that is running the current + * process, it's okay to read from that file. + */ + if (info && EqualSid(owner_sid, info->User.Sid)) + ret = GIT_OK; + else { + git_error_set(GIT_ERROR_INVALID, "programdata configuration file owner is not valid"); + ret = GIT_ERROR; + } + free(info); + +cleanup: + if (descriptor) + LocalFree(descriptor); + + return ret; +#endif +} |