]> granicus.if.org Git - sudo/commitdiff
Remove fallback to per-group lookup when matching groups in sudoers.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 25 Jul 2011 13:17:18 +0000 (09:17 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 25 Jul 2011 13:17:18 +0000 (09:17 -0400)
The sudo front-end will now use getgrouplist() to get the user's
list of groups if getgroups() fails or returns zero groups so we
always have a list of the user's groups.  For systems with
mbr_check_membership() which support more that NGROUPS_MAX groups
(Mac OS X), skip the call to getgroups() and use getgrouplist() so
we get all the groups.

plugins/sudoers/pwutil.c
plugins/sudoers/sudoers.c
plugins/sudoers/sudoers.h
src/sudo.c

index 5d4cd058952bb1c9a08a2c460fef38c0d3cf83ad..b511472c3fdc2e79be62d0c38a85f591b90ebc63 100644 (file)
@@ -777,7 +777,7 @@ get_group_list(struct passwd *pw)
      * Cache group db entry if it exists or a negative response if not.
      */
 #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
-    ngids = sysconf(_SC_NGROUPS_MAX) * 2;
+    ngids = (int)sysconf(_SC_NGROUPS_MAX) * 2;
     if (ngids < 0)
 #endif
        ngids = NGROUPS_MAX * 2;
@@ -833,135 +833,53 @@ set_group_list(const char *user, GETGROUPS_T *gids, int ngids)
     }
 }
 
-#ifndef HAVE_MBR_CHECK_MEMBERSHIP
-static int
-user_in_group_list(struct passwd *pw, struct group_list *grlist, const char *group)
+int
+user_in_group(struct passwd *pw, const char *group)
 {
+    struct group_list *grlist;
     struct group *grp = NULL;
-    int i, retval = FALSE;
+    int i, matched = FALSE;
 
-    /*
-     * If it could be a sudo-style group ID check gids first.
-     */
-    if (group[0] == '#') {
-       gid_t gid = atoi(group + 1);
-       if (gid == pw->pw_gid) {
-           retval = TRUE;
-           goto done;
-       }
-       for (i = 0; i < grlist->ngids; i++) {
-           if (gid == grlist->gids[i]) {
-               retval = TRUE;
+    if ((grlist = get_group_list(pw)) != NULL) {
+       /*
+        * If it could be a sudo-style group ID check gids first.
+        */
+       if (group[0] == '#') {
+           gid_t gid = atoi(group + 1);
+           if (gid == pw->pw_gid) {
+               matched = TRUE;
                goto done;
            }
+           for (i = 0; i < grlist->ngids; i++) {
+               if (gid == grlist->gids[i]) {
+                   matched = TRUE;
+                   goto done;
+               }
+           }
        }
-    }
-
-
-    /*
-     * 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) {
-           retval = TRUE;
-           goto done;
-       }
-    }
 
-    /* Finally check against user's primary (passwd file) group. */
-    if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
-       if (strcasecmp(group, grp->gr_name) == 0) {
-           retval = TRUE;
-           goto done;
+       /*
+        * 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;
+           }
        }
-    }
-
-done:
-    if (grp != NULL)
-       gr_delref(grp);
-    return retval;
-}
-#endif /* !HAVE_MBR_CHECK_MEMBERSHIP */
-
-int
-user_in_group_lookup(struct passwd *pw, const char *group)
-{
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-    uuid_t gu, uu;
-    int ismember;
-#else
-    char **gr_mem;
-#endif
-    struct group *grp;
-    int retval = FALSE;
-
-#ifdef HAVE_SETAUTHDB
-    aix_setauthdb(pw->pw_name);
-#endif
-    /* A group name that begins with a '#' may be a gid. */
-    if ((grp = sudo_getgrnam(group)) == NULL && *group == '#')
-       grp = sudo_getgrgid(atoi(group + 1));
-#ifdef HAVE_SETAUTHDB
-    aix_restoreauthdb();
-#endif
-    if (grp == NULL)
-       goto done;
-
-    /* check against user's primary (passwd file) gid */
-    if (grp->gr_gid == pw->pw_gid) {
-       retval = TRUE;
-       goto done;
-    }
 
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-    /* If we are matching the invoking user use the stashed uuid. */
-    if (strcmp(pw->pw_name, user_name) == 0) {
-       if (mbr_gid_to_uuid(grp->gr_gid, gu) == 0 &&
-           mbr_check_membership(user_uuid, gu, &ismember) == 0 && ismember) {
-           retval = TRUE;
-           goto done;
-       }
-    } else {
-       if (mbr_uid_to_uuid(pw->pw_uid, uu) == 0 &&
-           mbr_gid_to_uuid(grp->gr_gid, gu) == 0 &&
-           mbr_check_membership(uu, gu, &ismember) == 0 && ismember) {
-           retval = TRUE;
-           goto done;
-       }
-    }
-#else /* HAVE_MBR_CHECK_MEMBERSHIP */
-    if (grp->gr_mem != NULL) {
-       for (gr_mem = grp->gr_mem; *gr_mem; gr_mem++) {
-           if (strcmp(*gr_mem, pw->pw_name) == 0) {
-               retval = TRUE;
+       /* Finally check against user's primary (passwd file) group. */
+       if ((grp = sudo_getgrgid(pw->pw_gid)) != NULL) {
+           if (strcasecmp(group, grp->gr_name) == 0) {
+               matched = TRUE;
                goto done;
            }
        }
-    }
-#endif /* HAVE_MBR_CHECK_MEMBERSHIP */
-
 done:
-    if (grp != NULL)
-       gr_delref(grp);
-    return retval;
-}
-
-int
-user_in_group(struct passwd *pw, const char *group)
-{
-#ifndef HAVE_MBR_CHECK_MEMBERSHIP
-    struct group_list *grlist;
-
-    if ((grlist = get_group_list(pw)) != NULL) {
-       /* The base gid (from passwd) is always present. */
-       if (grlist->ngids > 1) {
-           int matched = user_in_group_list(pw, grlist, group);
-           grlist_delref(grlist);
-           return matched;
-       }
+       if (grp != NULL)
+           gr_delref(grp);
        grlist_delref(grlist);
     }
-#endif /* !HAVE_MBR_CHECK_MEMBERSHIP */
-    return user_in_group_lookup(pw, group);
+    return matched;
 }
index 90a7a9cec804dd895fcad5287e50f420df90e47d..db897d5f282e4b5ad3ad657af92e8f76464cf63f 100644 (file)
@@ -74,9 +74,6 @@
 #ifdef HAVE_SELINUX
 # include <selinux/selinux.h>
 #endif
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-# include <membership.h>
-#endif
 #include <ctype.h>
 #include <setjmp.h>
 
@@ -455,9 +452,6 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
                    if (sudo_user.pw != NULL)
                        pw_delref(sudo_user.pw);
                    sudo_user.pw = pw;
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-                   mbr_uid_to_uuid(user_uid, user_uuid);
-#endif
            }
        }
     }
@@ -827,10 +821,6 @@ init_vars(char * const envp[])
     if (user_group_list == NULL)
        user_group_list = get_group_list(sudo_user.pw);
 
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-    mbr_uid_to_uuid(user_uid, user_uuid);
-#endif
-
     /* It is now safe to use log_error() and set_perms() */
 }
 
index 6b26746e433befcdf05da4318a15b04c86dd8662..3c8c6a1e35456899576e7733d689e29860728394 100644 (file)
 #define DEFAULT_TEXT_DOMAIN    "sudoers"
 #include "gettext.h"
 
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-# include <membership.h>
-#endif
-
 /*
  * Password db and supplementary group IDs with associated group names.
  */
@@ -86,9 +82,6 @@ struct sudo_user {
     int   cols;
     uid_t uid;
     uid_t gid;
-#ifdef HAVE_MBR_CHECK_MEMBERSHIP
-    uuid_t uuid;
-#endif
 };
 
 /*
index 6fccf46d650d5ce4004fef811d7b082869f29699..c0eb9942d4d9bacdfdd42bbfe79c30136ea6c430 100644 (file)
@@ -339,20 +339,66 @@ fix_fds(void)
     }
 }
 
+/*
+ * Allocate space for groups and fill in using getgrouplist()
+ * for when we cannot use getgroups().
+ */
+static int
+fill_group_list(struct user_details *ud)
+{
+    int maxgroups, tries, rval = -1;
+
+#if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX)
+    maxgroups = (int)sysconf(_SC_NGROUPS_MAX);
+    if (maxgroups < 0)
+#endif
+       maxgroups = NGROUPS_MAX;
+
+    /*
+     * It is possible to belong to more groups in the group database
+     * than NGROUPS_MAX.  We start off with NGROUPS_MAX * 2 entries
+     * and double this as needed.
+     */
+    ud->groups = NULL;
+    ud->ngroups = maxgroups;
+    for (tries = 0; tries < 10 && rval == -1; tries++) {
+       ud->ngroups *= 2;
+       efree(ud->groups);
+       ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
+       rval = getgrouplist(ud->username, ud->gid, ud->groups, &ud->ngroups);
+    }
+    return rval;
+}
+
 static char *
 get_user_groups(struct user_details *ud)
 {
-    char *gid_list = NULL;
+    char *cp, *gid_list = NULL;
     size_t glsize;
-    char *cp;
     int i, len;
 
-    if ((ud->ngroups = getgroups(0, NULL)) <= 0)
-       return NULL;
+    /*
+     * Systems with mbr_check_membership() support more than NGROUPS_MAX
+     * groups so we cannot use getgroups().
+     */
+    ud->groups = NULL;
+#ifndef HAVE_MBR_CHECK_MEMBERSHIP
+    if ((ud->ngroups = getgroups(0, NULL)) > 0) {
+       ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
+       if (getgroups(ud->ngroups, ud->groups) < 0) {
+           efree(ud->groups);
+           ud->groups = NULL;
+       }
+    }
+#endif /* HAVE_MBR_CHECK_MEMBERSHIP */
+    if (ud->groups == NULL) {
+       if (fill_group_list(ud) == -1)
+           error(1, _("unable to get group vector"));
+    }
 
-    ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T));
-    if (getgroups(ud->ngroups, ud->groups) < 0)
-       error(1, _("unable to get group vector"));
+    /*
+     * Format group list as a comma-separated string of gids.
+     */
     glsize = sizeof("groups=") - 1 + (ud->ngroups * (MAX_UID_T_LEN + 1));
     gid_list = emalloc(glsize);
     memcpy(gid_list, "groups=", sizeof("groups=") - 1);