Cache the user's group IDs and group names separately and only

resolve group IDs -> names when needed.  If the sudoers file doesn't
contain groups we will no longer try to resolve all the user's group
IDs to names, which can be expensive on some systems.
This commit is contained in:
Todd C. Miller
2016-08-13 16:27:44 -06:00
parent c3b8e97a6e
commit 985ab1dd3e
8 changed files with 408 additions and 190 deletions

View File

@@ -392,7 +392,7 @@ struct sudo_ldap_handle {
LDAP *ld; LDAP *ld;
struct ldap_result *result; struct ldap_result *result;
const char *username; const char *username;
struct group_list *grlist; struct gid_list *gidlist;
}; };
struct sudo_nss sudo_nss_ldap = { 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]; char *buf, timebuffer[TIMEFILTER_LENGTH + 1], gidbuf[MAX_UID_T_LEN + 1];
struct ldap_netgroup_list netgroups; struct ldap_netgroup_list netgroups;
struct ldap_netgroup *ng, *nextng; struct ldap_netgroup *ng, *nextng;
struct gid_list *gidlist;
struct group_list *grlist; struct group_list *grlist;
struct group *grp; struct group *grp;
size_t sz = 0; size_t sz = 0;
@@ -1628,8 +1629,10 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
continue; continue;
sz += 12 + sudo_ldap_value_len(grlist->groups[i]); 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; continue;
sz += 13 + MAX_UID_T_LEN; 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_LDAP_VCAT(buf, grlist->groups[i], sz);
CHECK_STRLCAT(buf, ")", 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; continue;
(void) snprintf(gidbuf, sizeof(gidbuf), "%u", (void) snprintf(gidbuf, sizeof(gidbuf), "%u",
(unsigned int)grlist->gids[i]); (unsigned int)gidlist->gids[i]);
CHECK_STRLCAT(buf, "(sudoUser=%#", sz); CHECK_STRLCAT(buf, "(sudoUser=%#", sz);
CHECK_STRLCAT(buf, gidbuf, sz); CHECK_STRLCAT(buf, gidbuf, sz);
CHECK_STRLCAT(buf, ")", sz); CHECK_STRLCAT(buf, ")", sz);
@@ -1708,6 +1713,8 @@ sudo_ldap_build_pass1(LDAP *ld, struct passwd *pw)
} }
/* Done with groups. */ /* Done with groups. */
if (gidlist != NULL)
sudo_gidlist_delref(gidlist);
if (grlist != NULL) if (grlist != NULL)
sudo_grlist_delref(grlist); sudo_grlist_delref(grlist);
if (grp != NULL) if (grp != NULL)
@@ -3101,7 +3108,7 @@ sudo_ldap_open(struct sudo_nss *nss)
handle->ld = ld; handle->ld = ld;
/* handle->result = NULL; */ /* handle->result = NULL; */
/* handle->username = NULL; */ /* handle->username = NULL; */
/* handle->grlist = NULL; */ /* handle->gidlist = NULL; */
nss->handle = handle; nss->handle = handle;
done: done:
@@ -3372,7 +3379,7 @@ sudo_ldap_result_free_nss(struct sudo_nss *nss)
DPRINTF1("removing reusable search result"); DPRINTF1("removing reusable search result");
sudo_ldap_result_free(handle->result); sudo_ldap_result_free(handle->result);
handle->username = NULL; handle->username = NULL;
handle->grlist = NULL; handle->gidlist = NULL;
handle->result = NULL; handle->result = NULL;
} }
debug_return; debug_return;
@@ -3400,7 +3407,7 @@ sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw)
* have to contact the LDAP server again. * have to contact the LDAP server again.
*/ */
if (handle->result) { if (handle->result) {
if (handle->grlist == user_group_list && if (handle->gidlist == user_gid_list &&
strcmp(pw->pw_name, handle->username) == 0) { strcmp(pw->pw_name, handle->username) == 0) {
DPRINTF1("reusing previous result (user %s) with %d entries", DPRINTF1("reusing previous result (user %s) with %d entries",
handle->username, handle->result->nentries); 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. */ /* Store everything in the sudo_nss handle. */
/* XXX - store pw and take a reference to it. */ /* XXX - store pw and take a reference to it. */
/* XXX - take refs for gidlist and grlist */
handle->result = lres; handle->result = lres;
handle->username = pw->pw_name; handle->username = pw->pw_name;
handle->grlist = user_group_list; handle->gidlist = user_gid_list;
debug_return_ptr(lres); debug_return_ptr(lres);
} }

View File

@@ -492,11 +492,11 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask,
gid_t egid; gid_t egid;
size_t glsize; size_t glsize;
char *cp, *gid_list; 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. */ /* We reserve an extra spot in the list for the effective gid. */
glsize = sizeof("runas_groups=") - 1 + 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); gid_list = malloc(glsize);
if (gid_list == NULL) if (gid_list == NULL)
goto oom; goto oom;
@@ -513,10 +513,10 @@ sudoers_policy_exec_setup(char *argv[], char *envp[], mode_t cmnd_umask,
goto bad; goto bad;
} }
cp += len; cp += len;
for (i = 0; i < grlist->ngids; i++) { for (i = 0; i < gidlist->ngids; i++) {
if (grlist->gids[i] != egid) { if (gidlist->gids[i] != egid) {
len = snprintf(cp, glsize - (cp - gid_list), ",%u", 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)) { if (len < 0 || (size_t)len >= glsize - (cp - gid_list)) {
sudo_warnx(U_("internal error, %s overflow"), __func__); sudo_warnx(U_("internal error, %s overflow"), __func__);
free(gid_list); 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; command_info[info_len++] = gid_list;
sudo_grlist_delref(grlist); sudo_gidlist_delref(gidlist);
} }
if (def_closefrom >= 0) { if (def_closefrom >= 0) {
if (asprintf(&command_info[info_len++], "closefrom=%d", def_closefrom) == -1) 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); sudo_gr_delref(runas_gr);
runas_gr = NULL; runas_gr = NULL;
} }
if (user_group_list != NULL) { if (user_gid_list != NULL) {
sudo_grlist_delref(user_group_list); sudo_gidlist_delref(user_gid_list);
user_group_list = NULL; user_gid_list = NULL;
} }
free(user_gids); free(user_gids);
user_gids = NULL; user_gids = NULL;

View File

@@ -48,7 +48,7 @@
*/ */
static struct rbtree *pwcache_byuid, *pwcache_byname; static struct rbtree *pwcache_byuid, *pwcache_byname;
static struct rbtree *grcache_bygid, *grcache_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_pwuid(const void *, const void *);
static int cmp_pwnam(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); 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 void
sudo_grlist_addref(struct group_list *grlist) 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++; ptr_to_item(grlist)->refcnt++;
debug_return; debug_return;
} }
@@ -664,7 +692,7 @@ static void
sudo_grlist_delref_item(void *v) sudo_grlist_delref_item(void *v)
{ {
struct cache_item *item = 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) if (--item->refcnt == 0)
free(item); free(item);
@@ -675,7 +703,7 @@ sudo_grlist_delref_item(void *v)
void void
sudo_grlist_delref(struct group_list *grlist) 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)); sudo_grlist_delref_item(ptr_to_item(grlist));
debug_return; debug_return;
} }
@@ -697,6 +725,10 @@ sudo_freegrcache(void)
rbdestroy(grlist_cache, sudo_grlist_delref_item); rbdestroy(grlist_cache, sudo_grlist_delref_item);
grlist_cache = NULL; grlist_cache = NULL;
} }
if (gidlist_cache != NULL) {
rbdestroy(gidlist_cache, sudo_gidlist_delref_item);
gidlist_cache = NULL;
}
debug_return; debug_return;
} }
@@ -708,8 +740,11 @@ sudo_get_grlist(const struct passwd *pw)
struct rbnode *node; struct rbnode *node;
debug_decl(sudo_get_grlist, SUDOERS_DEBUG_NSS) 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) { if (grlist_cache == NULL) {
grlist_cache = rbcreate(cmp_grnam); grlist_cache = rbcreate(cmp_pwnam);
if (grlist_cache == NULL) { if (grlist_cache == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_ptr(NULL); 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. * 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) { if (item == NULL) {
/* Out of memory? */ /* Out of memory? */
debug_return_ptr(NULL); debug_return_ptr(NULL);
@@ -759,14 +794,14 @@ done:
} }
int 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 cache_item key, *item;
struct rbnode *node; struct rbnode *node;
debug_decl(sudo_set_grlist, SUDOERS_DEBUG_NSS) debug_decl(sudo_set_grlist, SUDOERS_DEBUG_NSS)
if (grlist_cache == NULL) { if (grlist_cache == NULL) {
grlist_cache = rbcreate(cmp_grnam); grlist_cache = rbcreate(cmp_pwnam);
if (grlist_cache == NULL) { if (grlist_cache == NULL) {
sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory")); sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
debug_return_int(-1); 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; key.k.name = pw->pw_name;
getauthregistry(NULL, key.registry); getauthregistry(NULL, key.registry);
if ((node = rbfind(grlist_cache, &key)) == NULL) { 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); sudo_warnx(U_("unable to parse groups for %s"), pw->pw_name);
debug_return_int(-1); debug_return_int(-1);
} }
@@ -800,17 +835,120 @@ sudo_set_grlist(struct passwd *pw, char * const *groups, char * const *gids)
debug_return_int(0); 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 bool
user_in_group(const struct passwd *pw, const char *group) 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; struct group *grp = NULL;
const char *errstr; const char *errstr;
int i; int i;
bool matched = false; bool matched = false;
debug_decl(user_in_group, SUDOERS_DEBUG_NSS) 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. * 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; matched = true;
goto done; goto done;
} }
for (i = 0; i < grlist->ngids; i++) { for (i = 0; i < gidlist->ngids; i++) {
if (gid == grlist->gids[i]) { if (gid == gidlist->gids[i]) {
matched = true; matched = true;
goto done; goto done;
} }
@@ -837,10 +975,12 @@ user_in_group(const struct passwd *pw, const char *group)
* Next check the supplementary group vector. * Next check the supplementary group vector.
* It usually includes the password db group too. * It usually includes the password db group too.
*/ */
for (i = 0; i < grlist->ngroups; i++) { if ((grlist = sudo_get_grlist(pw)) != NULL) {
if (strcasecmp(group, grlist->groups[i]) == 0) { for (i = 0; i < grlist->ngroups; i++) {
matched = true; if (strcasecmp(group, grlist->groups[i]) == 0) {
goto done; matched = true;
goto done;
}
} }
} }
@@ -854,7 +994,9 @@ user_in_group(const struct passwd *pw, const char *group)
done: done:
if (grp != NULL) if (grp != NULL)
sudo_gr_delref(grp); 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", sudo_debug_printf(SUDO_DEBUG_DEBUG, "%s: user %s %sin group %s",
__func__, pw->pw_name, matched ? "" : "NOT ", group); __func__, pw->pw_name, matched ? "" : "NOT ", group);

View File

@@ -36,12 +36,13 @@ struct cache_item {
struct passwd *pw; struct passwd *pw;
struct group *gr; struct group *gr;
struct group_list *grlist; struct group_list *grlist;
struct gid_list *gidlist;
} d; } d;
}; };
/* /*
* Container structs to simpify size and offset calculations and guarantee * 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_pw {
struct cache_item cache; struct cache_item cache;
@@ -59,8 +60,15 @@ struct cache_item_grlist {
/* actually bigger */ /* 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_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); struct cache_item *sudo_make_pwitem(uid_t uid, const char *user);
#endif /* SUDOERS_PWUTIL_H */ #endif /* SUDOERS_PWUTIL_H */

View File

@@ -230,17 +230,15 @@ sudo_make_gritem(gid_t gid, const char *name)
* elements. Fills in datum from user_gids or from getgrouplist(3). * elements. Fills in datum from user_gids or from getgrouplist(3).
*/ */
struct cache_item * struct cache_item *
sudo_make_grlist_item(const struct passwd *pw, char * const *unused1, sudo_make_gidlist_item(const struct passwd *pw, char * const *unused1)
char * const *unused2)
{ {
char *cp; char *cp;
size_t nsize, ngroups, total, len; size_t nsize, total;
struct cache_item_grlist *grlitem; struct cache_item_gidlist *glitem;
struct group_list *grlist; struct gid_list *gidlist;
GETGROUPS_T *gids; GETGROUPS_T *gids;
struct group *grp = NULL; int i, ngids;
int i, ngids, groupname_len; debug_decl(sudo_make_gidlist_item, SUDOERS_DEBUG_NSS)
debug_decl(sudo_make_grlist_item, SUDOERS_DEBUG_NSS)
if (pw == sudo_user.pw && sudo_user.gids != NULL) { if (pw == sudo_user.pw && sudo_user.gids != NULL) {
gids = user_gids; gids = user_gids;
@@ -286,27 +284,88 @@ sudo_make_grlist_item(const struct passwd *pw, char * const *unused1,
debug_return_ptr(NULL); 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. */ /* Allocate in one big chunk for easy freeing. */
nsize = strlen(pw->pw_name) + 1; nsize = strlen(pw->pw_name) + 1;
total = sizeof(*grlitem) + nsize; total = sizeof(*glitem) + nsize;
total += sizeof(char *) * ngids;
total += sizeof(gid_t *) * ngids; total += sizeof(gid_t *) * ngids;
total += groupname_len * ngids;
again: if ((glitem = calloc(1, total)) == NULL) {
if ((grlitem = calloc(1, total)) == NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"unable to allocate memory"); "unable to allocate memory");
free(gids); free(gids);
debug_return_ptr(NULL); 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 * Copy in group list and make pointers relative to space
* at the end of the buffer. Note that the groups array must come * at the end of the buffer. Note that the groups array must come
@@ -315,9 +374,7 @@ again:
grlist = &grlitem->grlist; grlist = &grlitem->grlist;
cp = (char *)(grlitem + 1); cp = (char *)(grlitem + 1);
grlist->groups = (char **)cp; grlist->groups = (char **)cp;
cp += sizeof(char *) * ngids; cp += sizeof(char *) * gidlist->ngids;
grlist->gids = (gid_t *)cp;
cp += sizeof(gid_t) * ngids;
/* Set key and datum. */ /* Set key and datum. */
memcpy(cp, pw->pw_name, nsize); memcpy(cp, pw->pw_name, nsize);
@@ -326,13 +383,6 @@ again:
grlitem->cache.refcnt = 1; grlitem->cache.refcnt = 1;
cp += nsize; 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. * Resolve and store group names by ID.
*/ */
@@ -341,8 +391,8 @@ again:
aix_setauthdb((char *) pw->pw_name, NULL); aix_setauthdb((char *) pw->pw_name, NULL);
#endif #endif
ngroups = 0; ngroups = 0;
for (i = 0; i < ngids; i++) { for (i = 0; i < gidlist->ngids; i++) {
if ((grp = sudo_getgrgid(gids[i])) != NULL) { if ((grp = sudo_getgrgid(gidlist->gids[i])) != NULL) {
len = strlen(grp->gr_name) + 1; len = strlen(grp->gr_name) + 1;
if (cp - (char *)grlitem + len > total) { if (cp - (char *)grlitem + len > total) {
total += len + groupname_len; total += len + groupname_len;
@@ -357,7 +407,7 @@ again:
} }
} }
grlist->ngroups = ngroups; grlist->ngroups = ngroups;
free(gids); sudo_gidlist_delref(gidlist);
#ifdef HAVE_SETAUTHDB #ifdef HAVE_SETAUTHDB
aix_restoreauthdb(); aix_restoreauthdb();

View File

@@ -44,7 +44,7 @@
* Prototypes * Prototypes
*/ */
#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) #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 #endif
/* /*
@@ -62,7 +62,7 @@ struct perm_state {
#if defined(HAVE_SETRESUID) || defined(ID_SAVED) #if defined(HAVE_SETRESUID) || defined(ID_SAVED)
gid_t sgid; gid_t sgid;
#endif #endif
struct group_list *grlist; struct gid_list *gidlist;
}; };
#define PERM_STACK_MAX 16 #define PERM_STACK_MAX 16
@@ -84,7 +84,7 @@ rewind_perms(void)
if (!restore_perms()) if (!restore_perms())
debug_return_bool(false); debug_return_bool(false);
} }
sudo_grlist_delref(perm_stack[0].grlist); sudo_gidlist_delref(perm_stack[0].gidlist);
} }
debug_return_bool(true); debug_return_bool(true);
@@ -147,8 +147,8 @@ set_perms(int perm)
state->egid = getegid(); state->egid = getegid();
state->sgid = state->egid; /* in case we are setgid */ state->sgid = state->egid; /* in case we are setgid */
#endif #endif
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
"ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d", "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
__func__, (int)state->ruid, (int)state->euid, (int)state->suid, __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"); errstr = N_("unable to change to root gid");
goto bad; goto bad;
} }
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
break; break;
case PERM_USER: case PERM_USER:
@@ -197,10 +197,10 @@ set_perms(int perm)
ID(rgid), ID(egid), ID(sgid)); ID(rgid), ID(egid), ID(sgid));
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_USER: setgroups"; errstr = "PERM_USER: setgroups";
goto bad; goto bad;
} }
@@ -234,10 +234,10 @@ set_perms(int perm)
ID(rgid), ID(egid), ID(sgid)); ID(rgid), ID(egid), ID(sgid));
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_FULL_USER: setgroups"; errstr = "PERM_FULL_USER: setgroups";
goto bad; goto bad;
} }
@@ -269,8 +269,8 @@ set_perms(int perm)
errstr = N_("unable to change to runas gid"); errstr = N_("unable to change to runas gid");
goto bad; goto bad;
} }
state->grlist = runas_setgroups(); state->gidlist = runas_setgroups();
if (state->grlist == NULL) { if (state->gidlist == NULL) {
errstr = N_("unable to set runas group vector"); errstr = N_("unable to set runas group vector");
goto bad; goto bad;
} }
@@ -288,8 +288,8 @@ set_perms(int perm)
break; break;
case PERM_SUDOERS: case PERM_SUDOERS:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
/* assumes euid == ROOT_UID, ruid == user */ /* assumes euid == ROOT_UID, ruid == user */
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
@@ -328,8 +328,8 @@ set_perms(int perm)
break; break;
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
state->egid = ostate->egid; state->egid = ostate->egid;
state->sgid = ostate->sgid; state->sgid = ostate->sgid;
@@ -402,13 +402,13 @@ restore_perms(void)
(int)OID(rgid), (int)OID(egid), (int)OID(sgid)); (int)OID(rgid), (int)OID(egid), (int)OID(sgid));
goto bad; goto bad;
} }
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
sudo_warn("setgroups()"); sudo_warn("setgroups()");
goto bad; goto bad;
} }
} }
sudo_grlist_delref(state->grlist); sudo_gidlist_delref(state->gidlist);
debug_return_bool(true); debug_return_bool(true);
bad: bad:
@@ -459,8 +459,8 @@ set_perms(int perm)
state->rgid = getgidx(ID_REAL); state->rgid = getgidx(ID_REAL);
state->egid = getgidx(ID_EFFECTIVE); state->egid = getgidx(ID_EFFECTIVE);
state->sgid = getgidx(ID_SAVED); state->sgid = getgidx(ID_SAVED);
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
"ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d", "ruid: %d, euid: %d, suid: %d, rgid: %d, egid: %d, sgid: %d",
__func__, (unsigned int)state->ruid, (unsigned int)state->euid, __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"); errstr = N_("unable to change to root gid");
goto bad; goto bad;
} }
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
break; break;
case PERM_USER: case PERM_USER:
@@ -510,10 +510,10 @@ set_perms(int perm)
"PERM_USER: setgidx(ID_EFFECTIVE, %d)", user_gid); "PERM_USER: setgidx(ID_EFFECTIVE, %d)", user_gid);
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_USER: setgroups"; errstr = "PERM_USER: setgroups";
goto bad; goto bad;
} }
@@ -555,10 +555,10 @@ set_perms(int perm)
user_gid); user_gid);
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_FULL_USER: setgroups"; errstr = "PERM_FULL_USER: setgroups";
goto bad; goto bad;
} }
@@ -590,8 +590,8 @@ set_perms(int perm)
errstr = N_("unable to change to runas gid"); errstr = N_("unable to change to runas gid");
goto bad; goto bad;
} }
state->grlist = runas_setgroups(); state->gidlist = runas_setgroups();
if (state->grlist == NULL) { if (state->gidlist == NULL) {
errstr = N_("unable to set runas group vector"); errstr = N_("unable to set runas group vector");
goto bad; goto bad;
} }
@@ -609,8 +609,8 @@ set_perms(int perm)
break; break;
case PERM_SUDOERS: case PERM_SUDOERS:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
/* assume euid == ROOT_UID, ruid == user */ /* assume euid == ROOT_UID, ruid == user */
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
@@ -658,8 +658,8 @@ set_perms(int perm)
break; break;
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
state->egid = ostate->egid; state->egid = ostate->egid;
state->sgid = ostate->sgid; state->sgid = ostate->sgid;
@@ -805,13 +805,13 @@ restore_perms(void)
} }
} }
} }
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
sudo_warn("setgroups()"); sudo_warn("setgroups()");
goto bad; goto bad;
} }
} }
sudo_grlist_delref(state->grlist); sudo_gidlist_delref(state->gidlist);
debug_return_bool(true); debug_return_bool(true);
bad: bad:
@@ -860,8 +860,8 @@ set_perms(int perm)
state->euid = geteuid(); state->euid = geteuid();
state->rgid = getgid(); state->rgid = getgid();
state->egid = getegid(); state->egid = getegid();
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
"ruid: %d, euid: %d, rgid: %d, egid: %d", __func__, "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
(int)state->ruid, (int)state->euid, (int)state->ruid, (int)state->euid,
@@ -901,8 +901,8 @@ set_perms(int perm)
"PERM_ROOT: setregid(%d, %d)", ID(rgid), ID(egid)); "PERM_ROOT: setregid(%d, %d)", ID(rgid), ID(egid));
goto bad; goto bad;
} }
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
break; break;
case PERM_USER: case PERM_USER:
@@ -916,10 +916,10 @@ set_perms(int perm)
"PERM_USER: setregid(%d, %d)", ID(rgid), ID(egid)); "PERM_USER: setregid(%d, %d)", ID(rgid), ID(egid));
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_USER: setgroups"; errstr = "PERM_USER: setgroups";
goto bad; goto bad;
} }
@@ -948,10 +948,10 @@ set_perms(int perm)
"PERM_FULL_USER: setregid(%d, %d)", ID(rgid), ID(egid)); "PERM_FULL_USER: setregid(%d, %d)", ID(rgid), ID(egid));
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_FULL_USER: setgroups"; errstr = "PERM_FULL_USER: setgroups";
goto bad; goto bad;
} }
@@ -978,8 +978,8 @@ set_perms(int perm)
errstr = N_("unable to change to runas gid"); errstr = N_("unable to change to runas gid");
goto bad; goto bad;
} }
state->grlist = runas_setgroups(); state->gidlist = runas_setgroups();
if (state->grlist == NULL) { if (state->gidlist == NULL) {
errstr = N_("unable to set runas group vector"); errstr = N_("unable to set runas group vector");
goto bad; goto bad;
} }
@@ -995,8 +995,8 @@ set_perms(int perm)
break; break;
case PERM_SUDOERS: case PERM_SUDOERS:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
/* assume euid == ROOT_UID, ruid == user */ /* assume euid == ROOT_UID, ruid == user */
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
@@ -1030,8 +1030,8 @@ set_perms(int perm)
break; break;
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
state->egid = ostate->egid; state->egid = ostate->egid;
state->ruid = ROOT_UID; state->ruid = ROOT_UID;
@@ -1103,13 +1103,13 @@ restore_perms(void)
(int)state->egid, (int)OID(rgid), (int)OID(egid)); (int)state->egid, (int)OID(rgid), (int)OID(egid));
goto bad; goto bad;
} }
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
sudo_warn("setgroups()"); sudo_warn("setgroups()");
goto bad; goto bad;
} }
} }
sudo_grlist_delref(state->grlist); sudo_gidlist_delref(state->gidlist);
debug_return_bool(true); debug_return_bool(true);
bad: bad:
@@ -1173,8 +1173,8 @@ set_perms(int perm)
state->euid = geteuid(); state->euid = geteuid();
state->rgid = getgid(); state->rgid = getgid();
state->egid = getegid(); state->egid = getegid();
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
"ruid: %d, euid: %d, rgid: %d, egid: %d", __func__, "ruid: %d, euid: %d, rgid: %d, egid: %d", __func__,
(int)state->ruid, (int)state->euid, (int)state->ruid, (int)state->euid,
@@ -1197,8 +1197,8 @@ set_perms(int perm)
errstr = N_("unable to change to root gid"); errstr = N_("unable to change to root gid");
goto bad; goto bad;
} }
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
break; break;
case PERM_USER: case PERM_USER:
@@ -1212,10 +1212,10 @@ set_perms(int perm)
"PERM_USER: setegid(%d)", user_gid); "PERM_USER: setegid(%d)", user_gid);
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_USER: setgroups"; errstr = "PERM_USER: setgroups";
goto bad; goto bad;
} }
@@ -1244,10 +1244,10 @@ set_perms(int perm)
"PERM_FULL_USER: setgid(%d)", user_gid); "PERM_FULL_USER: setgid(%d)", user_gid);
goto bad; goto bad;
} }
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_FULL_USER: setgroups"; errstr = "PERM_FULL_USER: setgroups";
goto bad; goto bad;
} }
@@ -1274,8 +1274,8 @@ set_perms(int perm)
errstr = N_("unable to change to runas gid"); errstr = N_("unable to change to runas gid");
goto bad; goto bad;
} }
state->grlist = runas_setgroups(); state->gidlist = runas_setgroups();
if (state->grlist == NULL) { if (state->gidlist == NULL) {
errstr = N_("unable to set runas group vector"); errstr = N_("unable to set runas group vector");
goto bad; goto bad;
} }
@@ -1291,8 +1291,8 @@ set_perms(int perm)
break; break;
case PERM_SUDOERS: case PERM_SUDOERS:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
/* assume euid == ROOT_UID, ruid == user */ /* assume euid == ROOT_UID, ruid == user */
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
@@ -1326,8 +1326,8 @@ set_perms(int perm)
break; break;
case PERM_TIMESTAMP: case PERM_TIMESTAMP:
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
state->egid = ostate->egid; state->egid = ostate->egid;
state->ruid = ROOT_UID; state->ruid = ROOT_UID;
@@ -1394,8 +1394,8 @@ restore_perms(void)
sudo_warn("setegid(%d)", (int)ostate->egid); sudo_warn("setegid(%d)", (int)ostate->egid);
goto bad; goto bad;
} }
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
sudo_warn("setgroups()"); sudo_warn("setgroups()");
goto bad; goto bad;
} }
@@ -1404,7 +1404,7 @@ restore_perms(void)
sudo_warn("seteuid(%d)", ostate->euid); sudo_warn("seteuid(%d)", ostate->euid);
goto bad; goto bad;
} }
sudo_grlist_delref(state->grlist); sudo_gidlist_delref(state->gidlist);
debug_return_bool(true); debug_return_bool(true);
bad: bad:
@@ -1447,8 +1447,8 @@ set_perms(int perm)
/* Stash initial state */ /* Stash initial state */
state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid(); state->ruid = geteuid() == ROOT_UID ? ROOT_UID : getuid();
state->rgid = getgid(); state->rgid = getgid();
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_INITIAL: "
"ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid); "ruid: %d, rgid: %d", __func__, (int)state->ruid, (int)state->rgid);
break; break;
@@ -1456,8 +1456,8 @@ set_perms(int perm)
case PERM_ROOT: case PERM_ROOT:
state->ruid = ROOT_UID; state->ruid = ROOT_UID;
state->rgid = ROOT_GID; state->rgid = ROOT_GID;
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_ROOT: uid: "
"[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid); "[%d] -> [%d]", __func__, (int)ostate->ruid, (int)state->ruid);
if (setuid(ROOT_UID)) { if (setuid(ROOT_UID)) {
@@ -1477,10 +1477,10 @@ set_perms(int perm)
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: " sudo_debug_printf(SUDO_DEBUG_INFO, "%s: PERM_FULL_USER: gid: "
"[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid); "[%d] -> [%d]", __func__, (int)ostate->rgid, (int)state->rgid);
(void) setgid(user_gid); (void) setgid(user_gid);
state->grlist = user_group_list; state->gidlist = user_gid_list;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(state->grlist->ngids, state->grlist->gids)) { if (sudo_setgroups(state->gidlist->ngids, state->gidlist->gids)) {
errstr = "PERM_FULL_USER: setgroups"; errstr = "PERM_FULL_USER: setgroups";
goto bad; goto bad;
} }
@@ -1502,8 +1502,8 @@ set_perms(int perm)
/* Unsupported since we can't set euid. */ /* Unsupported since we can't set euid. */
state->ruid = ostate->ruid; state->ruid = ostate->ruid;
state->rgid = ostate->rgid; state->rgid = ostate->rgid;
state->grlist = ostate->grlist; state->gidlist = ostate->gidlist;
sudo_grlist_addref(state->grlist); sudo_gidlist_addref(state->gidlist);
break; break;
} }
@@ -1541,13 +1541,13 @@ restore_perms(void)
sudo_warn("setgid(%d)", (int)ostate->rgid); sudo_warn("setgid(%d)", (int)ostate->rgid);
goto bad; goto bad;
} }
if (state->grlist != ostate->grlist) { if (state->gidlist != ostate->gidlist) {
if (sudo_setgroups(ostate->grlist->ngids, ostate->grlist->gids)) { if (sudo_setgroups(ostate->gidlist->ngids, ostate->gidlist->gids)) {
sudo_warn("setgroups()"); sudo_warn("setgroups()");
goto bad; goto bad;
} }
} }
sudo_grlist_delref(state->grlist); sudo_gidlist_delref(state->gidlist);
if (OID(ruid) != (uid_t)-1 && setuid(ostate->ruid)) { if (OID(ruid) != (uid_t)-1 && setuid(ostate->ruid)) {
sudo_warn("setuid(%d)", (int)ostate->ruid); sudo_warn("setuid(%d)", (int)ostate->ruid);
goto bad; goto bad;
@@ -1560,26 +1560,26 @@ bad:
#endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */
#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) #if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID)
static struct group_list * static struct gid_list *
runas_setgroups(void) runas_setgroups(void)
{ {
struct passwd *pw; struct passwd *pw;
struct group_list *grlist; struct gid_list *gidlist;
debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS) debug_decl(runas_setgroups, SUDOERS_DEBUG_PERMS)
if (def_preserve_groups) { if (def_preserve_groups) {
sudo_grlist_addref(user_group_list); sudo_gidlist_addref(user_gid_list);
debug_return_ptr(user_group_list); debug_return_ptr(user_gid_list);
} }
pw = runas_pw ? runas_pw : sudo_user.pw; pw = runas_pw ? runas_pw : sudo_user.pw;
grlist = sudo_get_grlist(pw); gidlist = sudo_get_gidlist(pw);
if (grlist != NULL) { if (gidlist != NULL) {
if (sudo_setgroups(grlist->ngids, grlist->gids) < 0) { if (sudo_setgroups(gidlist->ngids, gidlist->gids) < 0) {
sudo_grlist_delref(grlist); sudo_gidlist_delref(gidlist);
grlist = NULL; gidlist = NULL;
} }
} }
debug_return_ptr(grlist); debug_return_ptr(gidlist);
} }
#endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ #endif /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */

View File

@@ -695,8 +695,8 @@ init_vars(char * const envp[])
unknown_user = true; unknown_user = true;
} }
} }
if (user_group_list == NULL) if (user_gid_list == NULL)
user_group_list = sudo_get_grlist(sudo_user.pw); user_gid_list = sudo_get_gidlist(sudo_user.pw);
/* Store initialize permissions so we can restore them later. */ /* Store initialize permissions so we can restore them later. */
if (!set_perms(PERM_INITIAL)) if (!set_perms(PERM_INITIAL))

View File

@@ -45,13 +45,19 @@
#include "sudoers_debug.h" #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 { struct group_list {
char **groups;
GETGROUPS_T *gids;
int ngroups; int ngroups;
int ngids; char **groups;
}; };
/* /*
@@ -77,7 +83,7 @@ struct sudo_user {
char *cmnd_safe; char *cmnd_safe;
char *class_name; char *class_name;
char *krb5_ccname; char *krb5_ccname;
struct group_list *group_list; struct gid_list *gid_list;
char * const * env_vars; char * const * env_vars;
#ifdef HAVE_SELINUX #ifdef HAVE_SELINUX
char *role; char *role;
@@ -183,7 +189,7 @@ struct sudo_user {
#define user_dir (sudo_user.pw->pw_dir) #define user_dir (sudo_user.pw->pw_dir)
#define user_gids (sudo_user.gids) #define user_gids (sudo_user.gids)
#define user_ngids (sudo_user.ngids) #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_tty (sudo_user.tty)
#define user_ttypath (sudo_user.ttypath) #define user_ttypath (sudo_user.ttypath)
#define user_cwd (sudo_user.cwd) #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 *); __dso_public void sudo_gr_delref(struct group *);
bool user_in_group(const struct passwd *, const char *); bool user_in_group(const struct passwd *, const char *);
struct group *sudo_fakegrnam(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 group_list *sudo_get_grlist(const struct passwd *pw);
struct passwd *sudo_fakepwnam(const char *, gid_t); 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); 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_endspent(void);
void sudo_freegrcache(void); void sudo_freegrcache(void);
void sudo_freepwcache(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_addref(struct group_list *);
void sudo_grlist_delref(struct group_list *); void sudo_grlist_delref(struct group_list *);
void sudo_pw_addref(struct passwd *); void sudo_pw_addref(struct passwd *);
void sudo_pw_delref(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); void sudo_setspent(void);
/* timestr.c */ /* timestr.c */