2
* Copyright 1989 - 1994, Julianne Frances Haugh
2
* Copyright (c) 1989 - 1994, Julianne Frances Haugh
3
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
4
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
5
* Copyright (c) 2007 - 2008, Nicolas François
3
6
* All rights reserved.
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.
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
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.
30
33
#include <config.h>
32
#ident "$Id: chfn.c 1751 2008-02-03 16:28:03Z nekral-guest $"
35
#ident "$Id: chfn.c 2363 2008-09-06 23:46:44Z nekral-guest $"
54
57
* Global variables.
57
60
static char fullnm[BUFSIZ];
58
61
static char roomno[BUFSIZ];
59
62
static char workph[BUFSIZ];
60
63
static char homeph[BUFSIZ];
61
64
static char slop[BUFSIZ];
64
static int fflg = 0; /* -f - set full name */
65
static int rflg = 0; /* -r - set room number */
66
static int wflg = 0; /* -w - set work phone number */
67
static int hflg = 0; /* -h - set home phone number */
68
static int oflg = 0; /* -o - set other information */
70
static pam_handle_t *pamh = NULL;
67
static bool fflg = false; /* -f - set full name */
68
static bool rflg = false; /* -r - set room number */
69
static bool wflg = false; /* -w - set work phone number */
70
static bool hflg = false; /* -h - set home phone number */
71
static bool oflg = false; /* -o - set other information */
72
static bool pw_locked = false;
74
75
* External identifiers
77
78
/* local function prototypes */
79
static void fail_exit (int code);
78
80
static void usage (void);
79
static int may_change_field (int);
81
static bool may_change_field (int);
80
82
static void new_fields (void);
81
83
static char *copy_field (char *, char *, char *);
82
84
static void process_flags (int argc, char **argv);
85
87
static void get_old_fields (const char *gecos);
90
* fail_exit - exit with an error and do some cleanup
92
static void fail_exit (int code)
95
if (pw_unlock () == 0) {
96
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
97
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
88
109
* usage - print command line syntax and exit
90
111
static void usage (void)
166
187
if (may_change_field ('f')) {
167
188
change_field (fullnm, sizeof fullnm, _("Full Name"));
169
printf (_("\tFull Name: %s\n"), fullnm);
190
printf (_("\t%s: %s\n"), _("Full Name"), fullnm);
172
193
if (may_change_field ('r')) {
173
194
change_field (roomno, sizeof roomno, _("Room Number"));
175
printf (_("\tRoom Number: %s\n"), roomno);
196
printf (_("\t%s: %s\n"), _("Room Number"), fullnm);
178
199
if (may_change_field ('w')) {
179
200
change_field (workph, sizeof workph, _("Work Phone"));
181
printf (_("\tWork Phone: %s\n"), workph);
202
printf (_("\t%s: %s\n"), _("Work Phone"), fullnm);
184
205
if (may_change_field ('h')) {
185
206
change_field (homeph, sizeof homeph, _("Home Phone"));
187
printf (_("\tHome Phone: %s\n"), homeph);
208
printf (_("\t%s: %s\n"), _("Home Phone"), fullnm);
355
377
#else /* !USE_PAM */
356
retval = PAM_SUCCESS;
358
378
pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
360
retval = PAM_USER_UNKNOWN;
363
if (retval == PAM_SUCCESS) {
364
retval = pam_start ("chfn", pampw->pw_name, &conv, &pamh);
367
if (retval == PAM_SUCCESS) {
381
_("%s: Cannot determine your user name.\n"),
386
retval = pam_start ("chfn", pampw->pw_name, &conv, &pamh);
388
if (PAM_SUCCESS == retval) {
368
389
retval = pam_authenticate (pamh, 0);
369
if (retval != PAM_SUCCESS) {
370
pam_end (pamh, retval);
374
if (retval == PAM_SUCCESS) {
392
if (PAM_SUCCESS == retval) {
375
393
retval = pam_acct_mgmt (pamh, 0);
376
if (retval != PAM_SUCCESS) {
377
pam_end (pamh, retval);
381
if (retval != PAM_SUCCESS) {
397
(void) pam_end (pamh, retval);
399
if (PAM_SUCCESS != retval) {
382
400
fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
414
431
* password file. Get a lock on the file and open it.
416
433
if (pw_lock () == 0) {
417
fputs (_("Cannot lock the password file; try again later.\n"),
419
SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
435
_("%s: cannot lock %s; try again later.\n"),
437
fail_exit (E_NOPERM);
423
440
if (pw_open (O_RDWR) == 0) {
424
fputs (_("Cannot open the password file.\n"), stderr);
426
SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
442
_("%s: cannot open %s\n"), Prog, pw_dbname ());
443
fail_exit (E_NOPERM);
456
471
if (pw_update (&pwent) == 0) {
457
fputs (_("Error updating the password entry.\n"), stderr);
459
SYSLOG ((LOG_ERR, "error updating passwd entry"));
473
_("%s: failed to prepare the new %s entry '%s'\n"),
474
Prog, pw_dbname (), pwent.pw_name);
475
fail_exit (E_NOPERM);
465
479
* Changes have all been made, so commit them and unlock the file.
467
481
if (pw_close () == 0) {
468
fputs (_("Cannot commit password file changes.\n"), stderr);
470
SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
482
fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
483
SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
484
fail_exit (E_NOPERM);
474
486
if (pw_unlock () == 0) {
475
fputs (_("Cannot unlock the password file.\n"), stderr);
476
SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
487
fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
488
SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
537
549
static void check_fields (void)
539
if (valid_field (fullnm, ":,=")) {
552
err = valid_field (fullnm, ":,=");
554
fprintf (stderr, _("%s: name with non-ASCII characters: '%s'\n"), Prog, fullnm);
555
} else if (err < 0) {
540
556
fprintf (stderr, _("%s: invalid name: '%s'\n"), Prog, fullnm);
557
fail_exit (E_NOPERM);
544
if (valid_field (roomno, ":,=")) {
559
err = valid_field (roomno, ":,=");
561
fprintf (stderr, _("%s: room number with non-ASCII characters: '%s'\n"), Prog, roomno);
562
} else if (err < 0) {
545
563
fprintf (stderr, _("%s: invalid room number: '%s'\n"),
565
fail_exit (E_NOPERM);
550
if (valid_field (workph, ":,=")) {
567
if (valid_field (workph, ":,=") != 0) {
551
568
fprintf (stderr, _("%s: invalid work phone: '%s'\n"),
570
fail_exit (E_NOPERM);
556
if (valid_field (homeph, ":,=")) {
572
if (valid_field (homeph, ":,=") != 0) {
557
573
fprintf (stderr, _("%s: invalid home phone: '%s'\n"),
575
fail_exit (E_NOPERM);
562
if (valid_field (slop, ":")) {
577
err = valid_field (slop, ":");
579
fprintf (stderr, _("%s: '%s' contains non-ASCII characters\n"), Prog, slop);
580
} else if (err < 0) {
564
582
_("%s: '%s' contains illegal characters\n"),
584
fail_exit (E_NOPERM);
620
637
user = argv[optind];
621
638
pw = xgetpwnam (user);
622
639
if (NULL == pw) {
623
fprintf (stderr, _("%s: unknown user %s\n"), Prog,
640
fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog,
642
fail_exit (E_NOPERM);
628
645
pw = get_my_pwent ();
629
646
if (NULL == pw) {
632
("%s: Cannot determine your user name.\n"),
648
_("%s: Cannot determine your user name.\n"),
650
SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
651
(unsigned long) getuid ()));
652
fail_exit (E_NOPERM);
636
654
user = xstrdup (pw->pw_name);
688
706
if ((strlen (fullnm) + strlen (roomno) + strlen (workph) +
689
707
strlen (homeph) + strlen (slop)) > (unsigned int) 80) {
690
708
fprintf (stderr, _("%s: fields too long\n"), Prog);
709
fail_exit (E_NOPERM);
694
711
snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
695
fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop);
712
fullnm, roomno, workph, homeph,
713
('\0' != slop[0]) ? "," : "", slop);
697
715
/* Rewrite the user's gecos in the passwd file */
698
716
update_gecos (user, new_gecos);
700
SYSLOG ((LOG_INFO, "changed user `%s' information", user));
718
SYSLOG ((LOG_INFO, "changed user '%s' information", user));
702
720
nscd_flush_cache ("passwd");
705
pam_end (pamh, PAM_SUCCESS);
709
723
exit (E_SUCCESS);