summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2007-07-05 17:42:29 +0200
committerJim Meyering <jim@meyering.net>2007-07-06 07:44:39 +0200
commite0066f36c22dce02f9d6327cb881ee7eec6e7539 (patch)
tree39c5d9c47df892a1ab845e11fc89b93b8e9b6a1a
parentb8031ff7c74b153f1e929c059e42532a9771eb74 (diff)
downloadcoreutils-e0066f36c22dce02f9d6327cb881ee7eec6e7539.tar.xz
setuidgid: set all groups, not just the primary one; mgetgroups: new module
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.
-rw-r--r--ChangeLog18
-rw-r--r--bootstrap.conf3
-rw-r--r--gl/lib/mgetgroups.c80
-rw-r--r--gl/lib/mgetgroups.h21
-rw-r--r--gl/m4/mgetgroups.m410
-rw-r--r--gl/modules/mgetgroups25
-rw-r--r--lib/.cvsignore3
-rw-r--r--lib/.gitignore3
-rw-r--r--m4/.cvsignore1
-rw-r--r--m4/.gitignore2
-rw-r--r--src/id.c65
-rw-r--r--src/setuidgid.c20
12 files changed, 195 insertions, 56 deletions
diff --git a/ChangeLog b/ChangeLog
index 470c6099e..7aafd142e 100644
--- 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.
diff --git a/bootstrap.conf b/bootstrap.conf
index 9d2d67b53..7f460059b 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -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
index 000000000..8552f2639
--- /dev/null
+++ b/gl/lib/mgetgroups.c
@@ -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
index 000000000..23f04e189
--- /dev/null
+++ b/gl/lib/mgetgroups.h
@@ -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
index 000000000..81835415f
--- /dev/null
+++ b/gl/m4/mgetgroups.m4
@@ -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
index 000000000..3e2ead100
--- /dev/null
+++ b/gl/modules/mgetgroups
@@ -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
diff --git a/lib/.cvsignore b/lib/.cvsignore
index ea040c3b9..ee01fa6ec 100644
--- a/lib/.cvsignore
+++ b/lib/.cvsignore
@@ -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
diff --git a/lib/.gitignore b/lib/.gitignore
index ae7ef06e8..8f77f31ad 100644
--- a/lib/.gitignore
+++ b/lib/.gitignore
@@ -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
diff --git a/m4/.cvsignore b/m4/.cvsignore
index ec7015626..88f1d88aa 100644
--- a/m4/.cvsignore
+++ b/m4/.cvsignore
@@ -144,6 +144,7 @@ memmove.m4
mempcpy.m4
memrchr.m4
memset.m4
+mgetgroups.m4
mkancesdirs.m4
mkdir-p.m4
mkdir-slash.m4
diff --git a/m4/.gitignore b/m4/.gitignore
index a10566a9e..17ff10048 100644
--- a/m4/.gitignore
+++ b/m4/.gitignore
@@ -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
diff --git a/src/id.c b/src/id.c
index 208775eb5..90c944587 100644
--- 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;
}
diff --git a/src/setuidgid.c b/src/setuidgid.c
index 27c4c7991..ccc8403fc 100644
--- a/src/setuidgid.c
+++ b/src/setuidgid.c
@@ -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))