]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
setuidgid: accept numeric UID, and new option -g GID,GID1,GID2,...
authorLasse Collin <lasse.collin@tukaani.org>
Thu, 22 Nov 2007 09:25:24 +0000 (11:25 +0200)
committerJim Meyering <meyering@redhat.com>
Sat, 24 Nov 2007 14:08:43 +0000 (15:08 +0100)
* src/setuidgid.c: Add functionality for the new test above.

ChangeLog
src/setuidgid.c

index 3caaaa36ff5259cd39a6f579973b1064ee8d18a9..1810cb1716c3a17f2bb197788c7b213f4fcd4b90 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2007-11-24  Jim Meyering  <meyering@redhat.com>
 
+       setuidgid: accept numeric UID, and new option -g GID,GID1,GID2,...
+       * src/setuidgid.c: Add functionality for the new test above.
+
        "cp -p" tries to preserve GID even if preserving the UID fails.
        * NEWS: Mention this new feature.
        * src/copy.c (set_owner): Try to preserve just the GID,
index 7e0109abaf80a554b1a0fc0aa37901a04c59cf52..884c89ac6113f2a1a4082a5c4de6baa592597243 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "error.h"
 #include "long-options.h"
-#include "mgetgroups.h"
+#include "getugroups.h"
 #include "quote.h"
 
 #define PROGRAM_NAME "setuidgid"
@@ -72,8 +72,9 @@ This program is useful only when run by root (user ID zero).\n\
 int
 main (int argc, char **argv)
 {
-  char const *user_id;
-  struct passwd *pwd;
+  uid_t uid;
+  GETGROUPS_T gids[NGROUPS];
+  size_t gids_count = 0;
 
   initialize_main (&argc, &argv);
   program_name = argv[0];
@@ -86,8 +87,40 @@ main (int argc, char **argv)
 
   parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION,
                      usage, AUTHORS, (char const *) NULL);
-  if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
-    usage (SETUIDGID_FAILURE);
+  {
+    int c;
+    while ((c = getopt_long (argc, argv, "+g:", NULL, NULL)) != -1)
+      {
+        switch (c)
+          {
+            case 'g':
+              {
+                char *ptr = optarg;
+                while (*ptr != '\0')
+                  {
+                    if (gids_count == NGROUPS)
+                      {
+                        error (0, 0, _("invalid argument %s"), quote (optarg));
+                        usage (SETUIDGID_FAILURE);
+                      }
+
+                    /* FIXME: Integer overflow */
+                    gids[gids_count++] = strtoul (ptr, &ptr, 10);
+                  
+                    if (*ptr != '\0' && *ptr++ != ',')
+                      {
+                        error (0, 0, _("invalid argument %s"), quote (optarg));
+                        usage (SETUIDGID_FAILURE);
+                      }
+                  }
+                break;
+              }
+            
+            default:
+              usage (SETUIDGID_FAILURE);
+          }
+      }
+  }
 
   if (argc <= optind + 1)
     {
@@ -98,37 +131,61 @@ main (int argc, char **argv)
       usage (SETUIDGID_FAILURE);
     }
 
-  user_id = argv[optind];
-  pwd = getpwnam (user_id);
-  if (pwd == NULL)
-    error (SETUIDGID_FAILURE, errno,
-          _("unknown user-ID: %s"), quote (user_id));
+  {
+    const struct passwd *pwd;
+    char *ptr;
+
+    /* FIXME: Integer overflow */
+    uid = strtoul (argv[optind], &ptr, 10);
+    if (*ptr != '\0')
+      {
+        pwd = getpwnam (argv[optind]);
+        if (pwd == NULL)
+          {
+            error (SETUIDGID_FAILURE, errno,
+                   _("unknown user-ID: %s"), quote (argv[optind]));
+            usage (SETUIDGID_FAILURE);
+          }
+        uid = pwd->pw_uid;
+      }
+    else if (gids_count == 0)
+      {
+        pwd = getpwuid (uid);
+        /* FIXME: Error message */
+        if (pwd == NULL)
+          {
+            error (SETUIDGID_FAILURE, errno,
+                   _("to use user-ID %s you need to use -g too"),
+                   quote (argv[optind]));
+            usage (SETUIDGID_FAILURE);
+          }
+      }
 
 #if HAVE_SETGROUPS
-  {
-    GETGROUPS_T *groups;
-    int n_groups = mgetgroups (user_id, pwd->pw_gid, &groups);
-    if (n_groups < 0)
+    if (gids_count == 0)
       {
-       n_groups = 1;
-       groups = xmalloc (sizeof *groups);
-       *groups = pwd->pw_gid;
+        const int tmp = getugroups (NGROUPS, gids, pwd->pw_name, pwd->pw_gid);
+        if (tmp <= 0)
+          {
+            gids[0] = pwd->pw_gid;
+            gids_count = 1;
+          }
       }
 
-    if (0 < n_groups && setgroups (n_groups, groups))
+    if (setgroups (gids_count, gids))
       error (SETUIDGID_FAILURE, errno, _("cannot set supplemental group(s)"));
-
-    free (groups);
-  }
+#else
+    gids[0] = pwd->pw_gid;
 #endif
+  }
 
-  if (setgid (pwd->pw_gid))
+  if (setgid (gids[0]))
     error (SETUIDGID_FAILURE, errno,
-          _("cannot set group-ID to %lu"), (unsigned long int) pwd->pw_gid);
+          _("cannot set group-ID to %lu"), (unsigned long int) gids[0]);
 
-  if (setuid (pwd->pw_uid))
+  if (setuid (uid))
     error (SETUIDGID_FAILURE, errno,
-          _("cannot set user-ID to %lu"), (unsigned long int) pwd->pw_uid);
+          _("cannot set user-ID to %lu"), (unsigned long int) uid);
 
   {
     char **cmd = argv + optind + 1;