1375 lines
38 KiB
Diff
1375 lines
38 KiB
Diff
Add a --root command option to the following utilties:
|
|
|
|
* useradd
|
|
* groupadd
|
|
* usermod
|
|
* groupmod
|
|
* userdel
|
|
* groupdel
|
|
* passwd
|
|
* gpasswd
|
|
* pwconv
|
|
* pwunconv
|
|
* grpconv
|
|
* grpunconv
|
|
|
|
This option allows the utilities to be chrooted when run under pseudo.
|
|
They can then be used to manipulate user and group account information
|
|
in target sysroots.
|
|
|
|
The useradd utility was also modified to create home directories
|
|
recursively when necessary.
|
|
|
|
Upstream-Status: Inappropriate [Other]
|
|
Workaround is specific to our build system.
|
|
|
|
Signed-off-by: Scott Garman <scott.a.garman@intel.com>
|
|
|
|
2011-09-29 Fix the parsing of the --root option in gpasswd, useradd, usermod:
|
|
|
|
In programs which need to scan the command line in two passes to handle
|
|
--root option separately from the rest of the arguments, replace the first
|
|
calls to getopt_long with a simple iteration over the argument list since
|
|
getopt_long has the bad habit of reordering arguments on the command line.
|
|
|
|
Signed-off-by: Julian Pidancet <julian.pidancet@gmail.com>
|
|
|
|
diff -urN shadow-4.1.4.3.orig//src/gpasswd.c shadow-4.1.4.3//src/gpasswd.c
|
|
--- shadow-4.1.4.3.orig//src/gpasswd.c 2011-09-29 12:00:45.211000091 +0100
|
|
+++ shadow-4.1.4.3//src/gpasswd.c 2011-09-29 12:09:54.590000090 +0100
|
|
@@ -63,6 +63,7 @@
|
|
* (/etc/gshadow present) */
|
|
static bool is_shadowgrp;
|
|
#endif
|
|
+static const char *newroot = "";
|
|
|
|
/* Flags set by options */
|
|
static bool aflg = false;
|
|
@@ -97,6 +98,7 @@
|
|
static void usage (void);
|
|
static RETSIGTYPE catch_signals (int killed);
|
|
static bool is_valid_user_list (const char *users);
|
|
+static void process_root_flag (int argc, char **argv);
|
|
static void process_flags (int argc, char **argv);
|
|
static void check_flags (int argc, int opt_index);
|
|
static void open_files (void);
|
|
@@ -136,6 +138,7 @@
|
|
"Options:\n"
|
|
" -a, --add USER add USER to GROUP\n"
|
|
" -d, --delete USER remove USER from GROUP\n"
|
|
+ " -Q --root CHROOT_DIR directory to chroot into\n"
|
|
" -r, --remove-password remove the GROUP's password\n"
|
|
" -R, --restrict restrict access to GROUP to its members\n"
|
|
" -M, --members USER,... set the list of members of GROUP\n"
|
|
@@ -226,6 +229,57 @@
|
|
}
|
|
|
|
/*
|
|
+ * process_root_flag - chroot if given the --root option
|
|
+ *
|
|
+ * We do this outside of process_flags() because
|
|
+ * the is_shadow_pwd boolean needs to be set before
|
|
+ * process_flags(), and if we do need to chroot() we
|
|
+ * must do so before is_shadow_pwd gets set.
|
|
+ */
|
|
+static void process_root_flag (int argc, char **argv)
|
|
+{
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int i;
|
|
+ char *root;
|
|
+
|
|
+ for (i = 0; i < argc; i++) {
|
|
+ if (!strcmp (argv[i], "--root") || !strcmp (argv[i], "-Q")) {
|
|
+ if (i + 1 == argc) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: option '%s' requires an argument\n"),
|
|
+ Prog, argv[i]);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ root = argv[i + 1];
|
|
+
|
|
+ if ('/' != root[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, root);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = root;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
* process_flags - process the command line options and arguments
|
|
*/
|
|
static void process_flags (int argc, char **argv)
|
|
@@ -235,6 +289,7 @@
|
|
static struct option long_options[] = {
|
|
{"add", required_argument, NULL, 'a'},
|
|
{"delete", required_argument, NULL, 'd'},
|
|
+ {"root", required_argument, NULL, 'Q'},
|
|
{"remove-password", no_argument, NULL, 'r'},
|
|
{"restrict", no_argument, NULL, 'R'},
|
|
{"administrators", required_argument, NULL, 'A'},
|
|
@@ -242,7 +297,7 @@
|
|
{NULL, 0, NULL, '\0'}
|
|
};
|
|
|
|
- while ((flag = getopt_long (argc, argv, "a:A:d:gM:rR", long_options, &option_index)) != -1) {
|
|
+ while ((flag = getopt_long (argc, argv, "a:A:d:gM:Q:rR", long_options, &option_index)) != -1) {
|
|
switch (flag) {
|
|
case 'a': /* add a user */
|
|
aflg = true;
|
|
@@ -283,6 +338,9 @@
|
|
}
|
|
Mflg = true;
|
|
break;
|
|
+ case 'Q':
|
|
+ /* no-op since we handled this in process_root_flag() earlier */
|
|
+ break;
|
|
case 'r': /* remove group password */
|
|
rflg = true;
|
|
break;
|
|
@@ -995,6 +1053,8 @@
|
|
setbuf (stdout, NULL);
|
|
setbuf (stderr, NULL);
|
|
|
|
+ process_root_flag (argc, argv);
|
|
+
|
|
#ifdef SHADOWGRP
|
|
is_shadowgrp = sgr_file_present ();
|
|
#endif
|
|
diff -urN shadow-4.1.4.3.orig//src/groupadd.c shadow-4.1.4.3//src/groupadd.c
|
|
--- shadow-4.1.4.3.orig//src/groupadd.c 2011-09-29 12:00:45.212000091 +0100
|
|
+++ shadow-4.1.4.3//src/groupadd.c 2011-09-29 11:59:28.386000092 +0100
|
|
@@ -76,6 +76,7 @@
|
|
static gid_t group_id;
|
|
static /*@null@*/char *group_passwd;
|
|
static /*@null@*/char *empty_list = NULL;
|
|
+static const char *newroot = "";
|
|
|
|
static bool oflg = false; /* permit non-unique group ID to be specified with -g */
|
|
static bool gflg = false; /* ID value for the new group */
|
|
@@ -120,6 +121,7 @@
|
|
(void) fputs (_(" -o, --non-unique allow to create groups with duplicate\n"
|
|
" (non-unique) GID\n"), stderr);
|
|
(void) fputs (_(" -p, --password PASSWORD use this encrypted password for the new group\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
(void) fputs (_(" -r, --system create a system account\n"), stderr);
|
|
(void) fputs ("\n", stderr);
|
|
exit (E_USAGE);
|
|
@@ -383,12 +385,13 @@
|
|
{"key", required_argument, NULL, 'K'},
|
|
{"non-unique", no_argument, NULL, 'o'},
|
|
{"password", required_argument, NULL, 'p'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
{"system", no_argument, NULL, 'r'},
|
|
{NULL, 0, NULL, '\0'}
|
|
};
|
|
|
|
while ((c =
|
|
- getopt_long (argc, argv, "fg:hK:op:r", long_options,
|
|
+ getopt_long (argc, argv, "fg:hK:op:R:r", long_options,
|
|
&option_index)) != -1) {
|
|
switch (c) {
|
|
case 'f':
|
|
@@ -440,6 +443,28 @@
|
|
pflg = true;
|
|
group_passwd = optarg;
|
|
break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
case 'r':
|
|
rflg = true;
|
|
break;
|
|
diff -urN shadow-4.1.4.3.orig//src/groupdel.c shadow-4.1.4.3//src/groupdel.c
|
|
--- shadow-4.1.4.3.orig//src/groupdel.c 2011-09-29 12:00:45.212000091 +0100
|
|
+++ shadow-4.1.4.3//src/groupdel.c 2011-09-29 11:59:28.386000092 +0100
|
|
@@ -36,6 +36,7 @@
|
|
|
|
#include <ctype.h>
|
|
#include <fcntl.h>
|
|
+#include <getopt.h>
|
|
#include <grp.h>
|
|
#include <pwd.h>
|
|
#ifdef ACCT_TOOLS_SETUID
|
|
@@ -59,6 +60,7 @@
|
|
|
|
static char *group_name;
|
|
static gid_t group_id = -1;
|
|
+static const char *newroot = "";
|
|
|
|
#ifdef SHADOWGRP
|
|
static bool is_shadow_grp;
|
|
@@ -70,12 +72,14 @@
|
|
/*@-exitarg@*/
|
|
#define E_SUCCESS 0 /* success */
|
|
#define E_USAGE 2 /* invalid command syntax */
|
|
+#define E_BAD_ARG 3 /* invalid argument to option */
|
|
#define E_NOTFOUND 6 /* specified group doesn't exist */
|
|
#define E_GROUP_BUSY 8 /* can't remove user's primary group */
|
|
#define E_GRP_UPDATE 10 /* can't update group file */
|
|
|
|
/* local function prototypes */
|
|
static void usage (void);
|
|
+static void process_flags (int argc, char **argv);
|
|
static void grp_update (void);
|
|
static void close_files (void);
|
|
static void open_files (void);
|
|
@@ -86,11 +90,78 @@
|
|
*/
|
|
static void usage (void)
|
|
{
|
|
- fputs (_("Usage: groupdel group\n"), stderr);
|
|
+ (void) fprintf (stderr,
|
|
+ _("Usage: groupdel [options]\n"
|
|
+ "\n"
|
|
+ "Options:\n"),
|
|
+ Prog);
|
|
+ (void) fputs (_(" -g, --group GROUP group name to delete\n"), stderr);
|
|
+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
+ (void) fputs ("\n", stderr);
|
|
exit (E_USAGE);
|
|
}
|
|
|
|
/*
|
|
+ * process_flags - perform command line argument setting
|
|
+ *
|
|
+ * process_flags() interprets the command line arguments and sets
|
|
+ * the values that the user will be created with accordingly. The
|
|
+ * values are checked for sanity.
|
|
+ */
|
|
+static void process_flags (int argc, char **argv)
|
|
+{
|
|
+ {
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int c;
|
|
+ static struct option long_options[] = {
|
|
+ {"group", required_argument, NULL, 'g'},
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
+ {NULL, 0, NULL, '\0'}
|
|
+ };
|
|
+ while ((c = getopt_long (argc, argv,
|
|
+ "g:R:",
|
|
+ long_options, NULL)) != -1) {
|
|
+ switch (c) {
|
|
+ case 'g':
|
|
+ group_name = optarg;
|
|
+ break;
|
|
+ case 'h':
|
|
+ usage ();
|
|
+ break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ usage ();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
* grp_update - update group file entries
|
|
*
|
|
* grp_update() writes the new records to the group files.
|
|
@@ -328,14 +399,14 @@
|
|
(void) bindtextdomain (PACKAGE, LOCALEDIR);
|
|
(void) textdomain (PACKAGE);
|
|
|
|
- if (argc != 2) {
|
|
+ if (argc == 1) {
|
|
usage ();
|
|
}
|
|
|
|
- group_name = argv[1];
|
|
-
|
|
OPENLOG ("groupdel");
|
|
|
|
+ process_flags (argc, argv);
|
|
+
|
|
#ifdef ACCT_TOOLS_SETUID
|
|
#ifdef USE_PAM
|
|
{
|
|
diff -urN shadow-4.1.4.3.orig//src/groupmod.c shadow-4.1.4.3//src/groupmod.c
|
|
--- shadow-4.1.4.3.orig//src/groupmod.c 2011-09-29 12:00:45.212000091 +0100
|
|
+++ shadow-4.1.4.3//src/groupmod.c 2011-09-29 11:59:28.387000092 +0100
|
|
@@ -79,6 +79,7 @@
|
|
static char *group_passwd;
|
|
static gid_t group_id;
|
|
static gid_t group_newid;
|
|
+static char *newroot = "";
|
|
|
|
struct cleanup_info_mod info_passwd;
|
|
struct cleanup_info_mod info_group;
|
|
@@ -126,6 +127,7 @@
|
|
(void) fputs (_(" -o, --non-unique allow to use a duplicate (non-unique) GID\n"), stderr);
|
|
(void) fputs (_(" -p, --password PASSWORD change the password to this (encrypted)\n"
|
|
" PASSWORD\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
(void) fputs ("\n", stderr);
|
|
exit (E_USAGE);
|
|
}
|
|
@@ -346,10 +348,11 @@
|
|
{"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:",
|
|
+ getopt_long (argc, argv, "g:hn:op:R:",
|
|
long_options, &option_index)) != -1) {
|
|
switch (c) {
|
|
case 'g':
|
|
@@ -373,6 +376,28 @@
|
|
group_passwd = optarg;
|
|
pflg = true;
|
|
break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
default:
|
|
usage ();
|
|
}
|
|
diff -urN shadow-4.1.4.3.orig//src/grpconv.c shadow-4.1.4.3//src/grpconv.c
|
|
--- shadow-4.1.4.3.orig//src/grpconv.c 2011-09-29 12:00:45.213000091 +0100
|
|
+++ shadow-4.1.4.3//src/grpconv.c 2011-09-29 11:59:28.387000092 +0100
|
|
@@ -39,6 +39,7 @@
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
+#include <getopt.h>
|
|
#include <grp.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
@@ -50,6 +51,14 @@
|
|
#ifdef SHADOWGRP
|
|
#include "groupio.h"
|
|
#include "sgroupio.h"
|
|
+
|
|
+/*
|
|
+ * exit status values
|
|
+ */
|
|
+/*@-exitarg@*/
|
|
+#define E_USAGE 2 /* invalid command syntax */
|
|
+#define E_BAD_ARG 3 /* invalid argument to option */
|
|
+
|
|
/*
|
|
* Global variables
|
|
*/
|
|
@@ -57,9 +66,12 @@
|
|
|
|
static bool gr_locked = false;
|
|
static bool sgr_locked = false;
|
|
+static const char *newroot = "";
|
|
|
|
/* local function prototypes */
|
|
static void fail_exit (int status);
|
|
+static void usage (void);
|
|
+static void process_flags (int argc, char **argv);
|
|
|
|
static void fail_exit (int status)
|
|
{
|
|
@@ -82,6 +94,77 @@
|
|
exit (status);
|
|
}
|
|
|
|
+/*
|
|
+ * usage - display usage message and exit
|
|
+ */
|
|
+static void usage (void)
|
|
+{
|
|
+ (void) fprintf (stderr,
|
|
+ _("Usage: grpconv [options]\n"
|
|
+ "\n"
|
|
+ "Options:\n"),
|
|
+ Prog);
|
|
+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
+ (void) fputs ("\n", stderr);
|
|
+ exit (E_USAGE);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * process_flags - perform command line argument setting
|
|
+ *
|
|
+ * process_flags() interprets the command line arguments and sets
|
|
+ * the values that the user will be created with accordingly. The
|
|
+ * values are checked for sanity.
|
|
+ */
|
|
+static void process_flags (int argc, char **argv)
|
|
+{
|
|
+ {
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int c;
|
|
+ static struct option long_options[] = {
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
+ {NULL, 0, NULL, '\0'}
|
|
+ };
|
|
+ while ((c = getopt_long (argc, argv,
|
|
+ "R:",
|
|
+ long_options, NULL)) != -1) {
|
|
+ switch (c) {
|
|
+ case 'h':
|
|
+ usage ();
|
|
+ break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ usage ();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
int main (int argc, char **argv)
|
|
{
|
|
const struct group *gr;
|
|
@@ -100,6 +183,8 @@
|
|
|
|
OPENLOG ("grpconv");
|
|
|
|
+ process_flags (argc, argv);
|
|
+
|
|
if (gr_lock () == 0) {
|
|
fprintf (stderr,
|
|
_("%s: cannot lock %s; try again later.\n"),
|
|
diff -urN shadow-4.1.4.3.orig//src/grpunconv.c shadow-4.1.4.3//src/grpunconv.c
|
|
--- shadow-4.1.4.3.orig//src/grpunconv.c 2011-09-29 12:00:45.213000091 +0100
|
|
+++ shadow-4.1.4.3//src/grpunconv.c 2011-09-29 11:59:28.387000092 +0100
|
|
@@ -43,6 +43,7 @@
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
+#include <getopt.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <grp.h>
|
|
@@ -51,6 +52,14 @@
|
|
#ifdef SHADOWGRP
|
|
#include "groupio.h"
|
|
#include "sgroupio.h"
|
|
+
|
|
+/*
|
|
+ * exit status values
|
|
+ */
|
|
+/*@-exitarg@*/
|
|
+#define E_USAGE 2 /* invalid command syntax */
|
|
+#define E_BAD_ARG 3 /* invalid argument to option */
|
|
+
|
|
/*
|
|
* Global variables
|
|
*/
|
|
@@ -58,9 +67,12 @@
|
|
|
|
static bool gr_locked = false;
|
|
static bool sgr_locked = false;
|
|
+static const char *newroot = "";
|
|
|
|
/* local function prototypes */
|
|
static void fail_exit (int status);
|
|
+static void usage (void);
|
|
+static void process_flags (int argc, char **argv);
|
|
|
|
static void fail_exit (int status)
|
|
{
|
|
@@ -83,6 +95,77 @@
|
|
exit (status);
|
|
}
|
|
|
|
+/*
|
|
+ * usage - display usage message and exit
|
|
+ */
|
|
+static void usage (void)
|
|
+{
|
|
+ (void) fprintf (stderr,
|
|
+ _("Usage: grpunconv [options]\n"
|
|
+ "\n"
|
|
+ "Options:\n"),
|
|
+ Prog);
|
|
+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
+ (void) fputs ("\n", stderr);
|
|
+ exit (E_USAGE);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * process_flags - perform command line argument setting
|
|
+ *
|
|
+ * process_flags() interprets the command line arguments and sets
|
|
+ * the values that the user will be created with accordingly. The
|
|
+ * values are checked for sanity.
|
|
+ */
|
|
+static void process_flags (int argc, char **argv)
|
|
+{
|
|
+ {
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int c;
|
|
+ static struct option long_options[] = {
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
+ {NULL, 0, NULL, '\0'}
|
|
+ };
|
|
+ while ((c = getopt_long (argc, argv,
|
|
+ "R:",
|
|
+ long_options, NULL)) != -1) {
|
|
+ switch (c) {
|
|
+ case 'h':
|
|
+ usage ();
|
|
+ break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ usage ();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
int main (int argc, char **argv)
|
|
{
|
|
const struct group *gr;
|
|
@@ -100,6 +183,8 @@
|
|
|
|
OPENLOG ("grpunconv");
|
|
|
|
+ process_flags (argc, argv);
|
|
+
|
|
if (sgr_file_present () == 0) {
|
|
exit (0); /* no /etc/gshadow, nothing to do */
|
|
}
|
|
diff -urN shadow-4.1.4.3.orig//src/passwd.c shadow-4.1.4.3//src/passwd.c
|
|
--- shadow-4.1.4.3.orig//src/passwd.c 2011-09-29 12:00:45.214000091 +0100
|
|
+++ shadow-4.1.4.3//src/passwd.c 2011-09-29 11:59:28.388000092 +0100
|
|
@@ -75,6 +75,7 @@
|
|
static char *name; /* The name of user whose password is being changed */
|
|
static char *myname; /* The current user's name */
|
|
static bool amroot; /* The caller's real UID was 0 */
|
|
+static const char *newroot = "";
|
|
|
|
static bool
|
|
aflg = false, /* -a - show status for all users */
|
|
@@ -174,6 +175,7 @@
|
|
" -n, --mindays MIN_DAYS set minimum number of days before password\n"
|
|
" change to MIN_DAYS\n"
|
|
" -q, --quiet quiet mode\n"
|
|
+ " -R, --root CHROOT_DIR directory to chroot into\n"
|
|
" -r, --repository REPOSITORY change password in REPOSITORY repository\n"
|
|
" -S, --status report password status on the named account\n"
|
|
" -u, --unlock unlock the password of the named account\n"
|
|
@@ -803,6 +805,7 @@
|
|
{"lock", no_argument, NULL, 'l'},
|
|
{"mindays", required_argument, NULL, 'n'},
|
|
{"quiet", no_argument, NULL, 'q'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
{"repository", required_argument, NULL, 'r'},
|
|
{"status", no_argument, NULL, 'S'},
|
|
{"unlock", no_argument, NULL, 'u'},
|
|
@@ -811,7 +814,7 @@
|
|
{NULL, 0, NULL, '\0'}
|
|
};
|
|
|
|
- while ((c = getopt_long (argc, argv, "adei:kln:qr:Suw:x:",
|
|
+ while ((c = getopt_long (argc, argv, "adei:kln:qR:r:Suw:x:",
|
|
long_options, &option_index)) != -1) {
|
|
switch (c) {
|
|
case 'a':
|
|
@@ -858,6 +861,28 @@
|
|
case 'q':
|
|
qflg = true; /* ok for users */
|
|
break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
case 'r':
|
|
/* -r repository (files|nis|nisplus) */
|
|
/* only "files" supported for now */
|
|
diff -urN shadow-4.1.4.3.orig//src/pwconv.c shadow-4.1.4.3//src/pwconv.c
|
|
--- shadow-4.1.4.3.orig//src/pwconv.c 2011-09-29 12:00:45.214000091 +0100
|
|
+++ shadow-4.1.4.3//src/pwconv.c 2011-09-29 11:59:28.388000092 +0100
|
|
@@ -59,6 +59,7 @@
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
+#include <getopt.h>
|
|
#include <pwd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
@@ -79,6 +80,7 @@
|
|
#define E_SUCCESS 0 /* success */
|
|
#define E_NOPERM 1 /* permission denied */
|
|
#define E_USAGE 2 /* invalid command syntax */
|
|
+#define E_BAD_ARG 3 /* invalid argument to option */
|
|
#define E_FAILURE 3 /* unexpected failure, nothing done */
|
|
#define E_MISSING 4 /* unexpected failure, passwd file missing */
|
|
#define E_PWDBUSY 5 /* passwd file(s) busy */
|
|
@@ -90,9 +92,12 @@
|
|
|
|
static bool spw_locked = false;
|
|
static bool pw_locked = false;
|
|
+static const char *newroot = "";
|
|
|
|
/* local function prototypes */
|
|
static void fail_exit (int status);
|
|
+static void usage (void);
|
|
+static void process_flags (int argc, char **argv);
|
|
|
|
static void fail_exit (int status)
|
|
{
|
|
@@ -115,6 +120,77 @@
|
|
exit (status);
|
|
}
|
|
|
|
+/*
|
|
+ * usage - display usage message and exit
|
|
+ */
|
|
+static void usage (void)
|
|
+{
|
|
+ (void) fprintf (stderr,
|
|
+ _("Usage: pwconv [options]\n"
|
|
+ "\n"
|
|
+ "Options:\n"),
|
|
+ Prog);
|
|
+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
+ (void) fputs ("\n", stderr);
|
|
+ exit (E_USAGE);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * process_flags - perform command line argument setting
|
|
+ *
|
|
+ * process_flags() interprets the command line arguments and sets
|
|
+ * the values that the user will be created with accordingly. The
|
|
+ * values are checked for sanity.
|
|
+ */
|
|
+static void process_flags (int argc, char **argv)
|
|
+{
|
|
+ {
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int c;
|
|
+ static struct option long_options[] = {
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
+ {NULL, 0, NULL, '\0'}
|
|
+ };
|
|
+ while ((c = getopt_long (argc, argv,
|
|
+ "R:",
|
|
+ long_options, NULL)) != -1) {
|
|
+ switch (c) {
|
|
+ case 'h':
|
|
+ usage ();
|
|
+ break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ usage ();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
int main (int argc, char **argv)
|
|
{
|
|
const struct passwd *pw;
|
|
@@ -122,9 +198,6 @@
|
|
const struct spwd *sp;
|
|
struct spwd spent;
|
|
|
|
- if (1 != argc) {
|
|
- (void) fputs (_("Usage: pwconv\n"), stderr);
|
|
- }
|
|
Prog = Basename (argv[0]);
|
|
|
|
(void) setlocale (LC_ALL, "");
|
|
@@ -133,6 +206,8 @@
|
|
|
|
OPENLOG ("pwconv");
|
|
|
|
+ process_flags (argc, argv);
|
|
+
|
|
if (pw_lock () == 0) {
|
|
fprintf (stderr,
|
|
_("%s: cannot lock %s; try again later.\n"),
|
|
diff -urN shadow-4.1.4.3.orig//src/pwunconv.c shadow-4.1.4.3//src/pwunconv.c
|
|
--- shadow-4.1.4.3.orig//src/pwunconv.c 2011-09-29 12:00:45.214000091 +0100
|
|
+++ shadow-4.1.4.3//src/pwunconv.c 2011-09-29 11:59:28.388000092 +0100
|
|
@@ -35,6 +35,7 @@
|
|
#ident "$Id: pwunconv.c 2852 2009-04-30 21:44:35Z nekral-guest $"
|
|
|
|
#include <fcntl.h>
|
|
+#include <getopt.h>
|
|
#include <pwd.h>
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
@@ -46,15 +47,24 @@
|
|
#include "shadowio.h"
|
|
|
|
/*
|
|
+ * exit status values
|
|
+ */
|
|
+/*@-exitarg@*/
|
|
+#define E_USAGE 2 /* invalid command syntax */
|
|
+#define E_BAD_ARG 3 /* invalid argument to option */
|
|
+/*
|
|
* Global variables
|
|
*/
|
|
char *Prog;
|
|
|
|
static bool spw_locked = false;
|
|
static bool pw_locked = false;
|
|
+static const char *newroot = "";
|
|
|
|
/* local function prototypes */
|
|
static void fail_exit (int status);
|
|
+static void usage (void);
|
|
+static void process_flags (int argc, char **argv);
|
|
|
|
static void fail_exit (int status)
|
|
{
|
|
@@ -75,6 +85,76 @@
|
|
exit (status);
|
|
}
|
|
|
|
+/*
|
|
+ * usage - display usage message and exit
|
|
+ */
|
|
+static void usage (void)
|
|
+{
|
|
+ (void) fprintf (stderr,
|
|
+ _("Usage: pwunconv [options]\n"
|
|
+ "\n"
|
|
+ "Options:\n"),
|
|
+ Prog);
|
|
+ (void) fputs (_(" -h, --help display this help message and exit\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
+ (void) fputs ("\n", stderr);
|
|
+ exit (E_USAGE);
|
|
+}
|
|
+
|
|
+/*
|
|
+ * process_flags - perform command line argument setting
|
|
+ *
|
|
+ * process_flags() interprets the command line arguments and sets
|
|
+ * the values that the user will be created with accordingly. The
|
|
+ * values are checked for sanity.
|
|
+ */
|
|
+static void process_flags (int argc, char **argv)
|
|
+{
|
|
+ {
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int c;
|
|
+ static struct option long_options[] = {
|
|
+ {"help", no_argument, NULL, 'h'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
+ {NULL, 0, NULL, '\0'}
|
|
+ };
|
|
+ while ((c = getopt_long (argc, argv,
|
|
+ "R:",
|
|
+ long_options, NULL)) != -1) {
|
|
+ switch (c) {
|
|
+ case 'h':
|
|
+ usage ();
|
|
+ break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ default:
|
|
+ usage ();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
@@ -93,6 +173,8 @@
|
|
|
|
OPENLOG ("pwunconv");
|
|
|
|
+ process_flags (argc, argv);
|
|
+
|
|
if (!spw_file_present ()) {
|
|
/* shadow not installed, do nothing */
|
|
exit (0);
|
|
diff -urN shadow-4.1.4.3.orig//src/useradd.c shadow-4.1.4.3//src/useradd.c
|
|
--- shadow-4.1.4.3.orig//src/useradd.c 2011-09-29 12:00:45.215000091 +0100
|
|
+++ shadow-4.1.4.3//src/useradd.c 2011-09-29 11:59:28.520000092 +0100
|
|
@@ -112,6 +112,7 @@
|
|
#ifdef WITH_SELINUX
|
|
static const char *user_selinux = "";
|
|
#endif
|
|
+static const char *newroot = "";
|
|
|
|
static long user_expire = -1;
|
|
static bool is_shadow_pwd;
|
|
@@ -189,6 +190,7 @@
|
|
static void new_spent (struct spwd *);
|
|
static void grp_update (void);
|
|
|
|
+static void process_root_flag (int argc, char **argv);
|
|
static void process_flags (int argc, char **argv);
|
|
static void close_files (void);
|
|
static void open_files (void);
|
|
@@ -711,6 +713,7 @@
|
|
(void) fputs (_(" -o, --non-unique allow to create users with duplicate\n"
|
|
" (non-unique) UID\n"), stderr);
|
|
(void) fputs (_(" -p, --password PASSWORD encrypted password of the new account\n"), stderr);
|
|
+ (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), stderr);
|
|
(void) fputs (_(" -r, --system create a system account\n"), stderr);
|
|
(void) fputs (_(" -s, --shell SHELL login shell of the new account\n"), stderr);
|
|
(void) fputs (_(" -u, --uid UID user ID of the new account\n"), stderr);
|
|
@@ -943,6 +946,57 @@
|
|
}
|
|
|
|
/*
|
|
+ * process_root_flag - chroot if given the --root option
|
|
+ *
|
|
+ * We do this outside of process_flags() because
|
|
+ * the is_shadow_pwd boolean needs to be set before
|
|
+ * process_flags(), and if we do need to chroot() we
|
|
+ * must do so before is_shadow_pwd gets set.
|
|
+ */
|
|
+static void process_root_flag (int argc, char **argv)
|
|
+{
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int i;
|
|
+ char *root;
|
|
+
|
|
+ for (i = 0; i < argc; i++) {
|
|
+ if (!strcmp (argv[i], "--root") || !strcmp (argv[i], "-R")) {
|
|
+ if (i + 1 == argc) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: option '%s' requires an argument\n"),
|
|
+ Prog, argv[i]);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ root = argv[i + 1];
|
|
+
|
|
+ if ('/' != root[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, root);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = root;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
* process_flags - perform command line argument setting
|
|
*
|
|
* process_flags() interprets the command line arguments and sets
|
|
@@ -978,6 +1032,7 @@
|
|
{"no-user-group", no_argument, NULL, 'N'},
|
|
{"non-unique", no_argument, NULL, 'o'},
|
|
{"password", required_argument, NULL, 'p'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
{"system", no_argument, NULL, 'r'},
|
|
{"shell", required_argument, NULL, 's'},
|
|
#ifdef WITH_SELINUX
|
|
@@ -989,9 +1044,9 @@
|
|
};
|
|
while ((c = getopt_long (argc, argv,
|
|
#ifdef WITH_SELINUX
|
|
- "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:UZ:",
|
|
+ "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:UZ:",
|
|
#else
|
|
- "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
|
|
+ "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:U",
|
|
#endif
|
|
long_options, NULL)) != -1) {
|
|
switch (c) {
|
|
@@ -1156,6 +1211,9 @@
|
|
}
|
|
user_pass = optarg;
|
|
break;
|
|
+ case 'R':
|
|
+ /* no-op since we handled this in process_root_flag() earlier */
|
|
+ break;
|
|
case 'r':
|
|
rflg = true;
|
|
break;
|
|
@@ -1735,6 +1793,36 @@
|
|
}
|
|
}
|
|
#endif
|
|
+
|
|
+/*
|
|
+ * mkdir_p - create directories, including parent directories when needed
|
|
+ *
|
|
+ * similar to mkdir -p
|
|
+ */
|
|
+void mkdir_p(const char *path) {
|
|
+ int len = strlen(path);
|
|
+ char newdir[len + 1];
|
|
+ mode_t mode = 0755;
|
|
+ int i = 0;
|
|
+
|
|
+ if (path[i] == '\0') {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ /* skip the leading '/' */
|
|
+ i++;
|
|
+
|
|
+ while(path[i] != '\0') {
|
|
+ if (path[i] == '/') {
|
|
+ strncpy(newdir, path, i);
|
|
+ newdir[i] = '\0';
|
|
+ mkdir(newdir, mode);
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+ mkdir(path, mode);
|
|
+}
|
|
+
|
|
/*
|
|
* create_home - create the user's home directory
|
|
*
|
|
@@ -1748,34 +1836,31 @@
|
|
#ifdef WITH_SELINUX
|
|
selinux_file_context (user_home);
|
|
#endif
|
|
- /* XXX - create missing parent directories. --marekm */
|
|
- if (mkdir (user_home, 0) != 0) {
|
|
- fprintf (stderr,
|
|
- _("%s: cannot create directory %s\n"),
|
|
- Prog, user_home);
|
|
-#ifdef WITH_AUDIT
|
|
- audit_logger (AUDIT_ADD_USER, Prog,
|
|
- "adding home directory",
|
|
- user_name, (unsigned int) user_id,
|
|
- SHADOW_AUDIT_FAILURE);
|
|
-#endif
|
|
- fail_exit (E_HOMEDIR);
|
|
- }
|
|
- chown (user_home, user_id, user_gid);
|
|
- chmod (user_home,
|
|
- 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
|
|
- home_added = true;
|
|
+ mkdir_p(user_home);
|
|
+ }
|
|
+ if (access (user_home, F_OK) != 0) {
|
|
#ifdef WITH_AUDIT
|
|
audit_logger (AUDIT_ADD_USER, Prog,
|
|
"adding home directory",
|
|
user_name, (unsigned int) user_id,
|
|
- SHADOW_AUDIT_SUCCESS);
|
|
+ SHADOW_AUDIT_FAILURE);
|
|
+#endif
|
|
+ fail_exit (E_HOMEDIR);
|
|
+ }
|
|
+ chown (user_home, user_id, user_gid);
|
|
+ chmod (user_home,
|
|
+ 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
|
|
+ home_added = true;
|
|
+#ifdef WITH_AUDIT
|
|
+ audit_logger (AUDIT_ADD_USER, Prog,
|
|
+ "adding home directory",
|
|
+ user_name, (unsigned int) user_id,
|
|
+ SHADOW_AUDIT_SUCCESS);
|
|
#endif
|
|
#ifdef WITH_SELINUX
|
|
- /* Reset SELinux to create files with default contexts */
|
|
- setfscreatecon (NULL);
|
|
+ /* Reset SELinux to create files with default contexts */
|
|
+ setfscreatecon (NULL);
|
|
#endif
|
|
- }
|
|
}
|
|
|
|
/*
|
|
@@ -1861,6 +1946,7 @@
|
|
*/
|
|
user_groups[0] = (char *) 0;
|
|
|
|
+ process_root_flag (argc, argv);
|
|
|
|
is_shadow_pwd = spw_file_present ();
|
|
#ifdef SHADOWGRP
|
|
diff -urN shadow-4.1.4.3.orig//src/userdel.c shadow-4.1.4.3//src/userdel.c
|
|
--- shadow-4.1.4.3.orig//src/userdel.c 2011-09-29 12:00:45.216000091 +0100
|
|
+++ shadow-4.1.4.3//src/userdel.c 2011-09-29 11:59:28.389000092 +0100
|
|
@@ -79,6 +79,7 @@
|
|
static char *user_name;
|
|
static uid_t user_id;
|
|
static char *user_home;
|
|
+static const char *newroot = "";
|
|
|
|
static bool fflg = false;
|
|
static bool rflg = false;
|
|
@@ -119,6 +120,7 @@
|
|
" -f, --force force removal of files,\n"
|
|
" even if not owned by user\n"
|
|
" -h, --help display this help message and exit\n"
|
|
+ " -R, --root CHROOT_DIR directory to chroot into\n"
|
|
" -r, --remove remove home directory and mail spool\n"
|
|
"\n"), stderr);
|
|
exit (E_USAGE);
|
|
@@ -768,12 +770,34 @@
|
|
{"remove", no_argument, NULL, 'r'},
|
|
{NULL, 0, NULL, '\0'}
|
|
};
|
|
- while ((c = getopt_long (argc, argv, "fhr",
|
|
+ while ((c = getopt_long (argc, argv, "fhR:r",
|
|
long_options, NULL)) != -1) {
|
|
switch (c) {
|
|
case 'f': /* force remove even if not owned by user */
|
|
fflg = true;
|
|
break;
|
|
+ case 'R':
|
|
+ if ('/' != optarg[0]) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, optarg);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = optarg;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
case 'r': /* remove home dir and mailbox */
|
|
rflg = true;
|
|
break;
|
|
diff -urN shadow-4.1.4.3.orig//src/usermod.c shadow-4.1.4.3//src/usermod.c
|
|
--- shadow-4.1.4.3.orig//src/usermod.c 2011-09-29 12:00:45.216000091 +0100
|
|
+++ shadow-4.1.4.3//src/usermod.c 2011-09-29 11:59:28.390000092 +0100
|
|
@@ -110,6 +110,7 @@
|
|
static long user_newinactive;
|
|
static long sys_ngroups;
|
|
static char **user_groups; /* NULL-terminated list */
|
|
+static const char *newroot = "";
|
|
|
|
static bool
|
|
aflg = false, /* append to existing secondary group set */
|
|
@@ -164,6 +165,7 @@
|
|
#endif
|
|
static void grp_update (void);
|
|
|
|
+static void process_root_flag (int, char **);
|
|
static void process_flags (int, char **);
|
|
static void close_files (void);
|
|
static void open_files (void);
|
|
@@ -323,6 +325,7 @@
|
|
" new location (use only with -d)\n"
|
|
" -o, --non-unique allow using duplicate (non-unique) UID\n"
|
|
" -p, --password PASSWORD use encrypted password for the new password\n"
|
|
+ " -R --root CHROOT_DIR directory to chroot into\n"
|
|
" -s, --shell SHELL new login shell for the user account\n"
|
|
" -u, --uid UID new UID for the user account\n"
|
|
" -U, --unlock unlock the user account\n"
|
|
@@ -802,6 +805,58 @@
|
|
}
|
|
|
|
/*
|
|
+ * process_root_flag - chroot if given the --root option
|
|
+ *
|
|
+ * We do this outside of process_flags() because
|
|
+ * the is_shadow_pwd boolean needs to be set before
|
|
+ * process_flags(), and if we do need to chroot() we
|
|
+ * must do so before is_shadow_pwd gets set.
|
|
+ */
|
|
+static void process_root_flag (int argc, char **argv)
|
|
+{
|
|
+ /*
|
|
+ * Parse the command line options.
|
|
+ */
|
|
+ int i;
|
|
+ char *root;
|
|
+
|
|
+ for (i = 0; i < argc; i++) {
|
|
+ if (!strcmp (argv[i], "--root") || !strcmp (argv[i], "-R")) {
|
|
+ if (i + 1 == argc) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: option '%s' requires an argument\n"),
|
|
+ Prog, argv[i]);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ root = argv[i + 1];
|
|
+
|
|
+ if ( (!VALID (root) )
|
|
+ || ( ('/' != root[0]) ) ) {
|
|
+ fprintf (stderr,
|
|
+ _("%s: invalid chroot path '%s'\n"),
|
|
+ Prog, root);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ newroot = root;
|
|
+
|
|
+ if (access (newroot, F_OK) != 0) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: chroot directory %s does not exist\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ if ( chroot(newroot) != 0 ) {
|
|
+ fprintf(stderr,
|
|
+ _("%s: unable to chroot to directory %s\n"),
|
|
+ Prog, newroot);
|
|
+ exit (E_BAD_ARG);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
* process_flags - perform command line argument setting
|
|
*
|
|
* process_flags() interprets the command line arguments and sets the
|
|
@@ -895,6 +950,7 @@
|
|
{"move-home", no_argument, NULL, 'm'},
|
|
{"non-unique", no_argument, NULL, 'o'},
|
|
{"password", required_argument, NULL, 'p'},
|
|
+ {"root", required_argument, NULL, 'R'},
|
|
#ifdef WITH_SELINUX
|
|
{"selinux-user", required_argument, NULL, 'Z'},
|
|
#endif
|
|
@@ -905,9 +961,9 @@
|
|
};
|
|
while ((c = getopt_long (argc, argv,
|
|
#ifdef WITH_SELINUX
|
|
- "ac:d:e:f:g:G:hl:Lmop:s:u:UZ:",
|
|
+ "ac:d:e:f:g:G:hl:Lmop:R:s:u:UZ:",
|
|
#else
|
|
- "ac:d:e:f:g:G:hl:Lmop:s:u:U",
|
|
+ "ac:d:e:f:g:G:hl:Lmop:R:s:u:U",
|
|
#endif
|
|
long_options, NULL)) != -1) {
|
|
switch (c) {
|
|
@@ -999,6 +1055,9 @@
|
|
user_pass = optarg;
|
|
pflg = true;
|
|
break;
|
|
+ case 'R':
|
|
+ /* no-op since we handled this in process_root_flag() earlier */
|
|
+ break;
|
|
case 's':
|
|
if (!VALID (optarg)) {
|
|
fprintf (stderr,
|
|
@@ -1715,6 +1774,8 @@
|
|
|
|
OPENLOG ("usermod");
|
|
|
|
+ process_root_flag (argc, argv);
|
|
+
|
|
is_shadow_pwd = spw_file_present ();
|
|
#ifdef SHADOWGRP
|
|
is_shadow_grp = sgr_file_present ();
|