]> granicus.if.org Git - shadow/blobdiff - src/useradd.c
Updated copyright dates.
[shadow] / src / useradd.c
index 476587d7d2c26dc5d536b5ff6b6f16f2ce272234..d419039afdd2fbf1994856fc0a63ebcf951f2595 100644 (file)
@@ -48,6 +48,7 @@
 #endif                         /* USE_PAM */
 #endif                         /* ACCT_TOOLS_SETUID */
 #include <stdio.h>
+#include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <time.h>
@@ -64,6 +65,9 @@
 #include "sgroupio.h"
 #endif
 #include "shadowio.h"
+#ifdef WITH_TCB
+#include "tcbfuncs.h"
+#endif
 
 #ifndef SKEL_DIR
 #define SKEL_DIR "/etc/skel"
@@ -108,6 +112,9 @@ static const char *user_comment = "";
 static const char *user_home = "";
 static const char *user_shell = "";
 static const char *create_mail_spool = "";
+#ifdef WITH_SELINUX
+static const char *user_selinux = "";
+#endif
 
 static long user_expire = -1;
 static bool is_shadow_pwd;
@@ -141,13 +148,15 @@ static bool
     rflg = false,              /* create a system account */
     sflg = false,              /* shell program for new account */
     uflg = false,              /* specify user ID for new account */
-    Uflg = false;              /* create a group having the same name as the user */
+    Uflg = false,              /* create a group having the same name as the user */
+    Zflg = false;              /* new selinux user */
 
 static bool home_added = false;
 
 /*
  * exit status values
  */
+/*@-exitarg@*/
 #define E_SUCCESS      0       /* success */
 #define E_PW_UPDATE    1       /* can't update password file */
 #define E_USAGE                2       /* invalid command syntax */
@@ -160,12 +169,12 @@ static bool home_added = false;
 #define        E_MAIL_SPOOL    13      /* can't create mail spool */
 
 #define DGROUP                 "GROUP="
-#define HOME                   "HOME="
-#define SHELL                  "SHELL="
-#define INACT                  "INACTIVE="
-#define EXPIRE                 "EXPIRE="
-#define SKEL                   "SKEL="
-#define CREATE_MAIL_SPOOL      "CREATE_MAIL_SPOOL="
+#define DHOME                  "HOME="
+#define DSHELL                 "SHELL="
+#define DINACT                 "INACTIVE="
+#define DEXPIRE                        "EXPIRE="
+#define DSKEL                  "SKEL="
+#define DCREATE_MAIL_SPOOL     "CREATE_MAIL_SPOOL="
 
 /* local function prototypes */
 static void fail_exit (int);
@@ -173,8 +182,11 @@ static void get_defaults (void);
 static void show_defaults (void);
 static int set_defaults (void);
 static int get_groups (char *);
-static void usage (void);
+static void usage (int status);
 static void new_pwent (struct passwd *);
+#ifdef WITH_SELINUX
+static void selinux_update_mapping (void);
+#endif
 
 static long scale_age (long);
 static void new_spent (struct spwd *);
@@ -183,6 +195,7 @@ static void grp_update (void);
 static void process_flags (int argc, char **argv);
 static void close_files (void);
 static void open_files (void);
+static void open_shadow (void);
 static void faillog_reset (uid_t);
 static void lastlog_reset (uid_t);
 static void usr_update (void);
@@ -325,21 +338,21 @@ static void get_defaults (void)
                /*
                 * Default HOME filesystem
                 */
-               else if (MATCH (buf, HOME)) {
+               else if (MATCH (buf, DHOME)) {
                        def_home = xstrdup (cp);
                }
 
                /*
                 * Default Login Shell command
                 */
-               else if (MATCH (buf, SHELL)) {
+               else if (MATCH (buf, DSHELL)) {
                        def_shell = xstrdup (cp);
                }
 
                /*
                 * Default Password Inactive value
                 */
-               else if (MATCH (buf, INACT)) {
+               else if (MATCH (buf, DINACT)) {
                        if (   (getlong (cp, &def_inactive) == 0)
                            || (def_inactive < -1)) {
                                fprintf (stderr,
@@ -347,7 +360,7 @@ static void get_defaults (void)
                                         Prog, optarg);
                                fprintf (stderr,
                                         _("%s: the %s configuration in %s will be ignored\n"),
-                                        Prog, INACT, def_file);
+                                        Prog, DINACT, def_file);
                                def_inactive = -1;
                        }
                }
@@ -355,14 +368,14 @@ static void get_defaults (void)
                /*
                 * Default account expiration date
                 */
-               else if (MATCH (buf, EXPIRE)) {
+               else if (MATCH (buf, DEXPIRE)) {
                        def_expire = xstrdup (cp);
                }
 
                /*
                 * Default Skeleton information
                 */
-               else if (MATCH (buf, SKEL)) {
+               else if (MATCH (buf, DSKEL)) {
                        if ('\0' == *cp) {
                                cp = SKEL_DIR;  /* XXX warning: const */
                        }
@@ -373,9 +386,9 @@ static void get_defaults (void)
                /*
                 * Create by default user mail spool or not ?
                 */
-               else if (MATCH (buf, CREATE_MAIL_SPOOL)) {
+               else if (MATCH (buf, DCREATE_MAIL_SPOOL)) {
                        if (*cp == '\0') {
-                               cp = CREATE_MAIL_SPOOL; /* XXX warning: const */
+                               cp = "no";      /* XXX warning: const */
                        }
 
                        def_create_mail_spool = xstrdup (cp);
@@ -416,6 +429,7 @@ static int set_defaults (void)
        static char new_file[] = NEW_USER_FILE;
        char *cp;
        int ofd;
+       int wlen;
        bool out_group = false;
        bool out_home = false;
        bool out_inactive = false;
@@ -458,30 +472,40 @@ static int set_defaults (void)
                cp = strrchr (buf, '\n');
                if (NULL != cp) {
                        *cp = '\0';
+               } else {
+                       /* A line which does not end with \n is only valid
+                        * at the end of the file.
+                        */
+                       if (feof (ifp) == 0) {
+                               fprintf (stderr,
+                                        _("%s: line too long in %s: %s..."),
+                                        Prog, def_file, buf);
+                               return -1;
+                       }
                }
 
                if (!out_group && MATCH (buf, DGROUP)) {
                        fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
                        out_group = true;
-               } else if (!out_home && MATCH (buf, HOME)) {
-                       fprintf (ofp, HOME "%s\n", def_home);
+               } else if (!out_home && MATCH (buf, DHOME)) {
+                       fprintf (ofp, DHOME "%s\n", def_home);
                        out_home = true;
-               } else if (!out_inactive && MATCH (buf, INACT)) {
-                       fprintf (ofp, INACT "%ld\n", def_inactive);
+               } else if (!out_inactive && MATCH (buf, DINACT)) {
+                       fprintf (ofp, DINACT "%ld\n", def_inactive);
                        out_inactive = true;
-               } else if (!out_expire && MATCH (buf, EXPIRE)) {
-                       fprintf (ofp, EXPIRE "%s\n", def_expire);
+               } else if (!out_expire && MATCH (buf, DEXPIRE)) {
+                       fprintf (ofp, DEXPIRE "%s\n", def_expire);
                        out_expire = true;
-               } else if (!out_shell && MATCH (buf, SHELL)) {
-                       fprintf (ofp, SHELL "%s\n", def_shell);
+               } else if (!out_shell && MATCH (buf, DSHELL)) {
+                       fprintf (ofp, DSHELL "%s\n", def_shell);
                        out_shell = true;
-               } else if (!out_skel && MATCH (buf, SKEL)) {
-                       fprintf (ofp, SKEL "%s\n", def_template);
+               } else if (!out_skel && MATCH (buf, DSKEL)) {
+                       fprintf (ofp, DSKEL "%s\n", def_template);
                        out_skel = true;
                } else if (!out_create_mail_spool
-                          && MATCH (buf, CREATE_MAIL_SPOOL)) {
+                          && MATCH (buf, DCREATE_MAIL_SPOOL)) {
                        fprintf (ofp,
-                                CREATE_MAIL_SPOOL "%s\n",
+                                DCREATE_MAIL_SPOOL "%s\n",
                                 def_create_mail_spool);
                        out_create_mail_spool = true;
                } else
@@ -498,18 +522,18 @@ static int set_defaults (void)
        if (!out_group)
                fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
        if (!out_home)
-               fprintf (ofp, HOME "%s\n", def_home);
+               fprintf (ofp, DHOME "%s\n", def_home);
        if (!out_inactive)
-               fprintf (ofp, INACT "%ld\n", def_inactive);
+               fprintf (ofp, DINACT "%ld\n", def_inactive);
        if (!out_expire)
-               fprintf (ofp, EXPIRE "%s\n", def_expire);
+               fprintf (ofp, DEXPIRE "%s\n", def_expire);
        if (!out_shell)
-               fprintf (ofp, SHELL "%s\n", def_shell);
+               fprintf (ofp, DSHELL "%s\n", def_shell);
        if (!out_skel)
-               fprintf (ofp, SKEL "%s\n", def_template);
+               fprintf (ofp, DSKEL "%s\n", def_template);
 
        if (!out_create_mail_spool)
-               fprintf (ofp, CREATE_MAIL_SPOOL "%s\n", def_create_mail_spool);
+               fprintf (ofp, DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool);
 
        /*
         * Flush and close the file. Check for errors to make certain
@@ -526,10 +550,13 @@ static int set_defaults (void)
        /*
         * Rename the current default file to its backup name.
         */
-       snprintf (buf, sizeof buf, "%s-", def_file);
+       wlen = snprintf (buf, sizeof buf, "%s-", def_file);
+       assert (wlen < (int) sizeof buf);
        if ((rename (def_file, buf) != 0) && (ENOENT != errno)) {
-               snprintf (buf, sizeof buf, _("%s: rename: %s"), Prog, def_file);
-               perror (buf);
+               int err = errno;
+               fprintf (stderr,
+                        _("%s: rename: %s: %s"),
+                        Prog, def_file, strerror (err));
                unlink (new_file);
                return -1;
        }
@@ -538,8 +565,10 @@ static int set_defaults (void)
         * Rename the new default file to its correct name.
         */
        if (rename (new_file, def_file) != 0) {
-               snprintf (buf, sizeof buf, _("%s: rename: %s"), Prog, new_file);
-               perror (buf);
+               int err = errno;
+               fprintf (stderr,
+                        _("%s: rename: %s: %s"),
+                        Prog, new_file, strerror (err));
                return -1;
        }
 #ifdef WITH_AUDIT
@@ -656,44 +685,46 @@ static int get_groups (char *list)
 /*
  * usage - display usage message and exit
  */
-static void usage (void)
+static void usage (int status)
 {
-       fputs (_("Usage: useradd [options] LOGIN\n"
-                "\n"
-                "Options:\n"
-                "  -b, --base-dir BASE_DIR       base directory for the new user account\n"
-                "                                home directory\n"
-                "  -c, --comment COMMENT         set the GECOS field for the new user account\n"
-                "  -d, --home-dir HOME_DIR       home directory for the new user account\n"
-                "  -D, --defaults                print or save modified default useradd\n"
-                "                                configuration\n"
-                "  -e, --expiredate EXPIRE_DATE  set account expiration date to EXPIRE_DATE\n"
-                "  -f, --inactive INACTIVE       set password inactive after expiration\n"
-                "                                to INACTIVE\n"
-                "  -g, --gid GROUP               force use GROUP for the new user account\n"
-                "  -G, --groups GROUPS           list of supplementary groups for the new\n"
-                "                                user account\n"
-                "  -h, --help                    display this help message and exit\n"
-                "  -k, --skel SKEL_DIR           specify an alternative skel directory\n"
-                "  -K, --key KEY=VALUE           overrides /etc/login.defs defaults\n"
-                "  -l, --no-log-init             do not add the user to the lastlog and\n"
-                "                                faillog databases\n"
-                "  -m, --create-home             create home directory for the new user\n"
-                "                                account\n"
-                "  -M, --no-create-home          do not create user's home directory\n"
-                "                                (overrides /etc/login.defs)\n"
-                "  -N, --no-user-group           do not create a group with the same name as\n"
-                "                                the user\n"
-                "  -o, --non-unique              allow create user with duplicate\n"
-                "                                (non-unique) UID\n"
-                "  -p, --password PASSWORD       use encrypted password for the new user\n"
-                "                                account\n"
-                "  -r, --system                  create a system account\n"
-                "  -s, --shell SHELL             the login shell for the new user account\n"
-                "  -u, --uid UID                 force use the UID for the new user account\n"
-                "  -U, --user-group              create a group with the same name as the user\n"
-                "\n"), stderr);
-       exit (E_USAGE);
+       FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
+       (void) fprintf (usageout,
+                       _("Usage: %s [options] LOGIN\n"
+                         "\n"
+                         "Options:\n"),
+                       Prog);
+       (void) fputs (_("  -b, --base-dir BASE_DIR       base directory for the home directory of the\n"
+                       "                                new account\n"), usageout);
+       (void) fputs (_("  -c, --comment COMMENT         GECOS field of the new account\n"), usageout);
+       (void) fputs (_("  -d, --home-dir HOME_DIR       home directory of the new account\n"), usageout);
+       (void) fputs (_("  -D, --defaults                print or change default useradd configuration\n"), usageout);
+       (void) fputs (_("  -e, --expiredate EXPIRE_DATE  expiration date of the new account\n"), usageout);
+       (void) fputs (_("  -f, --inactive INACTIVE       password inactivity period of the new account\n"), usageout);
+       (void) fputs (_("  -g, --gid GROUP               name or ID of the primary group of the new\n"
+                       "                                account\n"), usageout);
+       (void) fputs (_("  -G, --groups GROUPS           list of supplementary groups of the new\n"
+                       "                                account\n"), usageout);
+       (void) fputs (_("  -h, --help                    display this help message and exit\n"), usageout);
+       (void) fputs (_("  -k, --skel SKEL_DIR           use this alternative skeleton directory\n"), usageout);
+       (void) fputs (_("  -K, --key KEY=VALUE           override /etc/login.defs defaults\n"), usageout);
+       (void) fputs (_("  -l, --no-log-init             do not add the user to the lastlog and\n"
+                       "                                faillog databases\n"), usageout);
+       (void) fputs (_("  -m, --create-home             create the user's home directory\n"), usageout);
+       (void) fputs (_("  -M, --no-create-home          do not create the user's home directory\n"), usageout);
+       (void) fputs (_("  -N, --no-user-group           do not create a group with the same name as\n"
+                       "                                the user\n"), usageout);
+       (void) fputs (_("  -o, --non-unique              allow to create users with duplicate\n"
+                       "                                (non-unique) UID\n"), usageout);
+       (void) fputs (_("  -p, --password PASSWORD       encrypted password of the new account\n"), usageout);
+       (void) fputs (_("  -r, --system                  create a system account\n"), usageout);
+       (void) fputs (_("  -s, --shell SHELL             login shell of the new account\n"), usageout);
+       (void) fputs (_("  -u, --uid UID                 user ID of the new account\n"), usageout);
+       (void) fputs (_("  -U, --user-group              create a group with the same name as the user\n"), usageout);
+#ifdef WITH_SELINUX
+       (void) fputs (_("  -Z, --selinux-user SEUSER     use a specific SEUSER for the SELinux user mapping\n"), usageout);
+#endif
+       (void) fputs ("\n", usageout);
+       exit (status);
 }
 
 /*
@@ -954,12 +985,19 @@ static void process_flags (int argc, char **argv)
                        {"password", required_argument, NULL, 'p'},
                        {"system", no_argument, NULL, 'r'},
                        {"shell", required_argument, NULL, 's'},
+#ifdef WITH_SELINUX
+                       {"selinux-user", required_argument, NULL, 'Z'},
+#endif
                        {"uid", required_argument, NULL, 'u'},
                        {"user-group", no_argument, NULL, 'U'},
                        {NULL, 0, NULL, '\0'}
                };
                while ((c = getopt_long (argc, argv,
-                                        "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
+#ifdef WITH_SELINUX
+                                        "b:c:d:De:f:g:G:hk:K:lmMNop:rs:u:UZ:",
+#else
+                                        "b:c:d:De:f:g:G:hk:K:lmMNop:rs:u:U",
+#endif
                                         long_options, NULL)) != -1) {
                        switch (c) {
                        case 'b':
@@ -996,7 +1034,7 @@ static void process_flags (int argc, char **argv)
                                break;
                        case 'D':
                                if (anyflag) {
-                                       usage ();
+                                       usage (E_USAGE);
                                }
                                Dflg = true;
                                break;
@@ -1033,7 +1071,7 @@ static void process_flags (int argc, char **argv)
                                        fprintf (stderr,
                                                 _("%s: invalid numeric argument '%s'\n"),
                                                 Prog, optarg);
-                                       usage ();
+                                       usage (E_USAGE);
                                }
                                /*
                                 * -f -1 is allowed
@@ -1073,7 +1111,7 @@ static void process_flags (int argc, char **argv)
                                Gflg = true;
                                break;
                        case 'h':
-                               usage ();
+                               usage (E_SUCCESS);
                                break;
                        case 'k':
                                def_template = optarg;
@@ -1153,8 +1191,22 @@ static void process_flags (int argc, char **argv)
                        case 'U':
                                Uflg = true;
                                break;
+#ifdef WITH_SELINUX
+                       case 'Z':
+                               if (is_selinux_enabled () > 0) {
+                                       user_selinux = optarg;
+                                       Zflg = true;
+                               } else {
+                                       fprintf (stderr,
+                                                _("%s: -Z requires SELinux enabled kernel\n"),
+                                                Prog);
+
+                                       exit (E_BAD_ARG);
+                               }
+                               break;
+#endif
                        default:
-                               usage ();
+                               usage (E_USAGE);
                        }
                        anyflag = true;
                }
@@ -1173,31 +1225,31 @@ static void process_flags (int argc, char **argv)
                fprintf (stderr,
                         _("%s: %s flag is only allowed with the %s flag\n"),
                         Prog, "-o", "-u");
-               usage ();
+               usage (E_USAGE);
        }
        if (kflg && !mflg) {
                fprintf (stderr,
                         _("%s: %s flag is only allowed with the %s flag\n"),
                         Prog, "-k", "-m");
-               usage ();
+               usage (E_USAGE);
        }
        if (Uflg && gflg) {
                fprintf (stderr,
                         _("%s: options %s and %s conflict\n"),
                         Prog, "-U", "-g");
-               usage ();
+               usage (E_USAGE);
        }
        if (Uflg && Nflg) {
                fprintf (stderr,
                         _("%s: options %s and %s conflict\n"),
                         Prog, "-U", "-N");
-               usage ();
+               usage (E_USAGE);
        }
        if (mflg && Mflg) {
                fprintf (stderr,
                         _("%s: options %s and %s conflict\n"),
                         Prog, "-m", "-M");
-               usage ();
+               usage (E_USAGE);
        }
 
        /*
@@ -1206,15 +1258,15 @@ static void process_flags (int argc, char **argv)
         */
        if (Dflg) {
                if (optind != argc) {
-                       usage ();
+                       usage (E_USAGE);
                }
 
                if (uflg || oflg || Gflg || dflg || cflg || mflg) {
-                       usage ();
+                       usage (E_USAGE);
                }
        } else {
                if (optind != argc - 1) {
-                       usage ();
+                       usage (E_USAGE);
                }
 
                user_name = argv[optind];
@@ -1232,10 +1284,13 @@ static void process_flags (int argc, char **argv)
                }
                if (!dflg) {
                        char *uh;
+                       size_t len = strlen (def_home) + strlen (user_name) + 2;
+                       int wlen;
+
+                       uh = xmalloc (len);
+                       wlen = snprintf (uh, len, "%s/%s", def_home, user_name);
+                       assert (wlen == (int) len -1);
 
-                       uh = xmalloc (strlen (def_home) +
-                                     strlen (user_name) + 2);
-                       sprintf (uh, "%s/%s", def_home, user_name);
                        user_home = uh;
                }
        }
@@ -1257,7 +1312,7 @@ static void process_flags (int argc, char **argv)
        if (!rflg) {
                /* for system accounts defaults are ignored and we
                 * do not create a home dir */
-               if (getdef_bool("CREATE_HOME")) {
+               if (getdef_bool ("CREATE_HOME")) {
                        mflg = true;
                }
        }
@@ -1378,21 +1433,8 @@ static void open_files (void)
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
                fail_exit (E_PW_UPDATE);
        }
-       if (is_shadow_pwd) {
-               if (spw_lock () == 0) {
-                       fprintf (stderr,
-                                _("%s: cannot lock %s; try again later.\n"),
-                                Prog, spw_dbname ());
-                       fail_exit (E_PW_UPDATE);
-               }
-               spw_locked = true;
-               if (spw_open (O_RDWR) == 0) {
-                       fprintf (stderr,
-                                _("%s: cannot open %s\n"),
-                                Prog, spw_dbname ());
-                       fail_exit (E_PW_UPDATE);
-               }
-       }
+
+       /* shadow file will be opened by open_shadow(); */
 
        /*
         * Lock and open the group file.
@@ -1427,6 +1469,26 @@ static void open_files (void)
 #endif
 }
 
+static void open_shadow (void)
+{
+       if (!is_shadow_pwd) {
+               return;
+       }
+       if (spw_lock () == 0) {
+               fprintf (stderr,
+                        _("%s: cannot lock %s; try again later.\n"),
+                        Prog, spw_dbname ());
+               fail_exit (E_PW_UPDATE);
+       }
+       spw_locked = true;
+       if (spw_open (O_RDWR) == 0) {
+               fprintf (stderr,
+                        _("%s: cannot open %s\n"),
+                        Prog, spw_dbname ());
+               fail_exit (E_PW_UPDATE);
+       }
+}
+
 static char *empty_list = NULL;
 
 /*
@@ -1659,6 +1721,32 @@ static void usr_update (void)
        }
 }
 
+#ifdef WITH_SELINUX
+static void selinux_update_mapping (void) {
+       if (is_selinux_enabled () <= 0) return;
+
+       if (*user_selinux) { /* must be done after passwd write() */
+               const char *argv[7];
+               argv[0] = "/usr/sbin/semanage";
+               argv[1] = "login";
+               argv[2] = "-a";
+               argv[3] = "-s";
+               argv[4] = user_selinux;
+               argv[5] = user_name;
+               argv[6] = NULL;
+               if (safe_system (argv[0], argv, NULL, 0)) {
+                       fprintf (stderr,
+                                _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
+                                Prog, user_name, user_selinux);
+#ifdef WITH_AUDIT
+                       audit_logger (AUDIT_ADD_USER, Prog,
+                                     "adding SELinux user mapping",
+                                     user_name, (unsigned int) user_id, 0);
+#endif
+               }
+       }
+}
+#endif
 /*
  * create_home - create the user's home directory
  *
@@ -1669,6 +1757,9 @@ static void usr_update (void)
 static void create_home (void)
 {
        if (access (user_home, F_OK) != 0) {
+#ifdef WITH_SELINUX
+               selinux_file_context (user_home);
+#endif
                /* XXX - create missing parent directories.  --marekm */
                if (mkdir (user_home, 0) != 0) {
                        fprintf (stderr,
@@ -1691,6 +1782,10 @@ static void create_home (void)
                              "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);
 #endif
        }
 }
@@ -1772,7 +1867,7 @@ int main (int argc, char **argv)
        OPENLOG ("useradd");
 
        sys_ngroups = sysconf (_SC_NGROUPS_MAX);
-       user_groups = malloc ((1 + sys_ngroups) * sizeof (char *));
+       user_groups = (char **) xmalloc ((1 + sys_ngroups) * sizeof (char *));
        /*
         * Initialize the list to be empty
         */
@@ -1906,6 +2001,18 @@ int main (int argc, char **argv)
                }
        }
 
+#ifdef WITH_TCB
+       if (getdef_bool ("USE_TCB")) {
+               if (shadowtcb_create (user_name, user_id) == 0) {
+                       fprintf (stderr,
+                                _("%s: Failed to create tcb directory for %s\n"),
+                                Prog, user_name);
+                       fail_exit (E_UID_IN_USE);
+               }
+       }
+#endif
+       open_shadow ();
+
        /* do we have to add a group for that user? This is why we need to
         * open the group files in the open_files() function  --gafton */
        if (Uflg) {
@@ -1934,12 +2041,16 @@ int main (int argc, char **argv)
        }
 
        /* Do not create mail directory for system accounts */
-       if( !rflg ) {
+       if (!rflg) {
                create_mail ();
        }
 
        close_files ();
 
+#ifdef WITH_SELINUX
+       selinux_update_mapping ();
+#endif
+
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");