~xnox/ubuntu/quantal/shadow/clear-locks

« back to all changes in this revision

Viewing changes to src/useradd.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2009-05-05 09:45:21 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090505094521-wpk2wn3q7957tlah
Tags: 1:4.1.3.1-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Ubuntu specific:
    + debian/login.defs: use SHA512 by default for password crypt routine.
  - debian/patches/stdout-encrypted-password.patch: chpasswd can report
    password hashes on stdout (debian bug 505640).
  - debian/login.pam: Enable SELinux support (debian bug 527106).
  - debian/securetty.linux: support Freescale MX-series (debian bug 527095).
* Add debian/patches/300_lastlog_failure: fixed upstream (debian bug 524873).
* Drop debian/patches/593_omit_lastchange_field_if_clock_is_misset: fixed
  upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright 1991 - 1994, Julianne Frances Haugh
 
2
 * Copyright (c) 1991 - 1994, 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
3
6
 * All rights reserved.
4
7
 *
5
8
 * Redistribution and use in source and binary forms, with or without
10
13
 * 2. Redistributions in binary form must reproduce the above copyright
11
14
 *    notice, this list of conditions and the following disclaimer in the
12
15
 *    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
 * 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.
16
19
 *
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.
 
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.
28
31
 */
29
32
 
30
33
#include <config.h>
31
34
 
32
 
#ident "$Id: useradd.c 1891 2008-03-08 22:44:53Z nekral-guest $"
 
35
#ident "$Id: useradd.c 2691 2009-04-15 21:14:08Z nekral-guest $"
33
36
 
34
37
#include <assert.h>
35
38
#include <ctype.h>
39
42
#include <grp.h>
40
43
#include <lastlog.h>
41
44
#include <pwd.h>
 
45
#ifdef ACCT_TOOLS_SETUID
42
46
#ifdef USE_PAM
43
47
#include "pam_defs.h"
44
48
#endif                          /* USE_PAM */
 
49
#endif                          /* ACCT_TOOLS_SETUID */
45
50
#include <stdio.h>
46
51
#include <sys/stat.h>
47
52
#include <sys/types.h>
76
81
/*
77
82
 * Global variables
78
83
 */
 
84
char *Prog;
 
85
 
79
86
/*
80
87
 * These defaults are used if there is no defaults file.
81
88
 */
101
108
static const char *user_home = "";
102
109
static const char *user_shell = "";
103
110
static const char *create_mail_spool = "";
 
111
#ifdef WITH_SELINUX
 
112
static const char *user_selinux = "";
 
113
#endif
104
114
 
105
115
static long user_expire = -1;
106
 
static int is_shadow_pwd;
 
116
static bool is_shadow_pwd;
107
117
 
108
118
#ifdef SHADOWGRP
109
 
static int is_shadow_grp;
110
 
static int gshadow_locked = 0;
 
119
static bool is_shadow_grp;
 
120
static bool sgr_locked = false;
111
121
#endif
112
 
static int passwd_locked = 0;
113
 
static int group_locked = 0;
114
 
static int shadow_locked = 0;
 
122
static bool pw_locked = false;
 
123
static bool gr_locked = false;
 
124
static bool spw_locked = false;
115
125
static char **user_groups;      /* NULL-terminated list */
116
126
static long sys_ngroups;
117
 
static int do_grp_update = 0;   /* group files need to be updated */
118
 
 
119
 
static char *Prog;
120
 
 
121
 
static int
122
 
    bflg = 0,                   /* new default root of home directory */
123
 
    cflg = 0,                   /* comment (GECOS) field for new account */
124
 
    dflg = 0,                   /* home directory for new account */
125
 
    Dflg = 0,                   /* set/show new user default values */
126
 
    eflg = 0,                   /* days since 1970-01-01 when account is locked */
127
 
    fflg = 0,                   /* days until account with expired password is locked */
128
 
    gflg = 0,                   /* primary group ID for new account */
129
 
    Gflg = 0,                   /* secondary group set for new account */
130
 
    kflg = 0,                   /* specify a directory to fill new user directory */
131
 
    lflg = 0,                   /* do not add user to lastlog database file */
132
 
    mflg = 0,                   /* create user's home directory if it doesn't exist */
133
 
    Nflg = 0,                   /* do not create a group having the same name as the user, but add the user to def_group (or the group specified with -g) */
134
 
    oflg = 0,                   /* permit non-unique user ID to be specified with -u */
135
 
    rflg = 0,                   /* create a system account */
136
 
    sflg = 0,                   /* shell program for new account */
137
 
    uflg = 0,                   /* specify user ID for new account */
138
 
    Uflg = 0;                   /* create a group having the same name as the user */
139
 
 
140
 
static int home_added;
 
127
static bool do_grp_update = false;      /* group files need to be updated */
 
128
 
 
129
static bool
 
130
    bflg = false,               /* new default root of home directory */
 
131
    cflg = false,               /* comment (GECOS) field for new account */
 
132
    dflg = false,               /* home directory for new account */
 
133
    Dflg = false,               /* set/show new user default values */
 
134
    eflg = false,               /* days since 1970-01-01 when account is locked */
 
135
    fflg = false,               /* days until account with expired password is locked */
 
136
    gflg = false,               /* primary group ID for new account */
 
137
    Gflg = false,               /* secondary group set for new account */
 
138
    kflg = false,               /* specify a directory to fill new user directory */
 
139
    lflg = false,               /* do not add user to lastlog/faillog databases */
 
140
    mflg = false,               /* create user's home directory if it doesn't exist */
 
141
    Mflg = false,               /* do not create user's home directory even if CREATE_HOME is set */
 
142
    Nflg = false,               /* do not create a group having the same name as the user, but add the user to def_group (or the group specified with -g) */
 
143
    oflg = false,               /* permit non-unique user ID to be specified with -u */
 
144
    rflg = false,               /* create a system account */
 
145
    sflg = false,               /* shell program for new account */
 
146
    uflg = false,               /* specify user ID for new account */
 
147
    Uflg = false,               /* create a group having the same name as the user */
 
148
    Zflg = false;               /* new selinux user */
 
149
 
 
150
static bool home_added = false;
141
151
 
142
152
/*
143
153
 * exit status values
163
173
 
164
174
/* local function prototypes */
165
175
static void fail_exit (int);
166
 
static struct group *getgr_nam_gid (const char *);
167
 
static long get_number (const char *);
168
 
static uid_t get_uid (const char *);
169
176
static void get_defaults (void);
170
177
static void show_defaults (void);
171
178
static int set_defaults (void);
172
179
static int get_groups (char *);
173
180
static void usage (void);
174
181
static void new_pwent (struct passwd *);
 
182
#ifdef WITH_SELINUX
 
183
static void selinux_update_mapping (void);
 
184
#endif
175
185
 
176
186
static long scale_age (long);
177
187
static void new_spent (struct spwd *);
191
201
 */
192
202
static void fail_exit (int code)
193
203
{
194
 
        if (home_added)
 
204
        if (home_added) {
195
205
                rmdir (user_home);
 
206
        }
196
207
 
197
 
        if (shadow_locked) {
198
 
                spw_unlock ();
199
 
        }
200
 
        if (passwd_locked) {
201
 
                pw_unlock ();
202
 
        }
203
 
        if (group_locked) {
204
 
                gr_unlock ();
 
208
        if (spw_locked) {
 
209
                if (spw_unlock () == 0) {
 
210
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
 
211
                        SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
 
212
#ifdef WITH_AUDIT
 
213
                        audit_logger (AUDIT_ADD_USER, Prog,
 
214
                                      "unlocking shadow file",
 
215
                                      user_name, AUDIT_NO_ID,
 
216
                                      SHADOW_AUDIT_FAILURE);
 
217
#endif
 
218
                        /* continue */
 
219
                }
 
220
        }
 
221
        if (pw_locked) {
 
222
                if (pw_unlock () == 0) {
 
223
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
 
224
                        SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
 
225
#ifdef WITH_AUDIT
 
226
                        audit_logger (AUDIT_ADD_USER, Prog,
 
227
                                      "unlocking passwd file",
 
228
                                      user_name, AUDIT_NO_ID,
 
229
                                      SHADOW_AUDIT_FAILURE);
 
230
#endif
 
231
                        /* continue */
 
232
                }
 
233
        }
 
234
        if (gr_locked) {
 
235
                if (gr_unlock () == 0) {
 
236
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
 
237
                        SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
 
238
#ifdef WITH_AUDIT
 
239
                        audit_logger (AUDIT_ADD_USER, Prog,
 
240
                                      "unlocking group file",
 
241
                                      user_name, AUDIT_NO_ID,
 
242
                                      SHADOW_AUDIT_FAILURE);
 
243
#endif
 
244
                        /* continue */
 
245
                }
205
246
        }
206
247
#ifdef  SHADOWGRP
207
 
        if (gshadow_locked) {
208
 
                sgr_unlock ();
 
248
        if (sgr_locked) {
 
249
                if (sgr_unlock () == 0) {
 
250
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
 
251
                        SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
 
252
#ifdef WITH_AUDIT
 
253
                        audit_logger (AUDIT_ADD_USER, Prog,
 
254
                                      "unlocking gshadow file",
 
255
                                      user_name, AUDIT_NO_ID,
 
256
                                      SHADOW_AUDIT_FAILURE);
 
257
#endif
 
258
                        /* continue */
 
259
                }
209
260
        }
210
261
#endif
211
262
 
212
263
#ifdef WITH_AUDIT
213
 
        audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user", user_name, -1,
214
 
                      0);
 
264
        audit_logger (AUDIT_ADD_USER, Prog,
 
265
                      "adding user",
 
266
                      user_name, AUDIT_NO_ID,
 
267
                      SHADOW_AUDIT_FAILURE);
215
268
#endif
216
 
        SYSLOG ((LOG_INFO, "failed adding user `%s', data deleted", user_name));
 
269
        SYSLOG ((LOG_INFO, "failed adding user '%s', data deleted", user_name));
217
270
        exit (code);
218
271
}
219
272
 
220
 
static struct group *getgr_nam_gid (const char *grname)
221
 
{
222
 
        long gid;
223
 
        char *errptr;
224
 
 
225
 
        gid = strtol (grname, &errptr, 10);
226
 
        if (*grname != '\0' && *errptr == '\0' && errno != ERANGE && gid >= 0)
227
 
                return xgetgrgid (gid);
228
 
        return xgetgrnam (grname);
229
 
}
230
 
 
231
 
static long get_number (const char *numstr)
232
 
{
233
 
        long val;
234
 
        char *errptr;
235
 
 
236
 
        val = strtol (numstr, &errptr, 10);
237
 
        if (*errptr || errno == ERANGE) {
238
 
                fprintf (stderr, _("%s: invalid numeric argument '%s'\n"), Prog,
239
 
                         numstr);
240
 
                exit (E_BAD_ARG);
241
 
        }
242
 
        return val;
243
 
}
244
 
 
245
 
static uid_t get_uid (const char *uidstr)
246
 
{
247
 
        long val;
248
 
        char *errptr;
249
 
 
250
 
        val = strtol (uidstr, &errptr, 10);
251
 
        if (*errptr || errno == ERANGE || val < 0) {
252
 
                fprintf (stderr,
253
 
                         _("%s: invalid numeric argument '%s'\n"), Prog,
254
 
                         uidstr);
255
 
                exit (E_BAD_ARG);
256
 
        }
257
 
        return val;
258
 
}
259
 
 
260
273
#define MATCH(x,y) (strncmp((x),(y),strlen(y)) == 0)
261
274
 
262
275
/*
270
283
{
271
284
        FILE *fp;
272
285
        char buf[1024];
273
 
        char *cp, *ep;
 
286
        char *cp;
274
287
 
275
288
        /*
276
289
         * Open the defaults file for reading.
277
290
         */
278
291
 
279
 
        if (!(fp = fopen (def_file, "r")))
 
292
        fp = fopen (def_file, "r");
 
293
        if (NULL == fp) {
280
294
                return;
 
295
        }
281
296
 
282
297
        /*
283
298
         * Read the file a line at a time. Only the lines that have relevant
284
299
         * values are used, everything else can be ignored.
285
300
         */
286
 
        while (fgets (buf, sizeof buf, fp)) {
287
 
                if ((cp = strrchr (buf, '\n')))
 
301
        while (fgets (buf, (int) sizeof buf, fp) == buf) {
 
302
                cp = strrchr (buf, '\n');
 
303
                if (NULL != cp) {
288
304
                        *cp = '\0';
 
305
                }
289
306
 
290
 
                if (!(cp = strchr (buf, '=')))
 
307
                cp = strchr (buf, '=');
 
308
                if (NULL == cp) {
291
309
                        continue;
 
310
                }
292
311
 
293
312
                cp++;
294
313
 
296
315
                 * Primary GROUP identifier
297
316
                 */
298
317
                if (MATCH (buf, DGROUP)) {
299
 
                        unsigned int val = (unsigned int) strtoul (cp, &ep, 10);
300
 
                        const struct group *grp;
301
 
 
302
 
                        if (*cp != '\0' && *ep == '\0') { /* valid number */
303
 
                                def_group = val;
304
 
                                /* local, no need for xgetgrgid */
305
 
                                if ((grp = getgrgid (def_group))) {
306
 
                                        def_gname = xstrdup (grp->gr_name);
307
 
                                } else {
308
 
                                        fprintf (stderr,
309
 
                                                 _("%s: unknown GID %s\n"),
310
 
                                                 Prog, cp);
311
 
                                }
312
 
                        /* local, no need for xgetgrnam */
313
 
                        } else if ((grp = getgrnam (cp))) {
 
318
                        const struct group *grp = getgr_nam_gid (cp);
 
319
                        if (NULL == grp) {
 
320
                                fprintf (stderr,
 
321
                                         _("%s: group '%s' does not exist\n"),
 
322
                                         Prog, cp);
 
323
                                fprintf (stderr,
 
324
                                         _("%s: the %s configuration in %s will be ignored\n"),
 
325
                                         Prog, DGROUP, def_file);
 
326
                        } else {
314
327
                                def_group = grp->gr_gid;
315
 
                                def_gname = xstrdup (cp);
316
 
                        } else {
317
 
                                fprintf (stderr,
318
 
                                         _("%s: unknown group %s\n"), Prog, cp);
 
328
                                def_gname = xstrdup (grp->gr_name);
319
329
                        }
320
330
                }
321
331
 
337
347
                 * Default Password Inactive value
338
348
                 */
339
349
                else if (MATCH (buf, INACT)) {
340
 
                        long val = strtol (cp, &ep, 10);
341
 
 
342
 
                        if (*cp || errno == ERANGE)
343
 
                                def_inactive = val;
344
 
                        else
 
350
                        if (   (getlong (cp, &def_inactive) == 0)
 
351
                            || (def_inactive < -1)) {
 
352
                                fprintf (stderr,
 
353
                                         _("%s: invalid numeric argument '%s'\n"),
 
354
                                         Prog, optarg);
 
355
                                fprintf (stderr,
 
356
                                         _("%s: the %s configuration in %s will be ignored\n"),
 
357
                                         Prog, INACT, def_file);
345
358
                                def_inactive = -1;
 
359
                        }
346
360
                }
347
361
 
348
362
                /*
356
370
                 * Default Skeleton information
357
371
                 */
358
372
                else if (MATCH (buf, SKEL)) {
359
 
                        if (*cp == '\0')
 
373
                        if ('\0' == *cp) {
360
374
                                cp = SKEL_DIR;  /* XXX warning: const */
 
375
                        }
361
376
 
362
377
                        def_template = xstrdup (cp);
363
378
                }
366
381
                 * Create by default user mail spool or not ?
367
382
                 */
368
383
                else if (MATCH (buf, CREATE_MAIL_SPOOL)) {
369
 
                        if (*cp == '\0')
 
384
                        if (*cp == '\0') {
370
385
                                cp = CREATE_MAIL_SPOOL; /* XXX warning: const */
 
386
                        }
371
387
 
372
388
                        def_create_mail_spool = xstrdup (cp);
373
389
                }
374
390
        }
 
391
        (void) fclose (fp);
375
392
}
376
393
 
377
394
/*
406
423
        static char new_file[] = NEW_USER_FILE;
407
424
        char *cp;
408
425
        int ofd;
409
 
        int out_group = 0;
410
 
        int out_home = 0;
411
 
        int out_inactive = 0;
412
 
        int out_expire = 0;
413
 
        int out_shell = 0;
414
 
        int out_skel = 0;
415
 
        int out_create_mail_spool = 0;
 
426
        bool out_group = false;
 
427
        bool out_home = false;
 
428
        bool out_inactive = false;
 
429
        bool out_expire = false;
 
430
        bool out_shell = false;
 
431
        bool out_skel = false;
 
432
        bool out_create_mail_spool = false;
416
433
 
417
434
        /*
418
435
         * Create a temporary file to copy the new output to.
419
436
         */
420
 
        if ((ofd = mkstemp (new_file)) == -1) {
 
437
        ofd = mkstemp (new_file);
 
438
        if (-1 == ofd) {
421
439
                fprintf (stderr,
422
 
                         _("%s: cannot create new defaults file\n"), Prog);
 
440
                         _("%s: cannot create new defaults file\n"),
 
441
                         Prog);
423
442
                return -1;
424
443
        }
425
444
 
426
 
        if (!(ofp = fdopen (ofd, "w"))) {
427
 
                fprintf (stderr, _("%s: cannot open new defaults file\n"),
428
 
                         Prog);
 
445
        ofp = fdopen (ofd, "w");
 
446
        if (NULL == ofp) {
 
447
                fprintf (stderr,
 
448
                         _("%s: cannot open new defaults file\n"),
 
449
                         Prog);
429
450
                return -1;
430
451
        }
431
452
 
434
455
         * temporary file, using any new values. Each line is checked
435
456
         * to insure that it is not output more than once.
436
457
         */
437
 
        if (!(ifp = fopen (def_file, "r"))) {
 
458
        ifp = fopen (def_file, "r");
 
459
        if (NULL == ifp) {
438
460
                fprintf (ofp, "# useradd defaults file\n");
439
461
                goto skip;
440
462
        }
441
463
 
442
 
        while (fgets (buf, sizeof buf, ifp)) {
443
 
                if ((cp = strrchr (buf, '\n')))
 
464
        while (fgets (buf, (int) sizeof buf, ifp) == buf) {
 
465
                cp = strrchr (buf, '\n');
 
466
                if (NULL != cp) {
444
467
                        *cp = '\0';
 
468
                }
445
469
 
446
470
                if (!out_group && MATCH (buf, DGROUP)) {
447
471
                        fprintf (ofp, DGROUP "%u\n", (unsigned int) def_group);
448
 
                        out_group++;
 
472
                        out_group = true;
449
473
                } else if (!out_home && MATCH (buf, HOME)) {
450
474
                        fprintf (ofp, HOME "%s\n", def_home);
451
 
                        out_home++;
 
475
                        out_home = true;
452
476
                } else if (!out_inactive && MATCH (buf, INACT)) {
453
477
                        fprintf (ofp, INACT "%ld\n", def_inactive);
454
 
                        out_inactive++;
 
478
                        out_inactive = true;
455
479
                } else if (!out_expire && MATCH (buf, EXPIRE)) {
456
480
                        fprintf (ofp, EXPIRE "%s\n", def_expire);
457
 
                        out_expire++;
 
481
                        out_expire = true;
458
482
                } else if (!out_shell && MATCH (buf, SHELL)) {
459
483
                        fprintf (ofp, SHELL "%s\n", def_shell);
460
 
                        out_shell++;
 
484
                        out_shell = true;
461
485
                } else if (!out_skel && MATCH (buf, SKEL)) {
462
486
                        fprintf (ofp, SKEL "%s\n", def_template);
463
 
                        out_skel++;
 
487
                        out_skel = true;
464
488
                } else if (!out_create_mail_spool
465
489
                           && MATCH (buf, CREATE_MAIL_SPOOL)) {
466
 
                        fprintf (ofp, CREATE_MAIL_SPOOL "%s\n",
467
 
                                 def_create_mail_spool);
468
 
                        out_create_mail_spool++;
 
490
                        fprintf (ofp,
 
491
                                 CREATE_MAIL_SPOOL "%s\n",
 
492
                                 def_create_mail_spool);
 
493
                        out_create_mail_spool = true;
469
494
                } else
470
495
                        fprintf (ofp, "%s\n", buf);
471
496
        }
472
 
        fclose (ifp);
 
497
        (void) fclose (ifp);
473
498
 
474
499
      skip:
475
500
        /*
497
522
         * Flush and close the file. Check for errors to make certain
498
523
         * the new file is intact.
499
524
         */
500
 
        fflush (ofp);
501
 
        if (ferror (ofp) || fclose (ofp)) {
 
525
        (void) fflush (ofp);
 
526
        if (   (ferror (ofp) != 0)
 
527
            || (fsync (fileno (ofp)) != 0)
 
528
            || (fclose (ofp) != 0)) {
502
529
                unlink (new_file);
503
530
                return -1;
504
531
        }
507
534
         * Rename the current default file to its backup name.
508
535
         */
509
536
        snprintf (buf, sizeof buf, "%s-", def_file);
510
 
        if (rename (def_file, buf) && errno != ENOENT) {
 
537
        if ((rename (def_file, buf) != 0) && (ENOENT != errno)) {
511
538
                snprintf (buf, sizeof buf, _("%s: rename: %s"), Prog, def_file);
512
539
                perror (buf);
513
540
                unlink (new_file);
517
544
        /*
518
545
         * Rename the new default file to its correct name.
519
546
         */
520
 
        if (rename (new_file, def_file)) {
 
547
        if (rename (new_file, def_file) != 0) {
521
548
                snprintf (buf, sizeof buf, _("%s: rename: %s"), Prog, new_file);
522
549
                perror (buf);
523
550
                return -1;
524
551
        }
525
552
#ifdef WITH_AUDIT
526
 
        audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "changing user defaults",
527
 
                      NULL, -1, 1);
 
553
        audit_logger (AUDIT_USYS_CONFIG, Prog,
 
554
                      "changing useradd defaults",
 
555
                      NULL, AUDIT_NO_ID,
 
556
                      SHADOW_AUDIT_SUCCESS);
528
557
#endif
529
558
        SYSLOG ((LOG_INFO,
530
 
                 "useradd defaults: GROUP=%u, HOME=%s, SHELL=%s, INACTIVE=%ld, "
531
 
                 "EXPIRE=%s, SKEL=%s, CREATE_MAIL_SPOOL=%s",
532
 
                 (unsigned int) def_group, def_home, def_shell,
533
 
                 def_inactive, def_expire, def_template,
534
 
                 def_create_mail_spool));
 
559
                 "useradd defaults: GROUP=%u, HOME=%s, SHELL=%s, INACTIVE=%ld, "
 
560
                 "EXPIRE=%s, SKEL=%s, CREATE_MAIL_SPOOL=%s",
 
561
                 (unsigned int) def_group, def_home, def_shell,
 
562
                 def_inactive, def_expire, def_template,
 
563
                 def_create_mail_spool));
535
564
        return 0;
536
565
}
537
566
 
549
578
        int errors = 0;
550
579
        int ngroups = 0;
551
580
 
552
 
        if (!*list)
 
581
        if ('\0' == *list) {
553
582
                return 0;
 
583
        }
554
584
 
555
585
        /*
556
586
         * So long as there is some data to be converted, strip off
561
591
                /*
562
592
                 * Strip off a single name from the list
563
593
                 */
564
 
                if ((cp = strchr (list, ',')))
 
594
                cp = strchr (list, ',');
 
595
                if (NULL != cp) {
565
596
                        *cp++ = '\0';
 
597
                }
566
598
 
567
599
                /*
568
600
                 * Names starting with digits are treated as numerical
574
606
                 * There must be a match, either by GID value or by
575
607
                 * string name.
576
608
                 */
577
 
                if (!grp) {
578
 
                        fprintf (stderr, _("%s: unknown group %s\n"),
579
 
                                 Prog, list);
 
609
                if (NULL == grp) {
 
610
                        fprintf (stderr,
 
611
                                 _("%s: group '%s' does not exist\n"),
 
612
                                 Prog, list);
580
613
                        errors++;
581
614
                }
582
615
                list = cp;
585
618
                 * If the group doesn't exist, don't dump core...
586
619
                 * Instead, try the next one.  --marekm
587
620
                 */
588
 
                if (!grp)
 
621
                if (NULL == grp) {
589
622
                        continue;
 
623
                }
590
624
 
591
625
#ifdef  USE_NIS
592
626
                /*
595
629
                 */
596
630
                if (__isgrNIS ()) {
597
631
                        fprintf (stderr,
598
 
                                 _("%s: group '%s' is a NIS group.\n"),
599
 
                                 Prog, grp->gr_name);
 
632
                                 _("%s: group '%s' is a NIS group.\n"),
 
633
                                 Prog, grp->gr_name);
600
634
                        continue;
601
635
                }
602
636
#endif
603
637
 
604
638
                if (ngroups == sys_ngroups) {
605
639
                        fprintf (stderr,
606
 
                                 _
607
 
                                 ("%s: too many groups specified (max %d).\n"),
608
 
                                 Prog, ngroups);
 
640
                                 _("%s: too many groups specified (max %d).\n"),
 
641
                                 Prog, ngroups);
609
642
                        break;
610
643
                }
611
644
 
613
646
                 * Add the group name to the user's list of groups.
614
647
                 */
615
648
                user_groups[ngroups++] = xstrdup (grp->gr_name);
616
 
        } while (list);
 
649
        } while (NULL != list);
617
650
 
618
651
        user_groups[ngroups] = (char *) 0;
619
652
 
620
653
        /*
621
654
         * Any errors in finding group names are fatal
622
655
         */
623
 
        if (errors)
 
656
        if (0 != errors) {
624
657
                return -1;
 
658
        }
625
659
 
626
660
        return 0;
627
661
}
631
665
 */
632
666
static void usage (void)
633
667
{
634
 
        fputs (_("Usage: useradd [options] LOGIN\n"
 
668
        fprintf (stderr,
 
669
                 _("Usage: useradd [options] LOGIN\n"
635
670
                 "\n"
636
671
                 "Options:\n"
637
672
                 "  -b, --base-dir BASE_DIR       base directory for the new user account\n"
649
684
                 "  -h, --help                    display this help message and exit\n"
650
685
                 "  -k, --skel SKEL_DIR           specify an alternative skel directory\n"
651
686
                 "  -K, --key KEY=VALUE           overrides /etc/login.defs defaults\n"
652
 
                 "  -l,                           do not add the user to the lastlog and\n"
 
687
                 "  -l, --no-log-init             do not add the user to the lastlog and\n"
653
688
                 "                                faillog databases\n"
654
689
                 "  -m, --create-home             create home directory for the new user\n"
655
690
                 "                                account\n"
 
691
                 "  -M, --no-create-home          do not create user's home directory\n"
 
692
                 "                                (overrides /etc/login.defs)\n"
656
693
                 "  -N, --no-user-group           do not create a group with the same name as\n"
657
694
                 "                                the user\n"
658
695
                 "  -o, --non-unique              allow create user with duplicate\n"
663
700
                 "  -s, --shell SHELL             the login shell for the new user account\n"
664
701
                 "  -u, --uid UID                 force use the UID for the new user account\n"
665
702
                 "  -U, --user-group              create a group with the same name as the user\n"
666
 
                 "\n"), stderr);
 
703
                 "%s"
 
704
                 "\n"),
 
705
#ifdef WITH_SELINUX
 
706
                 _("  -Z, --selinux-user SEUSER     use a specific SEUSER for the SELinux user mapping\n")
 
707
#else
 
708
                 ""
 
709
#endif
 
710
                 );
667
711
        exit (E_USAGE);
668
712
}
669
713
 
677
721
{
678
722
        memzero (pwent, sizeof *pwent);
679
723
        pwent->pw_name = (char *) user_name;
680
 
        if (is_shadow_pwd)
 
724
        if (is_shadow_pwd) {
681
725
                pwent->pw_passwd = (char *) SHADOW_PASSWD_STRING;
682
 
        else
 
726
        } else {
683
727
                pwent->pw_passwd = (char *) user_pass;
 
728
        }
684
729
 
685
730
        pwent->pw_uid = user_id;
686
731
        pwent->pw_gid = user_gid;
691
736
 
692
737
static long scale_age (long x)
693
738
{
694
 
        if (x <= 0)
 
739
        if (x <= 0) {
695
740
                return x;
 
741
        }
696
742
 
697
743
        return x * (DAY / SCALE);
698
744
}
708
754
        memzero (spent, sizeof *spent);
709
755
        spent->sp_namp = (char *) user_name;
710
756
        spent->sp_pwdp = (char *) user_pass;
711
 
        spent->sp_lstchg = time ((time_t *) 0) / SCALE;
 
757
        spent->sp_lstchg = (long) time ((time_t *) 0) / SCALE;
 
758
        if (0 == spent->sp_lstchg) {
 
759
                /* Better disable aging than requiring a password change */
 
760
                spent->sp_lstchg = -1;
 
761
        }
712
762
        if (!rflg) {
713
 
        spent->sp_min = scale_age (getdef_num ("PASS_MIN_DAYS", -1));
714
 
        spent->sp_max = scale_age (getdef_num ("PASS_MAX_DAYS", -1));
715
 
        spent->sp_warn = scale_age (getdef_num ("PASS_WARN_AGE", -1));
716
 
        spent->sp_inact = scale_age (def_inactive);
717
 
        spent->sp_expire = scale_age (user_expire);
 
763
                spent->sp_min = scale_age (getdef_num ("PASS_MIN_DAYS", -1));
 
764
                spent->sp_max = scale_age (getdef_num ("PASS_MAX_DAYS", -1));
 
765
                spent->sp_warn = scale_age (getdef_num ("PASS_WARN_AGE", -1));
 
766
                spent->sp_inact = scale_age (def_inactive);
 
767
                spent->sp_expire = scale_age (user_expire);
718
768
        } else {
719
769
                spent->sp_min = scale_age (-1);
720
770
                spent->sp_max = scale_age (-1);
722
772
                spent->sp_inact = scale_age (-1);
723
773
                spent->sp_expire = scale_age (-1);
724
774
        }
725
 
        spent->sp_flag = -1;
 
775
        spent->sp_flag = SHADOW_SP_FLAG_UNSET;
726
776
}
727
777
 
728
778
/*
750
800
         * Scan through the entire group file looking for the groups that
751
801
         * the user is a member of.
752
802
         */
753
 
        for (gr_rewind (), grp = gr_next (); grp; grp = gr_next ()) {
 
803
        for (gr_rewind (), grp = gr_next (); NULL != grp; grp = gr_next ()) {
754
804
 
755
805
                /*
756
806
                 * See if the user specified this group as one of their
757
807
                 * concurrent groups.
758
808
                 */
759
 
                if (!is_on_list (user_groups, grp->gr_name))
 
809
                if (!is_on_list (user_groups, grp->gr_name)) {
760
810
                        continue;
 
811
                }
761
812
 
762
813
                /*
763
814
                 * Make a copy - gr_update() will free() everything
764
815
                 * from the old entry, and we need it later.
765
816
                 */
766
817
                ngrp = __gr_dup (grp);
767
 
                if (!ngrp) {
 
818
                if (NULL == ngrp) {
768
819
                        fprintf (stderr,
769
 
                                 _("%s: Out of memory. Cannot update the group database.\n"),
770
 
                                 Prog);
 
820
                                 _("%s: Out of memory. Cannot update %s.\n"),
 
821
                                 Prog, gr_dbname ());
 
822
                        SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name));
 
823
#ifdef WITH_AUDIT
 
824
                        audit_logger (AUDIT_ADD_USER, Prog,
 
825
                                      "adding user to group",
 
826
                                      user_name, AUDIT_NO_ID,
 
827
                                      SHADOW_AUDIT_FAILURE);
 
828
#endif
771
829
                        fail_exit (E_GRP_UPDATE);       /* XXX */
772
830
                }
773
831
 
776
834
                 * update the group entry to reflect the change.
777
835
                 */
778
836
                ngrp->gr_mem = add_list (ngrp->gr_mem, user_name);
779
 
                if (!gr_update (ngrp)) {
 
837
                if (gr_update (ngrp) == 0) {
780
838
                        fprintf (stderr,
781
 
                                 _("%s: error adding new group entry\n"), Prog);
 
839
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
 
840
                                 Prog, gr_dbname (), ngrp->gr_name);
 
841
                        SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", gr_dbname (), user_name));
 
842
#ifdef WITH_AUDIT
 
843
                        audit_logger (AUDIT_ADD_USER, Prog,
 
844
                                      "adding user to group",
 
845
                                      user_name, AUDIT_NO_ID,
 
846
                                      SHADOW_AUDIT_FAILURE);
 
847
#endif
782
848
                        fail_exit (E_GRP_UPDATE);
783
849
                }
784
850
#ifdef WITH_AUDIT
785
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
786
 
                              "adding user to group", user_name, -1, 1);
 
851
                audit_logger (AUDIT_ADD_USER, Prog,
 
852
                              "adding user to group",
 
853
                              user_name, AUDIT_NO_ID,
 
854
                              SHADOW_AUDIT_SUCCESS);
787
855
#endif
788
 
                SYSLOG ((LOG_INFO, "add `%s' to group `%s'",
789
 
                         user_name, ngrp->gr_name));
 
856
                SYSLOG ((LOG_INFO,
 
857
                         "add '%s' to group '%s'",
 
858
                         user_name, ngrp->gr_name));
790
859
        }
791
860
 
792
861
#ifdef  SHADOWGRP
798
867
         * that the user is a member of. The administrative list isn't
799
868
         * modified.
800
869
         */
801
 
        for (sgr_rewind (), sgrp = sgr_next (); sgrp; sgrp = sgr_next ()) {
 
870
        for (sgr_rewind (), sgrp = sgr_next (); NULL != sgrp; sgrp = sgr_next ()) {
802
871
 
803
872
                /*
804
873
                 * See if the user specified this group as one of their
805
874
                 * concurrent groups.
806
875
                 */
807
 
                if (!gr_locate (sgrp->sg_name))
 
876
                if (gr_locate (sgrp->sg_name) == NULL) {
808
877
                        continue;
 
878
                }
809
879
 
810
 
                if (!is_on_list (user_groups, sgrp->sg_name))
 
880
                if (!is_on_list (user_groups, sgrp->sg_name)) {
811
881
                        continue;
 
882
                }
812
883
 
813
884
                /*
814
885
                 * Make a copy - sgr_update() will free() everything
815
886
                 * from the old entry, and we need it later.
816
887
                 */
817
888
                nsgrp = __sgr_dup (sgrp);
818
 
                if (!nsgrp) {
 
889
                if (NULL == nsgrp) {
819
890
                        fprintf (stderr,
820
 
                                 _("%s: Out of memory. Cannot update the shadow group database.\n"),
821
 
                                 Prog);
 
891
                                 _("%s: Out of memory. Cannot update %s.\n"),
 
892
                                 Prog, sgr_dbname ());
 
893
                        SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name));
 
894
#ifdef WITH_AUDIT
 
895
                        audit_logger (AUDIT_ADD_USER, Prog,
 
896
                                      "adding user to shadow group",
 
897
                                      user_name, AUDIT_NO_ID,
 
898
                                      SHADOW_AUDIT_FAILURE);
 
899
#endif
822
900
                        fail_exit (E_GRP_UPDATE);       /* XXX */
823
901
                }
824
902
 
827
905
                 * update the group entry to reflect the change.
828
906
                 */
829
907
                nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_name);
830
 
                if (!sgr_update (nsgrp)) {
 
908
                if (sgr_update (nsgrp) == 0) {
831
909
                        fprintf (stderr,
832
 
                                 _("%s: error adding new group entry\n"), Prog);
 
910
                                 _("%s: failed to prepare the new %s entry '%s'\n"),
 
911
                                 Prog, sgr_dbname (), nsgrp->sg_name);
 
912
                        SYSLOG ((LOG_ERR, "failed to prepare the new %s entry '%s'", sgr_dbname (), user_name));
 
913
#ifdef WITH_AUDIT
 
914
                        audit_logger (AUDIT_ADD_USER, Prog,
 
915
                                      "adding user to shadow group",
 
916
                                      user_name, AUDIT_NO_ID,
 
917
                                      SHADOW_AUDIT_FAILURE);
 
918
#endif
833
919
                        fail_exit (E_GRP_UPDATE);
834
920
                }
835
921
#ifdef WITH_AUDIT
836
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
837
 
                              "adding user to shadow group", user_name, -1, 1);
 
922
                audit_logger (AUDIT_ADD_USER, Prog,
 
923
                              "adding user to shadow group",
 
924
                              user_name, AUDIT_NO_ID,
 
925
                              SHADOW_AUDIT_SUCCESS);
838
926
#endif
839
 
                SYSLOG ((LOG_INFO, "add `%s' to shadow group `%s'",
840
 
                         user_name, nsgrp->sg_name));
 
927
                SYSLOG ((LOG_INFO,
 
928
                         "add '%s' to shadow group '%s'",
 
929
                         user_name, nsgrp->sg_name));
841
930
        }
842
931
#endif                          /* SHADOWGRP */
843
932
}
852
941
static void process_flags (int argc, char **argv)
853
942
{
854
943
        const struct group *grp;
855
 
        int anyflag = 0;
 
944
        bool anyflag = false;
856
945
        char *cp;
857
946
 
858
947
        {
873
962
                        {"skel", required_argument, NULL, 'k'},
874
963
                        {"key", required_argument, NULL, 'K'},
875
964
                        {"create-home", no_argument, NULL, 'm'},
 
965
                        {"no-create-home", no_argument, NULL, 'M'},
 
966
                        {"no-log-init", no_argument, NULL, 'l'},
876
967
                        {"no-user-group", no_argument, NULL, 'N'},
877
968
                        {"non-unique", no_argument, NULL, 'o'},
878
969
                        {"password", required_argument, NULL, 'p'},
879
970
                        {"system", no_argument, NULL, 'r'},
880
971
                        {"shell", required_argument, NULL, 's'},
 
972
#ifdef WITH_SELINUX
 
973
                        {"selinux-user", required_argument, NULL, 'Z'},
 
974
#endif
881
975
                        {"uid", required_argument, NULL, 'u'},
882
976
                        {"user-group", no_argument, NULL, 'U'},
883
977
                        {NULL, 0, NULL, '\0'}
884
978
                };
885
 
                while ((c =
886
 
                        getopt_long (argc, argv, "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
887
 
                                     long_options, NULL)) != -1) {
 
979
                while ((c = getopt_long (argc, argv,
 
980
#ifdef WITH_SELINUX
 
981
                                         "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:UZ:",
 
982
#else
 
983
                                         "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
 
984
#endif
 
985
                                         long_options, NULL)) != -1) {
888
986
                        switch (c) {
889
987
                        case 'b':
890
 
                                if (!VALID (optarg)
891
 
                                    || optarg[0] != '/') {
 
988
                                if (   ( !VALID (optarg) )
 
989
                                    || ( optarg[0] != '/' )) {
892
990
                                        fprintf (stderr,
893
 
                                                 _
894
 
                                                 ("%s: invalid base directory '%s'\n"),
895
 
                                                 Prog, optarg);
 
991
                                                 _("%s: invalid base directory '%s'\n"),
 
992
                                                 Prog, optarg);
896
993
                                        exit (E_BAD_ARG);
897
994
                                }
898
995
                                def_home = optarg;
899
 
                                bflg++;
 
996
                                bflg = true;
900
997
                                break;
901
998
                        case 'c':
902
999
                                if (!VALID (optarg)) {
903
1000
                                        fprintf (stderr,
904
 
                                                 _
905
 
                                                 ("%s: invalid comment '%s'\n"),
906
 
                                                 Prog, optarg);
 
1001
                                                 _("%s: invalid comment '%s'\n"),
 
1002
                                                 Prog, optarg);
907
1003
                                        exit (E_BAD_ARG);
908
1004
                                }
909
1005
                                user_comment = optarg;
910
 
                                cflg++;
 
1006
                                cflg = true;
911
1007
                                break;
912
1008
                        case 'd':
913
 
                                if (!VALID (optarg)
914
 
                                    || optarg[0] != '/') {
 
1009
                                if (   ( !VALID (optarg) )
 
1010
                                    || ( optarg[0] != '/' )) {
915
1011
                                        fprintf (stderr,
916
 
                                                 _
917
 
                                                 ("%s: invalid home directory '%s'\n"),
918
 
                                                 Prog, optarg);
 
1012
                                                 _("%s: invalid home directory '%s'\n"),
 
1013
                                                 Prog, optarg);
919
1014
                                        exit (E_BAD_ARG);
920
1015
                                }
921
1016
                                user_home = optarg;
922
 
                                dflg++;
 
1017
                                dflg = true;
923
1018
                                break;
924
1019
                        case 'D':
925
 
                                if (anyflag)
 
1020
                                if (anyflag) {
926
1021
                                        usage ();
927
 
                                Dflg++;
 
1022
                                }
 
1023
                                Dflg = true;
928
1024
                                break;
929
1025
                        case 'e':
930
 
                                if (*optarg) {
 
1026
                                if ('\0' != *optarg) {
931
1027
                                        user_expire = strtoday (optarg);
932
1028
                                        if (user_expire == -1) {
933
1029
                                                fprintf (stderr,
934
 
                                                         _
935
 
                                                         ("%s: invalid date '%s'\n"),
936
 
                                                         Prog, optarg);
 
1030
                                                         _("%s: invalid date '%s'\n"),
 
1031
                                                         Prog, optarg);
937
1032
                                                exit (E_BAD_ARG);
938
1033
                                        }
939
 
                                } else
 
1034
                                } else {
940
1035
                                        user_expire = -1;
 
1036
                                }
941
1037
 
942
1038
                                /*
943
1039
                                 * -e "" is allowed - it's a no-op without /etc/shadow
944
1040
                                 */
945
 
                                if (*optarg && !is_shadow_pwd) {
 
1041
                                if (('\0' != *optarg) && !is_shadow_pwd) {
946
1042
                                        fprintf (stderr,
947
 
                                                 _
948
 
                                                 ("%s: shadow passwords required for -e\n"),
949
 
                                                 Prog);
 
1043
                                                 _("%s: shadow passwords required for -e\n"),
 
1044
                                                 Prog);
950
1045
                                        exit (E_USAGE);
951
1046
                                }
952
 
                                if (Dflg)
 
1047
                                if (Dflg) {
953
1048
                                        def_expire = optarg;
954
 
                                eflg++;
 
1049
                                }
 
1050
                                eflg = true;
955
1051
                                break;
956
1052
                        case 'f':
957
 
                                def_inactive = get_number (optarg);
 
1053
                                if (   (getlong (optarg, &def_inactive) == 0)
 
1054
                                    || (def_inactive < -1)) {
 
1055
                                        fprintf (stderr,
 
1056
                                                 _("%s: invalid numeric argument '%s'\n"),
 
1057
                                                 Prog, optarg);
 
1058
                                        usage ();
 
1059
                                }
958
1060
                                /*
959
 
                                 * -f -1 is allowed - it's a no-op without /etc/shadow
 
1061
                                 * -f -1 is allowed
 
1062
                                 * it's a no-op without /etc/shadow
960
1063
                                 */
961
 
                                if (def_inactive != -1 && !is_shadow_pwd) {
 
1064
                                if ((-1 != def_inactive) && !is_shadow_pwd) {
962
1065
                                        fprintf (stderr,
963
 
                                                 _
964
 
                                                 ("%s: shadow passwords required for -f\n"),
965
 
                                                 Prog);
 
1066
                                                 _("%s: shadow passwords required for -f\n"),
 
1067
                                                 Prog);
966
1068
                                        exit (E_USAGE);
967
1069
                                }
968
 
                                fflg++;
 
1070
                                fflg = true;
969
1071
                                break;
970
1072
                        case 'g':
971
1073
                                grp = getgr_nam_gid (optarg);
972
 
                                if (!grp) {
 
1074
                                if (NULL == grp) {
973
1075
                                        fprintf (stderr,
974
 
                                                 _
975
 
                                                 ("%s: unknown group %s\n"),
976
 
                                                 Prog, optarg);
 
1076
                                                 _("%s: group '%s' does not exist\n"),
 
1077
                                                 Prog, optarg);
977
1078
                                        exit (E_NOTFOUND);
978
1079
                                }
979
1080
                                if (Dflg) {
982
1083
                                } else {
983
1084
                                        user_gid = grp->gr_gid;
984
1085
                                }
985
 
                                gflg++;
 
1086
                                gflg = true;
986
1087
                                break;
987
1088
                        case 'G':
988
 
                                if (get_groups (optarg))
 
1089
                                if (get_groups (optarg) != 0) {
989
1090
                                        exit (E_NOTFOUND);
990
 
                                if (user_groups[0])
991
 
                                        do_grp_update++;
992
 
                                Gflg++;
 
1091
                                }
 
1092
                                if (NULL != user_groups[0]) {
 
1093
                                        do_grp_update = true;
 
1094
                                }
 
1095
                                Gflg = true;
993
1096
                                break;
994
1097
                        case 'h':
995
1098
                                usage ();
996
1099
                                break;
997
1100
                        case 'k':
998
1101
                                def_template = optarg;
999
 
                                kflg++;
 
1102
                                kflg = true;
1000
1103
                                break;
1001
1104
                        case 'K':
1002
1105
                                /*
1005
1108
                                 * note: -K UID_MIN=10,UID_MAX=499 doesn't work yet
1006
1109
                                 */
1007
1110
                                cp = strchr (optarg, '=');
1008
 
                                if (!cp) {
 
1111
                                if (NULL == cp) {
1009
1112
                                        fprintf (stderr,
1010
 
                                                 _
1011
 
                                                 ("%s: -K requires KEY=VALUE\n"),
1012
 
                                                 Prog);
 
1113
                                                 _("%s: -K requires KEY=VALUE\n"),
 
1114
                                                 Prog);
1013
1115
                                        exit (E_BAD_ARG);
1014
1116
                                }
1015
1117
                                /* terminate name, point to value */
1016
 
                                *cp++ = '\0';
1017
 
                                if (putdef_str (optarg, cp) < 0)
 
1118
                                *cp = '\0';
 
1119
                                cp++;
 
1120
                                if (putdef_str (optarg, cp) < 0) {
1018
1121
                                        exit (E_BAD_ARG);
 
1122
                                }
1019
1123
                                break;
1020
1124
                        case 'l':
1021
 
                                lflg++;
 
1125
                                lflg = true;
1022
1126
                                break;
1023
1127
                        case 'm':
1024
 
                                mflg++;
 
1128
                                mflg = true;
 
1129
                                break;
 
1130
                        case 'M':
 
1131
                                Mflg = true;
1025
1132
                                break;
1026
1133
                        case 'N':
1027
 
                                Nflg++;
 
1134
                                Nflg = true;
1028
1135
                                break;
1029
1136
                        case 'o':
1030
 
                                oflg++;
 
1137
                                oflg = true;
1031
1138
                                break;
1032
1139
                        case 'p':       /* set encrypted password */
1033
1140
                                if (!VALID (optarg)) {
1034
1141
                                        fprintf (stderr,
1035
 
                                                 _
1036
 
                                                 ("%s: invalid field '%s'\n"),
1037
 
                                                 Prog, optarg);
 
1142
                                                 _("%s: invalid field '%s'\n"),
 
1143
                                                 Prog, optarg);
1038
1144
                                        exit (E_BAD_ARG);
1039
1145
                                }
1040
1146
                                user_pass = optarg;
1041
1147
                                break;
1042
1148
                        case 'r':
1043
 
                                rflg++;
 
1149
                                rflg = true;
1044
1150
                                break;
1045
1151
                        case 's':
1046
 
                                if (!VALID (optarg)
1047
 
                                    || (optarg[0]
1048
 
                                        && (optarg[0] != '/'
1049
 
                                            && optarg[0] != '*'))) {
 
1152
                                if (   ( !VALID (optarg) )
 
1153
                                    || (   ('\0' != optarg[0])
 
1154
                                        && ('/'  != optarg[0])
 
1155
                                        && ('*'  != optarg[0]) )) {
1050
1156
                                        fprintf (stderr,
1051
 
                                                 _
1052
 
                                                 ("%s: invalid shell '%s'\n"),
1053
 
                                                 Prog, optarg);
 
1157
                                                 _("%s: invalid shell '%s'\n"),
 
1158
                                                 Prog, optarg);
1054
1159
                                        exit (E_BAD_ARG);
1055
1160
                                }
1056
1161
                                user_shell = optarg;
1057
1162
                                def_shell = optarg;
1058
 
                                sflg++;
 
1163
                                sflg = true;
1059
1164
                                break;
1060
1165
                        case 'u':
1061
 
                                user_id = get_uid (optarg);
1062
 
                                uflg++;
 
1166
                                if (   (get_uid (optarg, &user_id) == 0)
 
1167
                                    || (user_id == (gid_t)-1)) {
 
1168
                                        fprintf (stderr,
 
1169
                                                 _("%s: invalid user ID '%s'\n"),
 
1170
                                                 Prog, optarg);
 
1171
                                        exit (E_BAD_ARG);
 
1172
                                }
 
1173
                                uflg = true;
1063
1174
                                break;
1064
1175
                        case 'U':
1065
 
                                Uflg++;
1066
 
                                break;
 
1176
                                Uflg = true;
 
1177
                                break;
 
1178
#ifdef WITH_SELINUX
 
1179
                        case 'Z':
 
1180
                                if (is_selinux_enabled () > 0) {
 
1181
                                        user_selinux = optarg;
 
1182
                                        Zflg = true;
 
1183
                                } else {
 
1184
                                        fprintf (stderr,
 
1185
                                                 _("%s: -Z requires SELinux enabled kernel\n"),
 
1186
                                                 Prog);
 
1187
 
 
1188
                                        exit (E_BAD_ARG);
 
1189
                                }
 
1190
                                break;
 
1191
#endif
1067
1192
                        default:
1068
1193
                                usage ();
1069
1194
                        }
1070
 
                        anyflag++;
 
1195
                        anyflag = true;
1071
1196
                }
1072
1197
        }
1073
1198
 
1074
 
        if (!gflg && !Nflg && ! Uflg) {
 
1199
        if (!gflg && !Nflg && !Uflg) {
1075
1200
                /* Get the settings from login.defs */
1076
1201
                Uflg = getdef_bool ("USERGROUPS_ENAB");
1077
1202
        }
1082
1207
         */
1083
1208
        if (oflg && !uflg) {
1084
1209
                fprintf (stderr,
1085
 
                         _("%s: %s flag is ONLY allowed with the %s flag\n"),
 
1210
                         _("%s: %s flag is only allowed with the %s flag\n"),
1086
1211
                         Prog, "-o", "-u");
1087
1212
                usage ();
1088
1213
        }
1089
1214
        if (kflg && !mflg) {
1090
1215
                fprintf (stderr,
1091
 
                         _("%s: %s flag is ONLY allowed with the %s flag\n"),
 
1216
                         _("%s: %s flag is only allowed with the %s flag\n"),
1092
1217
                         Prog, "-k", "-m");
1093
1218
                usage ();
1094
1219
        }
1104
1229
                         Prog, "-U", "-N");
1105
1230
                usage ();
1106
1231
        }
 
1232
        if (mflg && Mflg) {
 
1233
                fprintf (stderr,
 
1234
                         _("%s: options %s and %s conflict\n"),
 
1235
                         Prog, "-m", "-M");
 
1236
                usage ();
 
1237
        }
1107
1238
 
1108
1239
        /*
1109
1240
         * Either -D or username is required. Defaults can be set with -D
1110
1241
         * for the -b, -e, -f, -g, -s options only.
1111
1242
         */
1112
1243
        if (Dflg) {
1113
 
                if (optind != argc)
 
1244
                if (optind != argc) {
1114
1245
                        usage ();
 
1246
                }
1115
1247
 
1116
 
                if (uflg || oflg || Gflg || dflg || cflg || mflg)
 
1248
                if (uflg || oflg || Gflg || dflg || cflg || mflg) {
1117
1249
                        usage ();
 
1250
                }
1118
1251
        } else {
1119
 
                if (optind != argc - 1)
 
1252
                if (optind != argc - 1) {
1120
1253
                        usage ();
 
1254
                }
1121
1255
 
1122
1256
                user_name = argv[optind];
1123
 
                if (!check_user_name (user_name)) {
 
1257
                if (!is_valid_user_name (user_name)) {
1124
1258
                        fprintf (stderr,
1125
 
                                 _
1126
 
                                 ("%s: invalid user name '%s'\n"),
1127
 
                                 Prog, user_name);
 
1259
                                 _("%s: invalid user name '%s'\n"),
 
1260
                                 Prog, user_name);
1128
1261
#ifdef WITH_AUDIT
1129
 
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user",
1130
 
                                      user_name, -1, 0);
 
1262
                        audit_logger (AUDIT_ADD_USER, Prog,
 
1263
                                      "adding user",
 
1264
                                      user_name, AUDIT_NO_ID,
 
1265
                                      SHADOW_AUDIT_FAILURE);
1131
1266
#endif
1132
1267
                        exit (E_BAD_ARG);
1133
1268
                }
1135
1270
                        char *uh;
1136
1271
 
1137
1272
                        uh = xmalloc (strlen (def_home) +
1138
 
                                      strlen (user_name) + 2);
 
1273
                                      strlen (user_name) + 2);
1139
1274
                        sprintf (uh, "%s/%s", def_home, user_name);
1140
1275
                        user_home = uh;
1141
1276
                }
1142
1277
        }
1143
1278
 
1144
 
        if (!eflg)
 
1279
        if (!eflg) {
1145
1280
                user_expire = strtoday (def_expire);
 
1281
        }
1146
1282
 
1147
 
        if (!gflg)
 
1283
        if (!gflg) {
1148
1284
                user_gid = def_group;
 
1285
        }
1149
1286
 
1150
 
        if (!sflg)
 
1287
        if (!sflg) {
1151
1288
                user_shell = def_shell;
 
1289
        }
1152
1290
 
1153
 
        /* TODO: add handle change default spool mail creation by 
1154
 
           -K CREATE_MAIL_SPOOL={yes,no}. It need rewrite internal API for handle
1155
 
           shadow tools configuration */
1156
1291
        create_mail_spool = def_create_mail_spool;
 
1292
 
 
1293
        if (!rflg) {
 
1294
                /* for system accounts defaults are ignored and we
 
1295
                 * do not create a home dir */
 
1296
                if (getdef_bool("CREATE_HOME")) {
 
1297
                        mflg = true;
 
1298
                }
 
1299
        }
 
1300
 
 
1301
        if (Mflg) {
 
1302
                /* absolutely sure that we do not create home dirs */
 
1303
                mflg = false;
 
1304
        }
1157
1305
}
1158
1306
 
1159
1307
/*
1164
1312
 */
1165
1313
static void close_files (void)
1166
1314
{
1167
 
        if (!pw_close ()) {
1168
 
                fprintf (stderr, _("%s: cannot rewrite password file\n"), Prog);
 
1315
        if (pw_close () == 0) {
 
1316
                fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
 
1317
                SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
1169
1318
                fail_exit (E_PW_UPDATE);
1170
1319
        }
1171
 
        if (is_shadow_pwd && !spw_close ()) {
 
1320
        if (is_shadow_pwd && (spw_close () == 0)) {
1172
1321
                fprintf (stderr,
1173
 
                         _("%s: cannot rewrite shadow password file\n"), Prog);
 
1322
                         _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ());
 
1323
                SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
1174
1324
                fail_exit (E_PW_UPDATE);
1175
1325
        }
1176
1326
        if (do_grp_update) {
1177
 
                if (!gr_close ()) {
 
1327
                if (gr_close () == 0) {
1178
1328
                        fprintf (stderr,
1179
 
                                 _("%s: cannot rewrite group file\n"), Prog);
 
1329
                                 _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ());
 
1330
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
1180
1331
                        fail_exit (E_GRP_UPDATE);
1181
1332
                }
1182
1333
#ifdef  SHADOWGRP
1183
 
                if (is_shadow_grp && !sgr_close ()) {
 
1334
                if (is_shadow_grp && (sgr_close () == 0)) {
1184
1335
                        fprintf (stderr,
1185
 
                                 _
1186
 
                                 ("%s: cannot rewrite shadow group file\n"),
1187
 
                                 Prog);
 
1336
                                 _("%s: failure while writing changes to %s\n"),
 
1337
                                 Prog, sgr_dbname ());
 
1338
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
1188
1339
                        fail_exit (E_GRP_UPDATE);
1189
1340
                }
1190
1341
#endif
1191
1342
        }
1192
1343
        if (is_shadow_pwd) {
1193
 
                spw_unlock ();
1194
 
                shadow_locked--;
1195
 
        }
1196
 
        pw_unlock ();
1197
 
        passwd_locked--;
1198
 
        gr_unlock ();
1199
 
        group_locked--;
 
1344
                if (spw_unlock () == 0) {
 
1345
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
 
1346
                        SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
 
1347
#ifdef WITH_AUDIT
 
1348
                        audit_logger (AUDIT_ADD_USER, Prog,
 
1349
                                      "unlocking shadow file",
 
1350
                                      user_name, AUDIT_NO_ID,
 
1351
                                      SHADOW_AUDIT_FAILURE);
 
1352
#endif
 
1353
                        /* continue */
 
1354
                }
 
1355
                spw_locked = false;
 
1356
        }
 
1357
        if (pw_unlock () == 0) {
 
1358
                fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
 
1359
                SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
 
1360
#ifdef WITH_AUDIT
 
1361
                audit_logger (AUDIT_ADD_USER, Prog,
 
1362
                              "unlocking passwd file",
 
1363
                              user_name, AUDIT_NO_ID,
 
1364
                              SHADOW_AUDIT_FAILURE);
 
1365
#endif
 
1366
                /* continue */
 
1367
        }
 
1368
        pw_locked = false;
 
1369
        if (gr_unlock () == 0) {
 
1370
                fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
 
1371
                SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
 
1372
#ifdef WITH_AUDIT
 
1373
                audit_logger (AUDIT_ADD_USER, Prog,
 
1374
                              "unlocking group file",
 
1375
                              user_name, AUDIT_NO_ID,
 
1376
                              SHADOW_AUDIT_FAILURE);
 
1377
#endif
 
1378
                /* continue */
 
1379
        }
 
1380
        gr_locked = false;
1200
1381
#ifdef  SHADOWGRP
1201
1382
        if (is_shadow_grp) {
1202
 
                sgr_unlock ();
1203
 
                gshadow_locked--;
 
1383
                if (sgr_unlock () == 0) {
 
1384
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
 
1385
                        SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
 
1386
#ifdef WITH_AUDIT
 
1387
                        audit_logger (AUDIT_ADD_USER, Prog,
 
1388
                                      "unlocking gshadow file",
 
1389
                                      user_name, AUDIT_NO_ID,
 
1390
                                      SHADOW_AUDIT_FAILURE);
 
1391
#endif
 
1392
                        /* continue */
 
1393
                }
 
1394
                sgr_locked = false;
1204
1395
        }
1205
1396
#endif
1206
1397
}
1212
1403
 */
1213
1404
static void open_files (void)
1214
1405
{
1215
 
        if (!pw_lock ()) {
1216
 
                fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
1217
 
#ifdef WITH_AUDIT
1218
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1219
 
                              "locking password file", user_name, user_id, 0);
1220
 
#endif
 
1406
        if (pw_lock () == 0) {
 
1407
                fprintf (stderr,
 
1408
                         _("%s: cannot lock %s; try again later.\n"),
 
1409
                         Prog, pw_dbname ());
1221
1410
                exit (E_PW_UPDATE);
1222
1411
        }
1223
 
        passwd_locked++;
1224
 
        if (!pw_open (O_RDWR)) {
1225
 
                fprintf (stderr, _("%s: unable to open password file\n"), Prog);
1226
 
#ifdef WITH_AUDIT
1227
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1228
 
                              "opening password file", user_name, user_id, 0);
1229
 
#endif
 
1412
        pw_locked = true;
 
1413
        if (pw_open (O_RDWR) == 0) {
 
1414
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
1230
1415
                fail_exit (E_PW_UPDATE);
1231
1416
        }
1232
1417
        if (is_shadow_pwd) {
1233
 
                if (!spw_lock ()) {
 
1418
                if (spw_lock () == 0) {
1234
1419
                        fprintf (stderr,
1235
 
                                 _("%s: cannot lock shadow password file\n"),
1236
 
                                 Prog);
1237
 
#ifdef WITH_AUDIT
1238
 
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1239
 
                                      "locking shadow password file", user_name,
1240
 
                                      user_id, 0);
1241
 
#endif
 
1420
                                 _("%s: cannot lock %s; try again later.\n"),
 
1421
                                 Prog, spw_dbname ());
1242
1422
                        fail_exit (E_PW_UPDATE);
1243
1423
                }
1244
 
                shadow_locked++;
1245
 
                if (!spw_open (O_RDWR)) {
 
1424
                spw_locked = true;
 
1425
                if (spw_open (O_RDWR) == 0) {
1246
1426
                        fprintf (stderr,
1247
 
                                 _("%s: cannot open shadow password file\n"),
1248
 
                                 Prog);
1249
 
#ifdef WITH_AUDIT
1250
 
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1251
 
                                      "opening shadow password file", user_name,
1252
 
                                      user_id, 0);
1253
 
#endif
 
1427
                                 _("%s: cannot open %s\n"),
 
1428
                                 Prog, spw_dbname ());
1254
1429
                        fail_exit (E_PW_UPDATE);
1255
1430
                }
1256
1431
        }
1258
1433
        /*
1259
1434
         * Lock and open the group file.
1260
1435
         */
1261
 
        if (!gr_lock ()) {
1262
 
                fprintf (stderr, _("%s: error locking group file\n"), Prog);
 
1436
        if (gr_lock () == 0) {
 
1437
                fprintf (stderr,
 
1438
                         _("%s: cannot lock %s; try again later.\n"),
 
1439
                         Prog, gr_dbname ());
1263
1440
                fail_exit (E_GRP_UPDATE);
1264
1441
        }
1265
 
        group_locked++;
1266
 
        if (!gr_open (O_RDWR)) {
1267
 
                fprintf (stderr, _("%s: error opening group file\n"), Prog);
 
1442
        gr_locked = true;
 
1443
        if (gr_open (O_RDWR) == 0) {
 
1444
                fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
1268
1445
                fail_exit (E_GRP_UPDATE);
1269
1446
        }
1270
1447
#ifdef  SHADOWGRP
1271
1448
        if (is_shadow_grp) {
1272
 
                if (!sgr_lock ()) {
 
1449
                if (sgr_lock () == 0) {
1273
1450
                        fprintf (stderr,
1274
 
                                 _("%s: error locking shadow group file\n"),
1275
 
                                 Prog);
 
1451
                                 _("%s: cannot lock %s; try again later.\n"),
 
1452
                                 Prog, sgr_dbname ());
1276
1453
                        fail_exit (E_GRP_UPDATE);
1277
1454
                }
1278
 
                gshadow_locked++;
1279
 
                if (!sgr_open (O_RDWR)) {
 
1455
                sgr_locked = true;
 
1456
                if (sgr_open (O_RDWR) == 0) {
1280
1457
                        fprintf (stderr,
1281
 
                                 _("%s: error opening shadow group file\n"),
1282
 
                                 Prog);
 
1458
                                 _("%s: cannot open %s\n"),
 
1459
                                 Prog, sgr_dbname ());
1283
1460
                        fail_exit (E_GRP_UPDATE);
1284
1461
                }
1285
1462
        }
1348
1525
        /*
1349
1526
         * Write out the new group file entry.
1350
1527
         */
1351
 
        if (!gr_update (&grp)) {
1352
 
                fprintf (stderr, _("%s: error adding new group entry\n"), Prog);
 
1528
        if (gr_update (&grp) == 0) {
 
1529
                fprintf (stderr,
 
1530
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
1531
                         Prog, gr_dbname (), grp.gr_name);
 
1532
#ifdef WITH_AUDIT
 
1533
                audit_logger (AUDIT_ADD_GROUP, Prog,
 
1534
                              "adding group",
 
1535
                              grp.gr_name, AUDIT_NO_ID,
 
1536
                              SHADOW_AUDIT_FAILURE);
 
1537
#endif
1353
1538
                fail_exit (E_GRP_UPDATE);
1354
1539
        }
1355
1540
#ifdef  SHADOWGRP
1356
1541
        /*
1357
1542
         * Write out the new shadow group entries as well.
1358
1543
         */
1359
 
        if (is_shadow_grp && !sgr_update (&sgrp)) {
1360
 
                fprintf (stderr, _("%s: error adding new group entry\n"), Prog);
 
1544
        if (is_shadow_grp && (sgr_update (&sgrp) == 0)) {
 
1545
                fprintf (stderr,
 
1546
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
1547
                         Prog, sgr_dbname (), sgrp.sg_name);
 
1548
#ifdef WITH_AUDIT
 
1549
                audit_logger (AUDIT_ADD_GROUP, Prog,
 
1550
                              "adding group",
 
1551
                              grp.gr_name, AUDIT_NO_ID,
 
1552
                              SHADOW_AUDIT_FAILURE);
 
1553
#endif
1361
1554
                fail_exit (E_GRP_UPDATE);
1362
1555
        }
1363
1556
#endif                          /* SHADOWGRP */
1364
1557
        SYSLOG ((LOG_INFO, "new group: name=%s, GID=%u", user_name, user_gid));
1365
 
        do_grp_update++;
 
1558
#ifdef WITH_AUDIT
 
1559
        audit_logger (AUDIT_ADD_GROUP, Prog,
 
1560
                      "adding group",
 
1561
                      grp.gr_name, AUDIT_NO_ID,
 
1562
                      SHADOW_AUDIT_SUCCESS);
 
1563
#endif
 
1564
        do_grp_update = true;
1366
1565
}
1367
1566
 
1368
1567
static void faillog_reset (uid_t uid)
1369
1568
{
1370
1569
        struct faillog fl;
1371
1570
        int fd;
 
1571
        off_t offset_uid = (off_t) (sizeof fl) * uid;
 
1572
 
 
1573
        if (access (FAILLOG_FILE, F_OK) != 0) {
 
1574
                return;
 
1575
        }
 
1576
 
 
1577
        memzero (&fl, sizeof (fl));
1372
1578
 
1373
1579
        fd = open (FAILLOG_FILE, O_RDWR);
1374
 
        if (fd >= 0) {
1375
 
                memzero (&fl, sizeof (fl));
1376
 
                lseek (fd, (off_t) sizeof (fl) * uid, SEEK_SET);
1377
 
                write (fd, &fl, sizeof (fl));
1378
 
                close (fd);
 
1580
        if (   (-1 == fd)
 
1581
            || (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
 
1582
            || (write (fd, &fl, sizeof (fl)) != (ssize_t) sizeof (fl))
 
1583
            || (fsync (fd) != 0)
 
1584
            || (close (fd) != 0)) {
 
1585
                fprintf (stderr,
 
1586
                         _("%s: failed to reset the faillog entry of UID %lu: %s\n"),
 
1587
                         Prog, (unsigned long) uid, strerror (errno));
 
1588
                SYSLOG ((LOG_WARN, "failed to reset the faillog entry of UID %lu", (unsigned long) uid));
 
1589
                /* continue */
1379
1590
        }
1380
1591
}
1381
1592
 
1383
1594
{
1384
1595
        struct lastlog ll;
1385
1596
        int fd;
 
1597
        off_t offset_uid = (off_t) (sizeof ll) * uid;
 
1598
 
 
1599
        if (access (LASTLOG_FILE, F_OK) != 0) {
 
1600
                return;
 
1601
        }
 
1602
 
 
1603
        memzero (&ll, sizeof (ll));
1386
1604
 
1387
1605
        fd = open (LASTLOG_FILE, O_RDWR);
1388
 
        if (fd >= 0) {
1389
 
                memzero (&ll, sizeof (ll));
1390
 
                lseek (fd, (off_t) sizeof (ll) * uid, SEEK_SET);
1391
 
                write (fd, &ll, sizeof (ll));
1392
 
                close (fd);
 
1606
        if (   (-1 == fd)
 
1607
            || (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
 
1608
            || (write (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
 
1609
            || (fsync (fd) != 0)
 
1610
            || (close (fd) != 0)) {
 
1611
                fprintf (stderr,
 
1612
                         _("%s: failed to reset the lastlog entry of UID %lu: %s\n"),
 
1613
                         Prog, (unsigned long) uid, strerror (errno));
 
1614
                SYSLOG ((LOG_WARN, "failed to reset the lastlog entry of UID %lu", (unsigned long) uid));
 
1615
                /* continue */
1393
1616
        }
1394
1617
}
1395
1618
 
1416
1639
         * happens so we know what we were trying to accomplish.
1417
1640
         */
1418
1641
        SYSLOG ((LOG_INFO,
1419
 
                 "new user: name=%s, UID=%u, GID=%u, home=%s, shell=%s",
1420
 
                 user_name, (unsigned int) user_id,
1421
 
                 (unsigned int) user_gid, user_home, user_shell));
 
1642
                 "new user: name=%s, UID=%u, GID=%u, home=%s, shell=%s",
 
1643
                 user_name, (unsigned int) user_id,
 
1644
                 (unsigned int) user_gid, user_home, user_shell));
1422
1645
 
1423
1646
        /*
1424
1647
         * Initialize faillog and lastlog entries for this UID in case
1435
1658
        /*
1436
1659
         * Put the new (struct passwd) in the table.
1437
1660
         */
1438
 
        if (!pw_update (&pwent)) {
 
1661
        if (pw_update (&pwent) == 0) {
1439
1662
                fprintf (stderr,
1440
 
                         _("%s: error adding new password entry\n"), Prog);
 
1663
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
1664
                         Prog, pw_dbname (), pwent.pw_name);
1441
1665
                fail_exit (E_PW_UPDATE);
1442
1666
        }
1443
1667
 
1444
1668
        /*
1445
1669
         * Put the new (struct spwd) in the table.
1446
1670
         */
1447
 
        if (is_shadow_pwd && !spw_update (&spent)) {
 
1671
        if (is_shadow_pwd && (spw_update (&spent) == 0)) {
1448
1672
                fprintf (stderr,
1449
 
                         _
1450
 
                         ("%s: error adding new shadow password entry\n"),
1451
 
                         Prog);
 
1673
                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
1674
                         Prog, spw_dbname (), spent.sp_namp);
1452
1675
#ifdef WITH_AUDIT
1453
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1454
 
                              "adding shadow password", user_name, user_id, 0);
 
1676
                audit_logger (AUDIT_ADD_USER, Prog,
 
1677
                              "adding shadow password",
 
1678
                              user_name, (unsigned int) user_id,
 
1679
                              SHADOW_AUDIT_FAILURE);
1455
1680
#endif
1456
1681
                fail_exit (E_PW_UPDATE);
1457
1682
        }
1458
1683
#ifdef WITH_AUDIT
1459
 
        audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user", user_name,
1460
 
                      user_id, 1);
 
1684
        audit_logger (AUDIT_ADD_USER, Prog,
 
1685
                      "adding user",
 
1686
                      user_name, (unsigned int) user_id,
 
1687
                      SHADOW_AUDIT_SUCCESS);
1461
1688
#endif
1462
1689
 
1463
1690
        /*
1464
1691
         * Do any group file updates for this user.
1465
1692
         */
1466
 
        if (do_grp_update)
 
1693
        if (do_grp_update) {
1467
1694
                grp_update ();
1468
 
}
1469
 
 
 
1695
        }
 
1696
}
 
1697
 
 
1698
#ifdef WITH_SELINUX
 
1699
static void selinux_update_mapping (void) {
 
1700
        if (is_selinux_enabled () <= 0) return;
 
1701
 
 
1702
        if (*user_selinux) { /* must be done after passwd write() */
 
1703
                const char *argv[7];
 
1704
                argv[0] = "/usr/sbin/semanage";
 
1705
                argv[1] = "login";
 
1706
                argv[2] = "-a";
 
1707
                argv[3] = "-s";
 
1708
                argv[4] = user_selinux;
 
1709
                argv[5] = user_name;
 
1710
                argv[6] = NULL;
 
1711
                if (safe_system (argv[0], argv, NULL, 0)) {
 
1712
                        fprintf (stderr,
 
1713
                                 _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
 
1714
                                 Prog, user_name, user_selinux);
 
1715
#ifdef WITH_AUDIT
 
1716
                        audit_logger (AUDIT_ADD_USER, Prog,
 
1717
                                      "adding SELinux user mapping",
 
1718
                                      user_name, (unsigned int) user_id, 0);
 
1719
#endif
 
1720
                }
 
1721
        }
 
1722
}
 
1723
#endif
1470
1724
/*
1471
1725
 * create_home - create the user's home directory
1472
1726
 *
1476
1730
 */
1477
1731
static void create_home (void)
1478
1732
{
1479
 
        if (access (user_home, F_OK)) {
 
1733
        if (access (user_home, F_OK) != 0) {
 
1734
#ifdef WITH_SELINUX
 
1735
                selinux_file_context (user_home);
 
1736
#endif
1480
1737
                /* XXX - create missing parent directories.  --marekm */
1481
 
                if (mkdir (user_home, 0)) {
 
1738
                if (mkdir (user_home, 0) != 0) {
1482
1739
                        fprintf (stderr,
1483
 
                                 _
1484
 
                                 ("%s: cannot create directory %s\n"),
1485
 
                                 Prog, user_home);
 
1740
                                 _("%s: cannot create directory %s\n"),
 
1741
                                 Prog, user_home);
1486
1742
#ifdef WITH_AUDIT
1487
 
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1488
 
                                      "adding home directory", user_name,
1489
 
                                      user_id, 0);
 
1743
                        audit_logger (AUDIT_ADD_USER, Prog,
 
1744
                                      "adding home directory",
 
1745
                                      user_name, (unsigned int) user_id,
 
1746
                                      SHADOW_AUDIT_FAILURE);
1490
1747
#endif
1491
1748
                        fail_exit (E_HOMEDIR);
1492
1749
                }
1493
1750
                chown (user_home, user_id, user_gid);
1494
1751
                chmod (user_home,
1495
1752
                       0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
1496
 
                home_added++;
 
1753
                home_added = true;
1497
1754
#ifdef WITH_AUDIT
1498
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1499
 
                              "adding home directory", user_name, user_id, 1);
 
1755
                audit_logger (AUDIT_ADD_USER, Prog,
 
1756
                              "adding home directory",
 
1757
                              user_name, (unsigned int) user_id,
 
1758
                              SHADOW_AUDIT_SUCCESS);
 
1759
#endif
 
1760
#ifdef WITH_SELINUX
 
1761
                /* Reset SELinux to create files with default contexts */
 
1762
                setfscreatecon (NULL);
1500
1763
#endif
1501
1764
        }
1502
1765
}
1530
1793
                }
1531
1794
 
1532
1795
                gr = getgrnam ("mail"); /* local, no need for xgetgrnam */
1533
 
                if (!gr) {
 
1796
                if (NULL == gr) {
1534
1797
                        fputs (_("Group 'mail' not found. Creating the user mailbox file with 0600 mode.\n"),
1535
1798
                               stderr);
1536
1799
                        gid = user_gid;
1540
1803
                        mode = 0660;
1541
1804
                }
1542
1805
 
1543
 
                if (fchown (fd, user_id, gid) || fchmod (fd, mode))
 
1806
                if (   (fchown (fd, user_id, gid) != 0)
 
1807
                    || (fchmod (fd, mode) != 0)) {
1544
1808
                        perror (_("Setting mailbox file permissions"));
 
1809
                }
1545
1810
 
 
1811
                fsync (fd);
1546
1812
                close (fd);
1547
1813
        }
1548
1814
}
1552
1818
 */
1553
1819
int main (int argc, char **argv)
1554
1820
{
 
1821
#ifdef ACCT_TOOLS_SETUID
1555
1822
#ifdef USE_PAM
1556
1823
        pam_handle_t *pamh = NULL;
1557
1824
        int retval;
1558
 
#endif
 
1825
#endif                          /* USE_PAM */
 
1826
#endif                          /* ACCT_TOOLS_SETUID */
1559
1827
 
1560
1828
#ifdef WITH_AUDIT
1561
1829
        audit_help_open ();
1566
1834
         */
1567
1835
        Prog = Basename (argv[0]);
1568
1836
 
1569
 
        setlocale (LC_ALL, "");
1570
 
        bindtextdomain (PACKAGE, LOCALEDIR);
1571
 
        textdomain (PACKAGE);
 
1837
        (void) setlocale (LC_ALL, "");
 
1838
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
 
1839
        (void) textdomain (PACKAGE);
1572
1840
 
1573
1841
        OPENLOG ("useradd");
1574
1842
 
1589
1857
 
1590
1858
        process_flags (argc, argv);
1591
1859
 
 
1860
#ifdef ACCT_TOOLS_SETUID
1592
1861
#ifdef USE_PAM
1593
 
        retval = PAM_SUCCESS;
1594
 
 
1595
1862
        {
1596
1863
                struct passwd *pampw;
1597
1864
                pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
1598
1865
                if (pampw == NULL) {
1599
 
                        retval = PAM_USER_UNKNOWN;
 
1866
                        fprintf (stderr,
 
1867
                                 _("%s: Cannot determine your user name.\n"),
 
1868
                                 Prog);
 
1869
                        fail_exit (1);
1600
1870
                }
1601
1871
 
1602
 
                if (retval == PAM_SUCCESS) {
1603
 
                        retval = pam_start ("useradd", pampw->pw_name,
1604
 
                                            &conv, &pamh);
1605
 
                }
 
1872
                retval = pam_start ("useradd", pampw->pw_name, &conv, &pamh);
1606
1873
        }
1607
1874
 
1608
 
        if (retval == PAM_SUCCESS) {
 
1875
        if (PAM_SUCCESS == retval) {
1609
1876
                retval = pam_authenticate (pamh, 0);
1610
 
                if (retval != PAM_SUCCESS) {
1611
 
                        pam_end (pamh, retval);
1612
 
                }
1613
1877
        }
1614
1878
 
1615
 
        if (retval == PAM_SUCCESS) {
 
1879
        if (PAM_SUCCESS == retval) {
1616
1880
                retval = pam_acct_mgmt (pamh, 0);
1617
 
                if (retval != PAM_SUCCESS) {
1618
 
                        pam_end (pamh, retval);
1619
 
                }
1620
1881
        }
1621
1882
 
1622
 
        if (retval != PAM_SUCCESS) {
 
1883
        if (NULL != pamh) {
 
1884
                (void) pam_end (pamh, retval);
 
1885
        }
 
1886
        if (PAM_SUCCESS != retval) {
1623
1887
                fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
1624
1888
                fail_exit (1);
1625
1889
        }
1626
1890
#endif                          /* USE_PAM */
 
1891
#endif                          /* ACCT_TOOLS_SETUID */
1627
1892
 
1628
1893
        /*
1629
1894
         * See if we are messing with the defaults file, or creating
1630
1895
         * a new user.
1631
1896
         */
1632
1897
        if (Dflg) {
1633
 
                if (gflg || bflg || fflg || eflg || sflg)
1634
 
                        exit (set_defaults ()? 1 : 0);
 
1898
                if (gflg || bflg || fflg || eflg || sflg) {
 
1899
                        exit ((set_defaults () != 0) ? 1 : 0);
 
1900
                }
1635
1901
 
1636
1902
                show_defaults ();
1637
1903
                exit (E_SUCCESS);
1640
1906
        /*
1641
1907
         * Start with a quick check to see if the user exists.
1642
1908
         */
1643
 
        if (getpwnam (user_name)) { /* local, no need for xgetpwnam */
1644
 
                fprintf (stderr, _("%s: user %s exists\n"), Prog, user_name);
 
1909
        if (getpwnam (user_name) != NULL) { /* local, no need for xgetpwnam */
 
1910
                fprintf (stderr, _("%s: user '%s' already exists\n"), Prog, user_name);
1645
1911
#ifdef WITH_AUDIT
1646
 
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user",
1647
 
                              user_name, -1, 0);
 
1912
                audit_logger (AUDIT_ADD_USER, Prog,
 
1913
                              "adding user",
 
1914
                              user_name, AUDIT_NO_ID,
 
1915
                              SHADOW_AUDIT_FAILURE);
1648
1916
#endif
1649
1917
                fail_exit (E_NAME_IN_USE);
1650
1918
        }
1656
1924
         * --bero
1657
1925
         */
1658
1926
        if (Uflg) {
1659
 
                if (getgrnam (user_name)) { /* local, no need for xgetgrnam */
 
1927
                /* local, no need for xgetgrnam */
 
1928
                if (getgrnam (user_name) != NULL) {
1660
1929
                        fprintf (stderr,
1661
 
                                 _
1662
 
                                 ("%s: group %s exists - if you want to add this user to that group, use -g.\n"),
1663
 
                                 Prog, user_name);
 
1930
                                 _("%s: group %s exists - if you want to add this user to that group, use -g.\n"),
 
1931
                                 Prog, user_name);
1664
1932
#ifdef WITH_AUDIT
1665
 
                        audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
1666
 
                                      "adding group", user_name, -1, 0);
 
1933
                        audit_logger (AUDIT_ADD_USER, Prog,
 
1934
                                      "adding group",
 
1935
                                      user_name, AUDIT_NO_ID,
 
1936
                                      SHADOW_AUDIT_FAILURE);
1667
1937
#endif
1668
1938
                        fail_exit (E_NAME_IN_USE);
1669
1939
                }
1691
1961
                        }
1692
1962
                } else {
1693
1963
                        if (getpwuid (user_id) != NULL) {
1694
 
                                fprintf (stderr, _("%s: UID %u is not unique\n"), Prog, (unsigned int) user_id);
 
1964
                                fprintf (stderr,
 
1965
                                         _("%s: UID %lu is not unique\n"),
 
1966
                                         Prog, (unsigned long) user_id);
1695
1967
#ifdef WITH_AUDIT
1696
 
                                audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "adding user", user_name, user_id, 0);
 
1968
                                audit_logger (AUDIT_ADD_USER, Prog,
 
1969
                                              "adding user",
 
1970
                                              user_name, (unsigned int) user_id,
 
1971
                                              SHADOW_AUDIT_FAILURE);
1697
1972
#endif
1698
1973
                                fail_exit (E_UID_IN_USE);
1699
1974
                        }
1705
1980
        if (Uflg) {
1706
1981
                if (find_new_gid (rflg, &user_gid, &user_id) < 0) {
1707
1982
                        fprintf (stderr,
1708
 
                                 _("%s: can't create group\n"),
1709
 
                                 Prog);
 
1983
                                 _("%s: can't create group\n"),
 
1984
                                 Prog);
1710
1985
                        fail_exit (4);
1711
1986
                }
1712
1987
                grp_add ();
1716
1991
 
1717
1992
        if (mflg) {
1718
1993
                create_home ();
1719
 
                if (home_added)
 
1994
                if (home_added) {
1720
1995
                        copy_tree (def_template, user_home, user_id, user_gid);
1721
 
                else
 
1996
                } else {
1722
1997
                        fprintf (stderr,
1723
 
                                 _
1724
 
                                 ("%s: warning: the home directory already exists.\n"
1725
 
                                  "Not copying any file from skel directory into it.\n"),
1726
 
                                 Prog);
1727
 
 
1728
 
        } else if (getdef_str ("CREATE_HOME")) {
1729
 
                /*
1730
 
                 * RedHat added the CREATE_HOME option in login.defs in their
1731
 
                 * version of shadow-utils (which makes -m the default, with
1732
 
                 * new -M option to turn it off). Unfortunately, this
1733
 
                 * changes the way useradd works (it can be run by scripts
1734
 
                 * expecting some standard behaviour), compared to other
1735
 
                 * Unices and other Linux distributions, and also adds a lot
1736
 
                 * of confusion :-(.
1737
 
                 * So we now recognize CREATE_HOME and give a warning here
1738
 
                 * (better than "configuration error ... notify administrator"
1739
 
                 * errors in every program that reads /etc/login.defs). -MM
1740
 
                 */
1741
 
                fprintf (stderr,
1742
 
                         _
1743
 
                         ("%s: warning: CREATE_HOME not supported, please use -m instead.\n"),
1744
 
                         Prog);
1745
 
        }
1746
 
 
1747
 
        create_mail ();
 
1998
                                 _("%s: warning: the home directory already exists.\n"
 
1999
                                   "Not copying any file from skel directory into it.\n"),
 
2000
                                 Prog);
 
2001
                }
 
2002
 
 
2003
        }
 
2004
 
 
2005
        /* Do not create mail directory for system accounts */
 
2006
        if( !rflg ) {
 
2007
                create_mail ();
 
2008
        }
1748
2009
 
1749
2010
        close_files ();
1750
2011
 
 
2012
#ifdef WITH_SELINUX
 
2013
        selinux_update_mapping ();
 
2014
#endif
 
2015
 
1751
2016
        nscd_flush_cache ("passwd");
1752
2017
        nscd_flush_cache ("group");
1753
2018
 
1754
 
#ifdef USE_PAM
1755
 
        if (retval == PAM_SUCCESS)
1756
 
                pam_end (pamh, PAM_SUCCESS);
1757
 
#endif                          /* USE_PAM */
1758
 
 
1759
2019
        return E_SUCCESS;
1760
2020
}
 
2021