2
* Copyright 1992 - 1994, Julianne Frances Haugh
2
* Copyright (c) 1992 - 1994, Julianne Frances Haugh
3
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
4
* Copyright (c) 2001 , Michał Moskal
5
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
6
* Copyright (c) 2007 - 2009, Nicolas François
3
7
* All rights reserved.
5
9
* Redistribution and use in source and binary forms, with or without
10
14
* 2. Redistributions in binary form must reproduce the above copyright
11
15
* notice, this list of conditions and the following disclaimer in the
12
16
* 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.
17
* 3. The name of the copyright holders or contributors may not be used to
18
* endorse or promote products derived from this software without
19
* specific prior written permission.
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
21
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
34
#include <config.h>
32
#ident "$Id: pwck.c 1751 2008-02-03 16:28:03Z nekral-guest $"
36
#ident "$Id: pwck.c 2587 2009-04-05 21:23:27Z nekral-guest $"
54
58
#define E_CANTOPEN 3
55
59
#define E_CANTLOCK 4
56
60
#define E_CANTUPDATE 5
63
68
static const char *pwd_file = PASSWD_FILE;
64
static int use_system_pw_file = 1;
69
static bool use_system_pw_file = true;
65
70
static const char *spw_file = SHADOW_FILE;
66
static int use_system_spw_file = 1;
68
static int is_shadow = 0;
71
static bool use_system_spw_file = true;
73
static bool is_shadow = false;
75
static bool pw_locked = false;
76
static bool spw_locked = false;
71
static int read_only = 0;
72
static int sort_mode = 0;
73
static int quiet = 0; /* don't report warnings, only errors */
79
static bool read_only = false;
80
static bool sort_mode = false;
81
static bool quiet = false; /* don't report warnings, only errors */
75
83
/* local function prototypes */
84
static void fail_exit (int code);
76
85
static void usage (void);
77
86
static void process_flags (int argc, char **argv);
78
87
static void open_files (void);
79
static void close_files (int changed);
80
static void check_pw_file (int *errors, int *changed);
81
static void check_spw_file (int *errors, int *changed);
88
static void close_files (bool changed);
89
static void check_pw_file (int *errors, bool *changed);
90
static void check_spw_file (int *errors, bool *changed);
93
* fail_exit - do some cleanup and exit with the given error code
95
static void fail_exit (int code)
98
if (spw_unlock () == 0) {
99
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
100
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
106
if (pw_unlock () == 0) {
107
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
108
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
84
118
* usage - print syntax message and exit
138
172
if (optind != argc) {
139
173
pwd_file = argv[optind];
141
use_system_pw_file = 0;
174
pw_setdbname (pwd_file);
175
use_system_pw_file = false;
143
177
if ((optind + 2) == argc) {
144
178
spw_file = argv[optind + 1];
147
use_system_spw_file = 0;
179
spw_setdbname (spw_file);
181
use_system_spw_file = false;
148
182
} else if (optind == argc) {
149
183
is_shadow = spw_file_present ();
164
198
if (!read_only) {
165
199
if (pw_lock () == 0) {
166
fprintf (stderr, _("%s: cannot lock file %s\n"),
201
_("%s: cannot lock %s; try again later.\n"),
168
if (use_system_pw_file) {
169
SYSLOG ((LOG_WARN, "cannot lock %s", pwd_file));
203
fail_exit (E_CANTLOCK);
174
if (is_shadow && (spw_lock () == 0)) {
175
fprintf (stderr, _("%s: cannot lock file %s\n"),
177
if (use_system_spw_file) {
178
SYSLOG ((LOG_WARN, "cannot lock %s", spw_file));
207
if (spw_lock () == 0) {
209
_("%s: cannot lock %s; try again later.\n"),
211
fail_exit (E_CANTLOCK);
189
221
if (pw_open (read_only ? O_RDONLY : O_RDWR) == 0) {
190
fprintf (stderr, _("%s: cannot open file %s\n"),
222
fprintf (stderr, _("%s: cannot open %s\n"),
192
224
if (use_system_pw_file) {
193
225
SYSLOG ((LOG_WARN, "cannot open %s", pwd_file));
227
fail_exit (E_CANTOPEN);
198
229
if (is_shadow && (spw_open (read_only ? O_RDONLY : O_RDWR) == 0)) {
199
fprintf (stderr, _("%s: cannot open file %s\n"),
230
fprintf (stderr, _("%s: cannot open %s\n"),
201
232
if (use_system_spw_file) {
202
233
SYSLOG ((LOG_WARN, "cannot open %s", spw_file));
235
fail_exit (E_CANTOPEN);
223
253
if (pw_close () == 0) {
224
fprintf (stderr, _("%s: cannot update file %s\n"),
254
fprintf (stderr, _("%s: failure while writing changes to %s\n"),
226
SYSLOG ((LOG_WARN, "cannot update %s", pwd_file));
256
SYSLOG ((LOG_ERR, "failure while writing changes to %s", pwd_file));
257
fail_exit (E_CANTUPDATE);
230
259
if (is_shadow && (spw_close () == 0)) {
231
fprintf (stderr, _("%s: cannot update file %s\n"),
260
fprintf (stderr, _("%s: failure while writing changes to %s\n"),
233
SYSLOG ((LOG_WARN, "cannot update %s", spw_file));
262
SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_file));
263
fail_exit (E_CANTUPDATE);
240
268
* Don't be anti-social - unlock the files when you're done.
271
if (spw_unlock () == 0) {
272
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
273
SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
279
if (pw_unlock () == 0) {
280
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
281
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
249
289
* check_pw_file - check the content of the passwd file
251
static void check_pw_file (int *errors, int *changed)
291
static void check_pw_file (int *errors, bool *changed)
253
293
struct commonio_entry *pfe, *tpfe;
254
294
struct passwd *pwd;
351
391
* Check for invalid usernames. --marekm
353
if (!check_user_name (pwd->pw_name)) {
393
if (!is_valid_user_name (pwd->pw_name)) {
354
394
printf (_("invalid user name '%s'\n"), pwd->pw_name);
399
* Check for invalid user ID.
401
if (pwd->pw_uid == (uid_t)-1) {
402
printf (_("invalid user ID '%lu'\n"), (long unsigned int)pwd->pw_uid);
359
407
* Make sure the primary group exists
361
409
/* local, no need for xgetgrgid */
365
413
* No primary group, just give a warning
368
printf (_("user %s: no group %u\n"),
369
pwd->pw_name, pwd->pw_gid);
416
printf (_("user '%s': no group %lu\n"),
417
pwd->pw_name, (unsigned long) pwd->pw_gid);
414
462
struct passwd pw;
416
sp.sp_namp = pwd->pw_name;
417
sp.sp_pwdp = pwd->pw_passwd;
464
sp.sp_namp = pwd->pw_name;
465
sp.sp_pwdp = pwd->pw_passwd;
419
467
getdef_num ("PASS_MIN_DAYS", -1);
421
469
getdef_num ("PASS_MAX_DAYS", -1);
423
471
getdef_num ("PASS_WARN_AGE", -1);
425
473
sp.sp_expire = -1;
428
time ((time_t *) 0) / (24L * 3600L);
474
sp.sp_flag = SHADOW_SP_FLAG_UNSET;
475
sp.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
476
if (0 == sp.sp_lstchg) {
477
/* Better disable aging than
478
* requiring a password change
431
484
if (spw_update (&sp) == 0) {
433
_("%s: can't update shadow entry for %s\n"),
486
_("%s: failed to prepare the new %s entry '%s'\n"),
487
Prog, spw_dbname (), sp.sp_namp);
435
488
exit (E_CANTUPDATE);
437
490
/* remove password from /etc/passwd */
439
492
pw.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */
440
493
if (pw_update (&pw) == 0) {
442
_("%s: can't update passwd entry for %s\n"),
495
_("%s: failed to prepare the new %s entry '%s'\n"),
496
Prog, pw_dbname (), pw.pw_name);
444
497
exit (E_CANTUPDATE);
598
651
int main (int argc, char **argv)
654
bool changed = false;
604
657
* Get my name so that I can use it to report errors.
606
659
Prog = Basename (argv[0]);
608
setlocale (LC_ALL, "");
609
bindtextdomain (PACKAGE, LOCALEDIR);
610
textdomain (PACKAGE);
661
(void) setlocale (LC_ALL, "");
662
(void) bindtextdomain (PACKAGE, LOCALEDIR);
663
(void) textdomain (PACKAGE);
612
665
OPENLOG ("pwck");