Change daemon's gid list to use an "item_list".
authorWayne Davison <wayned@samba.org>
Mon, 24 Aug 2015 18:23:31 +0000 (11:23 -0700)
committerWayne Davison <wayned@samba.org>
Mon, 24 Aug 2015 18:54:00 +0000 (11:54 -0700)
NEWS
authenticate.c
clientserver.c
configure.ac
uidlist.c
util.c

diff --git a/NEWS b/NEWS
index 9a3ddd5795707b94d39e18dcb39fdfebadedecf6..3fe3d3e3ba79378bc0a3d81d83d2e37756c2eda5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ Changes since 3.1.1:
       right.
     - Don't create an empty backup dir for a transferred file that doesn't
       exist yet.
+    - Allow more than 32 group IDs per user in the daemon's gid=LIST config.
 
   ENHANCEMENTS:
 
@@ -31,7 +32,6 @@ Changes since 3.1.1:
 
   DEVELOPER RELATED:
 
-    - Added --with-max-daemon-gid=NUM option to configure.
     - Fixed a bug with the Makefile's use of INSTALL_STRIP.
     - Improve a test in the suite that could get an erroneous timestamp error.
     - Tweaks for newer versions of git in the packaging tools.
index fe1e8390ba915e56b5c5ac2c6cb1e9b7812ae2ec..5f125dea2aac029718fb424502f4a2fbb15b8006 100644 (file)
@@ -279,17 +279,18 @@ char *auth_server(int f_in, int f_out, int module, const char *host,
                        /* See if authorizing user is a real user, and if so, see
                         * if it is in a group that matches tok+1 wildmat. */
                        if (auth_uid_groups_cnt < 0) {
-                               gid_t gid_list[64];
+                               item_list gid_list = EMPTY_ITEM_LIST;
                                uid_t auth_uid;
-                               auth_uid_groups_cnt = sizeof gid_list / sizeof (gid_t);
                                if (!user_to_uid(line, &auth_uid, False)
-                                || getallgroups(auth_uid, gid_list, &auth_uid_groups_cnt) != NULL)
+                                || getallgroups(auth_uid, &gid_list) != NULL)
                                        auth_uid_groups_cnt = 0;
                                else {
+                                       gid_t *gid_array = gid_list.items;
+                                       auth_uid_groups_cnt = gid_list.count;
                                        if ((auth_uid_groups = new_array(char *, auth_uid_groups_cnt)) == NULL)
                                                out_of_memory("auth_server");
                                        for (j = 0; j < auth_uid_groups_cnt; j++)
-                                               auth_uid_groups[j] = gid_to_group(gid_list[j]);
+                                               auth_uid_groups[j] = gid_to_group(gid_array[j]);
                                }
                        }
                        for (j = 0; j < auth_uid_groups_cnt; j++) {
index cf602a179d5342edc097c0b29add34a1e2503769..27f8cd38b737d29e0ef30daf77d05ee99b4c59c0 100644 (file)
@@ -79,8 +79,7 @@ static int rl_nulls = 0;
 static struct sigaction sigact;
 #endif
 
-static gid_t gid_list[MAX_DAEMON_GID_LIST];
-static int gid_count = 0;
+static item_list gid_list = EMPTY_ITEM_LIST;
 
 /* Used when "reverse lookup" is off. */
 const char undetermined_hostname[] = "UNDETERMINED";
@@ -436,18 +435,14 @@ static int path_failure(int f_out, const char *dir, BOOL was_chdir)
 
 static int add_a_group(int f_out, const char *gname)
 {
-       gid_t gid;
+       gid_t gid, *gid_p;
        if (!group_to_gid(gname, &gid, True)) {
                rprintf(FLOG, "Invalid gid %s\n", gname);
                io_printf(f_out, "@ERROR: invalid gid %s\n", gname);
                return -1;
        }
-       if (gid_count == MAX_DAEMON_GID_LIST) {
-               rprintf(FLOG, "Too many groups specified via gid parameter.\n");
-               io_printf(f_out, "@ERROR: too many groups\n");
-               return -1;
-       }
-       gid_list[gid_count++] = gid;
+       gid_p = EXPAND_ITEM_LIST(&gid_list, gid_t, -32);
+       *gid_p = gid;
        return 0;
 }
 
@@ -455,8 +450,7 @@ static int add_a_group(int f_out, const char *gname)
 static int want_all_groups(int f_out, uid_t uid)
 {
        const char *err;
-       gid_count = MAX_DAEMON_GID_LIST;
-       if ((err = getallgroups(uid, gid_list, &gid_count)) != NULL) {
+       if ((err = getallgroups(uid, &gid_list)) != NULL) {
                rsyserr(FLOG, errno, "%s", err);
                io_printf(f_out, "@ERROR: %s\n", err);
                return -1;
@@ -467,14 +461,15 @@ static int want_all_groups(int f_out, uid_t uid)
 static struct passwd *want_all_groups(int f_out, uid_t uid)
 {
        struct passwd *pw;
+       gid_t *gid_p;
        if ((pw = getpwuid(uid)) == NULL) {
                rsyserr(FLOG, errno, "getpwuid failed");
                io_printf(f_out, "@ERROR: getpwuid failed\n");
                return NULL;
        }
-       /* Start with the default group and initgroups() will add the reset. */
-       gid_count = 1;
-       gid_list[0] = pw->pw_gid;
+       /* Start with the default group and initgroups() will add the rest. */
+       gid_p = EXPAND_ITEM_LIST(&gid_list, gid_t, -32);
+       *gid_p = pw->pw_gid;
        return pw;
 }
 #endif
@@ -816,15 +811,16 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
                }
        }
 
-       if (gid_count) {
-               if (setgid(gid_list[0])) {
-                       rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_list[0]);
+       if (gid_list.count) {
+               gid_t *gid_array = gid_list.items;
+               if (setgid(gid_array[0])) {
+                       rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_array[0]);
                        io_printf(f_out, "@ERROR: setgid failed\n");
                        return -1;
                }
 #ifdef HAVE_SETGROUPS
                /* Set the group(s) we want to be active. */
-               if (setgroups(gid_count, gid_list)) {
+               if (setgroups(gid_list.count, gid_array)) {
                        rsyserr(FLOG, errno, "setgroups failed");
                        io_printf(f_out, "@ERROR: setgroups failed\n");
                        return -1;
index 89753667816d16743375927e7f208586b44e0e25..3aca2a1003b1e4e5470e895ff7e8f4d56eba1094 100644 (file)
@@ -98,14 +98,6 @@ AC_ARG_WITH(rsync-path,
 
 AC_DEFINE_UNQUOTED(RSYNC_PATH, "$RSYNC_PATH", [location of rsync on remote machine])
 
-AC_ARG_WITH(max-daemon-gid,
-       AS_HELP_STRING([--with-max-daemon-gid=NUM],
-                      [set maximum number of GIDs in the daemon "gid=LIST" config item (default: 32)]),
-                      [ MAX_DAEMON_GID_LIST=$with_max_daemon_gid ],
-                      [ MAX_DAEMON_GID_LIST=32 ])
-
-AC_DEFINE_UNQUOTED(MAX_DAEMON_GID_LIST, $MAX_DAEMON_GID_LIST, [maximum GIDs in a daemon module gid list])
-
 AC_ARG_WITH(rsyncd-conf,
        AS_HELP_STRING([--with-rsyncd-conf=PATH],[set configuration file for rsync server to PATH (default: /etc/rsyncd.conf)]),
        [ if test ! -z "$with_rsyncd_conf" ; then
index 879eeebdaa520a5dbf2ff1b92d192e46d8e48aac..1ccdd6441cbd7328fc8ed1f5958f42c87112c9c2 100644 (file)
--- a/uidlist.c
+++ b/uidlist.c
@@ -524,25 +524,49 @@ void parse_name_map(char *map, BOOL usernames)
 }
 
 #ifdef HAVE_GETGROUPLIST
-const char *getallgroups(uid_t uid, gid_t *gid_list, int *size_ptr)
+const char *getallgroups(uid_t uid, item_list *gid_list)
 {
        struct passwd *pw;
+       gid_t *gid_array;
+       int size;
+
        if ((pw = getpwuid(uid)) == NULL)
                return "getpwuid failed";
+
+       gid_list->count = 0; /* We're overwriting any items in the list */
+       EXPAND_ITEM_LIST(gid_list, gid_t, 32);
+       size = gid_list->malloced;
+
        /* Get all the process's groups, with the pw_gid group first. */
-       if (getgrouplist(pw->pw_name, pw->pw_gid, gid_list, size_ptr) < 0)
-               return "getgrouplist failed";
+       if (getgrouplist(pw->pw_name, pw->pw_gid, gid_list->items, &size) < 0) {
+               if (size > (int)gid_list->malloced) {
+                       gid_list->count = gid_list->malloced;
+                       EXPAND_ITEM_LIST(gid_list, gid_t, size);
+                       if (getgrouplist(pw->pw_name, pw->pw_gid, gid_list->items, &size) < 0)
+                               size = -1;
+               } else
+                       size = -1;
+               if (size < 0)
+                       return "getgrouplist failed";
+       }
+       gid_list->count = size;
+       gid_array = gid_list->items;
+
        /* Paranoia: is the default group not first in the list? */
-       if (gid_list[0] != pw->pw_gid) {
+       if (gid_array[0] != pw->pw_gid) {
                int j;
-               for (j = 0; j < *size_ptr; j++) {
-                       if (gid_list[j] == pw->pw_gid) {
-                               gid_list[j] = gid_list[0];
-                               gid_list[0] = pw->pw_gid;
+               for (j = 1; j < size; j++) {
+                       if (gid_array[j] == pw->pw_gid)
                                break;
-                       }
                }
+               if (j == size) { /* The default group wasn't found! */
+                       EXPAND_ITEM_LIST(gid_list, gid_t, size+1);
+                       gid_array = gid_list->items;
+               }
+               gid_array[j] = gid_array[0];
+               gid_array[0] = pw->pw_gid;
        }
+
        return NULL;
 }
 #endif
diff --git a/util.c b/util.c
index c0e239d4ae4e3b75a8c18c18d7292b8c4e4138e8..41e0c780161e6261c538edeb21a620309f5406cb 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1615,7 +1615,7 @@ void *expand_item_list(item_list *lp, size_t item_size,
                if (incr < 0)
                        new_size += -incr; /* increase slowly */
                else if (new_size < (size_t)incr)
-                       new_size += incr;
+                       new_size = incr;
                else
                        new_size *= 2;
                if (new_size < lp->malloced)