Commit be29b861 by Edward Thomson

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.
parent 35905738
...@@ -1117,13 +1117,16 @@ int git_config_find_system(git_buf *path) ...@@ -1117,13 +1117,16 @@ int git_config_find_system(git_buf *path)
int git_config_find_programdata(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; bool is_safe;
int ret;
if ((ret = git_buf_sanitize(path)) < 0 || if ((ret = git_buf_sanitize(path)) < 0 ||
(ret = git_sysdir_find_programdata_file(path, (ret = git_sysdir_find_programdata_file(path,
GIT_CONFIG_FILENAME_PROGRAMDATA)) < 0 || 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; return ret;
if (!is_safe) { if (!is_safe) {
......
...@@ -2118,74 +2118,41 @@ static int file_owner_sid(PSID *out, const char *path) ...@@ -2118,74 +2118,41 @@ static int file_owner_sid(PSID *out, const char *path)
return error; 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; PSID owner_sid = NULL, user_sid = NULL;
int error = -1; int error;
if (mock_owner) { if (mock_owner) {
*out = (mock_owner == GIT_PATH_OWNER_CURRENT_USER); *out = ((mock_owner & owner_type) != 0);
return 0; return 0;
} }
if ((error = file_owner_sid(&owner_sid, path)) < 0 || if ((error = file_owner_sid(&owner_sid, path)) < 0)
(error = current_user_sid(&user_sid)) < 0)
goto done; goto done;
*out = EqualSid(owner_sid, user_sid); if ((owner_type & GIT_PATH_OWNER_CURRENT_USER) != 0) {
error = 0; if ((error = current_user_sid(&user_sid)) < 0)
goto done;
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 (mock_owner) { if (EqualSid(owner_sid, user_sid)) {
*out = (mock_owner == GIT_PATH_OWNER_ADMINISTRATOR || *out = true;
mock_owner == GIT_PATH_OWNER_CURRENT_USER); goto done;
return 0; }
} }
if (file_owner_sid(&owner_sid, path) < 0) if ((owner_type & GIT_PATH_OWNER_ADMINISTRATOR) != 0) {
goto done; if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) || *out = true;
IsWellKnownSid(owner_sid, WinLocalSystemSid)) { goto done;
*out = 1; }
error = 0;
goto done;
} }
if (current_user_sid(&user_sid) < 0) *out = false;
goto done;
*out = EqualSid(owner_sid, user_sid);
error = 0;
done: done:
git__free(owner_sid); git__free(owner_sid);
...@@ -2195,10 +2162,25 @@ done: ...@@ -2195,10 +2162,25 @@ done:
#else #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; 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; *out = false;
...@@ -2210,7 +2192,7 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid ...@@ -2210,7 +2192,7 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid
return -1; return -1;
} }
for (i = 0; i < uids_len; i++) { for (i = 0; i < uid_count; i++) {
if (uids[i] == st.st_uid) { if (uids[i] == st.st_uid) {
*out = true; *out = true;
break; break;
...@@ -2219,42 +2201,14 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid ...@@ -2219,42 +2201,14 @@ static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t uid
return 0; return 0;
} }
#endif
int git_path_owner_is_current_user(bool *out, const char *path) int git_path_owner_is_current_user(bool *out, const char *path)
{ {
uid_t userid = geteuid(); return git_path_owner_is(out, path, GIT_PATH_OWNER_CURRENT_USER);
if (mock_owner) {
*out = (mock_owner == GIT_PATH_OWNER_CURRENT_USER);
return 0;
}
return fs_path_owner_is(out, path, &userid, 1);
} }
int git_path_owner_is_system(bool *out, const char *path) int git_path_owner_is_system(bool *out, const char *path)
{ {
uid_t userid = 0; return git_path_owner_is(out, path, GIT_PATH_OWNER_ADMINISTRATOR);
if (mock_owner) {
*out = (mock_owner == GIT_PATH_OWNER_ADMINISTRATOR);
return 0;
}
return fs_path_owner_is(out, path, &userid, 1);
} }
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
...@@ -731,15 +731,8 @@ typedef enum { ...@@ -731,15 +731,8 @@ typedef enum {
/** The file must be owned by the system account. */ /** The file must be owned by the system account. */
GIT_PATH_OWNER_ADMINISTRATOR = (1 << 1), 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. */ /** The file may be owned by another user. */
GIT_PATH_OWNER_OTHER = (1 << 4) GIT_PATH_OWNER_OTHER = (1 << 2)
} git_path_owner_t; } git_path_owner_t;
/** /**
...@@ -749,6 +742,12 @@ typedef enum { ...@@ -749,6 +742,12 @@ typedef enum {
*/ */
void git_path__set_owner(git_path_owner_t owner); 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 * Verify that the file in question is owned by an administrator or system
* account. * account.
...@@ -761,10 +760,4 @@ int git_path_owner_is_system(bool *out, const char *path); ...@@ -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); 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 #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment