]> granicus.if.org Git - shadow/blob - src/useradd.c
Avoid ?: construct without the middle term.
[shadow] / src / useradd.c
1 /*
2  * Copyright 1991 - 1994, Julianne Frances Haugh
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 #include <config.h>
31
32 #ident "$Id$"
33
34 #include <assert.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <getopt.h>
39 #include <grp.h>
40 #include <lastlog.h>
41 #include <pwd.h>
42 #ifdef USE_PAM
43 #include "pam_defs.h"
44 #endif                          /* USE_PAM */
45 #include <stdio.h>
46 #include <sys/stat.h>
47 #include <sys/types.h>
48 #include <time.h>
49 #include "chkname.h"
50 #include "defines.h"
51 #include "faillog.h"
52 #include "getdef.h"
53 #include "groupio.h"
54 #include "nscd.h"
55 #include "prototypes.h"
56 #include "pwauth.h"
57 #include "pwio.h"
58 #ifdef  SHADOWGRP
59 #include "sgroupio.h"
60 #endif
61 #include "shadowio.h"
62
63 #ifndef SKEL_DIR
64 #define SKEL_DIR "/etc/skel"
65 #endif
66 #ifndef USER_DEFAULTS_FILE
67 #define USER_DEFAULTS_FILE "/etc/default/useradd"
68 #define NEW_USER_FILE "/etc/default/nuaddXXXXXX"
69 #endif
70 /*
71  * Needed for MkLinux DR1/2/2.1 - J.
72  */
73 #ifndef LASTLOG_FILE
74 #define LASTLOG_FILE "/var/log/lastlog"
75 #endif
76 /*
77  * Global variables
78  */
79 /*
80  * These defaults are used if there is no defaults file.
81  */
82 static gid_t def_group = 100;
83 static const char *def_gname = "other";
84 static const char *def_home = "/home";
85 static const char *def_shell = "";
86 static const char *def_template = SKEL_DIR;
87 static const char *def_create_mail_spool = "no";
88
89 static long def_inactive = -1;
90 static const char *def_expire = "";
91
92 static char def_file[] = USER_DEFAULTS_FILE;
93
94 #define VALID(s)        (strcspn (s, ":\n") == strlen (s))
95
96 static const char *user_name = "";
97 static const char *user_pass = "!";
98 static uid_t user_id;
99 static gid_t user_gid;
100 static const char *user_comment = "";
101 static const char *user_home = "";
102 static const char *user_shell = "";
103 static const char *create_mail_spool = "";
104
105 static long user_expire = -1;
106 static int is_shadow_pwd;
107
108 #ifdef SHADOWGRP
109 static int is_shadow_grp;
110 #endif
111 static char **user_groups;      /* NULL-terminated list */
112 static long sys_ngroups;
113 static int do_grp_update = 0;   /* group files need to be updated */
114
115 static char *Prog;
116
117 static int
118     bflg = 0,                   /* new default root of home directory */
119     cflg = 0,                   /* comment (GECOS) field for new account */
120     dflg = 0,                   /* home directory for new account */
121     Dflg = 0,                   /* set/show new user default values */
122     eflg = 0,                   /* days since 1970-01-01 when account is locked */
123     fflg = 0,                   /* days until account with expired password is locked */
124     gflg = 0,                   /* primary group ID for new account */
125     Gflg = 0,                   /* secondary group set for new account */
126     kflg = 0,                   /* specify a directory to fill new user directory */
127     lflg = 0,                   /* do not add user to lastlog database file */
128     mflg = 0,                   /* create user's home directory if it doesn't exist */
129     nflg = 0,                   /* create a group having the same name as the user */
130     oflg = 0,                   /* permit non-unique user ID to be specified with -u */
131     sflg = 0,                   /* shell program for new account */
132     uflg = 0;                   /* specify user ID for new account */
133
134 extern char *optarg;
135 extern int optind;
136
137 static int home_added;
138
139 /*
140  * exit status values
141  */
142 #define E_SUCCESS       0       /* success */
143 #define E_PW_UPDATE     1       /* can't update password file */
144 #define E_USAGE         2       /* invalid command syntax */
145 #define E_BAD_ARG       3       /* invalid argument to option */
146 #define E_UID_IN_USE    4       /* UID already in use (and no -o) */
147 #define E_NOTFOUND      6       /* specified group doesn't exist */
148 #define E_NAME_IN_USE   9       /* username already in use */
149 #define E_GRP_UPDATE    10      /* can't update group file */
150 #define E_HOMEDIR       12      /* can't create home directory */
151 #define E_MAIL_SPOOL    13      /* can't create mail spool */
152
153 #define DGROUP                  "GROUP="
154 #define HOME                    "HOME="
155 #define SHELL                   "SHELL="
156 #define INACT                   "INACTIVE="
157 #define EXPIRE                  "EXPIRE="
158 #define SKEL                    "SKEL="
159 #define CREATE_MAIL_SPOOL       "CREATE_MAIL_SPOOL="
160
161 /* local function prototypes */
162 static void fail_exit (int);
163 static struct group *getgr_nam_gid (const char *);
164 static long get_number (const char *);
165 static uid_t get_uid (const char *);
166 static void get_defaults (void);
167 static void show_defaults (void);
168 static int set_defaults (void);
169 static int get_groups (char *);
170 static void usage (void);
171 static void new_pwent (struct passwd *);
172
173 static long scale_age (long);
174 static void new_spent (struct spwd *);
175 static void grp_update (void);
176 static void find_new_uid (void);
177
178 static void process_flags (int argc, char **argv);
179 static void close_files (void);
180 static void open_files (void);
181 static void faillog_reset (uid_t);
182 static void lastlog_reset (uid_t);
183 static void usr_update (void);
184 static void create_home (void);
185 static void create_mail (void);
186
187 /*
188  * fail_exit - undo as much as possible
189  */
190 static void fail_exit (int code)
191 {
192         if (home_added)
193                 rmdir (user_home);
194
195 #ifdef WITH_AUDIT
196         audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user", user_name, -1,
197                       0);
198 #endif
199         SYSLOG ((LOG_INFO, "failed adding user `%s', data deleted", user_name));
200         exit (code);
201 }
202
203 static struct group *getgr_nam_gid (const char *grname)
204 {
205         long gid;
206         char *errptr;
207
208         gid = strtol (grname, &errptr, 10);
209         if (*grname != '\0' && *errptr == '\0' && errno != ERANGE && gid >= 0)
210                 return xgetgrgid (gid);
211         return xgetgrnam (grname);
212 }
213
214 static long get_number (const char *numstr)
215 {
216         long val;
217         char *errptr;
218
219         val = strtol (numstr, &errptr, 10);
220         if (*errptr || errno == ERANGE) {
221                 fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
222                          numstr);
223                 exit (E_BAD_ARG);
224         }
225         return val;
226 }
227
228 static uid_t get_uid (const char *uidstr)
229 {
230         long val;
231         char *errptr;
232
233         val = strtol (uidstr, &errptr, 10);
234         if (*errptr || errno == ERANGE || val < 0) {
235                 fprintf (stderr,
236                          _("%s: invalid numeric argument '%s'\n"), Prog,
237                          uidstr);
238                 exit (E_BAD_ARG);
239         }
240         return val;
241 }
242
243 #define MATCH(x,y) (strncmp((x),(y),strlen(y)) == 0)
244
245 /*
246  * get_defaults - read the defaults file
247  *
248  *      get_defaults() reads the defaults file for this command. It sets the
249  *      various values from the file, or uses built-in default values if the
250  *      file does not exist.
251  */
252 static void get_defaults (void)
253 {
254         FILE *fp;
255         char buf[1024];
256         char *cp, *ep;
257
258         /*
259          * Open the defaults file for reading.
260          */
261
262         if (!(fp = fopen (def_file, "r")))
263                 return;
264
265         /*
266          * Read the file a line at a time. Only the lines that have relevant
267          * values are used, everything else can be ignored.
268          */
269         while (fgets (buf, sizeof buf, fp)) {
270                 if ((cp = strrchr (buf, '\n')))
271                         *cp = '\0';
272
273                 if (!(cp = strchr (buf, '=')))
274                         continue;
275
276                 cp++;
277
278                 /*
279                  * Primary GROUP identifier
280                  */
281                 if (MATCH (buf, DGROUP)) {
282                         unsigned int val = (unsigned int) strtoul (cp, &ep, 10);
283                         const struct group *grp;
284
285                         if (*cp != '\0' && *ep == '\0') { /* valid number */
286                                 def_group = val;
287                                 /* local, no need for xgetgrgid */
288                                 if ((grp = getgrgid (def_group))) {
289                                         def_gname = xstrdup (grp->gr_name);
290                                 } else {
291                                         fprintf (stderr,
292                                                  _("%s: unknown GID %s\n"),
293                                                  Prog, cp);
294                                 }
295                         /* local, no need for xgetgrnam */
296                         } else if ((grp = getgrnam (cp))) {
297                                 def_group = grp->gr_gid;
298                                 def_gname = xstrdup (cp);
299                         } else {
300                                 fprintf (stderr,
301                                          _("%s: unknown group %s\n"), Prog, cp);
302                         }
303                 }
304
305                 /*
306                  * Default HOME filesystem
307                  */
308                 else if (MATCH (buf, HOME)) {
309                         def_home = xstrdup (cp);
310                 }
311
312                 /*
313                  * Default Login Shell command
314                  */
315                 else if (MATCH (buf, SHELL)) {
316                         def_shell = xstrdup (cp);
317                 }
318
319                 /*
320                  * Default Password Inactive value
321                  */
322                 else if (MATCH (buf, INACT)) {
323                         long val = strtol (cp, &ep, 10);
324
325                         if (*cp || errno == ERANGE)
326                                 def_inactive = val;
327                         else
328                                 def_inactive = -1;
329                 }
330
331                 /*
332                  * Default account expiration date
333                  */
334                 else if (MATCH (buf, EXPIRE)) {
335                         def_expire = xstrdup (cp);
336                 }
337
338                 /*
339                  * Default Skeleton information
340                  */
341                 else if (MATCH (buf, SKEL)) {
342                         if (*cp == '\0')
343                                 cp = SKEL_DIR;  /* XXX warning: const */
344
345                         def_template = xstrdup (cp);
346                 }
347
348                 /*
349                  * Create by default user mail spool or not ?
350                  */
351                 else if (MATCH (buf, CREATE_MAIL_SPOOL)) {
352                         if (*cp == '\0')
353                                 cp = CREATE_MAIL_SPOOL; /* XXX warning: const */
354
355                         def_create_mail_spool = xstrdup (cp);
356                 }
357         }
358 }
359
360 /*
361  * show_defaults - show the contents of the defaults file
362  *
363  *      show_defaults() displays the values that are used from the default
364  *      file and the built-in values.
365  */
366 static void show_defaults (void)
367 {
368         printf ("GROUP=%u\n", (unsigned int) def_group);
369         printf ("HOME=%s\n", def_home);
370         printf ("INACTIVE=%ld\n", def_inactive);
371         printf ("EXPIRE=%s\n", def_expire);
372         printf ("SHELL=%s\n", def_shell);
373         printf ("SKEL=%s\n", def_template);
374         printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool);
375 }
376
377 /*
378  * set_defaults - write new defaults file
379  *
380  *      set_defaults() re-writes the defaults file using the values that
381  *      are currently set. Duplicated lines are pruned, missing lines are
382  *      added, and unrecognized lines are copied as is.
383  */
384 static int set_defaults (void)
385 {
386         FILE *ifp;
387         FILE *ofp;
388         char buf[1024];
389         static char new_file[] = NEW_USER_FILE;
390         char *cp;
391         int ofd;
392         int out_group = 0;
393         int out_home = 0;
394         int out_inactive = 0;
395         int out_expire = 0;
396         int out_shell = 0;
397         int out_skel = 0;
398         int out_create_mail_spool = 0;
399
400         /*
401          * Create a temporary file to copy the new output to.
402          */
403         if ((ofd = mkstemp (new_file)) == -1) {
404                 fprintf (stderr,
405                          _("%s: cannot create new defaults file\n"), Prog);
406                 return -1;
407         }
408
409         if (!(ofp = fdopen (ofd, "w"))) {
410                 fprintf (stderr, _("%s: cannot open new defaults file\n"),
411                          Prog);
412                 return -1;
413         }
414
415         /*
416          * Open the existing defaults file and copy the lines to the
417          * temporary file, using any new values. Each line is checked
418          * to insure that it is not output more than once.
419          */
420         if (!(ifp = fopen (def_file, "r"))) {
421                 fprintf (ofp, "# useradd defaults file\n");
422                 goto skip;
423         }
424
425         while (fgets (buf, sizeof buf, ifp)) {
426                 if ((cp = strrchr (buf, '\n')))
427                         *cp = '\0';
428
429                 if (!out_group && MATCH (buf, DGROUP)) {
430                         fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
431                         out_group++;
432                 } else if (!out_home && MATCH (buf, HOME)) {
433                         fprintf (ofp, HOME "%s\n", def_home);
434                         out_home++;
435                 } else if (!out_inactive && MATCH (buf, INACT)) {
436                         fprintf (ofp, INACT "%ld\n", def_inactive);
437                         out_inactive++;
438                 } else if (!out_expire && MATCH (buf, EXPIRE)) {
439                         fprintf (ofp, EXPIRE "%s\n", def_expire);
440                         out_expire++;
441                 } else if (!out_shell && MATCH (buf, SHELL)) {
442                         fprintf (ofp, SHELL "%s\n", def_shell);
443                         out_shell++;
444                 } else if (!out_skel && MATCH (buf, SKEL)) {
445                         fprintf (ofp, SKEL "%s\n", def_template);
446                         out_skel++;
447                 } else if (!out_create_mail_spool
448                            && MATCH (buf, CREATE_MAIL_SPOOL)) {
449                         fprintf (ofp, CREATE_MAIL_SPOOL "%s\n",
450                                  def_create_mail_spool);
451                         out_create_mail_spool++;
452                 } else
453                         fprintf (ofp, "%s\n", buf);
454         }
455         fclose (ifp);
456
457       skip:
458         /*
459          * Check each line to insure that every line was output. This
460          * causes new values to be added to a file which did not previously
461          * have an entry for that value.
462          */
463         if (!out_group)
464                 fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
465         if (!out_home)
466                 fprintf (ofp, HOME "%s\n", def_home);
467         if (!out_inactive)
468                 fprintf (ofp, INACT "%ld\n", def_inactive);
469         if (!out_expire)
470                 fprintf (ofp, EXPIRE "%s\n", def_expire);
471         if (!out_shell)
472                 fprintf (ofp, SHELL "%s\n", def_shell);
473         if (!out_skel)
474                 fprintf (ofp, SKEL "%s\n", def_template);
475
476         if (!out_create_mail_spool)
477                 fprintf (ofp, CREATE_MAIL_SPOOL "%s\n", def_create_mail_spool);
478
479         /*
480          * Flush and close the file. Check for errors to make certain
481          * the new file is intact.
482          */
483         fflush (ofp);
484         if (ferror (ofp) || fclose (ofp)) {
485                 unlink (new_file);
486                 return -1;
487         }
488
489         /*
490          * Rename the current default file to its backup name.
491          */
492         snprintf (buf, sizeof buf, "%s-", def_file);
493         if (rename (def_file, buf) && errno != ENOENT) {
494                 snprintf (buf, sizeof buf, _("%s: rename: %s"), Prog, def_file);
495                 perror (buf);
496                 unlink (new_file);
497                 return -1;
498         }
499
500         /*
501          * Rename the new default file to its correct name.
502          */
503         if (rename (new_file, def_file)) {
504                 snprintf (buf, sizeof buf, _("%s: rename: %s"), Prog, new_file);
505                 perror (buf);
506                 return -1;
507         }
508 #ifdef WITH_AUDIT
509         audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "changing user defaults",
510                       NULL, -1, 1);
511 #endif
512         SYSLOG ((LOG_INFO,
513                  "useradd defaults: GROUP=%u, HOME=%s, SHELL=%s, INACTIVE=%ld, "
514                  "EXPIRE=%s, SKEL=%s, CREATE_MAIL_SPOOL=%s",
515                  (unsigned int) def_group, def_home, def_shell,
516                  def_inactive, def_expire, def_template,
517                  def_create_mail_spool));
518         return 0;
519 }
520
521 /*
522  * get_groups - convert a list of group names to an array of group IDs
523  *
524  *      get_groups() takes a comma-separated list of group names and
525  *      converts it to a NULL-terminated array. Any unknown group
526  *      names are reported as errors.
527  */
528 static int get_groups (char *list)
529 {
530         char *cp;
531         const struct group *grp;
532         int errors = 0;
533         int ngroups = 0;
534
535         if (!*list)
536                 return 0;
537
538         /*
539          * So long as there is some data to be converted, strip off
540          * each name and look it up. A mix of numerical and string
541          * values for group identifiers is permitted.
542          */
543         do {
544                 /*
545                  * Strip off a single name from the list
546                  */
547                 if ((cp = strchr (list, ',')))
548                         *cp++ = '\0';
549
550                 /*
551                  * Names starting with digits are treated as numerical
552                  * GID values, otherwise the string is looked up as is.
553                  */
554                 grp = getgr_nam_gid (list);
555
556                 /*
557                  * There must be a match, either by GID value or by
558                  * string name.
559                  */
560                 if (!grp) {
561                         fprintf (stderr, _("%s: unknown group %s\n"),
562                                  Prog, list);
563                         errors++;
564                 }
565                 list = cp;
566
567                 /*
568                  * If the group doesn't exist, don't dump core...
569                  * Instead, try the next one.  --marekm
570                  */
571                 if (!grp)
572                         continue;
573
574 #ifdef  USE_NIS
575                 /*
576                  * Don't add this group if they are an NIS group. Tell
577                  * the user to go to the server for this group.
578                  */
579                 if (__isgrNIS ()) {
580                         fprintf (stderr,
581                                  _("%s: group '%s' is a NIS group.\n"),
582                                  Prog, grp->gr_name);
583                         continue;
584                 }
585 #endif
586
587                 if (ngroups == sys_ngroups) {
588                         fprintf (stderr,
589                                  _
590                                  ("%s: too many groups specified (max %d).\n"),
591                                  Prog, ngroups);
592                         break;
593                 }
594
595                 /*
596                  * Add the group name to the user's list of groups.
597                  */
598                 user_groups[ngroups++] = xstrdup (grp->gr_name);
599         } while (list);
600
601         user_groups[ngroups] = (char *) 0;
602
603         /*
604          * Any errors in finding group names are fatal
605          */
606         if (errors)
607                 return -1;
608
609         return 0;
610 }
611
612 /*
613  * usage - display usage message and exit
614  */
615 static void usage (void)
616 {
617         fprintf (stderr, _("Usage: useradd [options] LOGIN\n"
618                            "\n"
619                            "Options:\n"
620                            "  -b, --base-dir BASE_DIR       base directory for the new user account\n"
621                            "                                home directory\n"
622                            "  -c, --comment COMMENT         set the GECOS field for the new user account\n"
623                            "  -d, --home-dir HOME_DIR       home directory for the new user account\n"
624                            "  -D, --defaults                print or save modified default useradd\n"
625                            "                                configuration\n"
626                            "  -e, --expiredate EXPIRE_DATE  set account expiration date to EXPIRE_DATE\n"
627                            "  -f, --inactive INACTIVE       set password inactive after expiration\n"
628                            "                                to INACTIVE\n"
629                            "  -g, --gid GROUP               force use GROUP for the new user account\n"
630                            "  -G, --groups GROUPS           list of supplementary groups for the new\n"
631                            "                                user account\n"
632                            "  -h, --help                    display this help message and exit\n"
633                            "  -k, --skel SKEL_DIR           specify an alternative skel directory\n"
634                            "  -K, --key KEY=VALUE           overrides /etc/login.defs defaults\n"
635                            "  -l,                           do not add the user to the lastlog and\n"
636                            "                                faillog databases\n"
637                            "  -m, --create-home             create home directory for the new user\n"
638                            "                                account\n"
639                            "  -o, --non-unique              allow create user with duplicate\n"
640                            "                                (non-unique) UID\n"
641                            "  -p, --password PASSWORD       use encrypted password for the new user\n"
642                            "                                account\n"
643                            "  -s, --shell SHELL             the login shell for the new user account\n"
644                            "  -u, --uid UID                 force use the UID for the new user account\n"
645                            "\n"));
646         exit (E_USAGE);
647 }
648
649 /*
650  * new_pwent - initialize the values in a password file entry
651  *
652  *      new_pwent() takes all of the values that have been entered and
653  *      fills in a (struct passwd) with them.
654  */
655 static void new_pwent (struct passwd *pwent)
656 {
657         memzero (pwent, sizeof *pwent);
658         pwent->pw_name = (char *) user_name;
659         if (is_shadow_pwd)
660                 pwent->pw_passwd = (char *) SHADOW_PASSWD_STRING;
661         else
662                 pwent->pw_passwd = (char *) user_pass;
663
664         pwent->pw_uid = user_id;
665         pwent->pw_gid = user_gid;
666         pwent->pw_gecos = (char *) user_comment;
667         pwent->pw_dir = (char *) user_home;
668         pwent->pw_shell = (char *) user_shell;
669 }
670
671 static long scale_age (long x)
672 {
673         if (x <= 0)
674                 return x;
675
676         return x * (DAY / SCALE);
677 }
678
679 /*
680  * new_spent - initialize the values in a shadow password file entry
681  *
682  *      new_spent() takes all of the values that have been entered and
683  *      fills in a (struct spwd) with them.
684  */
685 static void new_spent (struct spwd *spent)
686 {
687         memzero (spent, sizeof *spent);
688         spent->sp_namp = (char *) user_name;
689         spent->sp_pwdp = (char *) user_pass;
690         spent->sp_lstchg = time ((time_t *) 0) / SCALE;
691         spent->sp_min = scale_age (getdef_num ("PASS_MIN_DAYS", -1));
692         spent->sp_max = scale_age (getdef_num ("PASS_MAX_DAYS", -1));
693         spent->sp_warn = scale_age (getdef_num ("PASS_WARN_AGE", -1));
694         spent->sp_inact = scale_age (def_inactive);
695         spent->sp_expire = scale_age (user_expire);
696         spent->sp_flag = -1;
697 }
698
699 /*
700  * grp_update - add user to secondary group set
701  *
702  *      grp_update() takes the secondary group set given in user_groups
703  *      and adds the user to each group given by that set.
704  *
705  *      The group files are opened and locked in open_files().
706  *
707  *      close_files() should be called afterwards to commit the changes
708  *      and unlocking the group files.
709  */
710 static void grp_update (void)
711 {
712         const struct group *grp;
713         struct group *ngrp;
714
715 #ifdef  SHADOWGRP
716         const struct sgrp *sgrp;
717         struct sgrp *nsgrp;
718 #endif
719
720         /*
721          * Scan through the entire group file looking for the groups that
722          * the user is a member of.
723          */
724         for (gr_rewind (), grp = gr_next (); grp; grp = gr_next ()) {
725
726                 /*
727                  * See if the user specified this group as one of their
728                  * concurrent groups.
729                  */
730                 if (!is_on_list (user_groups, grp->gr_name))
731                         continue;
732
733                 /*
734                  * Make a copy - gr_update() will free() everything
735                  * from the old entry, and we need it later.
736                  */
737                 ngrp = __gr_dup (grp);
738                 if (!ngrp) {
739                         fprintf (stderr,
740                                  _("%s: Out of memory. Cannot update the group database.\n"),
741                                  Prog);
742                         fail_exit (E_GRP_UPDATE);       /* XXX */
743                 }
744
745                 /* 
746                  * Add the username to the list of group members and
747                  * update the group entry to reflect the change.
748                  */
749                 ngrp->gr_mem = add_list (ngrp->gr_mem, user_name);
750                 if (!gr_update (ngrp)) {
751                         fprintf (stderr,
752                                  _("%s: error adding new group entry\n"), Prog);
753                         fail_exit (E_GRP_UPDATE);
754                 }
755 #ifdef WITH_AUDIT
756                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
757                               "adding user to group", user_name, -1, 1);
758 #endif
759                 SYSLOG ((LOG_INFO, "add `%s' to group `%s'",
760                          user_name, ngrp->gr_name));
761         }
762
763 #ifdef  SHADOWGRP
764         if (!is_shadow_grp)
765                 return;
766
767         /*
768          * Scan through the entire shadow group file looking for the groups
769          * that the user is a member of. The administrative list isn't
770          * modified.
771          */
772         for (sgr_rewind (), sgrp = sgr_next (); sgrp; sgrp = sgr_next ()) {
773
774                 /*
775                  * See if the user specified this group as one of their
776                  * concurrent groups.
777                  */
778                 if (!gr_locate (sgrp->sg_name))
779                         continue;
780
781                 if (!is_on_list (user_groups, sgrp->sg_name))
782                         continue;
783
784                 /*
785                  * Make a copy - sgr_update() will free() everything
786                  * from the old entry, and we need it later.
787                  */
788                 nsgrp = __sgr_dup (sgrp);
789                 if (!nsgrp) {
790                         fprintf (stderr,
791                                  _("%s: Out of memory. Cannot update the shadow group database.\n"),
792                                  Prog);
793                         fail_exit (E_GRP_UPDATE);       /* XXX */
794                 }
795
796                 /* 
797                  * Add the username to the list of group members and
798                  * update the group entry to reflect the change.
799                  */
800                 nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_name);
801                 if (!sgr_update (nsgrp)) {
802                         fprintf (stderr,
803                                  _("%s: error adding new group entry\n"), Prog);
804                         fail_exit (E_GRP_UPDATE);
805                 }
806 #ifdef WITH_AUDIT
807                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
808                               "adding user to shadow group", user_name, -1, 1);
809 #endif
810                 SYSLOG ((LOG_INFO, "add `%s' to shadow group `%s'",
811                          user_name, nsgrp->sg_name));
812         }
813 #endif                          /* SHADOWGRP */
814 }
815
816 /*
817  * find_new_uid - find the next available UID
818  *
819  *      find_new_uid() locates the next highest unused UID in the password
820  *      file.
821  */
822 static void find_new_uid (void)
823 {
824         const struct passwd *pwd;
825         uid_t uid_min, uid_max;
826
827         /*
828          * It doesn't make sense to use find_new_uid(),
829          * if an UID is specified via "-u" option.
830          */
831         assert (!uflg);
832
833         uid_min = getdef_unum ("UID_MIN", 1000);
834         uid_max = getdef_unum ("UID_MAX", 60000);
835
836         user_id = uid_min;
837
838         /*
839          * Search the entire password file,
840          * looking for the largest unused value.
841          */
842         setpwent ();
843         while ((pwd = getpwent ()) != NULL) {
844                 if ((pwd->pw_uid >= user_id) && (pwd->pw_uid <= uid_max)) {
845                         user_id = pwd->pw_uid + 1;
846                 }
847         }
848
849         /*
850          * If a user with UID equal to UID_MAX exists, the above algorithm
851          * will give us UID_MAX+1 even if not unique. Search for the first
852          * free UID starting with UID_MIN (it's O(n*n) but can be avoided
853          * by not having users with UID equal to UID_MAX).  --marekm
854          */
855         if (user_id == uid_max + 1) {
856                 for (user_id = uid_min; user_id < uid_max; user_id++) {
857                         /* local, no need for xgetpwuid */
858                         if (!getpwuid (user_id))
859                                 break;
860                 }
861                 if (user_id == uid_max) {
862                         fprintf (stderr, _("%s: can't get unique UID (run out of UIDs)\n"), Prog);
863                         fail_exit (E_UID_IN_USE);
864                 }
865         }
866 }
867
868 /*
869  * find_new_gid - find the next available GID
870  *
871  *      find_new_gid() locates the next highest unused GID in the group
872  *      file
873  */
874 static void find_new_gid ()
875 {
876         const struct group *grp;
877         gid_t gid_min, gid_max;
878
879         /*
880          * It doesn't make sense to use find_new_gid(),
881          * if a group is specified via "-g" option.
882          */
883         assert (!gflg);
884
885         gid_min = getdef_num ("GID_MIN", 500);
886         gid_max = getdef_num ("GID_MAX", 60000);
887
888         user_gid = gid_min;
889
890         /*
891          * Search the entire group file, either looking for this
892          * GID (if the user specified one with -g) or looking for the
893          * largest unused value.
894          */
895         setgrent ();
896         while ((grp = getgrent ())) {
897                 if ((grp->gr_gid >= user_gid) && (grp->gr_gid <= gid_max)) {
898                         user_gid = grp->gr_gid + 1;
899                 }
900         }
901         if (user_gid == gid_max + 1) {
902                 for (user_gid = gid_min; user_gid < gid_max; user_gid++) {
903                         /* local, no need for xgetgrgid */
904                         if (!getgrgid (user_gid))
905                                 break;
906                 }
907                 if (user_gid == gid_max) {
908                         fprintf (stderr,
909                                  "%s: can't get unique gid (run out of GIDs)\n",
910                                  Prog);
911                         fail_exit (4);
912                 }
913         }
914 }
915
916 /*
917  * process_flags - perform command line argument setting
918  *
919  *      process_flags() interprets the command line arguments and sets
920  *      the values that the user will be created with accordingly. The
921  *      values are checked for sanity.
922  */
923 static void process_flags (int argc, char **argv)
924 {
925         const struct group *grp;
926         int anyflag = 0;
927         char *cp;
928
929         {
930                 /*
931                  * Parse the command line options.
932                  */
933                 int c;
934                 static struct option long_options[] = {
935                         {"base-dir", required_argument, NULL, 'b'},
936                         {"comment", required_argument, NULL, 'c'},
937                         {"home-dir", required_argument, NULL, 'd'},
938                         {"defaults", required_argument, NULL, 'D'},
939                         {"expiredate", required_argument, NULL, 'e'},
940                         {"inactive", required_argument, NULL, 'f'},
941                         {"gid", required_argument, NULL, 'g'},
942                         {"groups", required_argument, NULL, 'G'},
943                         {"help", no_argument, NULL, 'h'},
944                         {"skel", required_argument, NULL, 'k'},
945                         {"key", required_argument, NULL, 'K'},
946                         {"create-home", no_argument, NULL, 'm'},
947                         {"non-unique", no_argument, NULL, 'o'},
948                         {"password", required_argument, NULL, 'p'},
949                         {"shell", required_argument, NULL, 's'},
950                         {"uid", required_argument, NULL, 'u'},
951                         {NULL, 0, NULL, '\0'}
952                 };
953                 while ((c =
954                         getopt_long (argc, argv, "b:c:d:De:f:g:G:k:K:lmMop:s:u:",
955                                      long_options, NULL)) != -1) {
956                         switch (c) {
957                         case 'b':
958                                 if (!VALID (optarg)
959                                     || optarg[0] != '/') {
960                                         fprintf (stderr,
961                                                  _
962                                                  ("%s: invalid base directory '%s'\n"),
963                                                  Prog, optarg);
964                                         exit (E_BAD_ARG);
965                                 }
966                                 def_home = optarg;
967                                 bflg++;
968                                 break;
969                         case 'c':
970                                 if (!VALID (optarg)) {
971                                         fprintf (stderr,
972                                                  _
973                                                  ("%s: invalid comment '%s'\n"),
974                                                  Prog, optarg);
975                                         exit (E_BAD_ARG);
976                                 }
977                                 user_comment = optarg;
978                                 cflg++;
979                                 break;
980                         case 'd':
981                                 if (!VALID (optarg)
982                                     || optarg[0] != '/') {
983                                         fprintf (stderr,
984                                                  _
985                                                  ("%s: invalid home directory '%s'\n"),
986                                                  Prog, optarg);
987                                         exit (E_BAD_ARG);
988                                 }
989                                 user_home = optarg;
990                                 dflg++;
991                                 break;
992                         case 'D':
993                                 if (anyflag)
994                                         usage ();
995                                 Dflg++;
996                                 break;
997                         case 'e':
998                                 if (*optarg) {
999                                         user_expire = strtoday (optarg);
1000                                         if (user_expire == -1) {
1001                                                 fprintf (stderr,
1002                                                          _
1003                                                          ("%s: invalid date '%s'\n"),
1004                                                          Prog, optarg);
1005                                                 exit (E_BAD_ARG);
1006                                         }
1007                                 } else
1008                                         user_expire = -1;
1009
1010                                 /*
1011                                  * -e "" is allowed - it's a no-op without /etc/shadow
1012                                  */
1013                                 if (*optarg && !is_shadow_pwd) {
1014                                         fprintf (stderr,
1015                                                  _
1016                                                  ("%s: shadow passwords required for -e\n"),
1017                                                  Prog);
1018                                         exit (E_USAGE);
1019                                 }
1020                                 if (Dflg)
1021                                         def_expire = optarg;
1022                                 eflg++;
1023                                 break;
1024                         case 'f':
1025                                 def_inactive = get_number (optarg);
1026                                 /*
1027                                  * -f -1 is allowed - it's a no-op without /etc/shadow
1028                                  */
1029                                 if (def_inactive != -1 && !is_shadow_pwd) {
1030                                         fprintf (stderr,
1031                                                  _
1032                                                  ("%s: shadow passwords required for -f\n"),
1033                                                  Prog);
1034                                         exit (E_USAGE);
1035                                 }
1036                                 fflg++;
1037                                 break;
1038                         case 'g':
1039                                 grp = getgr_nam_gid (optarg);
1040                                 if (!grp) {
1041                                         fprintf (stderr,
1042                                                  _
1043                                                  ("%s: unknown group %s\n"),
1044                                                  Prog, optarg);
1045                                         exit (E_NOTFOUND);
1046                                 }
1047                                 if (Dflg) {
1048                                         def_group = grp->gr_gid;
1049                                         def_gname = optarg;
1050                                 } else {
1051                                         user_gid = grp->gr_gid;
1052                                 }
1053                                 gflg++;
1054                                 break;
1055                         case 'G':
1056                                 if (get_groups (optarg))
1057                                         exit (E_NOTFOUND);
1058                                 if (user_groups[0])
1059                                         do_grp_update++;
1060                                 Gflg++;
1061                                 break;
1062                         case 'h':
1063                                 usage ();
1064                                 break;
1065                         case 'k':
1066                                 def_template = optarg;
1067                                 kflg++;
1068                                 break;
1069                         case 'K':
1070                                 /*
1071                                  * override login.defs defaults (-K name=value)
1072                                  * example: -K UID_MIN=100 -K UID_MAX=499
1073                                  * note: -K UID_MIN=10,UID_MAX=499 doesn't work yet
1074                                  */
1075                                 cp = strchr (optarg, '=');
1076                                 if (!cp) {
1077                                         fprintf (stderr,
1078                                                  _
1079                                                  ("%s: -K requires KEY=VALUE\n"),
1080                                                  Prog);
1081                                         exit (E_BAD_ARG);
1082                                 }
1083                                 /* terminate name, point to value */
1084                                 *cp++ = '\0';
1085                                 if (putdef_str (optarg, cp) < 0)
1086                                         exit (E_BAD_ARG);
1087                                 break;
1088                         case 'l':
1089                                 lflg++;
1090                                 break;
1091                         case 'm':
1092                                 mflg++;
1093                                 break;
1094                         case 'o':
1095                                 oflg++;
1096                                 break;
1097                         case 'p':       /* set encrypted password */
1098                                 if (!VALID (optarg)) {
1099                                         fprintf (stderr,
1100                                                  _
1101                                                  ("%s: invalid field '%s'\n"),
1102                                                  Prog, optarg);
1103                                         exit (E_BAD_ARG);
1104                                 }
1105                                 user_pass = optarg;
1106                                 break;
1107                         case 's':
1108                                 if (!VALID (optarg)
1109                                     || (optarg[0]
1110                                         && (optarg[0] != '/'
1111                                             && optarg[0] != '*'))) {
1112                                         fprintf (stderr,
1113                                                  _
1114                                                  ("%s: invalid shell '%s'\n"),
1115                                                  Prog, optarg);
1116                                         exit (E_BAD_ARG);
1117                                 }
1118                                 user_shell = optarg;
1119                                 def_shell = optarg;
1120                                 sflg++;
1121                                 break;
1122                         case 'u':
1123                                 user_id = get_uid (optarg);
1124                                 uflg++;
1125                                 break;
1126                         default:
1127                                 usage ();
1128                         }
1129                         anyflag++;
1130                 }
1131         }
1132
1133         /*
1134          * Certain options are only valid in combination with others.
1135          * Check it here so that they can be specified in any order.
1136          */
1137         if ((oflg && !uflg) || (kflg && !mflg))
1138                 usage ();
1139
1140         /*
1141          * Either -D or username is required. Defaults can be set with -D
1142          * for the -b, -e, -f, -g, -s options only.
1143          */
1144         if (Dflg) {
1145                 if (optind != argc)
1146                         usage ();
1147
1148                 if (uflg || oflg || Gflg || dflg || cflg || mflg)
1149                         usage ();
1150         } else {
1151                 if (optind != argc - 1)
1152                         usage ();
1153
1154                 user_name = argv[optind];
1155                 if (!check_user_name (user_name)) {
1156                         fprintf (stderr,
1157                                  _
1158                                  ("%s: invalid user name '%s'\n"),
1159                                  Prog, user_name);
1160 #ifdef WITH_AUDIT
1161                         audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user",
1162                                       user_name, -1, 0);
1163 #endif
1164                         exit (E_BAD_ARG);
1165                 }
1166                 if (!dflg) {
1167                         char *uh;
1168
1169                         uh = xmalloc (strlen (def_home) +
1170                                       strlen (user_name) + 2);
1171                         sprintf (uh, "%s/%s", def_home, user_name);
1172                         user_home = uh;
1173                 }
1174         }
1175
1176         if (!eflg)
1177                 user_expire = strtoday (def_expire);
1178
1179         if (!gflg)
1180                 user_gid = def_group;
1181
1182         if (!sflg)
1183                 user_shell = def_shell;
1184
1185         /* TODO: add handle change default spool mail creation by 
1186            -K CREATE_MAIL_SPOOL={yes,no}. It need rewrite internal API for handle
1187            shadow tools configuration */
1188         create_mail_spool = def_create_mail_spool;
1189 }
1190
1191 /*
1192  * close_files - close all of the files that were opened
1193  *
1194  *      close_files() closes all of the files that were opened for this
1195  *      new user. This causes any modified entries to be written out.
1196  */
1197 static void close_files (void)
1198 {
1199         if (!pw_close ()) {
1200                 fprintf (stderr, _("%s: cannot rewrite password file\n"), Prog);
1201                 fail_exit (E_PW_UPDATE);
1202         }
1203         if (is_shadow_pwd && !spw_close ()) {
1204                 fprintf (stderr,
1205                          _("%s: cannot rewrite shadow password file\n"), Prog);
1206                 fail_exit (E_PW_UPDATE);
1207         }
1208         if (do_grp_update) {
1209                 if (!gr_close ()) {
1210                         fprintf (stderr,
1211                                  _("%s: cannot rewrite group file\n"), Prog);
1212                         fail_exit (E_GRP_UPDATE);
1213                 }
1214 #ifdef  SHADOWGRP
1215                 if (is_shadow_grp && !sgr_close ()) {
1216                         fprintf (stderr,
1217                                  _
1218                                  ("%s: cannot rewrite shadow group file\n"),
1219                                  Prog);
1220                         fail_exit (E_GRP_UPDATE);
1221                 }
1222 #endif
1223         }
1224         if (is_shadow_pwd)
1225                 spw_unlock ();
1226         pw_unlock ();
1227         gr_unlock ();
1228 #ifdef  SHADOWGRP
1229         if (is_shadow_grp)
1230                 sgr_unlock ();
1231 #endif
1232 }
1233
1234 /*
1235  * open_files - lock and open the password files
1236  *
1237  *      open_files() opens the two password files.
1238  */
1239 static void open_files (void)
1240 {
1241         if (!pw_lock ()) {
1242                 fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
1243 #ifdef WITH_AUDIT
1244                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1245                               "locking password file", user_name, user_id, 0);
1246 #endif
1247                 exit (E_PW_UPDATE);
1248         }
1249         if (!pw_open (O_RDWR)) {
1250                 fprintf (stderr, _("%s: unable to open password file\n"), Prog);
1251 #ifdef WITH_AUDIT
1252                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1253                               "opening password file", user_name, user_id, 0);
1254 #endif
1255                 pw_unlock ();
1256                 exit (E_PW_UPDATE);
1257         }
1258         if (is_shadow_pwd && !spw_lock ()) {
1259                 fprintf (stderr,
1260                          _("%s: cannot lock shadow password file\n"), Prog);
1261 #ifdef WITH_AUDIT
1262                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1263                               "locking shadow password file", user_name,
1264                               user_id, 0);
1265 #endif
1266                 pw_unlock ();
1267                 exit (E_PW_UPDATE);
1268         }
1269         if (is_shadow_pwd && !spw_open (O_RDWR)) {
1270                 fprintf (stderr,
1271                          _("%s: cannot open shadow password file\n"), Prog);
1272 #ifdef WITH_AUDIT
1273                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1274                               "opening shadow password file", user_name,
1275                               user_id, 0);
1276 #endif
1277                 spw_unlock ();
1278                 pw_unlock ();
1279                 exit (E_PW_UPDATE);
1280         }
1281         /*
1282          * Lock and open the group file.
1283          */
1284
1285         if (!gr_lock ()) {
1286                 fprintf (stderr, _("%s: error locking group file\n"), Prog);
1287                 fail_exit (E_GRP_UPDATE);
1288         }
1289         if (!gr_open (O_RDWR)) {
1290                 fprintf (stderr, _("%s: error opening group file\n"), Prog);
1291                 fail_exit (E_GRP_UPDATE);
1292         }
1293 #ifdef  SHADOWGRP
1294         if (is_shadow_grp && !sgr_lock ()) {
1295                 fprintf (stderr,
1296                          _("%s: error locking shadow group file\n"), Prog);
1297                 fail_exit (E_GRP_UPDATE);
1298         }
1299         if (is_shadow_grp && !sgr_open (O_RDWR)) {
1300                 fprintf (stderr,
1301                          _("%s: error opening shadow group file\n"), Prog);
1302                 fail_exit (E_GRP_UPDATE);
1303         }
1304 #endif
1305 }
1306
1307 static char *empty_list = NULL;
1308
1309 /*
1310  * new_grent - initialize the values in a group file entry
1311  *
1312  *      new_grent() takes all of the values that have been entered and fills
1313  *      in a (struct group) with them.
1314  */
1315
1316 static void new_grent (struct group *grent)
1317 {
1318         memzero (grent, sizeof *grent);
1319         grent->gr_name = (char *) user_name;
1320         grent->gr_passwd = SHADOW_PASSWD_STRING;        /* XXX warning: const */
1321         grent->gr_gid = user_gid;
1322         grent->gr_mem = &empty_list;
1323 }
1324
1325 #ifdef  SHADOWGRP
1326 /*
1327  * new_sgent - initialize the values in a shadow group file entry
1328  *
1329  *      new_sgent() takes all of the values that have been entered and fills
1330  *      in a (struct sgrp) with them.
1331  */
1332
1333 static void new_sgent (struct sgrp *sgent)
1334 {
1335         memzero (sgent, sizeof *sgent);
1336         sgent->sg_name = (char *) user_name;
1337         sgent->sg_passwd = "!"; /* XXX warning: const */
1338         sgent->sg_adm = &empty_list;
1339         sgent->sg_mem = &empty_list;
1340 }
1341 #endif                          /* SHADOWGRP */
1342
1343
1344 /*
1345  * grp_add - add new group file entries
1346  *
1347  *      grp_add() writes the new records to the group files.
1348  */
1349
1350 static void grp_add (void)
1351 {
1352         struct group grp;
1353
1354 #ifdef  SHADOWGRP
1355         struct sgrp sgrp;
1356 #endif                          /* SHADOWGRP */
1357
1358         /*
1359          * Create the initial entries for this new group.
1360          */
1361         new_grent (&grp);
1362 #ifdef  SHADOWGRP
1363         new_sgent (&sgrp);
1364 #endif                          /* SHADOWGRP */
1365
1366         /*
1367          * Write out the new group file entry.
1368          */
1369         if (!gr_update (&grp)) {
1370                 fprintf (stderr, _("%s: error adding new group entry\n"), Prog);
1371                 fail_exit (E_GRP_UPDATE);
1372         }
1373 #ifdef  SHADOWGRP
1374         /*
1375          * Write out the new shadow group entries as well.
1376          */
1377         if (is_shadow_grp && !sgr_update (&sgrp)) {
1378                 fprintf (stderr, _("%s: error adding new group entry\n"), Prog);
1379                 fail_exit (E_GRP_UPDATE);
1380         }
1381 #endif                          /* SHADOWGRP */
1382         SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid));
1383         do_grp_update++;
1384 }
1385
1386 static void faillog_reset (uid_t uid)
1387 {
1388         struct faillog fl;
1389         int fd;
1390
1391         fd = open (FAILLOG_FILE, O_RDWR);
1392         if (fd >= 0) {
1393                 memzero (&fl, sizeof (fl));
1394                 lseek (fd, (off_t) sizeof (fl) * uid, SEEK_SET);
1395                 write (fd, &fl, sizeof (fl));
1396                 close (fd);
1397         }
1398 }
1399
1400 static void lastlog_reset (uid_t uid)
1401 {
1402         struct lastlog ll;
1403         int fd;
1404
1405         fd = open (LASTLOG_FILE, O_RDWR);
1406         if (fd >= 0) {
1407                 memzero (&ll, sizeof (ll));
1408                 lseek (fd, (off_t) sizeof (ll) * uid, SEEK_SET);
1409                 write (fd, &ll, sizeof (ll));
1410                 close (fd);
1411         }
1412 }
1413
1414 /*
1415  * usr_update - create the user entries
1416  *
1417  *      usr_update() creates the password file entries for this user
1418  *      and will update the group entries if required.
1419  */
1420 static void usr_update (void)
1421 {
1422         struct passwd pwent;
1423         struct spwd spent;
1424
1425         /*
1426          * Fill in the password structure with any new fields, making
1427          * copies of strings.
1428          */
1429         new_pwent (&pwent);
1430         new_spent (&spent);
1431
1432         /*
1433          * Create a syslog entry. We need to do this now in case anything
1434          * happens so we know what we were trying to accomplish.
1435          */
1436         SYSLOG ((LOG_INFO,
1437                  "new user: name=%s, UID=%u, GID=%u, home=%s, shell=%s",
1438                  user_name, (unsigned int) user_id,
1439                  (unsigned int) user_gid, user_home, user_shell));
1440
1441         /*
1442          * Initialize faillog and lastlog entries for this UID in case
1443          * it belongs to a previously deleted user. We do it only if
1444          * no user with this UID exists yet (entries for shared UIDs
1445          * are left unchanged).  --marekm
1446          */
1447         /* local, no need for xgetpwuid */
1448         if ((!lflg) && (getpwuid (user_id) == NULL)) {
1449                 faillog_reset (user_id);
1450                 lastlog_reset (user_id);
1451         }
1452
1453         /*
1454          * Put the new (struct passwd) in the table.
1455          */
1456         if (!pw_update (&pwent)) {
1457                 fprintf (stderr,
1458                          _("%s: error adding new password entry\n"), Prog);
1459                 exit (E_PW_UPDATE);
1460         }
1461
1462         /*
1463          * Put the new (struct spwd) in the table.
1464          */
1465         if (is_shadow_pwd && !spw_update (&spent)) {
1466                 fprintf (stderr,
1467                          _
1468                          ("%s: error adding new shadow password entry\n"),
1469                          Prog);
1470 #ifdef WITH_AUDIT
1471                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1472                               "adding shadow password", user_name, user_id, 0);
1473 #endif
1474                 exit (E_PW_UPDATE);
1475         }
1476 #ifdef WITH_AUDIT
1477         audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user", user_name,
1478                       user_id, 1);
1479 #endif
1480
1481         /*
1482          * Do any group file updates for this user.
1483          */
1484         if (do_grp_update)
1485                 grp_update ();
1486 }
1487
1488 /*
1489  * create_home - create the user's home directory
1490  *
1491  *      create_home() creates the user's home directory if it does not
1492  *      already exist. It will be created mode 755 owned by the user
1493  *      with the user's default group.
1494  */
1495 static void create_home (void)
1496 {
1497         if (access (user_home, F_OK)) {
1498                 /* XXX - create missing parent directories.  --marekm */
1499                 if (mkdir (user_home, 0)) {
1500                         fprintf (stderr,
1501                                  _
1502                                  ("%s: cannot create directory %s\n"),
1503                                  Prog, user_home);
1504 #ifdef WITH_AUDIT
1505                         audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1506                                       "adding home directory", user_name,
1507                                       user_id, 0);
1508 #endif
1509                         fail_exit (E_HOMEDIR);
1510                 }
1511                 chown (user_home, user_id, user_gid);
1512                 chmod (user_home,
1513                        0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
1514                 home_added++;
1515 #ifdef WITH_AUDIT
1516                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1517                               "adding home directory", user_name, user_id, 1);
1518 #endif
1519         }
1520 }
1521
1522 /*
1523  * create_mail - create the user's mail spool
1524  *
1525  *      create_mail() creates the user's mail spool if it does not already
1526  *      exist. It will be created mode 660 owned by the user and group
1527  *      'mail'
1528  */
1529 static void create_mail (void)
1530 {
1531         char *spool, *file;
1532         int fd;
1533         struct group *gr;
1534         gid_t gid;
1535         mode_t mode;
1536
1537         if (strcasecmp (create_mail_spool, "yes") == 0) {
1538                 spool = getdef_str ("MAIL_DIR");
1539                 if (NULL == spool) {
1540                         spool = "/var/mail";
1541                 }
1542                 file = alloca (strlen (spool) + strlen (user_name) + 2);
1543                 sprintf (file, "%s/%s", spool, user_name);
1544                 fd = open (file, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0);
1545                 if (fd < 0) {
1546                         perror (_("Creating mailbox file"));
1547                         return;
1548                 }
1549
1550                 gr = getgrnam ("mail"); /* local, no need for xgetgrnam */
1551                 if (!gr) {
1552                         fprintf (stderr,
1553                                  _
1554                                  ("Group 'mail' not found. Creating the user mailbox file with 0600 mode.\n"));
1555                         gid = user_gid;
1556                         mode = 0600;
1557                 } else {
1558                         gid = gr->gr_gid;
1559                         mode = 0660;
1560                 }
1561
1562                 if (fchown (fd, user_id, gid) || fchmod (fd, mode))
1563                         perror (_("Setting mailbox file permissions"));
1564
1565                 close (fd);
1566         }
1567 }
1568
1569 /*
1570  * main - useradd command
1571  */
1572 int main (int argc, char **argv)
1573 {
1574 #ifdef USE_PAM
1575         pam_handle_t *pamh = NULL;
1576         int retval;
1577 #endif
1578
1579 #ifdef WITH_AUDIT
1580         audit_help_open ();
1581 #endif
1582
1583         /*
1584          * Get my name so that I can use it to report errors.
1585          */
1586         Prog = Basename (argv[0]);
1587
1588         setlocale (LC_ALL, "");
1589         bindtextdomain (PACKAGE, LOCALEDIR);
1590         textdomain (PACKAGE);
1591
1592         OPENLOG ("useradd");
1593
1594         sys_ngroups = sysconf (_SC_NGROUPS_MAX);
1595         user_groups = malloc ((1 + sys_ngroups) * sizeof (char *));
1596         /*
1597          * Initialize the list to be empty
1598          */
1599         user_groups[0] = (char *) 0;
1600
1601
1602         is_shadow_pwd = spw_file_present ();
1603 #ifdef SHADOWGRP
1604         is_shadow_grp = sgr_file_present ();
1605 #endif
1606
1607         get_defaults ();
1608
1609         process_flags (argc, argv);
1610
1611 #ifdef USE_PAM
1612         retval = PAM_SUCCESS;
1613
1614         {
1615                 struct passwd *pampw;
1616                 pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
1617                 if (pampw == NULL) {
1618                         retval = PAM_USER_UNKNOWN;
1619                 }
1620
1621                 if (retval == PAM_SUCCESS) {
1622                         retval = pam_start ("useradd", pampw->pw_name,
1623                                             &conv, &pamh);
1624                 }
1625         }
1626
1627         if (retval == PAM_SUCCESS) {
1628                 retval = pam_authenticate (pamh, 0);
1629                 if (retval != PAM_SUCCESS) {
1630                         pam_end (pamh, retval);
1631                 }
1632         }
1633
1634         if (retval == PAM_SUCCESS) {
1635                 retval = pam_acct_mgmt (pamh, 0);
1636                 if (retval != PAM_SUCCESS) {
1637                         pam_end (pamh, retval);
1638                 }
1639         }
1640
1641         if (retval != PAM_SUCCESS) {
1642                 fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
1643                 exit (1);
1644         }
1645 #endif                          /* USE_PAM */
1646
1647         /*
1648          * See if we are messing with the defaults file, or creating
1649          * a new user.
1650          */
1651         if (Dflg) {
1652                 if (gflg || bflg || fflg || eflg || sflg)
1653                         exit (set_defaults ()? 1 : 0);
1654
1655                 show_defaults ();
1656                 exit (E_SUCCESS);
1657         }
1658
1659         /*
1660          * Start with a quick check to see if the user exists.
1661          */
1662         if (getpwnam (user_name)) { /* local, no need for xgetpwnam */
1663                 fprintf (stderr, _("%s: user %s exists\n"), Prog, user_name);
1664 #ifdef WITH_AUDIT
1665                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user",
1666                               user_name, -1, 0);
1667 #endif
1668                 exit (E_NAME_IN_USE);
1669         }
1670
1671         /*
1672          * Don't blindly overwrite a group when a user is added...
1673          * If you already have a group username, and want to add the user
1674          * to that group, use useradd -g username username.
1675          * --bero
1676          */
1677         if (!gflg) {
1678                 if (getgrnam (user_name)) { /* local, no need for xgetgrnam */
1679                         fprintf (stderr,
1680                                  _
1681                                  ("%s: group %s exists - if you want to add this user to that group, use -g.\n"),
1682                                  Prog, user_name);
1683 #ifdef WITH_AUDIT
1684                         audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1685                                       "adding group", user_name, -1, 0);
1686 #endif
1687                         exit (E_NAME_IN_USE);
1688                 }
1689         }
1690
1691         /*
1692          * Do the hard stuff:
1693          * - open the files,
1694          * - create the user entries,
1695          * - create the home directory,
1696          * - create user mail spool,
1697          * - flush nscd caches for passwd and group services,
1698          * - then close and update the files.
1699          */
1700         open_files ();
1701
1702         if (!oflg) {
1703                 /* first, seek for a valid uid to use for this user.
1704                  * We do this because later we can use the uid we found as
1705                  * gid too ... --gafton */
1706                 if (!uflg)
1707                         find_new_uid ();
1708                 else {
1709                         if (getpwuid (user_id) != NULL) {
1710                                 fprintf (stderr, _("%s: UID %u is not unique\n"), Prog, (unsigned int) user_id);
1711 #ifdef WITH_AUDIT
1712                                 audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user", user_name, user_id, 0);
1713 #endif
1714                                 exit (E_UID_IN_USE);
1715                         }
1716                 }
1717         }
1718
1719         /* do we have to add a group for that user? This is why we need to
1720          * open the group files in the open_files() function  --gafton */
1721         if (!(nflg || gflg)) {
1722                 find_new_gid ();
1723                 grp_add ();
1724         }
1725
1726         usr_update ();
1727
1728         if (mflg) {
1729                 create_home ();
1730                 if (home_added)
1731                         copy_tree (def_template, user_home, user_id, user_gid);
1732                 else
1733                         fprintf (stderr,
1734                                  _
1735                                  ("%s: warning: the home directory already exists.\n"
1736                                   "Not copying any file from skel directory into it.\n"),
1737                                  Prog);
1738
1739         } else if (getdef_str ("CREATE_HOME")) {
1740                 /*
1741                  * RedHat added the CREATE_HOME option in login.defs in their
1742                  * version of shadow-utils (which makes -m the default, with
1743                  * new -M option to turn it off). Unfortunately, this
1744                  * changes the way useradd works (it can be run by scripts
1745                  * expecting some standard behaviour), compared to other
1746                  * Unices and other Linux distributions, and also adds a lot
1747                  * of confusion :-(.
1748                  * So we now recognize CREATE_HOME and give a warning here
1749                  * (better than "configuration error ... notify administrator"
1750                  * errors in every program that reads /etc/login.defs). -MM
1751                  */
1752                 fprintf (stderr,
1753                          _
1754                          ("%s: warning: CREATE_HOME not supported, please use -m instead.\n"),
1755                          Prog);
1756         }
1757
1758         create_mail ();
1759
1760         close_files ();
1761
1762         nscd_flush_cache ("passwd");
1763         nscd_flush_cache ("group");
1764
1765 #ifdef USE_PAM
1766         if (retval == PAM_SUCCESS)
1767                 pam_end (pamh, PAM_SUCCESS);
1768 #endif                          /* USE_PAM */
1769
1770         exit (E_SUCCESS);
1771         /* NOT REACHED */
1772 }