diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c index d9ad04cc0..764def51b 100644 --- a/plugins/sudoers/ldap.c +++ b/plugins/sudoers/ldap.c @@ -392,7 +392,7 @@ struct sudo_ldap_handle { LDAP *ld; struct ldap_result *result; const char *username; - struct group_list *grlist; + struct gid_list *gidlist; }; struct sudo_nss sudo_nss_ldap = { @@ -1598,6 +1598,7 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw) char *buf, timebuffer[TIMEFILTER_LENGTH + 1], gidbuf[MAX_UID_T_LEN + 1]; struct ldap_netgroup_list netgroups; struct ldap_netgroup *ng, *nextng; + struct gid_list *gidlist; struct group_list *grlist; struct group *grp; size_t sz = 0; @@ -1628,8 +1629,10 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw) continue; sz += 12 + sudo_ldap_value_len(grlist->groups[i]); } - for (i = 0; i < grlist->ngids; i++) { - if (pw->pw_gid == grlist->gids[i]) + } + if ((gidlist = sudo_get_gidlist(pw)) != NULL) { + for (i = 0; i < gidlist->ngids; i++) { + if (pw->pw_gid == gidlist->gids[i]) continue; sz += 13 + MAX_UID_T_LEN; } @@ -1696,11 +1699,13 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw) CHECK_LDAP_VCAT(buf, grlist->groups[i], sz); CHECK_STRLCAT(buf, ")", sz); } - for (i = 0; i < grlist->ngids; i++) { - if (pw->pw_gid == grlist->gids[i]) + } + if (gidlist != NULL) { + for (i = 0; i < gidlist->ngids; i++) { + if (pw->pw_gid == gidlist->gids[i]) continue; (void) snprintf(gidbuf, sizeof(gidbuf), "%u", - (unsigned int)grlist->gids[i]); + (unsigned int)gidlist->gids[i]); CHECK_STRLCAT(buf, "(sudoUser=%#", sz); CHECK_STRLCAT(buf, gidbuf, sz); CHECK_STRLCAT(buf, ")", sz); @@ -1708,6 +1713,8 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw) } /* Done with groups. */ + if (gidlist != NULL) + sudo_gidlist_delref(gidlist); if (grlist != NULL) sudo_grlist_delref(grlist); if (grp != NULL) @@ -3101,7 +3108,7 @@ sudo_ldap_open(struct sudo_nss *nss) handle->ld = ld; /* handle->result = NULL; */ /* handle->username = NULL; */ - /* handle->grlist = NULL; */ + /* handle->gidlist = NULL; */ nss->handle = handle; done: @@ -3372,7 +3379,7 @@ sudo_ldap_result_free_nss(struct sudo_nss *nss) DPRINTF1("removing reusable search result"); sudo_ldap_result_free(handle->result); handle->username = NULL; - handle->grlist = NULL; + handle->gidlist = NULL; handle->result = NULL; } debug_return; @@ -3400,7 +3407,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw) * have to contact the LDAP server again. */ if (handle->result) { - if (handle->grlist == user_group_list && + if (handle->gidlist == user_gid_list && strcmp(pw->pw_name, handle->username) == 0) { DPRINTF1("reusing previous result (user %s) with %d entries", handle->username, handle->result->nentries); @@ -3501,9 +3508,10 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw) /* Store everything in the sudo_nss handle. */ /* XXX - store pw and take a reference to it. */ + /* XXX - take refs for gidlist and grlist */ handle->result = lres; handle->username = pw->pw_name; - handle->grlist = user_group_list; + handle->gidlist = user_gid_list; debug_return_ptr(lres); } diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index c393b49fe..2b551e6b2 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -492,11 +492,11 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask, gid_t egid; size_t glsize; char *cp, *gid_list; - struct group_list *grlist = sudo_get_grlist(runas_pw); + struct gid_list *gidlist = sudo_get_gidlist(runas_pw); /* We reserve an extra spot in the list for the effective gid. */ glsize = sizeof("runas_groups=") - 1 + - ((grlist->ngids + 1) * (MAX_UID_T_LEN + 1)); + ((gidlist->ngids + 1) * (MAX_UID_T_LEN + 1)); gid_list = malloc(glsize); if (gid_list == NULL) goto oom; @@ -513,10 +513,10 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask, goto bad; } cp += len; - for (i = 0; i < grlist->ngids; i++) { - if (grlist->gids[i] != egid) { + for (i = 0; i < gidlist->ngids; i++) { + if (gidlist->gids[i] != egid) { len = snprintf(cp, glsize - (cp - gid_list), ",%u", - (unsigned int) grlist->gids[i]); + (unsigned int) gidlist->gids[i]); if (len < 0 || (size_t)len >= glsize - (cp - gid_list)) { sudo_warnx(U_("internal error, %s overflow"), __func__); free(gid_list); @@ -526,7 +526,7 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask, } } command_info[info_len++] = gid_list; - sudo_grlist_delref(grlist); + sudo_gidlist_delref(gidlist); } if (def_closefrom >= 0) { if (asprintf(&command_info[info_len++], "closefrom=%d", def_closefrom) == -1) @@ -678,9 +678,9 @@ sudoers_policy_close(int exit_status, int error_code) sudo_gr_delref(runas_gr); runas_gr = NULL; } - if (user_group_list != NULL) { - sudo_grlist_delref(user_group_list); - user_group_list = NULL; + if (user_gid_list != NULL) { + sudo_gidlist_delref(user_gid_list); + user_gid_list = NULL; } free(user_gids); user_gids = NULL; diff --git a/plugins/sudoers/pwutil.c b/plugins/sudoers/pwutil.c index 354866a20..2ffd7ec76 100644 --- a/plugins/sudoers/pwutil.c +++ b/plugins/sudoers/pwutil.c @@ -48,7 +48,7 @@ */ static struct rbtree *pwcache_byuid, *pwcache_byname; static struct rbtree *grcache_bygid, *grcache_byname; -static struct rbtree *grlist_cache; +static struct rbtree *gidlist_cache, *grlist_cache; static int cmp_pwuid(const void *, const void *); static int cmp_pwnam(const void *, const void *); @@ -652,10 +652,38 @@ sudo_fakegrnam(const char *group) debug_return_ptr(item->d.gr); } +void +sudo_gidlist_addref(struct gid_list *gidlist) +{ + debug_decl(sudo_gidlist_addref, SUDOERS_DEBUG_NSS) + ptr_to_item(gidlist)->refcnt++; + debug_return; +} + +static void +sudo_gidlist_delref_item(void *v) +{ + struct cache_item *item = v; + debug_decl(sudo_gidlist_delref_item, SUDOERS_DEBUG_NSS) + + if (--item->refcnt == 0) + free(item); + + debug_return; +} + +void +sudo_gidlist_delref(struct gid_list *gidlist) +{ + debug_decl(sudo_gidlist_delref, SUDOERS_DEBUG_NSS) + sudo_gidlist_delref_item(ptr_to_item(gidlist)); + debug_return; +} + void sudo_grlist_addref(struct group_list *grlist) { - debug_decl(sudo_gr_addref, SUDOERS_DEBUG_NSS) + debug_decl(sudo_grlist_addref, SUDOERS_DEBUG_NSS) ptr_to_item(grlist)->refcnt++; debug_return; } @@ -664,7 +692,7 @@ static void sudo_grlist_delref_item(void *v) { struct cache_item *item = v; - debug_decl(sudo_gr_delref_item, SUDOERS_DEBUG_NSS) + debug_decl(sudo_grlist_delref_item, SUDOERS_DEBUG_NSS) if (--item->refcnt == 0) free(item); @@ -675,7 +703,7 @@ sudo_grlist_delref_item(void *v) void sudo_grlist_delref(struct group_list *grlist) { - debug_decl(sudo_gr_delref, SUDOERS_DEBUG_NSS) + debug_decl(sudo_grlist_delref, SUDOERS_DEBUG_NSS) sudo_grlist_delref_item(ptr_to_item(grlist)); debug_return; } @@ -697,6 +725,10 @@ sudo_freegrcache(void) rbdestroy(grlist_cache, sudo_grlist_delref_item); grlist_cache = NULL; } + if (gidlist_cache != NULL) { + rbdestroy(gidlist_cache, sudo_gidlist_delref_item); + gidlist_cache = NULL; + } debug_return; } @@ -708,8 +740,11 @@ sudo_get_grlist(const struct passwd *pw) struct rbnode *node; debug_decl(sudo_get_grlist, SUDOERS_DEBUG_NSS) + sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: looking up group names for %s", + __func__, pw->pw_name); + if (grlist_cache == NULL) { - grlist_cache = rbcreate(cmp_grnam); + grlist_cache = rbcreate(cmp_pwnam); if (grlist_cache == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); debug_return_ptr(NULL); @@ -725,7 +760,7 @@ sudo_get_grlist(const struct passwd *pw) /* * Cache group db entry if it exists or a negative response if not. */ - item = sudo_make_grlist_item(pw, NULL, NULL); + item = sudo_make_grlist_item(pw, NULL); if (item == NULL) { /* Out of memory? */ debug_return_ptr(NULL); @@ -759,14 +794,14 @@ done: } int -sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids) +sudo_set_grlist(struct passwd *pw, char * const *groups) { struct cache_item key, *item; struct rbnode *node; debug_decl(sudo_set_grlist, SUDOERS_DEBUG_NSS) if (grlist_cache == NULL) { - grlist_cache = rbcreate(cmp_grnam); + grlist_cache = rbcreate(cmp_pwnam); if (grlist_cache == NULL) { sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); debug_return_int(-1); @@ -779,7 +814,7 @@ sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids) key.k.name = pw->pw_name; getauthregistry(NULL, key.registry); if ((node = rbfind(grlist_cache, &key)) == NULL) { - if ((item = sudo_make_grlist_item(pw, groups, gids)) == NULL) { + if ((item = sudo_make_grlist_item(pw, groups)) == NULL) { sudo_warnx(U_("unable to parse groups for %s"), pw->pw_name); debug_return_int(-1); } @@ -800,17 +835,120 @@ sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids) debug_return_int(0); } +struct gid_list * +sudo_get_gidlist(const struct passwd *pw) +{ + struct cache_item key, *item; + struct rbnode *node; + debug_decl(sudo_get_gidlist, SUDOERS_DEBUG_NSS) + + sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: looking up group IDs for %s", + __func__, pw->pw_name); + + if (gidlist_cache == NULL) { + gidlist_cache = rbcreate(cmp_pwnam); + if (gidlist_cache == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_ptr(NULL); + } + } + + key.k.name = pw->pw_name; + getauthregistry(pw->pw_name, key.registry); + if ((node = rbfind(gidlist_cache, &key)) != NULL) { + item = node->data; + goto done; + } + /* + * Cache group db entry if it exists or a negative response if not. + */ + item = sudo_make_gidlist_item(pw, NULL); + if (item == NULL) { + /* Out of memory? */ + debug_return_ptr(NULL); + } + strlcpy(item->registry, key.registry, sizeof(item->registry)); + switch (rbinsert(gidlist_cache, item, NULL)) { + case 1: + /* should not happen */ + sudo_warnx(U_("unable to cache group list for %s, already exists"), + pw->pw_name); + item->refcnt = 0; + break; + case -1: + /* can't cache item, just return it */ + sudo_warnx(U_("unable to cache group list for %s, out of memory"), + pw->pw_name); + item->refcnt = 0; + break; + } + if (item->d.gidlist != NULL) { + int i; + for (i = 0; i < item->d.gidlist->ngids; i++) { + sudo_debug_printf(SUDO_DEBUG_DEBUG, + "%s: user %s has supplementary gid %u", __func__, + pw->pw_name, (unsigned int)item->d.gidlist->gids[i]); + } + } +done: + item->refcnt++; + debug_return_ptr(item->d.gidlist); +} + +int +sudo_set_gidlist(struct passwd *pw, char * const *gids) +{ + struct cache_item key, *item; + struct rbnode *node; + debug_decl(sudo_set_gidlist, SUDOERS_DEBUG_NSS) + + if (gidlist_cache == NULL) { + gidlist_cache = rbcreate(cmp_pwnam); + if (gidlist_cache == NULL) { + sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); + debug_return_int(-1); + } + } + + /* + * Cache group db entry if it doesn't already exist + */ + key.k.name = pw->pw_name; + getauthregistry(NULL, key.registry); + if ((node = rbfind(gidlist_cache, &key)) == NULL) { + if ((item = sudo_make_gidlist_item(pw, gids)) == NULL) { + sudo_warnx(U_("unable to parse gids for %s"), pw->pw_name); + debug_return_int(-1); + } + strlcpy(item->registry, key.registry, sizeof(item->registry)); + switch (rbinsert(gidlist_cache, item, NULL)) { + case 1: + sudo_warnx(U_("unable to cache group list for %s, already exists"), + pw->pw_name); + sudo_gidlist_delref_item(item); + break; + case -1: + sudo_warnx(U_("unable to cache group list for %s, out of memory"), + pw->pw_name); + sudo_gidlist_delref_item(item); + debug_return_int(-1); + } + } + debug_return_int(0); +} + bool user_in_group(const struct passwd *pw, const char *group) { - struct group_list *grlist; + struct group_list *grlist = NULL; + struct gid_list *gidlist = NULL; struct group *grp = NULL; const char *errstr; int i; bool matched = false; debug_decl(user_in_group, SUDOERS_DEBUG_NSS) - if ((grlist = sudo_get_grlist(pw)) != NULL) { + if ((gidlist = sudo_get_gidlist(pw)) != NULL) { /* * If it could be a sudo-style group ID check gids first. */ @@ -824,8 +962,8 @@ user_in_group(const struct passwd *pw, const char *group) matched = true; goto done; } - for (i = 0; i < grlist->ngids; i++) { - if (gid == grlist->gids[i]) { + for (i = 0; i < gidlist->ngids; i++) { + if (gid == gidlist->gids[i]) { matched = true; goto done; } @@ -837,10 +975,12 @@ user_in_group(const struct passwd *pw, const char *group) * Next check the supplementary group vector. * It usually includes the password db group too. */ - for (i = 0; i < grlist->ngroups; i++) { - if (strcasecmp(group, grlist->groups[i]) == 0) { - matched = true; - goto done; + if ((grlist = sudo_get_grlist(pw)) != NULL) { + for (i = 0; i < grlist->ngroups; i++) { + if (strcasecmp(group, grlist->groups[i]) == 0) { + matched = true; + goto done; + } } } @@ -854,7 +994,9 @@ user_in_group(const struct passwd *pw, const char *group) done: if (grp != NULL) sudo_gr_delref(grp); - sudo_grlist_delref(grlist); + if (grlist != NULL) + sudo_grlist_delref(grlist); + sudo_gidlist_delref(gidlist); } sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: user %s %sin group %s", __func__, pw->pw_name, matched ? "" : "NOT ", group); diff --git a/plugins/sudoers/pwutil.h b/plugins/sudoers/pwutil.h index 433e15687..f1ade0056 100644 --- a/plugins/sudoers/pwutil.h +++ b/plugins/sudoers/pwutil.h @@ -36,12 +36,13 @@ struct cache_item { struct passwd *pw; struct group *gr; struct group_list *grlist; + struct gid_list *gidlist; } d; }; /* * Container structs to simpify size and offset calculations and guarantee - * proper aligment of struct passwd, group and group_list. + * proper aligment of struct passwd, group, gid_list and group_list. */ struct cache_item_pw { struct cache_item cache; @@ -59,8 +60,15 @@ struct cache_item_grlist { /* actually bigger */ }; +struct cache_item_gidlist { + struct cache_item cache; + struct gid_list gidlist; + /* actually bigger */ +}; + struct cache_item *sudo_make_gritem(gid_t gid, const char *group); -struct cache_item *sudo_make_grlist_item(const struct passwd *pw, char * const *groups, char * const *gids); +struct cache_item *sudo_make_grlist_item(const struct passwd *pw, char * const *groups); +struct cache_item *sudo_make_gidlist_item(const struct passwd *pw, char * const *gids); struct cache_item *sudo_make_pwitem(uid_t uid, const char *user); #endif /* SUDOERS_PWUTIL_H */ diff --git a/plugins/sudoers/pwutil_impl.c b/plugins/sudoers/pwutil_impl.c index 1a1b4392f..8c469f583 100644 --- a/plugins/sudoers/pwutil_impl.c +++ b/plugins/sudoers/pwutil_impl.c @@ -230,17 +230,15 @@ sudo_make_gritem(gid_t gid, const char *name) * elements. Fills in datum from user_gids or from getgrouplist(3). */ struct cache_item * -sudo_make_grlist_item(const struct passwd *pw, char * const *unused1, - char * const *unused2) +sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1) { char *cp; - size_t nsize, ngroups, total, len; - struct cache_item_grlist *grlitem; - struct group_list *grlist; + size_t nsize, total; + struct cache_item_gidlist *glitem; + struct gid_list *gidlist; GETGROUPS_T *gids; - struct group *grp = NULL; - int i, ngids, groupname_len; - debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS) + int i, ngids; + debug_decl(sudo_make_gidlist_item, SUDOERS_DEBUG_NSS) if (pw == sudo_user.pw && sudo_user.gids != NULL) { gids = user_gids; @@ -286,27 +284,88 @@ sudo_make_grlist_item(const struct passwd *pw, char * const *unused1, debug_return_ptr(NULL); } -#ifdef _SC_LOGIN_NAME_MAX - groupname_len = MAX((int)sysconf(_SC_LOGIN_NAME_MAX), 32); -#else - groupname_len = MAX(LOGIN_NAME_MAX, 32); -#endif - /* Allocate in one big chunk for easy freeing. */ nsize = strlen(pw->pw_name) + 1; - total = sizeof(*grlitem) + nsize; - total += sizeof(char *) * ngids; + total = sizeof(*glitem) + nsize; total += sizeof(gid_t *) * ngids; - total += groupname_len * ngids; -again: - if ((grlitem = calloc(1, total)) == NULL) { + if ((glitem = calloc(1, total)) == NULL) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, "unable to allocate memory"); free(gids); debug_return_ptr(NULL); } + /* + * Copy in group list and make pointers relative to space + * at the end of the buffer. Note that the groups array must come + * immediately after struct group to guarantee proper alignment. + */ + gidlist = &glitem->gidlist; + cp = (char *)(glitem + 1); + gidlist->gids = (gid_t *)cp; + cp += sizeof(gid_t) * ngids; + + /* Set key and datum. */ + memcpy(cp, pw->pw_name, nsize); + glitem->cache.k.name = cp; + glitem->cache.d.gidlist = gidlist; + glitem->cache.refcnt = 1; + + /* + * Store group IDs. + */ + for (i = 0; i < ngids; i++) + gidlist->gids[i] = gids[i]; + gidlist->ngids = ngids; + free(gids); + + debug_return_ptr(&glitem->cache); +} + +/* + * Dynamically allocate space for a struct item plus the key and data + * elements. Fills in group names from a call to sudo_get_gidlist(). + */ +struct cache_item * +sudo_make_grlist_item(const struct passwd *pw, char * const *unused1) +{ + char *cp; + size_t nsize, ngroups, total, len; + struct cache_item_grlist *grlitem; + struct group_list *grlist; + struct gid_list *gidlist; + struct group *grp = NULL; + int i, groupname_len; + debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS) + + gidlist = sudo_get_gidlist(pw); + if (gidlist == NULL) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "no gid list for use %s", pw->pw_name); + errno = ENOENT; + debug_return_ptr(NULL); + } + +#ifdef _SC_LOGIN_NAME_MAX + groupname_len = MAX((int)sysconf(_SC_LOGIN_NAME_MAX), 32); +#else + groupname_len = MAX(LOGIN_NAME_MAX, 32); +#endif + + /* Allocate in one big chunk for easy freeing. */ + nsize = strlen(pw->pw_name) + 1; + total = sizeof(*grlitem) + nsize; + total += groupname_len * gidlist->ngids; + +again: + if ((grlitem = calloc(1, total)) == NULL) { + sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, + "unable to allocate memory"); + sudo_gidlist_delref(gidlist); + debug_return_ptr(NULL); + } + /* * Copy in group list and make pointers relative to space * at the end of the buffer. Note that the groups array must come @@ -315,9 +374,7 @@ again: grlist = &grlitem->grlist; cp = (char *)(grlitem + 1); grlist->groups = (char **)cp; - cp += sizeof(char *) * ngids; - grlist->gids = (gid_t *)cp; - cp += sizeof(gid_t) * ngids; + cp += sizeof(char *) * gidlist->ngids; /* Set key and datum. */ memcpy(cp, pw->pw_name, nsize); @@ -326,13 +383,6 @@ again: grlitem->cache.refcnt = 1; cp += nsize; - /* - * Store group IDs. - */ - for (i = 0; i < ngids; i++) - grlist->gids[i] = gids[i]; - grlist->ngids = ngids; - /* * Resolve and store group names by ID. */ @@ -341,8 +391,8 @@ again: aix_setauthdb((char *) pw->pw_name, NULL); #endif ngroups = 0; - for (i = 0; i < ngids; i++) { - if ((grp = sudo_getgrgid(gids[i])) != NULL) { + for (i = 0; i < gidlist->ngids; i++) { + if ((grp = sudo_getgrgid(gidlist->gids[i])) != NULL) { len = strlen(grp->gr_name) + 1; if (cp - (char *)grlitem + len > total) { total += len + groupname_len; @@ -357,7 +407,7 @@ again: } } grlist->ngroups = ngroups; - free(gids); + sudo_gidlist_delref(gidlist); #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); diff --git a/plugins/sudoers/set_perms.c b/plugins/sudoers/set_perms.c index e38d98de2..58c7cc636 100644 --- a/plugins/sudoers/set_perms.c +++ b/plugins/sudoers/set_perms.c @@ -44,7 +44,7 @@ * Prototypes */ #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) -static struct group_list *runas_setgroups(void); +static struct gid_list *runas_setgroups(void); #endif /* @@ -62,7 +62,7 @@ struct perm_state { #if defined(HAVE_SETRESUID) || defined(ID_SAVED) gid_t sgid; #endif - struct group_list *grlist; + struct gid_list *gidlist; }; #define PERM_STACK_MAX 16 @@ -84,7 +84,7 @@ rewind_perms(void) if (!restore_perms()) debug_return_bool(false); } - sudo_grlist_delref(perm_stack[0].grlist); + sudo_gidlist_delref(perm_stack[0].gidlist); } debug_return_bool(true); @@ -147,8 +147,8 @@ set_perms(int perm) state->egid = getegid(); state->sgid = state->egid; /* in case we are setgid */ #endif - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d", __func__, (int)state->ruid, (int)state->euid, (int)state->suid, @@ -180,8 +180,8 @@ set_perms(int perm) errstr = N_("unable to change to root gid"); goto bad; } - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); break; case PERM_USER: @@ -197,10 +197,10 @@ set_perms(int perm) ID(rgid), ID(egid), ID(sgid)); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_USER: setgroups"; goto bad; } @@ -234,10 +234,10 @@ set_perms(int perm) ID(rgid), ID(egid), ID(sgid)); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_FULL_USER: setgroups"; goto bad; } @@ -269,8 +269,8 @@ set_perms(int perm) errstr = N_("unable to change to runas gid"); goto bad; } - state->grlist = runas_setgroups(); - if (state->grlist == NULL) { + state->gidlist = runas_setgroups(); + if (state->gidlist == NULL) { errstr = N_("unable to set runas group vector"); goto bad; } @@ -288,8 +288,8 @@ set_perms(int perm) break; case PERM_SUDOERS: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); /* assumes euid == ROOT_UID, ruid == user */ state->rgid = ostate->rgid; @@ -328,8 +328,8 @@ set_perms(int perm) break; case PERM_TIMESTAMP: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); state->rgid = ostate->rgid; state->egid = ostate->egid; state->sgid = ostate->sgid; @@ -402,13 +402,13 @@ restore_perms(void) (int)OID(rgid), (int)OID(egid), (int)OID(sgid)); goto bad; } - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) { sudo_warn("setgroups()"); goto bad; } } - sudo_grlist_delref(state->grlist); + sudo_gidlist_delref(state->gidlist); debug_return_bool(true); bad: @@ -459,8 +459,8 @@ set_perms(int perm) state->rgid = getgidx(ID_REAL); state->egid = getgidx(ID_EFFECTIVE); state->sgid = getgidx(ID_SAVED); - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d", __func__, (unsigned int)state->ruid, (unsigned int)state->euid, @@ -493,8 +493,8 @@ set_perms(int perm) errstr = N_("unable to change to root gid"); goto bad; } - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); break; case PERM_USER: @@ -510,10 +510,10 @@ set_perms(int perm) "PERM_USER: setgidx(ID_EFFECTIVE, %d)", user_gid); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_USER: setgroups"; goto bad; } @@ -555,10 +555,10 @@ set_perms(int perm) user_gid); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_FULL_USER: setgroups"; goto bad; } @@ -590,8 +590,8 @@ set_perms(int perm) errstr = N_("unable to change to runas gid"); goto bad; } - state->grlist = runas_setgroups(); - if (state->grlist == NULL) { + state->gidlist = runas_setgroups(); + if (state->gidlist == NULL) { errstr = N_("unable to set runas group vector"); goto bad; } @@ -609,8 +609,8 @@ set_perms(int perm) break; case PERM_SUDOERS: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); /* assume euid == ROOT_UID, ruid == user */ state->rgid = ostate->rgid; @@ -658,8 +658,8 @@ set_perms(int perm) break; case PERM_TIMESTAMP: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); state->rgid = ostate->rgid; state->egid = ostate->egid; state->sgid = ostate->sgid; @@ -805,13 +805,13 @@ restore_perms(void) } } } - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) { sudo_warn("setgroups()"); goto bad; } } - sudo_grlist_delref(state->grlist); + sudo_gidlist_delref(state->gidlist); debug_return_bool(true); bad: @@ -860,8 +860,8 @@ set_perms(int perm) state->euid = geteuid(); state->rgid = getgid(); state->egid = getegid(); - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__, (int)state->ruid, (int)state->euid, @@ -901,8 +901,8 @@ set_perms(int perm) "PERM_ROOT: setregid(%d, %d)", ID(rgid), ID(egid)); goto bad; } - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); break; case PERM_USER: @@ -916,10 +916,10 @@ set_perms(int perm) "PERM_USER: setregid(%d, %d)", ID(rgid), ID(egid)); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_USER: setgroups"; goto bad; } @@ -948,10 +948,10 @@ set_perms(int perm) "PERM_FULL_USER: setregid(%d, %d)", ID(rgid), ID(egid)); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_FULL_USER: setgroups"; goto bad; } @@ -978,8 +978,8 @@ set_perms(int perm) errstr = N_("unable to change to runas gid"); goto bad; } - state->grlist = runas_setgroups(); - if (state->grlist == NULL) { + state->gidlist = runas_setgroups(); + if (state->gidlist == NULL) { errstr = N_("unable to set runas group vector"); goto bad; } @@ -995,8 +995,8 @@ set_perms(int perm) break; case PERM_SUDOERS: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); /* assume euid == ROOT_UID, ruid == user */ state->rgid = ostate->rgid; @@ -1030,8 +1030,8 @@ set_perms(int perm) break; case PERM_TIMESTAMP: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); state->rgid = ostate->rgid; state->egid = ostate->egid; state->ruid = ROOT_UID; @@ -1103,13 +1103,13 @@ restore_perms(void) (int)state->egid, (int)OID(rgid), (int)OID(egid)); goto bad; } - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) { sudo_warn("setgroups()"); goto bad; } } - sudo_grlist_delref(state->grlist); + sudo_gidlist_delref(state->gidlist); debug_return_bool(true); bad: @@ -1173,8 +1173,8 @@ set_perms(int perm) state->euid = geteuid(); state->rgid = getgid(); state->egid = getegid(); - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__, (int)state->ruid, (int)state->euid, @@ -1197,8 +1197,8 @@ set_perms(int perm) errstr = N_("unable to change to root gid"); goto bad; } - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); break; case PERM_USER: @@ -1212,10 +1212,10 @@ set_perms(int perm) "PERM_USER: setegid(%d)", user_gid); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_USER: setgroups"; goto bad; } @@ -1244,10 +1244,10 @@ set_perms(int perm) "PERM_FULL_USER: setgid(%d)", user_gid); goto bad; } - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_FULL_USER: setgroups"; goto bad; } @@ -1274,8 +1274,8 @@ set_perms(int perm) errstr = N_("unable to change to runas gid"); goto bad; } - state->grlist = runas_setgroups(); - if (state->grlist == NULL) { + state->gidlist = runas_setgroups(); + if (state->gidlist == NULL) { errstr = N_("unable to set runas group vector"); goto bad; } @@ -1291,8 +1291,8 @@ set_perms(int perm) break; case PERM_SUDOERS: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); /* assume euid == ROOT_UID, ruid == user */ state->rgid = ostate->rgid; @@ -1326,8 +1326,8 @@ set_perms(int perm) break; case PERM_TIMESTAMP: - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); state->rgid = ostate->rgid; state->egid = ostate->egid; state->ruid = ROOT_UID; @@ -1394,8 +1394,8 @@ restore_perms(void) sudo_warn("setegid(%d)", (int)ostate->egid); goto bad; } - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) { sudo_warn("setgroups()"); goto bad; } @@ -1404,7 +1404,7 @@ restore_perms(void) sudo_warn("seteuid(%d)", ostate->euid); goto bad; } - sudo_grlist_delref(state->grlist); + sudo_gidlist_delref(state->gidlist); debug_return_bool(true); bad: @@ -1447,8 +1447,8 @@ set_perms(int perm) /* Stash initial state */ state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid(); state->rgid = getgid(); - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " "ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid); break; @@ -1456,8 +1456,8 @@ set_perms(int perm) case PERM_ROOT: state->ruid = ROOT_UID; state->rgid = ROOT_GID; - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid); if (setuid(ROOT_UID)) { @@ -1477,10 +1477,10 @@ set_perms(int perm) sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: " "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid); (void) setgid(user_gid); - state->grlist = user_group_list; - sudo_grlist_addref(state->grlist); - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { + state->gidlist = user_gid_list; + sudo_gidlist_addref(state->gidlist); + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) { errstr = "PERM_FULL_USER: setgroups"; goto bad; } @@ -1502,8 +1502,8 @@ set_perms(int perm) /* Unsupported since we can't set euid. */ state->ruid = ostate->ruid; state->rgid = ostate->rgid; - state->grlist = ostate->grlist; - sudo_grlist_addref(state->grlist); + state->gidlist = ostate->gidlist; + sudo_gidlist_addref(state->gidlist); break; } @@ -1541,13 +1541,13 @@ restore_perms(void) sudo_warn("setgid(%d)", (int)ostate->rgid); goto bad; } - if (state->grlist != ostate->grlist) { - if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { + if (state->gidlist != ostate->gidlist) { + if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) { sudo_warn("setgroups()"); goto bad; } } - sudo_grlist_delref(state->grlist); + sudo_gidlist_delref(state->gidlist); if (OID(ruid) != (uid_t)-1 && setuid(ostate->ruid)) { sudo_warn("setuid(%d)", (int)ostate->ruid); goto bad; @@ -1560,26 +1560,26 @@ bad: #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) -static struct group_list * +static struct gid_list * runas_setgroups(void) { struct passwd *pw; - struct group_list *grlist; + struct gid_list *gidlist; debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS) if (def_preserve_groups) { - sudo_grlist_addref(user_group_list); - debug_return_ptr(user_group_list); + sudo_gidlist_addref(user_gid_list); + debug_return_ptr(user_gid_list); } pw = runas_pw ? runas_pw : sudo_user.pw; - grlist = sudo_get_grlist(pw); - if (grlist != NULL) { - if (sudo_setgroups(grlist->ngids, grlist->gids) < 0) { - sudo_grlist_delref(grlist); - grlist = NULL; + gidlist = sudo_get_gidlist(pw); + if (gidlist != NULL) { + if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) { + sudo_gidlist_delref(gidlist); + gidlist = NULL; } } - debug_return_ptr(grlist); + debug_return_ptr(gidlist); } #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c index 67dd6b275..74b02dcee 100644 --- a/plugins/sudoers/sudoers.c +++ b/plugins/sudoers/sudoers.c @@ -695,8 +695,8 @@ init_vars(char * const envp[]) unknown_user = true; } } - if (user_group_list == NULL) - user_group_list = sudo_get_grlist(sudo_user.pw); + if (user_gid_list == NULL) + user_gid_list = sudo_get_gidlist(sudo_user.pw); /* Store initialize permissions so we can restore them later. */ if (!set_perms(PERM_INITIAL)) diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index bf2ce13dd..5ff7346a0 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -45,13 +45,19 @@ #include "sudoers_debug.h" /* - * Password db and supplementary group IDs with associated group names. + * Supplementary group IDs for a user. + */ +struct gid_list { + int ngids; + GETGROUPS_T *gids; +}; + +/* + * Supplementary group names for a user. */ struct group_list { - char **groups; - GETGROUPS_T *gids; int ngroups; - int ngids; + char **groups; }; /* @@ -77,7 +83,7 @@ struct sudo_user { char *cmnd_safe; char *class_name; char *krb5_ccname; - struct group_list *group_list; + struct gid_list *gid_list; char * const * env_vars; #ifdef HAVE_SELINUX char *role; @@ -183,7 +189,7 @@ struct sudo_user { #define user_dir (sudo_user.pw->pw_dir) #define user_gids (sudo_user.gids) #define user_ngids (sudo_user.ngids) -#define user_group_list (sudo_user.group_list) +#define user_gid_list (sudo_user.gid_list) #define user_tty (sudo_user.tty) #define user_ttypath (sudo_user.ttypath) #define user_cwd (sudo_user.cwd) @@ -294,6 +300,7 @@ __dso_public void sudo_gr_addref(struct group *); __dso_public void sudo_gr_delref(struct group *); bool user_in_group(const struct passwd *, const char *); struct group *sudo_fakegrnam(const char *); +struct gid_list *sudo_get_gidlist(const struct passwd *pw); struct group_list *sudo_get_grlist(const struct passwd *pw); struct passwd *sudo_fakepwnam(const char *, gid_t); struct passwd *sudo_mkpwent(const char *user, uid_t uid, gid_t gid, const char *home, const char *shell); @@ -302,11 +309,14 @@ struct passwd *sudo_getpwuid(uid_t); void sudo_endspent(void); void sudo_freegrcache(void); void sudo_freepwcache(void); +void sudo_gidlist_addref(struct gid_list *); +void sudo_gidlist_delref(struct gid_list *); void sudo_grlist_addref(struct group_list *); void sudo_grlist_delref(struct group_list *); void sudo_pw_addref(struct passwd *); void sudo_pw_delref(struct passwd *); -int sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids); +int sudo_set_gidlist(struct passwd *pw, char * const *gids); +int sudo_set_grlist(struct passwd *pw, char * const *groups); void sudo_setspent(void); /* timestr.c */