]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
setuidgid: set all groups, not just the primary one; mgetgroups: new module
authorJim Meyering <jim@meyering.net>
Thu, 5 Jul 2007 15:42:29 +0000 (17:42 +0200)
committerJim Meyering <jim@meyering.net>
Fri, 6 Jul 2007 05:44:39 +0000 (07:44 +0200)
I wanted to use the xgetgroups function from id.c, so factored it out
and made it into a non-exiting function (hence the "m" prefix rather than "x").
* src/setuidgid.c (main): Use mgetgroups. Include "mgetgroups.h".

* src/id.c (xgetgroups): Remove function.
Include "mgetgroups.h".
(print_group_list): Use mgetgroups, not xgetgroups.

* gl/modules/mgetgroups: New module.
* gl/lib/mgetgroups.c: New file.  mgetgroups is derived from
id.c's xgetgroups function.
* bootstrap.conf (gnulib_modules): Add mgetgroups.
* gl/m4/mgetgroups.m4: New file.
* gl/lib/mgetgroups.h: New file.

12 files changed:
ChangeLog
bootstrap.conf
gl/lib/mgetgroups.c [new file with mode: 0644]
gl/lib/mgetgroups.h [new file with mode: 0644]
gl/m4/mgetgroups.m4 [new file with mode: 0644]
gl/modules/mgetgroups [new file with mode: 0644]
lib/.cvsignore
lib/.gitignore
m4/.cvsignore
m4/.gitignore
src/id.c
src/setuidgid.c

index 470c6099eb8a10f456fccc51f5c0e2e5a1384529..7aafd142e405b6c11a2b00c2c91ce69573448cac 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,23 @@
 2007-07-05  Jim Meyering  <jim@meyering.net>
 
+       setuidgid: set all groups, not just the primary one.
+       I wanted to use the xgetgroups function from id.c, so factored
+       it out and made it into a non-exiting function (hence the "m"
+       prefix rather than "x").
+       * src/setuidgid.c (main): Use mgetgroups.
+       Include "mgetgroups.h".
+
+       * src/id.c (xgetgroups): Remove function.
+       Include "mgetgroups.h".
+       (print_group_list): Use mgetgroups, not xgetgroups.
+
+       * gl/modules/mgetgroups: New module.
+       * gl/lib/mgetgroups.c: New file.  mgetgroups is derived from
+       id.c's xgetgroups function.
+       * bootstrap.conf (gnulib_modules): Add mgetgroups.
+       * gl/m4/mgetgroups.m4: New file.
+       * gl/lib/mgetgroups.h: New file.
+
        * bootstrap: Merge in changes from gnulib.
 
        * src/id.c: Include "getugroups.h" rather than declaring manually.
index 9d2d67b5351ad49d6db626cb0fa605cafc3b1e20..7f460059bb9c306ec444a40793e4919783357bc3 100644 (file)
@@ -60,7 +60,8 @@ gnulib_modules="
        inttostr inttypes isapipe
        lchmod lchown lib-ignore linebuffer link-follow
        long-options lstat malloc mbswidth memcasecmp mempcpy
-       memrchr mkancesdirs mkdir mkdir-p mkstemp mktime modechange
+       memrchr mgetgroups
+       mkancesdirs mkdir mkdir-p mkstemp mktime modechange
        mountlist mpsort obstack pathmax perl physmem posixtm posixver putenv
        quote quotearg raise readlink mreadlink-with-size readtokens
        readtokens0 readutmp
diff --git a/gl/lib/mgetgroups.c b/gl/lib/mgetgroups.c
new file mode 100644 (file)
index 0000000..8552f26
--- /dev/null
@@ -0,0 +1,80 @@
+/* getugroups.c -- return a list of the groups a user is in
+
+   Copyright (C) 2007 Free Software Foundation.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Extracted from coreutils' src/id.c. */
+
+#include <config.h>
+
+#include "mgetgroups.h"
+
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include "getugroups.h"
+#include "xalloc.h"
+
+/* Like getugroups, but store the result in malloc'd storage.
+   Set *GROUPS to the malloc'd list of all group IDs of which USERNAME
+   is a member.  If GID is not -1, store it first.  GID should be the
+   group ID (pw_gid) obtained from getpwuid, in case USERNAME is not
+   listed in the groups database (e.g., /etc/groups).  Upon failure,
+   don't modify *GROUPS, set errno, and return -1.  Otherwise, return
+   the number of groups.  */
+
+int
+mgetgroups (const char *username, gid_t gid, GETGROUPS_T **groups)
+{
+  int max_n_groups;
+  int ng;
+  GETGROUPS_T *g;
+
+  max_n_groups = (username
+                 ? getugroups (0, NULL, username, gid)
+                 : getgroups (0, NULL));
+
+  /* If we failed to count groups with NULL for a buffer,
+     try again with a non-NULL one, just in case.  */
+  if (max_n_groups < 0)
+      max_n_groups = 5;
+
+  if (xalloc_oversized (max_n_groups, sizeof *g))
+    {
+      errno = ENOMEM;
+      return -1;
+    }
+
+  g = malloc (max_n_groups * sizeof *g);
+  if (g == NULL)
+    return -1;
+
+  ng = (username
+       ? getugroups (max_n_groups, g, username, gid)
+       : getgroups (max_n_groups, g));
+
+  if (ng < 0)
+    {
+      int saved_errno = errno;
+      free (g);
+      errno = saved_errno;
+      return -1;
+    }
+
+  *groups = g;
+  return ng;
+}
diff --git a/gl/lib/mgetgroups.h b/gl/lib/mgetgroups.h
new file mode 100644 (file)
index 0000000..23f04e1
--- /dev/null
@@ -0,0 +1,21 @@
+/* Get a list of all group IDs associated with a specified user ID.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; see the file COPYING.
+   If not, write to the Free Software Foundation,
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#include <sys/types.h>
+
+int mgetgroups (const char *username, gid_t gid, GETGROUPS_T **groups);
diff --git a/gl/m4/mgetgroups.m4 b/gl/m4/mgetgroups.m4
new file mode 100644 (file)
index 0000000..8183541
--- /dev/null
@@ -0,0 +1,10 @@
+#serial 1
+dnl Copyright (C) 2007 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_MGETGROUPS],
+[
+  AC_LIBOBJ([mgetgroups])
+])
diff --git a/gl/modules/mgetgroups b/gl/modules/mgetgroups
new file mode 100644 (file)
index 0000000..3e2ead1
--- /dev/null
@@ -0,0 +1,25 @@
+Description:
+Return the group IDs of a user in malloc'd storage.
+
+Files:
+lib/mgetgroups.c
+lib/mgetgroups.h
+m4/mgetgroups.m4
+
+Depends-on:
+free
+getugroups
+xalloc
+
+configure.ac:
+gl_MGETGROUPS
+
+Makefile.am:
+
+Include:
+
+License:
+LGPL
+
+Maintainer:
+Jim Meyering
index ea040c3b93c81d7a907a4a3ea3ad86252cda4d39..ee01fa6ec1230ec268663a9c0d3a8f1850e6ca79 100644 (file)
@@ -151,6 +151,7 @@ gettext.h
 gettime.c
 gettimeofday.c
 getugroups.c
+getugroups.h
 getusershell.c
 gnulib.mk
 group-member.c
@@ -218,6 +219,8 @@ memmove.c
 mempcpy.c
 memrchr.c
 memset.c
+mgetgroups.c
+mgetgroups.h
 mkancesdirs.c
 mkancesdirs.h
 mkdir-p.c
index ae7ef06e8b71ca873edc7afac6d64bfb24f073d9..8f77f31ad3fb373a376e24b1f83b7a2fcac57062 100644 (file)
@@ -144,6 +144,7 @@ gettext.h
 gettime.c
 gettimeofday.c
 getugroups.c
+getugroups.h
 getusershell.c
 gnulib.mk
 group-member.c
@@ -212,6 +213,8 @@ memmove.c
 mempcpy.c
 memrchr.c
 memset.c
+mgetgroups.c
+mgetgroups.h
 mkancesdirs.c
 mkancesdirs.h
 mkdir-p.c
index ec7015626684a190d632102159cfe3c9c922bfcb..88f1d88aa84ec13e632922ec090b8aaef4f57327 100644 (file)
@@ -144,6 +144,7 @@ memmove.m4
 mempcpy.m4
 memrchr.m4
 memset.m4
+mgetgroups.m4
 mkancesdirs.m4
 mkdir-p.m4
 mkdir-slash.m4
index a10566a9e08f3be54ccd63566db0c46b07e0e918..17ff10048e266e7d5d10425bd3fc3a6925f1690f 100644 (file)
@@ -92,6 +92,7 @@ iconv.m4
 iconv_h.m4
 iconv_open.m4
 idcache.m4
+include_next.m4
 inet_ntop.m4
 inline.m4
 intl.m4
@@ -138,6 +139,7 @@ memmove.m4
 mempcpy.m4
 memrchr.m4
 memset.m4
+mgetgroups.m4
 mkancesdirs.m4
 mkdir-p.m4
 mkdir-slash.m4
index 208775eb59dfee49823530f26191907d113703bf..90c944587115a1a159612429525ea7cba02af976 100644 (file)
--- a/src/id.c
+++ b/src/id.c
@@ -30,6 +30,7 @@
 #include "system.h"
 #include "error.h"
 #include "getugroups.h"
+#include "mgetgroups.h"
 #include "quote.h"
 
 /* The official name of this program (e.g., no `g' prefix).  */
@@ -278,50 +279,6 @@ print_group (gid_t gid)
     printf ("%s", grp->gr_name);
 }
 
-#if HAVE_GETGROUPS
-
-/* FIXME: document */
-
-static bool
-xgetgroups (const char *username, gid_t gid, int *n_groups,
-           GETGROUPS_T **groups)
-{
-  int max_n_groups;
-  int ng;
-  GETGROUPS_T *g = NULL;
-
-  if (!username)
-    max_n_groups = getgroups (0, NULL);
-  else
-    max_n_groups = getugroups (0, NULL, username, gid);
-
-  if (max_n_groups < 0)
-    ng = -1;
-  else
-    {
-      g = xnmalloc (max_n_groups, sizeof *g);
-      if (!username)
-       ng = getgroups (max_n_groups, g);
-      else
-       ng = getugroups (max_n_groups, g, username, gid);
-    }
-
-  if (ng < 0)
-    {
-      error (0, errno, _("cannot get supplemental group list"));
-      free (g);
-      return false;
-    }
-  else
-    {
-      *n_groups = ng;
-      *groups = g;
-      return true;
-    }
-}
-
-#endif /* HAVE_GETGROUPS */
-
 /* Print all of the distinct groups the user is in. */
 
 static void
@@ -342,13 +299,15 @@ print_group_list (const char *username)
 
 #if HAVE_GETGROUPS
   {
-    int n_groups;
     GETGROUPS_T *groups;
-    int i;
+    size_t i;
 
-    if (! xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
-                     &n_groups, &groups))
+    int n_groups = mgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
+                              &groups);
+    if (n_groups < 0)
       {
+       error (0, errno, _("failed to get groups for user %s"),
+              quote (username));
        ok = false;
        return;
       }
@@ -400,13 +359,15 @@ print_full_info (const char *username)
 
 #if HAVE_GETGROUPS
   {
-    int n_groups;
     GETGROUPS_T *groups;
-    int i;
+    size_t i;
 
-    if (! xgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
-                     &n_groups, &groups))
+    int n_groups = mgetgroups (username, (pwd ? pwd->pw_gid : (gid_t) -1),
+                              &groups);
+    if (n_groups < 0)
       {
+       error (0, errno, _("failed to get groups for user %s"),
+              quote (username));
        ok = false;
        return;
       }
index 27c4c7991ac74137d58c0842ce26f48c7496a575..ccc8403fcc938ca2cc7c418804a270be80b05538 100644 (file)
@@ -1,5 +1,5 @@
 /* setuidgid - run a command with the UID and GID of a specified user
-   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003-2007 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
 
 #include "error.h"
 #include "long-options.h"
+#include "mgetgroups.h"
 #include "quote.h"
 
 #define PROGRAM_NAME "setuidgid"
@@ -105,8 +106,21 @@ main (int argc, char **argv)
           _("unknown user-ID: %s"), quote (user_id));
 
 #if HAVE_SETGROUPS
-  if (setgroups (1, &pwd->pw_gid))
-    error (SETUIDGID_FAILURE, errno, _("cannot set supplemental group"));
+  {
+    GETGROUPS_T *groups;
+    int n_groups = mgetgroups (user_id, pwd->pw_gid, &groups);
+    if (n_groups < 0)
+      {
+       n_groups = 1;
+       groups = xmalloc (sizeof *groups);
+       *groups = pwd->pw_gid;
+      }
+
+    if (0 < n_groups && setgroups (n_groups, groups))
+      error (SETUIDGID_FAILURE, errno, _("cannot set supplemental group(s)"));
+
+    free (groups);
+  }
 #endif
 
   if (setgid (pwd->pw_gid))