From 391ed95f501483e0308431fd32beada2a7086632 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 27 Oct 2018 06:37:34 -0600 Subject: [PATCH] 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. --- plugins/sudoers/match.c | 33 ++++++++++++++++++++++++++++++++- plugins/sudoers/parse.h | 1 + plugins/sudoers/set_perms.c | 12 ++---------- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/plugins/sudoers/match.c b/plugins/sudoers/match.c index 2611b420a..7faae7399 100644 --- a/plugins/sudoers/match.c +++ b/plugins/sudoers/match.c @@ -154,6 +154,22 @@ userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, 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. * 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 (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 */ + } 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; + } + } + } } } diff --git a/plugins/sudoers/parse.h b/plugins/sudoers/parse.h index 426144c53..7dcbdca63 100644 --- a/plugins/sudoers/parse.h +++ b/plugins/sudoers/parse.h @@ -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 userlist_matches(struct sudoers_parse_tree *parse_tree, const struct passwd *pw, const struct member_list *list); const char *sudo_getdomainname(void); +struct gid_list *runas_getgroups(void); /* toke.c */ void init_lexer(void); diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c index 6bdc7b977..5b8348829 100644 --- a/plugins/sudoers/set_perms.c +++ b/plugins/sudoers/set_perms.c @@ -1695,19 +1695,11 @@ bad: static struct gid_list * runas_setgroups(void) { - struct passwd *pw; struct gid_list *gidlist; debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS) - 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; - gidlist = sudo_get_gidlist(pw, ENTRY_TYPE_QUERIED); - if (gidlist != NULL) { + gidlist = runas_getgroups(); + if (gidlist != NULL && !def_preserve_groups) { if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) { sudo_gidlist_delref(gidlist); gidlist = NULL;