summaryrefslogtreecommitdiff
path: root/compat
diff options
context:
space:
mode:
Diffstat (limited to 'compat')
-rw-r--r--compat/mingw.c87
-rw-r--r--compat/mingw.h7
2 files changed, 94 insertions, 0 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index 58f347d6ae..6fe80fdf01 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1,5 +1,6 @@
#include "../git-compat-util.h"
#include "win32.h"
+#include <aclapi.h>
#include <conio.h>
#include <wchar.h>
#include "../strbuf.h"
@@ -2645,6 +2646,92 @@ static void setup_windows_environment(void)
}
}
+static PSID get_current_user_sid(void)
+{
+ HANDLE token;
+ DWORD len = 0;
+ PSID result = NULL;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
+ return NULL;
+
+ 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)) {
+ error(_("failed to copy SID (%ld)"),
+ GetLastError());
+ FREE_AND_NULL(result);
+ }
+ }
+ FREE_AND_NULL(info);
+ }
+ CloseHandle(token);
+
+ return result;
+}
+
+int is_path_owned_by_current_sid(const char *path)
+{
+ WCHAR wpath[MAX_PATH];
+ PSID sid = NULL;
+ PSECURITY_DESCRIPTOR descriptor = NULL;
+ DWORD err;
+
+ static wchar_t home[MAX_PATH];
+
+ int result = 0;
+
+ if (xutftowcs_path(wpath, path) < 0)
+ return 0;
+
+ /*
+ * On Windows, the home directory is owned by the administrator, but for
+ * all practical purposes, it belongs to the user. Do pretend that it is
+ * owned by the user.
+ */
+ if (!*home) {
+ DWORD size = ARRAY_SIZE(home);
+ DWORD len = GetEnvironmentVariableW(L"HOME", home, size);
+ if (!len || len > size)
+ wcscpy(home, L"::N/A::");
+ }
+ if (!wcsicmp(wpath, home))
+ return 1;
+
+ /* Get the owner SID */
+ err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ &sid, NULL, NULL, NULL, &descriptor);
+
+ if (err != ERROR_SUCCESS)
+ error(_("failed to get owner for '%s' (%ld)"), path, err);
+ else if (sid && IsValidSid(sid)) {
+ /* Now, verify that the SID matches the current user's */
+ static PSID current_user_sid;
+
+ if (!current_user_sid)
+ current_user_sid = get_current_user_sid();
+
+ if (current_user_sid &&
+ IsValidSid(current_user_sid) &&
+ EqualSid(sid, current_user_sid))
+ result = 1;
+ }
+
+ /*
+ * We can release the security descriptor struct only now because `sid`
+ * actually points into this struct.
+ */
+ if (descriptor)
+ LocalFree(descriptor);
+
+ return result;
+}
+
int is_valid_win32_path(const char *path, int allow_literal_nul)
{
const char *p = path;
diff --git a/compat/mingw.h b/compat/mingw.h
index 6074a3d3ce..494cc8de92 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -457,6 +457,13 @@ char *mingw_query_user_email(void);
#endif
/**
+ * Verifies that the specified path is owned by the user running the
+ * current process.
+ */
+int is_path_owned_by_current_sid(const char *path);
+#define is_path_owned_by_current_user is_path_owned_by_current_sid
+
+/**
* Verifies that the given path is a valid one on Windows.
*
* In particular, path segments are disallowed which