]> granicus.if.org Git - shadow/blobdiff - src/groupmod.c
Re-indent.
[shadow] / src / groupmod.c
index 9324822251b326591caa958dafc8fbedde6812a4..5b139df5f0a629437404efb8a99c307ae72178a9 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 1991 - 1994, Julianne Frances Haugh
  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
  * Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2009, Nicolas François
+ * Copyright (c) 2007 - 2011, Nicolas François
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -58,6 +58,7 @@
 /*
  * exit status values
  */
+/*@-exitarg@*/
 #define E_SUCCESS      0       /* success */
 #define E_USAGE                2       /* invalid command syntax */
 #define E_BAD_ARG      3       /* invalid argument to option */
@@ -68,7 +69,7 @@
 /*
  * Global variables
  */
-char *Prog;
+const char *Prog;
 
 #ifdef SHADOWGRP
 static bool is_shadow_grp;
@@ -79,10 +80,10 @@ static char *group_passwd;
 static gid_t group_id;
 static gid_t group_newid;
 
-struct cleanup_info_mod info_passwd;
-struct cleanup_info_mod info_group;
+static struct cleanup_info_mod info_passwd;
+static struct cleanup_info_mod info_group;
 #ifdef SHADOWGRP
-struct cleanup_info_mod info_gshadow;
+static struct cleanup_info_mod info_gshadow;
 #endif
 
 static bool
@@ -92,7 +93,7 @@ static bool
     pflg = false;              /* new encrypted password */
 
 /* local function prototypes */
-static void usage (void);
+static void usage (int status);
 static void new_grent (struct group *);
 
 #ifdef SHADOWGRP
@@ -112,18 +113,23 @@ static void update_primary_groups (gid_t ogid, gid_t ngid);
  * usage - display usage message and exit
  */
 
-static void usage (void)
+static void usage (int status)
 {
-       fputs (_("Usage: groupmod [options] GROUP\n"
-                "\n"
-                "Options:\n"
-                "  -g, --gid GID                 force use new GID by GROUP\n"
-                "  -h, --help                    display this help message and exit\n"
-                "  -n, --new-name NEW_GROUP      force use NEW_GROUP name by GROUP\n"
-                "  -o, --non-unique              allow using duplicate (non-unique) GID by GROUP\n"
-                "  -p, --password PASSWORD       use encrypted password for the new password\n"
-                "\n"), stderr);
-       exit (E_USAGE);
+       FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
+       (void) fprintf (usageout,
+                       _("Usage: %s [options] GROUP\n"
+                         "\n"
+                         "Options:\n"),
+                       Prog);
+       (void) fputs (_("  -g, --gid GID                 change the group ID to GID\n"), usageout);
+       (void) fputs (_("  -h, --help                    display this help message and exit\n"), usageout);
+       (void) fputs (_("  -n, --new-name NEW_GROUP      change the name to NEW_GROUP\n"), usageout);
+       (void) fputs (_("  -o, --non-unique              allow to use a duplicate (non-unique) GID\n"), usageout);
+       (void) fputs (_("  -p, --password PASSWORD       change the password to this (encrypted)\n"
+                       "                                PASSWORD\n"), usageout);
+       (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot into\n"), usageout);
+       (void) fputs ("\n", usageout);
+       exit (status);
 }
 
 /*
@@ -142,7 +148,17 @@ static void new_grent (struct group *grent)
                grent->gr_gid = group_newid;
        }
 
-       if (pflg) {
+       if (   pflg
+#ifdef SHADOWGRP
+           && (   (!is_shadow_grp)
+               || (strcmp (grent->gr_passwd, SHADOW_PASSWD_STRING) != 0))
+#endif
+               ) {
+               /* Update the password in group if there is no gshadow
+                * file or if the password is currently in group
+                * (gr_passwd != "x").  We do not force the usage of
+                * shadow passwords if it was not the case before.
+                */
                grent->gr_passwd = group_passwd;
        }
 }
@@ -160,6 +176,13 @@ static void new_sgent (struct sgrp *sgent)
                sgent->sg_name = xstrdup (group_newname);
        }
 
+       /* Always update the shadowed password if there is a shadow entry
+        * (even if shadowed passwords might not be enabled for this group
+        * (gr_passwd != "x")).
+        * It seems better to update the password in both places in case a
+        * shadow and a non shadow entry exist.
+        * This might occur only if there were already both entries.
+        */
        if (pflg) {
                sgent->sg_passwd = group_passwd;
        }
@@ -185,7 +208,7 @@ static void grp_update (void)
         * Get the current settings for this group.
         */
        ogrp = gr_locate (group_name);
-       if (!ogrp) {
+       if (NULL == ogrp) {
                fprintf (stderr,
                         _("%s: group '%s' does not exist in %s\n"),
                         Prog, group_name, gr_dbname ());
@@ -200,9 +223,21 @@ static void grp_update (void)
                if (NULL != osgrp) {
                        sgrp = *osgrp;
                        new_sgent (&sgrp);
-                       if (pflg) {
-                               grp.gr_passwd = SHADOW_PASSWD_STRING;
-                       }
+               } else if (   pflg
+                          && (strcmp (grp.gr_passwd, SHADOW_PASSWD_STRING) == 0)) {
+                       static char *empty = NULL;
+                       /* If there is a gshadow file with no entries for
+                        * the group, but the group file indicates a
+                        * shadowed password, we force the creation of a
+                        * gshadow entry when a new password is requested.
+                        */
+                       memset (&sgrp, 0, sizeof sgrp);
+                       sgrp.sg_name   = xstrdup (grp.gr_name);
+                       sgrp.sg_passwd = xstrdup (grp.gr_passwd);
+                       sgrp.sg_adm    = ∅
+                       sgrp.sg_mem    = dup_list (grp.gr_mem);
+                       new_sgent (&sgrp);
+                       osgrp = &sgrp; /* entry needs to be committed */
                }
        }
 #endif                         /* SHADOWGRP */
@@ -226,13 +261,12 @@ static void grp_update (void)
                         Prog, grp.gr_name, gr_dbname ());
                exit (E_GRP_UPDATE);
        }
-#ifdef SHADOWGRP
 
+#ifdef SHADOWGRP
        /*
         * Make sure there was a shadow entry to begin with.
         */
-       if (   (NULL != osgrp)
-           && (pflg || nflg)) {
+       if (NULL != osgrp) {
                /*
                 * Write out the new shadow group entries as well.
                 */
@@ -334,7 +368,6 @@ static void check_new_name (void)
  */
 static void process_flags (int argc, char **argv)
 {
-       int option_index = 0;
        int c;
        static struct option long_options[] = {
                {"gid", required_argument, NULL, 'g'},
@@ -342,11 +375,11 @@ static void process_flags (int argc, char **argv)
                {"new-name", required_argument, NULL, 'n'},
                {"non-unique", no_argument, NULL, 'o'},
                {"password", required_argument, NULL, 'p'},
+               {"root", required_argument, NULL, 'R'},
                {NULL, 0, NULL, '\0'}
        };
-       while ((c =
-               getopt_long (argc, argv, "g:hn:op:",
-                            long_options, &option_index)) != -1) {
+       while ((c = getopt_long (argc, argv, "g:hn:op:R:",
+                                long_options, NULL)) != -1) {
                switch (c) {
                case 'g':
                        gflg = true;
@@ -358,6 +391,9 @@ static void process_flags (int argc, char **argv)
                                exit (E_BAD_ARG);
                        }
                        break;
+               case 'h':
+                       usage (E_SUCCESS);
+                       break;
                case 'n':
                        nflg = true;
                        group_newname = optarg;
@@ -369,17 +405,19 @@ static void process_flags (int argc, char **argv)
                        group_passwd = optarg;
                        pflg = true;
                        break;
+               case 'R': /* no-op, handled in process_root_flag () */
+                       break;
                default:
-                       usage ();
+                       usage (E_USAGE);
                }
        }
 
        if (oflg && !gflg) {
-               usage ();
+               usage (E_USAGE);
        }
 
        if (optind != (argc - 1)) {
-               usage ();
+               usage (E_USAGE);
        }
 
        group_name = argv[argc - 1];
@@ -486,14 +524,14 @@ static void prepare_failure_reports (void)
 #endif
        info_passwd.audit_msg  = xmalloc (512);
 
-       snprintf (info_group.audit_msg, 511,
-                 "changing %s; ", gr_dbname ());
+       (void) snprintf (info_group.audit_msg, 511,
+                        "changing %s; ", gr_dbname ());
 #ifdef SHADOWGRP
-       snprintf (info_gshadow.audit_msg, 511,
-                 "changing %s; ", sgr_dbname ());
+       (void) snprintf (info_gshadow.audit_msg, 511,
+                        "changing %s; ", sgr_dbname ());
 #endif
-       snprintf (info_passwd.audit_msg, 511,
-                 "changing %s; ", pw_dbname ());
+       (void) snprintf (info_passwd.audit_msg, 511,
+                        "changing %s; ", pw_dbname ());
 
        info_group.action   =   info_group.audit_msg
                              + strlen (info_group.audit_msg);
@@ -504,14 +542,19 @@ static void prepare_failure_reports (void)
        info_passwd.action  =   info_passwd.audit_msg
                              + strlen (info_passwd.audit_msg);
 
-       snprintf (info_group.action,   511 - strlen (info_group.audit_msg),
-                 "group %s/%d", group_name, group_id);
+       (void) snprintf (info_group.action,
+                        511 - strlen (info_group.audit_msg),
+                        "group %s/%lu",
+                        group_name, (unsigned long int) group_id);
 #ifdef SHADOWGRP
-       snprintf (info_gshadow.action, 511 - strlen (info_group.audit_msg),
-                 "group %s", group_name);
+       (void) snprintf (info_gshadow.action,
+                        511 - strlen (info_group.audit_msg),
+                        "group %s", group_name);
 #endif
-       snprintf (info_passwd.action,  511 - strlen (info_group.audit_msg),
-                 "group %s/%d", group_name, group_id);
+       (void) snprintf (info_passwd.action,
+                        511 - strlen (info_group.audit_msg),
+                        "group %s/%lu",
+                        group_name, (unsigned long int) group_id);
 
        if (nflg) {
                strncat (info_group.action, ", new name: ",
@@ -543,15 +586,15 @@ static void prepare_failure_reports (void)
        if (gflg) {
                strncat (info_group.action, ", new gid: ",
                         511 - strlen (info_group.audit_msg));
-               snprintf (info_group.action+strlen (info_group.action),
-                         511 - strlen (info_group.audit_msg),
-                         "%d", group_newid);
+               (void) snprintf (info_group.action+strlen (info_group.action),
+                                511 - strlen (info_group.audit_msg),
+                                "%lu", (unsigned long int) group_newid);
 
                strncat (info_passwd.action, ", new gid: ",
                         511 - strlen (info_passwd.audit_msg));
-               snprintf (info_passwd.action+strlen (info_passwd.action),
-                         511 - strlen (info_passwd.audit_msg),
-                         "%d", group_newid);
+               (void) snprintf (info_passwd.action+strlen (info_passwd.action),
+                                511 - strlen (info_passwd.audit_msg),
+                                "%lu", (unsigned long int) group_newid);
        }
        info_group.audit_msg[511]   = '\0';
 #ifdef SHADOWGRP
@@ -693,11 +736,6 @@ int main (int argc, char **argv)
 #endif                         /* USE_PAM */
 #endif                         /* ACCT_TOOLS_SETUID */
 
-#ifdef WITH_AUDIT
-       audit_help_open ();
-#endif
-       atexit (do_cleanups);
-
        /*
         * Get my name so that I can use it to report errors.
         */
@@ -707,16 +745,28 @@ int main (int argc, char **argv)
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
        (void) textdomain (PACKAGE);
 
-       process_flags (argc, argv);
+       process_root_flag ("-R", argc, argv);
 
        OPENLOG ("groupmod");
+#ifdef WITH_AUDIT
+       audit_help_open ();
+#endif
+
+       if (atexit (do_cleanups) != 0) {
+               fprintf (stderr,
+                        _("%s: Cannot setup cleanup service.\n"),
+                        Prog);
+               exit (1);
+       }
+
+       process_flags (argc, argv);
 
 #ifdef ACCT_TOOLS_SETUID
 #ifdef USE_PAM
        {
                struct passwd *pampw;
                pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
-               if (NULL == pamh) {
+               if (NULL == pampw) {
                        fprintf (stderr,
                                 _("%s: Cannot determine your user name.\n"),
                                 Prog);
@@ -813,7 +863,6 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("group");
 
-       exit (E_SUCCESS);
-       /* NOT REACHED */
+       return E_SUCCESS;
 }