From be29b86129e888517f852a8e6c2c905b70daefcb Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 Jul 2022 15:20:59 -0400 Subject: fs: refactor file ownership checks Refactor the file ownership checks so that callers can provide discrete information about the ownership expectations to a single function. --- src/config.c | 7 +++- src/path.c | 130 +++++++++++++++++++---------------------------------------- src/path.h | 21 ++++------ 3 files changed, 54 insertions(+), 104 deletions(-) diff --git a/src/config.c b/src/config.c index 489eee643..048de1467 100644 --- a/src/config.c +++ b/src/config.c @@ -1117,13 +1117,16 @@ int git_config_find_system(git_buf *path) int git_config_find_programdata(git_buf *path) { - int ret; + git_path_owner_t owner_level = + GIT_PATH_OWNER_CURRENT_USER | + GIT_PATH_OWNER_ADMINISTRATOR; bool is_safe; + int ret; if ((ret = git_buf_sanitize(path)) < 0 || (ret = git_sysdir_find_programdata_file(path, GIT_CONFIG_FILENAME_PROGRAMDATA)) < 0 || - (ret = git_path_owner_is_system_or_current_user(&is_safe, path->ptr)) < 0) + (ret = git_path_owner_is(&is_safe, path->ptr, owner_level)) < 0) return ret; if (!is_safe) { diff --git a/src/path.c b/src/path.c index e9c30f4a6..efd094298 100644 --- a/src/path.c +++ b/src/path.c @@ -2118,74 +2118,41 @@ static int file_owner_sid(PSID *out, const char *path) return error; } -int git_path_owner_is_current_user(bool *out, const char *path) +int git_path_owner_is( + bool *out, + const char *path, + git_path_owner_t owner_type) { PSID owner_sid = NULL, user_sid = NULL; - int error = -1; + int error; if (mock_owner) { - *out = (mock_owner == GIT_PATH_OWNER_CURRENT_USER); + *out = ((mock_owner & owner_type) != 0); return 0; } - if ((error = file_owner_sid(&owner_sid, path)) < 0 || - (error = current_user_sid(&user_sid)) < 0) + if ((error = file_owner_sid(&owner_sid, path)) < 0) goto done; - *out = EqualSid(owner_sid, user_sid); - error = 0; - -done: - git__free(owner_sid); - git__free(user_sid); - return error; -} - -int git_path_owner_is_system(bool *out, const char *path) -{ - PSID owner_sid; - - if (mock_owner) { - *out = (mock_owner == GIT_PATH_OWNER_ADMINISTRATOR); - return 0; - } - - if (file_owner_sid(&owner_sid, path) < 0) - return -1; - - *out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) || - IsWellKnownSid(owner_sid, WinLocalSystemSid); - - git__free(owner_sid); - return 0; -} - -int git_path_owner_is_system_or_current_user(bool *out, const char *path) -{ - PSID owner_sid = NULL, user_sid = NULL; - int error = -1; + if ((owner_type & GIT_PATH_OWNER_CURRENT_USER) != 0) { + if ((error = current_user_sid(&user_sid)) < 0) + goto done; - if (mock_owner) { - *out = (mock_owner == GIT_PATH_OWNER_ADMINISTRATOR || - mock_owner == GIT_PATH_OWNER_CURRENT_USER); - return 0; + if (EqualSid(owner_sid, user_sid)) { + *out = true; + goto done; + } } - if (file_owner_sid(&owner_sid, path) < 0) - goto done; - - if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) || - IsWellKnownSid(owner_sid, WinLocalSystemSid)) { - *out = 1; - error = 0; - goto done; + if ((owner_type & GIT_PATH_OWNER_ADMINISTRATOR) != 0) { + if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) || + IsWellKnownSid(owner_sid, WinLocalSystemSid)) { + *out = true; + goto done; + } } - if (current_user_sid(&user_sid) < 0) - goto done; - - *out = EqualSid(owner_sid, user_sid); - error = 0; + *out = false; done: git__free(owner_sid); @@ -2195,10 +2162,25 @@ done: #else -static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uids_len) +int git_path_owner_is( + bool *out, + const char *path, + git_path_owner_t owner_type) { + uid_t uids[2] = { 0 }; + size_t uid_count = 0, i; struct stat st; - size_t i; + + if (mock_owner) { + *out = ((mock_owner & owner_type) != 0); + return 0; + } + + if (owner_type & GIT_PATH_OWNER_CURRENT_USER) + uids[uid_count++] = geteuid(); + + if (owner_type & GIT_PATH_OWNER_ADMINISTRATOR) + uids[uid_count++] = 0; *out = false; @@ -2210,7 +2192,7 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid return -1; } - for (i = 0; i < uids_len; i++) { + for (i = 0; i < uid_count; i++) { if (uids[i] == st.st_uid) { *out = true; break; @@ -2219,42 +2201,14 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid return 0; } +#endif int git_path_owner_is_current_user(bool *out, const char *path) { - uid_t userid = geteuid(); - - if (mock_owner) { - *out = (mock_owner == GIT_PATH_OWNER_CURRENT_USER); - return 0; - } - - return fs_path_owner_is(out, path, &userid, 1); + return git_path_owner_is(out, path, GIT_PATH_OWNER_CURRENT_USER); } int git_path_owner_is_system(bool *out, const char *path) { - uid_t userid = 0; - - if (mock_owner) { - *out = (mock_owner == GIT_PATH_OWNER_ADMINISTRATOR); - return 0; - } - - return fs_path_owner_is(out, path, &userid, 1); + return git_path_owner_is(out, path, GIT_PATH_OWNER_ADMINISTRATOR); } - -int git_path_owner_is_system_or_current_user(bool *out, const char *path) -{ - uid_t userids[2] = { geteuid(), 0 }; - - if (mock_owner) { - *out = (mock_owner == GIT_PATH_OWNER_ADMINISTRATOR || - mock_owner == GIT_PATH_OWNER_CURRENT_USER); - return 0; - } - - return fs_path_owner_is(out, path, userids, 2); -} - -#endif diff --git a/src/path.h b/src/path.h index 182135e65..4a23475e3 100644 --- a/src/path.h +++ b/src/path.h @@ -731,15 +731,8 @@ typedef enum { /** The file must be owned by the system account. */ GIT_PATH_OWNER_ADMINISTRATOR = (1 << 1), - /** - * The file may be owned by a system account if the current - * user is in an administrator group. Windows only; this is - * a noop on non-Windows systems. - */ - GIT_PATH_OWNER_CURRENT_USER_IS_ADMINISTRATOR = (1 << 2), - /** The file may be owned by another user. */ - GIT_PATH_OWNER_OTHER = (1 << 4) + GIT_PATH_OWNER_OTHER = (1 << 2) } git_path_owner_t; /** @@ -749,6 +742,12 @@ typedef enum { */ void git_path__set_owner(git_path_owner_t owner); +/** Verify that the file in question is owned by the given owner. */ +int git_path_owner_is( + bool *out, + const char *path, + git_path_owner_t owner_type); + /** * Verify that the file in question is owned by an administrator or system * account. @@ -761,10 +760,4 @@ int git_path_owner_is_system(bool *out, const char *path); int git_path_owner_is_current_user(bool *out, const char *path); -/** - * Verify that the file in question is owned by an administrator or system - * account _or_ the current user; - */ -int git_path_owner_is_system_or_current_user(bool *out, const char *path); - #endif -- cgit v1.2.1