diff -up sudo-1.8.6p7/plugins/sudoers/defaults.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/defaults.c --- sudo-1.8.6p7/plugins/sudoers/defaults.c.legacy-group-processing 2013-02-25 20:42:44.000000000 +0100 +++ sudo-1.8.6p7/plugins/sudoers/defaults.c 2015-08-28 10:52:13.658671686 +0200 @@ -362,6 +362,7 @@ init_defaults(void) } /* First initialize the flags. */ + def_legacy_group_processing = true; #ifdef LONG_OTP_PROMPT def_long_otp_prompt = true; #endif diff -up sudo-1.8.6p7/plugins/sudoers/def_data.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/def_data.c --- sudo-1.8.6p7/plugins/sudoers/def_data.c.legacy-group-processing 2015-08-28 10:52:13.604671687 +0200 +++ sudo-1.8.6p7/plugins/sudoers/def_data.c 2015-08-28 10:52:13.658671686 +0200 @@ -355,6 +355,10 @@ struct sudo_defs_types sudo_defs_table[] N_("Don't fork and wait for the command to finish, just exec it"), NULL, }, { + "legacy_group_processing", T_FLAG, + N_("Don't pre-resolve all group names"), + NULL, + }, { NULL, 0, NULL } }; diff -up sudo-1.8.6p7/plugins/sudoers/def_data.h.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/def_data.h --- sudo-1.8.6p7/plugins/sudoers/def_data.h.legacy-group-processing 2015-08-28 10:52:13.604671687 +0200 +++ sudo-1.8.6p7/plugins/sudoers/def_data.h 2015-08-28 10:52:13.658671686 +0200 @@ -164,6 +164,8 @@ #define I_LIMITPRIVS 81 #define def_cmnd_no_wait (sudo_defs_table[82].sd_un.flag) #define I_CMND_NO_WAIT 82 +#define def_legacy_group_processing (sudo_defs_table[83].sd_un.flag) +#define I_LEGACY_GROUP_PROCESSING 83 enum def_tuple { never, diff -up sudo-1.8.6p7/plugins/sudoers/ldap.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/ldap.c --- sudo-1.8.6p7/plugins/sudoers/ldap.c.legacy-group-processing 2015-08-28 10:52:13.656671686 +0200 +++ sudo-1.8.6p7/plugins/sudoers/ldap.c 2015-08-28 10:52:13.659671686 +0200 @@ -1220,6 +1220,15 @@ sudo_ldap_build_pass1(struct passwd *pw) } sz += 13 + MAX_UID_T_LEN; if ((grlist = sudo_get_grlist(pw)) != NULL) { + if (!grlist->groups_resolved) { + int rc = sudo_resolve_gids(grlist->gids, grlist->ngids, + grlist->groups, grlist->groups_buffer); + if (rc < 0) { + return NULL; + } + grlist->ngroups = rc; + grlist->groups_resolved = true; + } for (i = 0; i < grlist->ngroups; i++) { if (grp != NULL && strcasecmp(grlist->groups[i], grp->gr_name) == 0) continue; diff -up sudo-1.8.6p7/plugins/sudoers/pwutil.c.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/pwutil.c --- sudo-1.8.6p7/plugins/sudoers/pwutil.c.legacy-group-processing 2015-08-28 10:52:13.633671686 +0200 +++ sudo-1.8.6p7/plugins/sudoers/pwutil.c 2015-08-28 10:52:13.659671686 +0200 @@ -542,10 +542,9 @@ static struct cache_item * make_grlist_item(const char *user, GETGROUPS_T *gids, int ngids) { char *cp; - size_t i, nsize, ngroups, total, len; + size_t i, nsize, total; struct cache_item_grlist *grlitem; struct group_list *grlist; - struct group *grp; debug_decl(make_grlist_item, SUDO_DEBUG_NSS) #ifdef HAVE_SETAUTHDB @@ -559,7 +558,6 @@ make_grlist_item(const char *user, GETGR total += sizeof(gid_t *) * ngids; total += GROUPNAME_LEN * ngids; -again: grlitem = ecalloc(1, total); /* @@ -587,27 +585,26 @@ again: for (i = 0; i < ngids; i++) grlist->gids[i] = gids[i]; grlist->ngids = ngids; + grlist->groups_buffer = cp; /* - * Resolve and store group names by ID. + * Resolve and store group names by ID if legacy_group_processing is off. */ - ngroups = 0; - for (i = 0; i < ngids; i++) { - if ((grp = sudo_getgrgid(gids[i])) != NULL) { - len = strlen(grp->gr_name) + 1; - if (cp - (char *)grlitem + len > total) { - total += len + GROUPNAME_LEN; - efree(grlitem); - sudo_gr_delref(grp); - goto again; - } - memcpy(cp, grp->gr_name, len); - grlist->groups[ngroups++] = cp; - cp += len; - sudo_gr_delref(grp); - } + if (def_legacy_group_processing) { + for (i = 0; i < ngids; i++) { + grlist->groups[i] = NULL; + } + grlist->ngroups = 0; + grlist->groups_resolved = false; + } else { + int rc = sudo_resolve_gids(gids, ngids, grlist->groups, grlist->groups_buffer); + if (rc < 0) { + efree(grlitem); + return NULL; + } + grlist->ngroups = rc; + grlist->groups_resolved = true; } - grlist->ngroups = ngroups; #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); @@ -616,6 +613,35 @@ again: debug_return_ptr(&grlitem->cache); } +int sudo_resolve_gids(GETGROUPS_T *gids, int ngids, char **groups, char *group_buffer) +{ + struct group *grp; + int space_left = ngids * GROUPNAME_LEN; + int ngroups = 0; + int i; + char *cp = group_buffer; + debug_decl(sudo_resolve_gids, SUDO_DEBUG_NSS) + + for (i = 0; i < ngids; i++) { + if ((grp = sudo_getgrgid(gids[i])) != NULL) { + int len = strlen(grp->gr_name) + 1; + + if (space_left < len) { + sudo_gr_delref(grp); + debug_return_int(-1); + } + + memcpy(cp, grp->gr_name, len); + groups[ngroups++] = cp; + cp += len; + space_left -= len; + sudo_gr_delref(grp); + } + } + + debug_return_int(ngroups); +} + void sudo_gr_addref(struct group *gr) { @@ -917,8 +943,22 @@ user_in_group(const struct passwd *pw, c /* * If it could be a sudo-style group ID check gids first. */ + bool do_gid_lookup = false; + gid_t gid; + if (group[0] == '#') { - gid_t gid = atoi(group + 1); + gid = atoi(group + 1); + do_gid_lookup = true; + } else if (def_legacy_group_processing) { + struct group *grent = sudo_getgrnam(group); + if (grent == NULL) { + goto done; + } + gid = grent->gr_gid; + do_gid_lookup = true; + } + + if (do_gid_lookup) { if (gid == pw->pw_gid) { matched = true; goto done; @@ -931,6 +971,19 @@ user_in_group(const struct passwd *pw, c } } + if (def_legacy_group_processing) { + goto done; + } + if (!grlist->groups_resolved) { + int rc = sudo_resolve_gids(grlist->gids, grlist->ngids, + grlist->groups, grlist->groups_buffer); + if (rc < 0) { + goto done; + } + grlist->ngroups = rc; + grlist->groups_resolved = true; + } + /* * Next check the supplementary group vector. * It usually includes the password db group too. diff -up sudo-1.8.6p7/plugins/sudoers/sudoers.h.legacy-group-processing sudo-1.8.6p7/plugins/sudoers/sudoers.h --- sudo-1.8.6p7/plugins/sudoers/sudoers.h.legacy-group-processing 2015-08-28 10:52:13.634671686 +0200 +++ sudo-1.8.6p7/plugins/sudoers/sudoers.h 2015-08-28 10:52:13.659671686 +0200 @@ -52,6 +52,8 @@ struct group_list { GETGROUPS_T *gids; int ngroups; int ngids; + int groups_resolved; + char *groups_buffer; }; /* @@ -289,6 +291,8 @@ __dso_public struct group *sudo_getgrnam __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 *); +int sudo_resolve_gids(GETGROUPS_T *gids, int ngids, char **groups, char *group_buffer); + struct group *sudo_fakegrnam(const char *); struct group_list *sudo_get_grlist(const struct passwd *pw); struct passwd *sudo_fakepwnam(const char *, gid_t);