Allow the group set by "sudo -g" to be any of the target user's groups.

Previously, this was only allowed if the group matched the target
user's primary group ID (from the passwd database entry).
The sudoers policy will now allow the group if it is one of the
target user's supplemental groups as well.
This commit is contained in:
Todd C. Miller
2018-10-27 06:37:34 -06:00
parent ffe2041a02
commit 391ed95f50
3 changed files with 35 additions and 11 deletions

View File

@@ -154,6 +154,22 @@ userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw,
debug_return_int(matched); debug_return_int(matched);
} }
struct gid_list *
runas_getgroups(void)
{
const struct passwd *pw;
debug_decl(runas_getgroups, SUDOERS_DEBUG_MATCH)
if (def_preserve_groups) {
sudo_gidlist_addref(user_gid_list);
debug_return_ptr(user_gid_list);
}
/* Only use results from a group db query, not the front end. */
pw = runas_pw ? runas_pw : sudo_user.pw;
debug_return_ptr(sudo_get_gidlist(pw, ENTRY_TYPE_QUERIED));
}
/* /*
* Check for user described by pw in a list of members. * Check for user described by pw in a list of members.
* If both lists are empty compare against def_runas_default. * If both lists are empty compare against def_runas_default.
@@ -263,8 +279,23 @@ runaslist_matches(struct sudoers_parse_tree *parse_tree,
} }
} }
if (group_matched == UNSPEC) { if (group_matched == UNSPEC) {
if (runas_pw->pw_gid == runas_gr->gr_gid) struct gid_list *runas_groups;
/*
* The runas group was not explicitly allowed by sudoers.
* Check whether it is one of the target user's groups.
*/
if (runas_pw->pw_gid == runas_gr->gr_gid) {
group_matched = ALLOW; /* runas group matches passwd db */ group_matched = ALLOW; /* runas group matches passwd db */
} else if ((runas_groups = runas_getgroups()) != NULL) {
int i;
for (i = 0; i < runas_groups->ngids; i++) {
if (runas_groups->gids[i] == runas_gr->gr_gid) {
group_matched = ALLOW; /* matched aux group vector */
break;
}
}
}
} }
} }

View File

@@ -314,6 +314,7 @@ int runaslist_matches(struct sudoers_parse_tree *parse_tree, const struct member
int user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member *m); int user_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member *m);
int userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list); int userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list);
const char *sudo_getdomainname(void); const char *sudo_getdomainname(void);
struct gid_list *runas_getgroups(void);
/* toke.c */ /* toke.c */
void init_lexer(void); void init_lexer(void);

View File

@@ -1695,19 +1695,11 @@ bad:
static struct gid_list * static struct gid_list *
runas_setgroups(void) runas_setgroups(void)
{ {
struct passwd *pw;
struct gid_list *gidlist; struct gid_list *gidlist;
debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS) debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS)
if (def_preserve_groups) { gidlist = runas_getgroups();
sudo_gidlist_addref(user_gid_list); if (gidlist != NULL && !def_preserve_groups) {
debug_return_ptr(user_gid_list);
}
/* Only use results from a group db query, not the front end. */
pw = runas_pw ? runas_pw : sudo_user.pw;
gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_QUERIED);
if (gidlist != NULL) {
if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) { if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) {
sudo_gidlist_delref(gidlist); sudo_gidlist_delref(gidlist);
gidlist = NULL; gidlist = NULL;