]> granicus.if.org Git - shadow/blob - src/newusers.c
* src/gpasswd.c: Remove log_gpasswd_success_gshadow(). Writing in
[shadow] / src / newusers.c
1 /*
2  * Copyright (c) 1990 - 1993, Julianne Frances Haugh
3  * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4  * Copyright (c) 2000 - 2006, Tomasz Kłoczko
5  * Copyright (c) 2007 - 2009, Nicolas François
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the copyright holders or contributors may not be used to
17  *    endorse or promote products derived from this software without
18  *    specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  *      newusers - create users from a batch file
35  *
36  *      newusers creates a collection of entries in /etc/passwd
37  *      and related files by reading a passwd-format file and
38  *      adding entries in the related directories.
39  */
40
41 #include <config.h>
42
43 #ident "$Id$"
44
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <stdio.h>
48 #include <pwd.h>
49 #include <grp.h>
50 #include <fcntl.h>
51 #include <getopt.h>
52 #include <ctype.h>
53 #include <errno.h>
54 #include <string.h>
55 #ifdef ACCT_TOOLS_SETUID
56 #ifdef USE_PAM
57 #include "pam_defs.h"
58 #endif                          /* USE_PAM */
59 #endif                          /* ACCT_TOOLS_SETUID */
60 #include "prototypes.h"
61 #include "defines.h"
62 #include "getdef.h"
63 #include "groupio.h"
64 #include "nscd.h"
65 #include "pwio.h"
66 #include "sgroupio.h"
67 #include "shadowio.h"
68 #include "chkname.h"
69
70 /*
71  * Global variables
72  */
73 const char *Prog;
74
75 static bool rflg = false;       /* create a system account */
76 #ifndef USE_PAM
77 static /*@null@*//*@observer@*/char *crypt_method = NULL;
78 #define cflg (NULL != crypt_method)
79 #ifdef USE_SHA_CRYPT
80 static bool sflg = false;
81 static long sha_rounds = 5000;
82 #endif                          /* USE_SHA_CRYPT */
83 #endif                          /* !USE_PAM */
84
85 static bool is_shadow;
86 #ifdef SHADOWGRP
87 static bool is_shadow_grp;
88 static bool sgr_locked = false;
89 #endif
90 static bool pw_locked = false;
91 static bool gr_locked = false;
92 static bool spw_locked = false;
93
94 /* local function prototypes */
95 static void usage (int status);
96 static void fail_exit (int);
97 static int add_group (const char *, const char *, gid_t *, gid_t);
98 static int get_user_id (const char *, uid_t *);
99 static int add_user (const char *, uid_t, gid_t);
100 #ifndef USE_PAM
101 static void update_passwd (struct passwd *, const char *);
102 #endif                          /* !USE_PAM */
103 static int add_passwd (struct passwd *, const char *);
104 static void process_flags (int argc, char **argv);
105 static void check_flags (void);
106 static void check_perms (void);
107 static void open_files (void);
108 static void close_files (void);
109
110 /*
111  * usage - display usage message and exit
112  */
113 static void usage (int status)
114 {
115         FILE *usageout = (EXIT_SUCCESS != status) ? stderr : stdout;
116         (void) fprintf (usageout,
117                         _("Usage: %s [options]\n"
118                           "\n"
119                           "Options:\n"),
120                         Prog);
121 #ifndef USE_PAM
122         (void) fprintf (usageout,
123                         _("  -c, --crypt-method            the crypt method (one of %s)\n"),
124 #ifndef USE_SHA_CRYPT
125                         "NONE DES MD5"
126 #else                           /* USE_SHA_CRYPT */
127                         "NONE DES MD5 SHA256 SHA512"
128 #endif                          /* USE_SHA_CRYPT */
129                        );
130 #endif                          /* !USE_PAM */
131         (void) fputs (_("  -h, --help                    display this help message and exit\n"), usageout);
132         (void) fputs (_("  -r, --system                  create system accounts\n"), usageout);
133 #ifndef USE_PAM
134 #ifdef USE_SHA_CRYPT
135         (void) fputs (_("  -s, --sha-rounds              number of SHA rounds for the SHA*\n"
136                         "                                crypt algorithms\n"),
137                       usageout);
138 #endif                          /* USE_SHA_CRYPT */
139 #endif                          /* !USE_PAM */
140         (void) fputs ("\n", usageout);
141
142         exit (status);
143 }
144
145 /*
146  * fail_exit - undo as much as possible
147  */
148 static void fail_exit (int code)
149 {
150         if (spw_locked) {
151                 if (spw_unlock () == 0) {
152                         fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
153                         SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
154                         /* continue */
155                 }
156         }
157         if (pw_locked) {
158                 if (pw_unlock () == 0) {
159                         fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
160                         SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
161                         /* continue */
162                 }
163         }
164         if (gr_locked) {
165                 if (gr_unlock () == 0) {
166                         fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
167                         SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
168                         /* continue */
169                 }
170         }
171 #ifdef  SHADOWGRP
172         if (sgr_locked) {
173                 if (sgr_unlock () == 0) {
174                         fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
175                         SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
176                         /* continue */
177                 }
178         }
179 #endif
180
181         exit (code);
182 }
183
184 /*
185  * add_group - create a new group or add a user to an existing group
186  */
187 static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid)
188 {
189         const struct group *grp;
190         struct group grent;
191         char *members[1];
192 #ifdef SHADOWGRP
193         const struct sgrp *sg;
194 #endif
195
196         /*
197          * Start by seeing if the named group already exists. This will be
198          * very easy to deal with if it does.
199          */
200         grp = getgrnam (gid);
201         if (NULL == grp) {
202                 grp = gr_locate (gid);
203         }
204         if (NULL != grp) {
205                 /* The user will use this ID for her primary group */
206                 *ngid = grp->gr_gid;
207                 /* Don't check gshadow */
208                 return 0;
209         }
210
211         if (isdigit (gid[0])) {
212                 /*
213                  * The GID is a number, which means either this is a brand
214                  * new group, or an existing group.
215                  */
216
217                 if (get_gid (gid, &grent.gr_gid) == 0) {
218                         fprintf (stderr,
219                                  _("%s: invalid group ID '%s'\n"),
220                                  Prog, gid);
221                         return -1;
222                 }
223
224                 /* Look in both the system database (getgrgid) and in the
225                  * internal database (gr_locate_gid), which may contain
226                  * uncommitted changes */
227                 if (   (getgrgid ((gid_t) grent.gr_gid) != NULL)
228                     || (gr_locate_gid ((gid_t) grent.gr_gid) != NULL)) {
229                         /* The user will use this ID for her
230                          * primary group */
231                         *ngid = (gid_t) grent.gr_gid;
232                         return 0;
233                 }
234
235                 /* Do not create groups with GID == (gid_t)-1 */
236                 if (grent.gr_gid == (gid_t)-1) {
237                         fprintf (stderr,
238                                  _("%s: invalid group ID '%s'\n"),
239                                  Prog, gid);
240                         return -1;
241                 }
242         } else {
243                 /* The gid parameter can be "" or a name which is not
244                  * already the name of an existing group.
245                  * In both cases, figure out what group ID can be used.
246                  */
247                 if (find_new_gid(rflg, &grent.gr_gid, &uid) < 0) {
248                         return -1;
249                 }
250         }
251
252         /*
253          * Now I have all of the fields required to create the new group.
254          */
255         if (('\0' != gid[0]) && (!isdigit (gid[0]))) {
256                 grent.gr_name = xstrdup (gid);
257         } else {
258                 grent.gr_name = xstrdup (name);
259 /* FIXME: check if the group exists */
260         }
261
262         /* Check if this is a valid group name */
263         if (!is_valid_group_name (grent.gr_name)) {
264                 fprintf (stderr,
265                          _("%s: invalid group name '%s'\n"),
266                          Prog, grent.gr_name);
267                 free (grent.gr_name);
268                 return -1;
269         }
270
271         grent.gr_passwd = "x";  /* XXX warning: const */
272         members[0] = NULL;
273         grent.gr_mem = members;
274
275         *ngid = grent.gr_gid;
276
277 #ifdef SHADOWGRP
278         if (is_shadow_grp) {
279                 sg = sgr_locate (grent.gr_name);
280
281                 if (NULL != sg) {
282                         fprintf (stderr,
283                                  _("%s: group '%s' is a shadow group, but does not exist in /etc/group\n"),
284                                  Prog, grent.gr_name);
285                         return -1;
286                 }
287         }
288 #endif
289
290         if (gr_update (&grent) == 0) {
291                 return -1;
292         }
293
294 #ifdef SHADOWGRP
295         if (is_shadow_grp) {
296                 struct sgrp sgrent;
297                 char *admins[1];
298                 sgrent.sg_name = grent.gr_name;
299                 sgrent.sg_passwd = "*"; /* XXX warning: const */
300                 admins[0] = NULL;
301                 sgrent.sg_adm = admins;
302                 sgrent.sg_mem = members;
303
304                 if (sgr_update (&sgrent) == 0) {
305                         return -1;
306                 }
307         }
308 #endif
309
310         return 0;
311 }
312
313 static int get_user_id (const char *uid, uid_t *nuid) {
314
315         /*
316          * The first guess for the UID is either the numerical UID that the
317          * caller provided, or the next available UID.
318          */
319         if (isdigit (uid[0])) {
320                 if ((get_uid (uid, nuid) == 0) || (*nuid == (uid_t)-1)) {
321                         fprintf (stderr,
322                                  _("%s: invalid user ID '%s'\n"),
323                                  Prog, uid);
324                         return -1;
325                 }
326         } else {
327                 if ('\0' != uid[0]) {
328                         const struct passwd *pwd;
329                         /* local, no need for xgetpwnam */
330                         pwd = getpwnam (uid);
331                         if (NULL == pwd) {
332                                 pwd = pw_locate (uid);
333                         }
334
335                         if (NULL != pwd) {
336                                 *nuid = pwd->pw_uid;
337                         } else {
338                                 fprintf (stderr,
339                                          _("%s: user '%s' does not exist\n"),
340                                          Prog, uid);
341                                 return -1;
342                         }
343                 } else {
344                         if (find_new_uid (rflg, nuid, NULL) < 0) {
345                                 return -1;
346                         }
347                 }
348         }
349
350         return 0;
351 }
352
353 /*
354  * add_user - create a new user ID
355  */
356 static int add_user (const char *name, uid_t uid, gid_t gid)
357 {
358         struct passwd pwent;
359
360         /* Check if this is a valid user name */
361         if (!is_valid_user_name (name)) {
362                 fprintf (stderr,
363                          _("%s: invalid user name '%s'\n"),
364                          Prog, name);
365                 return -1;
366         }
367
368         /*
369          * I don't want to fill in the entire password structure members
370          * JUST YET, since there is still more data to be added. So, I fill
371          * in the parts that I have.
372          */
373         pwent.pw_name = xstrdup (name);
374         pwent.pw_uid = uid;
375         pwent.pw_passwd = "x";  /* XXX warning: const */
376         pwent.pw_gid = gid;
377         pwent.pw_gecos = "";    /* XXX warning: const */
378         pwent.pw_dir = "";      /* XXX warning: const */
379         pwent.pw_shell = "";    /* XXX warning: const */
380
381         return (pw_update (&pwent) == 0) ? -1 : 0;
382 }
383
384 #ifndef USE_PAM
385 static void update_passwd (struct passwd *pwd, const char *password)
386 {
387         void *crypt_arg = NULL;
388         if (crypt_method != NULL) {
389 #ifdef USE_SHA_CRYPT
390                 if (sflg) {
391                         crypt_arg = &sha_rounds;
392                 }
393 #endif
394         }
395
396         if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) {
397                 pwd->pw_passwd = (char *)password;
398         } else {
399                 pwd->pw_passwd = pw_encrypt (password,
400                                              crypt_make_salt (crypt_method,
401                                                               crypt_arg));
402         }
403 }
404 #endif                          /* !USE_PAM */
405
406 /*
407  * add_passwd - add or update the encrypted password
408  */
409 static int add_passwd (struct passwd *pwd, const char *password)
410 {
411         const struct spwd *sp;
412         struct spwd spent;
413
414 #ifndef USE_PAM
415         void *crypt_arg = NULL;
416         if (crypt_method != NULL) {
417 #ifdef USE_SHA_CRYPT
418                 if (sflg) {
419                         crypt_arg = &sha_rounds;
420                 }
421 #endif                          /* USE_SHA_CRYPT */
422         }
423
424         /*
425          * In the case of regular password files, this is real easy - pwd
426          * points to the entry in the password file. Shadow files are
427          * harder since there are zillions of things to do ...
428          */
429         if (!is_shadow) {
430                 update_passwd (pwd, password);
431                 return 0;
432         }
433 #endif                          /* USE_PAM */
434
435         /*
436          * Do the first and easiest shadow file case. The user already
437          * exists in the shadow password file.
438          */
439         sp = spw_locate (pwd->pw_name);
440 #ifndef USE_PAM
441         if (NULL != sp) {
442                 spent = *sp;
443                 if (   (NULL != crypt_method)
444                     && (0 == strcmp(crypt_method, "NONE"))) {
445                         spent.sp_pwdp = (char *)password;
446                 } else {
447                         const char *salt = crypt_make_salt (crypt_method,
448                                                             crypt_arg);
449                         spent.sp_pwdp = pw_encrypt (password, salt);
450                 }
451                 spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
452                 if (0 == spent.sp_lstchg) {
453                         /* Better disable aging than requiring a password
454                          * change */
455                         spent.sp_lstchg = -1;
456                 }
457                 return (spw_update (&spent) == 0);
458         }
459
460         /*
461          * Pick the next easiest case - the user has an encrypted password
462          * which isn't equal to "x". The password was set to "x" earlier
463          * when the entry was created, so this user would have to have had
464          * the password set someplace else.
465          */
466         if (strcmp (pwd->pw_passwd, "x") != 0) {
467                 update_passwd (pwd, password);
468                 return 0;
469         }
470 #else                           /* USE_PAM */
471         /*
472          * If there is already a shadow entry, do not touch it.
473          * If there is already a passwd entry with a password, do not
474          * touch it.
475          * The password will be updated later for all users using PAM.
476          */
477         if (   (NULL != sp)
478             || (strcmp (pwd->pw_passwd, "x") != 0)) {
479                 return 0;
480         }
481 #endif                          /* USE_PAM */
482
483         /*
484          * Now the really hard case - I need to create an entirely new
485          * shadow password file entry.
486          */
487         spent.sp_namp = pwd->pw_name;
488 #ifndef USE_PAM
489         if ((crypt_method != NULL) && (0 == strcmp(crypt_method, "NONE"))) {
490                 spent.sp_pwdp = (char *)password;
491         } else {
492                 const char *salt = crypt_make_salt (crypt_method, crypt_arg);
493                 spent.sp_pwdp = pw_encrypt (password, salt);
494         }
495 #else
496         /*
497          * Lock the password.
498          * The password will be updated later for all users using PAM.
499          */
500         spent.sp_pwdp = "!";
501 #endif
502         spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
503         if (0 == spent.sp_lstchg) {
504                 /* Better disable aging than requiring a password change */
505                 spent.sp_lstchg = -1;
506         }
507         spent.sp_min    = getdef_num ("PASS_MIN_DAYS", 0);
508         /* 10000 is infinity this week */
509         spent.sp_max    = getdef_num ("PASS_MAX_DAYS", 10000);
510         spent.sp_warn   = getdef_num ("PASS_WARN_AGE", -1);
511         spent.sp_inact  = -1;
512         spent.sp_expire = -1;
513         spent.sp_flag   = SHADOW_SP_FLAG_UNSET;
514
515         return (spw_update (&spent) == 0);
516 }
517
518 /*
519  * process_flags - parse the command line options
520  *
521  *      It will not return if an error is encountered.
522  */
523 static void process_flags (int argc, char **argv)
524 {
525         int option_index = 0;
526         int c;
527         static struct option long_options[] = {
528 #ifndef USE_PAM
529                 {"crypt-method", required_argument, NULL, 'c'},
530 #ifdef USE_SHA_CRYPT
531                 {"sha-rounds", required_argument, NULL, 's'},
532 #endif                          /* USE_SHA_CRYPT */
533 #endif                          /* !USE_PAM */
534                 {"help", no_argument, NULL, 'h'},
535                 {"system", no_argument, NULL, 'r'},
536                 {NULL, 0, NULL, '\0'}
537         };
538
539         while ((c = getopt_long (argc, argv,
540 #ifndef USE_PAM
541 #ifdef USE_SHA_CRYPT
542                                  "c:hrs:",
543 #else                           /* !USE_SHA_CRYPT */
544                                  "c:hr",
545 #endif                          /* !USE_SHA_CRYPT */
546 #else                           /* USE_PAM */
547                                  "hr",
548 #endif
549                              long_options, &option_index)) != -1) {
550                 switch (c) {
551                 case 'h':
552                         usage (EXIT_SUCCESS);
553                         break;
554                 case 'r':
555                         rflg = true;
556                         break;
557 #ifndef USE_PAM
558                 case 'c':
559                         crypt_method = optarg;
560                         break;
561 #ifdef USE_SHA_CRYPT
562                 case 's':
563                         sflg = true;
564                         if (getlong(optarg, &sha_rounds) == 0) {
565                                 fprintf (stderr,
566                                          _("%s: invalid numeric argument '%s'\n"),
567                                          Prog, optarg);
568                                 usage (EXIT_FAILURE);
569                         }
570                         break;
571 #endif                          /* USE_SHA_CRYPT */
572 #endif                          /* !USE_PAM */
573                 default:
574                         usage (EXIT_FAILURE);
575                         break;
576                 }
577         }
578
579         if (argv[optind] != NULL) {
580                 if (freopen (argv[optind], "r", stdin) == NULL) {
581                         char buf[BUFSIZ];
582                         snprintf (buf, sizeof buf, "%s: %s", Prog, argv[1]);
583                         perror (buf);
584                         fail_exit (EXIT_FAILURE);
585                 }
586         }
587
588         /* validate options */
589         check_flags ();
590 }
591
592 /*
593  * check_flags - check flags and parameters consistency
594  *
595  *      It will not return if an error is encountered.
596  */
597 static void check_flags (void)
598 {
599 #ifndef USE_PAM
600 #ifdef USE_SHA_CRYPT
601         if (sflg && !cflg) {
602                 fprintf (stderr,
603                          _("%s: %s flag is only allowed with the %s flag\n"),
604                          Prog, "-s", "-c");
605                 usage (EXIT_FAILURE);
606         }
607 #endif                          /* USE_SHA_CRYPT */
608
609         if (cflg) {
610                 if (   (0 != strcmp (crypt_method, "DES"))
611                     && (0 != strcmp (crypt_method, "MD5"))
612                     && (0 != strcmp (crypt_method, "NONE"))
613 #ifdef USE_SHA_CRYPT
614                     && (0 != strcmp (crypt_method, "SHA256"))
615                     && (0 != strcmp (crypt_method, "SHA512"))
616 #endif                          /* USE_SHA_CRYPT */
617                     ) {
618                         fprintf (stderr,
619                                  _("%s: unsupported crypt method: %s\n"),
620                                  Prog, crypt_method);
621                         usage (EXIT_FAILURE);
622                 }
623         }
624 #endif                          /* !USE_PAM */
625 }
626
627 /*
628  * check_perms - check if the caller is allowed to add a group
629  *
630  *      With PAM support, the setuid bit can be set on groupadd to allow
631  *      non-root users to groups.
632  *      Without PAM support, only users who can write in the group databases
633  *      can add groups.
634  *
635  *      It will not return if the user is not allowed.
636  */
637 static void check_perms (void)
638 {
639 #ifdef ACCT_TOOLS_SETUID
640 #ifdef USE_PAM
641         pam_handle_t *pamh = NULL;
642         int retval;
643         struct passwd *pampw;
644
645         pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
646         if (NULL == pampw) {
647                 fprintf (stderr,
648                          _("%s: Cannot determine your user name.\n"),
649                          Prog);
650                 fail_exit (EXIT_FAILURE);
651         }
652
653         retval = pam_start ("newusers", pampw->pw_name, &conv, &pamh);
654
655         if (PAM_SUCCESS == retval) {
656                 retval = pam_authenticate (pamh, 0);
657         }
658
659         if (PAM_SUCCESS == retval) {
660                 retval = pam_acct_mgmt (pamh, 0);
661         }
662
663         if (NULL != pamh) {
664                 (void) pam_end (pamh, retval);
665         }
666         if (PAM_SUCCESS != retval) {
667                 fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
668                 fail_exit (EXIT_FAILURE);
669         }
670 #endif                          /* USE_PAM */
671 #endif                          /* ACCT_TOOLS_SETUID */
672 }
673
674 /*
675  * open_files - lock and open the password, group and shadow databases
676  */
677 static void open_files (void)
678 {
679         /*
680          * Lock the password files and open them for update. This will bring
681          * all of the entries into memory where they may be searched for an
682          * modified, or new entries added. The password file is the key - if
683          * it gets locked, assume the others can be locked right away.
684          */
685         if (pw_lock () == 0) {
686                 fprintf (stderr,
687                          _("%s: cannot lock %s; try again later.\n"),
688                          Prog, pw_dbname ());
689                 fail_exit (EXIT_FAILURE);
690         }
691         pw_locked = true;
692         if (is_shadow) {
693                 if (spw_lock () == 0) {
694                         fprintf (stderr,
695                                  _("%s: cannot lock %s; try again later.\n"),
696                                  Prog, spw_dbname ());
697                         fail_exit (EXIT_FAILURE);
698                 }
699                 spw_locked = true;
700         }
701         if (gr_lock () == 0) {
702                 fprintf (stderr,
703                          _("%s: cannot lock %s; try again later.\n"),
704                          Prog, gr_dbname ());
705                 fail_exit (EXIT_FAILURE);
706         }
707         gr_locked = true;
708 #ifdef SHADOWGRP
709         if (is_shadow_grp) {
710                 if (sgr_lock () == 0) {
711                         fprintf (stderr,
712                                  _("%s: cannot lock %s; try again later.\n"),
713                                  Prog, sgr_dbname ());
714                         fail_exit (EXIT_FAILURE);
715                 }
716                 sgr_locked = true;
717         }
718 #endif
719
720         if (pw_open (O_RDWR) == 0) {
721                 fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
722                 fail_exit (EXIT_FAILURE);
723         }
724         if (is_shadow && (spw_open (O_RDWR) == 0)) {
725                 fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ());
726                 fail_exit (EXIT_FAILURE);
727         }
728         if (gr_open (O_RDWR) == 0) {
729                 fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
730                 fail_exit (EXIT_FAILURE);
731         }
732 #ifdef SHADOWGRP
733         if (is_shadow_grp && (sgr_open (O_RDWR) == 0)) {
734                 fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
735                 fail_exit (EXIT_FAILURE);
736         }
737 #endif
738 }
739
740 /*
741  * close_files - close and unlock the password, group and shadow databases
742  */
743 static void close_files (void)
744 {
745         if (pw_close () == 0) {
746                 fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
747                 SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
748                 fail_exit (EXIT_FAILURE);
749         }
750         if (pw_unlock () == 0) {
751                 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
752                 SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
753                 /* continue */
754         }
755         pw_locked = false;
756
757         if (is_shadow) {
758                 if (spw_close () == 0) {
759                         fprintf (stderr,
760                                  _("%s: failure while writing changes to %s\n"),
761                                  Prog, spw_dbname ());
762                         SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
763                         fail_exit (EXIT_FAILURE);
764                 }
765                 if (spw_unlock () == 0) {
766                         fprintf (stderr,
767                                  _("%s: failed to unlock %s\n"),
768                                  Prog, spw_dbname ());
769                         SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
770                         /* continue */
771                 }
772                 spw_locked = false;
773         }
774
775         if (gr_close () == 0) {
776                 fprintf (stderr,
777                          _("%s: failure while writing changes to %s\n"),
778                          Prog, gr_dbname ());
779                 SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
780                 fail_exit (EXIT_FAILURE);
781         }
782         if (gr_unlock () == 0) {
783                 fprintf (stderr,
784                          _("%s: failed to unlock %s\n"),
785                          Prog, gr_dbname ());
786                 SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
787                 /* continue */
788         }
789         gr_locked = false;
790
791 #ifdef SHADOWGRP
792         if (is_shadow_grp) {
793                 if (sgr_close () == 0) {
794                         fprintf (stderr,
795                                  _("%s: failure while writing changes to %s\n"),
796                                  Prog, sgr_dbname ());
797                         SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
798                         fail_exit (EXIT_FAILURE);
799                 }
800                 if (sgr_unlock () == 0) {
801                         fprintf (stderr,
802                                  _("%s: failed to unlock %s\n"),
803                                  Prog, sgr_dbname ());
804                         SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
805                         /* continue */
806                 }
807                 sgr_locked = false;
808         }
809 #endif
810 }
811
812 int main (int argc, char **argv)
813 {
814         char buf[BUFSIZ];
815         char *fields[8];
816         int nfields;
817         char *cp;
818         const struct passwd *pw;
819         struct passwd newpw;
820         int errors = 0;
821         int line = 0;
822         uid_t uid;
823         gid_t gid;
824 #ifdef USE_PAM
825         int *lines = NULL;
826         char **usernames = NULL;
827         char **passwords = NULL;
828         unsigned int nusers = 0;
829 #endif                          /* USE_PAM */
830
831         Prog = Basename (argv[0]);
832
833         (void) setlocale (LC_ALL, "");
834         (void) bindtextdomain (PACKAGE, LOCALEDIR);
835         (void) textdomain (PACKAGE);
836
837         OPENLOG ("newusers");
838
839         process_flags (argc, argv);
840
841         check_perms ();
842
843         is_shadow = spw_file_present ();
844
845 #ifdef SHADOWGRP
846         is_shadow_grp = sgr_file_present ();
847 #endif
848
849         open_files ();
850
851         /*
852          * Read each line. The line has the same format as a password file
853          * entry, except that certain fields are not constrained to be
854          * numerical values. If a group ID is entered which does not already
855          * exist, an attempt is made to allocate the same group ID as the
856          * numerical user ID. Should that fail, the next available group ID
857          * over 100 is allocated. The pw_gid field will be updated with that
858          * value.
859          */
860         while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
861                 line++;
862                 cp = strrchr (buf, '\n');
863                 if (NULL != cp) {
864                         *cp = '\0';
865                 } else {
866                         if (feof (stdin) == 0) {
867                                 fprintf (stderr,
868                                          _("%s: line %d: line too long\n"),
869                                          Prog, line);
870                                 errors++;
871                                 continue;
872                         }
873                 }
874
875                 /*
876                  * Break the string into fields and screw around with them.
877                  * There MUST be 7 colon separated fields, although the
878                  * values aren't that particular.
879                  */
880                 for (cp = buf, nfields = 0; nfields < 7; nfields++) {
881                         fields[nfields] = cp;
882                         cp = strchr (cp, ':');
883                         if (NULL != cp) {
884                                 *cp = '\0';
885                                 cp++;
886                         } else {
887                                 break;
888                         }
889                 }
890                 if (nfields != 6) {
891                         fprintf (stderr, _("%s: line %d: invalid line\n"),
892                                  Prog, line);
893                         continue;
894                 }
895
896                 /*
897                  * First check if we have to create or update an user
898                  */
899                 pw = pw_locate (fields[0]);
900                 /* local, no need for xgetpwnam */
901                 if (   (NULL == pw)
902                     && (getpwnam (fields[0]) != NULL)) {
903                         fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]);
904                         errors++;
905                         continue;
906                 }
907
908                 if (   (NULL == pw)
909                     && (get_user_id (fields[2], &uid) != 0)) {
910                         fprintf (stderr,
911                                  _("%s: line %d: can't create user\n"),
912                                  Prog, line);
913                         errors++;
914                         continue;
915                 }
916
917                 /*
918                  * Processed is the group name. A new group will be
919                  * created if the group name is non-numeric and does not
920                  * already exist. If the group name is a number (which is not
921                  * an existing GID), a group with the same name as the user
922                  * will be created, with the given GID. The given or created
923                  * group will be the primary group of the user. If
924                  * there is no named group to be a member of, the UID will
925                  * be figured out and that value will be a candidate for a
926                  * new group, if that group ID exists, a whole new group ID
927                  * will be made up.
928                  */
929                 if (   (NULL == pw)
930                     && (add_group (fields[0], fields[3], &gid, uid) != 0)) {
931                         fprintf (stderr,
932                                  _("%s: line %d: can't create group\n"),
933                                  Prog, line);
934                         errors++;
935                         continue;
936                 }
937
938                 /*
939                  * Now we work on the user ID. It has to be specified either
940                  * as a numerical value, or left blank. If it is a numerical
941                  * value, that value will be used, otherwise the next
942                  * available user ID is computed and used. After this there
943                  * will at least be a (struct passwd) for the user.
944                  */
945                 if (   (NULL == pw)
946                     && (add_user (fields[0], uid, gid) != 0)) {
947                         fprintf (stderr,
948                                  _("%s: line %d: can't create user\n"),
949                                  Prog, line);
950                         errors++;
951                         continue;
952                 }
953
954                 /*
955                  * The password, gecos field, directory, and shell fields
956                  * all come next.
957                  */
958                 pw = pw_locate (fields[0]);
959                 if (NULL == pw) {
960                         fprintf (stderr,
961                                  _("%s: line %d: user '%s' does not exist in %s\n"),
962                                  Prog, line, fields[0], pw_dbname ());
963                         errors++;
964                         continue;
965                 }
966                 newpw = *pw;
967
968 #ifdef USE_PAM
969                 /* keep the list of user/password for later update by PAM */
970                 nusers++;
971                 lines     = realloc (lines,     sizeof (lines[0])     * nusers);
972                 usernames = realloc (usernames, sizeof (usernames[0]) * nusers);
973                 passwords = realloc (passwords, sizeof (passwords[0]) * nusers);
974                 lines[nusers-1]     = line;
975                 usernames[nusers-1] = strdup (fields[0]);
976                 passwords[nusers-1] = strdup (fields[1]);
977 #endif                          /* USE_PAM */
978                 if (add_passwd (&newpw, fields[1]) != 0) {
979                         fprintf (stderr,
980                                  _("%s: line %d: can't update password\n"),
981                                  Prog, line);
982                         errors++;
983                         continue;
984                 }
985                 if ('\0' != fields[4][0]) {
986                         newpw.pw_gecos = fields[4];
987                 }
988
989                 if ('\0' != fields[5][0]) {
990                         newpw.pw_dir = fields[5];
991                 }
992
993                 if ('\0' != fields[6][0]) {
994                         newpw.pw_shell = fields[6];
995                 }
996
997                 if (   ('\0' != newpw.pw_dir[0])
998                     && (access (newpw.pw_dir, F_OK) != 0)) {
999 /* FIXME: should check for directory */
1000                         mode_t msk = 0777 & ~getdef_num ("UMASK",
1001                                                          GETDEF_DEFAULT_UMASK);
1002                         if (mkdir (newpw.pw_dir, msk) != 0) {
1003                                 fprintf (stderr,
1004                                          _("%s: line %d: mkdir %s failed: %s\n"),
1005                                          Prog, line, newpw.pw_dir,
1006                                          strerror (errno));
1007                         } else if (chown (newpw.pw_dir,
1008                                           newpw.pw_uid,
1009                                           newpw.pw_gid) != 0) {
1010                                 fprintf (stderr,
1011                                          _("%s: line %d: chown %s failed: %s\n"),
1012                                          Prog, line, newpw.pw_dir,
1013                                          strerror (errno));
1014                         }
1015                 }
1016
1017                 /*
1018                  * Update the password entry with the new changes made.
1019                  */
1020                 if (pw_update (&newpw) == 0) {
1021                         fprintf (stderr,
1022                                  _("%s: line %d: can't update entry\n"),
1023                                  Prog, line);
1024                         errors++;
1025                         continue;
1026                 }
1027         }
1028
1029         /*
1030          * Any detected errors will cause the entire set of changes to be
1031          * aborted. Unlocking the password file will cause all of the
1032          * changes to be ignored. Otherwise the file is closed, causing the
1033          * changes to be written out all at once, and then unlocked
1034          * afterwards.
1035          */
1036         if (0 != errors) {
1037                 fprintf (stderr,
1038                          _("%s: error detected, changes ignored\n"), Prog);
1039                 fail_exit (EXIT_FAILURE);
1040         }
1041
1042         close_files ();
1043
1044         nscd_flush_cache ("passwd");
1045         nscd_flush_cache ("group");
1046
1047 #ifdef USE_PAM
1048         unsigned int i;
1049         /* Now update the passwords using PAM */
1050         for (i = 0; i < nusers; i++) {
1051                 if (do_pam_passwd_non_interractive ("newusers", usernames[i], passwords[i]) != 0) {
1052                         fprintf (stderr,
1053                                  _("%s: (line %d, user %s) password not changed\n"),
1054                                  Prog, lines[i], usernames[i]);
1055                         errors++;
1056                 }
1057         }
1058 #endif                          /* USE_PAM */
1059
1060         return ((0 == errors) ? EXIT_SUCCESS : EXIT_FAILURE);
1061 }
1062