Deleted Added
full compact
pw_util.c (116344) pw_util.c (121193)
1/*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 2002 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * Portions of this software were developed for the FreeBSD Project by
8 * ThinkSec AS and NAI Labs, the Security Research Division of Network

--- 29 unchanged lines hidden (view full) ---

38 * SUCH DAMAGE.
39 */
40
41#ifndef lint
42#if 0
43static const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
44#endif
45static const char rcsid[] =
1/*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 2002 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * Portions of this software were developed for the FreeBSD Project by
8 * ThinkSec AS and NAI Labs, the Security Research Division of Network

--- 29 unchanged lines hidden (view full) ---

38 * SUCH DAMAGE.
39 */
40
41#ifndef lint
42#if 0
43static const char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
44#endif
45static const char rcsid[] =
46 "$FreeBSD: head/lib/libutil/pw_util.c 116344 2003-06-14 18:42:37Z markm $";
46 "$FreeBSD: head/lib/libutil/pw_util.c 121193 2003-10-18 10:04:16Z markm $";
47#endif /* not lint */
48
49/*
50 * This file is used by all the "password" programs; vipw(8), chpass(1),
51 * and passwd(1).
52 */
53
54#include <sys/param.h>

--- 20 unchanged lines hidden (view full) ---

75
76static pid_t editpid = -1;
77static int lockfd = -1;
78static char masterpasswd[PATH_MAX];
79static char passwd_dir[PATH_MAX];
80static char tempname[PATH_MAX];
81static int initialized;
82
47#endif /* not lint */
48
49/*
50 * This file is used by all the "password" programs; vipw(8), chpass(1),
51 * and passwd(1).
52 */
53
54#include <sys/param.h>

--- 20 unchanged lines hidden (view full) ---

75
76static pid_t editpid = -1;
77static int lockfd = -1;
78static char masterpasswd[PATH_MAX];
79static char passwd_dir[PATH_MAX];
80static char tempname[PATH_MAX];
81static int initialized;
82
83#if 0
83void
84pw_cont(int sig)
85{
86
87 if (editpid != -1)
88 kill(editpid, sig);
89}
84void
85pw_cont(int sig)
86{
87
88 if (editpid != -1)
89 kill(editpid, sig);
90}
91#endif
90
91/*
92 * Initialize statics and set limits, signals & umask to try to avoid
93 * interruptions, crashes etc. that might expose passord data.
94 */
95int
96pw_init(const char *dir, const char *master)
97{
98#if 0
99 struct rlimit rlim;
100#endif
101
102 if (dir == NULL) {
103 strcpy(passwd_dir, _PATH_ETC);
104 } else {
92
93/*
94 * Initialize statics and set limits, signals & umask to try to avoid
95 * interruptions, crashes etc. that might expose passord data.
96 */
97int
98pw_init(const char *dir, const char *master)
99{
100#if 0
101 struct rlimit rlim;
102#endif
103
104 if (dir == NULL) {
105 strcpy(passwd_dir, _PATH_ETC);
106 } else {
105 if (strlen(dir) >= sizeof passwd_dir) {
107 if (strlen(dir) >= sizeof(passwd_dir)) {
106 errno = ENAMETOOLONG;
107 return (-1);
108 }
109 strcpy(passwd_dir, dir);
110 }
111
112 if (master == NULL) {
113 if (dir == NULL) {
114 strcpy(masterpasswd, _PATH_MASTERPASSWD);
108 errno = ENAMETOOLONG;
109 return (-1);
110 }
111 strcpy(passwd_dir, dir);
112 }
113
114 if (master == NULL) {
115 if (dir == NULL) {
116 strcpy(masterpasswd, _PATH_MASTERPASSWD);
115 } else if (snprintf(masterpasswd, sizeof masterpasswd, "%s/%s",
116 passwd_dir, _MASTERPASSWD) > sizeof masterpasswd) {
117 } else if (snprintf(masterpasswd, sizeof(masterpasswd), "%s/%s",
118 passwd_dir, _MASTERPASSWD) > (int)sizeof(masterpasswd)) {
117 errno = ENAMETOOLONG;
118 return (-1);
119 }
120 } else {
119 errno = ENAMETOOLONG;
120 return (-1);
121 }
122 } else {
121 if (strlen(master) >= sizeof masterpasswd) {
123 if (strlen(master) >= sizeof(masterpasswd)) {
122 errno = ENAMETOOLONG;
123 return (-1);
124 }
125 strcpy(masterpasswd, master);
126 }
127
128 /*
129 * The code that follows is extremely disruptive to the calling

--- 81 unchanged lines hidden (view full) ---

211/*
212 * Create and open a presumably safe temp file for editing the password
213 * data, and copy the master password file into it.
214 */
215int
216pw_tmp(int mfd)
217{
218 char buf[8192];
124 errno = ENAMETOOLONG;
125 return (-1);
126 }
127 strcpy(masterpasswd, master);
128 }
129
130 /*
131 * The code that follows is extremely disruptive to the calling

--- 81 unchanged lines hidden (view full) ---

213/*
214 * Create and open a presumably safe temp file for editing the password
215 * data, and copy the master password file into it.
216 */
217int
218pw_tmp(int mfd)
219{
220 char buf[8192];
219 ssize_t nr, nw;
221 ssize_t nr;
220 const char *p;
221 int tfd;
222
223 if (*masterpasswd == '\0')
224 return (-1);
225 if ((p = strrchr(masterpasswd, '/')))
226 ++p;
227 else
228 p = masterpasswd;
222 const char *p;
223 int tfd;
224
225 if (*masterpasswd == '\0')
226 return (-1);
227 if ((p = strrchr(masterpasswd, '/')))
228 ++p;
229 else
230 p = masterpasswd;
229 if (snprintf(tempname, sizeof tempname, "%.*spw.XXXXXX",
230 (int)(p - masterpasswd), masterpasswd) >= sizeof tempname) {
231 if (snprintf(tempname, sizeof(tempname), "%.*spw.XXXXXX",
232 (int)(p - masterpasswd), masterpasswd) >= (int)sizeof(tempname)) {
231 errno = ENAMETOOLONG;
232 return (-1);
233 }
234 if ((tfd = mkstemp(tempname)) == -1)
235 return (-1);
236 if (mfd != -1) {
233 errno = ENAMETOOLONG;
234 return (-1);
235 }
236 if ((tfd = mkstemp(tempname)) == -1)
237 return (-1);
238 if (mfd != -1) {
237 while ((nr = read(mfd, buf, sizeof buf)) > 0)
238 if ((nw = write(tfd, buf, nr)) != nr)
239 while ((nr = read(mfd, buf, sizeof(buf))) > 0)
240 if (write(tfd, buf, (size_t)nr) != nr)
239 break;
240 if (nr != 0) {
241 unlink(tempname);
242 *tempname = '\0';
243 close(tfd);
244 return (-1);
245 }
246 }

--- 17 unchanged lines hidden (view full) ---

264 /* child */
265 if (user == NULL)
266 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
267 "-d", passwd_dir, tempname, NULL);
268 else
269 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
270 "-d", passwd_dir, "-u", user, tempname, NULL);
271 _exit(1);
241 break;
242 if (nr != 0) {
243 unlink(tempname);
244 *tempname = '\0';
245 close(tfd);
246 return (-1);
247 }
248 }

--- 17 unchanged lines hidden (view full) ---

266 /* child */
267 if (user == NULL)
268 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
269 "-d", passwd_dir, tempname, NULL);
270 else
271 execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
272 "-d", passwd_dir, "-u", user, tempname, NULL);
273 _exit(1);
274 /* NOTREACHED */
272 default:
273 /* parent */
274 break;
275 }
276 if (waitpid(pid, &pstat, 0) == -1)
277 return (-1);
278 if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
279 return (0);

--- 96 unchanged lines hidden (view full) ---

376 close(lockfd);
377 errno = serrno;
378}
379
380/*
381 * Compares two struct pwds.
382 */
383int
275 default:
276 /* parent */
277 break;
278 }
279 if (waitpid(pid, &pstat, 0) == -1)
280 return (-1);
281 if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
282 return (0);

--- 96 unchanged lines hidden (view full) ---

379 close(lockfd);
380 errno = serrno;
381}
382
383/*
384 * Compares two struct pwds.
385 */
386int
384pw_equal(struct passwd *pw1, struct passwd *pw2)
387pw_equal(const struct passwd *pw1, const struct passwd *pw2)
385{
386 return (strcmp(pw1->pw_name, pw2->pw_name) == 0 &&
387 pw1->pw_uid == pw2->pw_uid &&
388 pw1->pw_gid == pw2->pw_gid &&
389 strcmp(pw1->pw_class, pw2->pw_class) == 0 &&
390 pw1->pw_change == pw2->pw_change &&
391 pw1->pw_expire == pw2->pw_expire &&
392 strcmp(pw1->pw_gecos, pw2->pw_gecos) == 0 &&
393 strcmp(pw1->pw_dir, pw2->pw_dir) == 0 &&
394 strcmp(pw1->pw_shell, pw2->pw_shell) == 0);
395}
396
397/*
398 * Make a passwd line out of a struct passwd.
399 */
400char *
388{
389 return (strcmp(pw1->pw_name, pw2->pw_name) == 0 &&
390 pw1->pw_uid == pw2->pw_uid &&
391 pw1->pw_gid == pw2->pw_gid &&
392 strcmp(pw1->pw_class, pw2->pw_class) == 0 &&
393 pw1->pw_change == pw2->pw_change &&
394 pw1->pw_expire == pw2->pw_expire &&
395 strcmp(pw1->pw_gecos, pw2->pw_gecos) == 0 &&
396 strcmp(pw1->pw_dir, pw2->pw_dir) == 0 &&
397 strcmp(pw1->pw_shell, pw2->pw_shell) == 0);
398}
399
400/*
401 * Make a passwd line out of a struct passwd.
402 */
403char *
401pw_make(struct passwd *pw)
404pw_make(const struct passwd *pw)
402{
403 char *line;
404
405 asprintf(&line, "%s:%s:%ju:%ju:%s:%ju:%ju:%s:%s:%s", pw->pw_name,
406 pw->pw_passwd, (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
407 pw->pw_class, (uintmax_t)pw->pw_change, (uintmax_t)pw->pw_expire,
408 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
409 return line;
410}
411
412/*
413 * Copy password file from one descriptor to another, replacing or adding
414 * a single record on the way.
415 */
416int
405{
406 char *line;
407
408 asprintf(&line, "%s:%s:%ju:%ju:%s:%ju:%ju:%s:%s:%s", pw->pw_name,
409 pw->pw_passwd, (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
410 pw->pw_class, (uintmax_t)pw->pw_change, (uintmax_t)pw->pw_expire,
411 pw->pw_gecos, pw->pw_dir, pw->pw_shell);
412 return line;
413}
414
415/*
416 * Copy password file from one descriptor to another, replacing or adding
417 * a single record on the way.
418 */
419int
417pw_copy(int ffd, int tfd, struct passwd *pw, struct passwd *old_pw)
420pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
418{
419 char buf[8192], *end, *line, *p, *q, *r, t;
420 struct passwd *fpw;
421{
422 char buf[8192], *end, *line, *p, *q, *r, t;
423 struct passwd *fpw;
421 ssize_t len;
422 int eof;
424 size_t len;
425 int eof, readlen;
423
424 if ((line = pw_make(pw)) == NULL)
425 return (-1);
426
427 eof = 0;
428 len = 0;
429 p = q = end = buf;
430 for (;;) {
431 /* find the end of the current line */
432 for (p = q; q < end && *q != '\0'; ++q)
433 if (*q == '\n')
434 break;
435
436 /* if we don't have a complete line, fill up the buffer */
437 if (q >= end) {
438 if (eof)
439 break;
426
427 if ((line = pw_make(pw)) == NULL)
428 return (-1);
429
430 eof = 0;
431 len = 0;
432 p = q = end = buf;
433 for (;;) {
434 /* find the end of the current line */
435 for (p = q; q < end && *q != '\0'; ++q)
436 if (*q == '\n')
437 break;
438
439 /* if we don't have a complete line, fill up the buffer */
440 if (q >= end) {
441 if (eof)
442 break;
440 if (q - p >= sizeof buf) {
443 if ((size_t)(q - p) >= sizeof(buf)) {
441 warnx("passwd line too long");
442 errno = EINVAL; /* hack */
443 goto err;
444 }
445 if (p < end) {
446 q = memmove(buf, p, end - p);
447 end -= p - buf;
448 } else {
449 p = q = end = buf;
450 }
444 warnx("passwd line too long");
445 errno = EINVAL; /* hack */
446 goto err;
447 }
448 if (p < end) {
449 q = memmove(buf, p, end - p);
450 end -= p - buf;
451 } else {
452 p = q = end = buf;
453 }
451 len = read(ffd, end, sizeof buf - (end - buf));
452 if (len == -1)
454 readlen = read(ffd, end, sizeof(buf) - (end - buf));
455 if (readlen == -1)
453 goto err;
456 goto err;
457 else
458 len = (size_t)readlen;
454 if (len == 0 && p == buf)
455 break;
456 end += len;
457 len = end - buf;
459 if (len == 0 && p == buf)
460 break;
461 end += len;
462 len = end - buf;
458 if (len < sizeof buf) {
463 if (len < (ssize_t)sizeof(buf)) {
459 eof = 1;
460 if (len > 0 && buf[len - 1] != '\n')
461 ++len, *end++ = '\n';
462 }
463 continue;
464 }
465
466 /* is it a blank line or a comment? */

--- 25 unchanged lines hidden (view full) ---

492 free(fpw);
493 errno = EINVAL; /* hack */
494 goto err;
495 }
496 free(fpw);
497
498 /* it is, replace it */
499 len = strlen(line);
464 eof = 1;
465 if (len > 0 && buf[len - 1] != '\n')
466 ++len, *end++ = '\n';
467 }
468 continue;
469 }
470
471 /* is it a blank line or a comment? */

--- 25 unchanged lines hidden (view full) ---

497 free(fpw);
498 errno = EINVAL; /* hack */
499 goto err;
500 }
501 free(fpw);
502
503 /* it is, replace it */
504 len = strlen(line);
500 if (write(tfd, line, len) != len)
505 if (write(tfd, line, len) != (int)len)
501 goto err;
502
503 /* we're done, just copy the rest over */
504 for (;;) {
505 if (write(tfd, q, end - q) != end - q)
506 goto err;
507 q = buf;
506 goto err;
507
508 /* we're done, just copy the rest over */
509 for (;;) {
510 if (write(tfd, q, end - q) != end - q)
511 goto err;
512 q = buf;
508 len = read(ffd, buf, sizeof buf);
509 if (len == 0)
513 readlen = read(ffd, buf, sizeof(buf));
514 if (readlen == 0)
510 break;
515 break;
511 if (len == -1)
516 else
517 len = (size_t)readlen;
518 if (readlen == -1)
512 goto err;
513 end = buf + len;
514 }
515 goto done;
516 }
517
518 /* if we got here, we have a new entry */
519 len = strlen(line);
519 goto err;
520 end = buf + len;
521 }
522 goto done;
523 }
524
525 /* if we got here, we have a new entry */
526 len = strlen(line);
520 if (write(tfd, line, len) != len ||
527 if ((size_t)write(tfd, line, len) != len ||
521 write(tfd, "\n", 1) != 1)
522 goto err;
523 done:
524 free(line);
525 return (0);
526 err:
527 free(line);
528 return (-1);

--- 8 unchanged lines hidden (view full) ---

537
538 return (tempname);
539}
540
541/*
542 * Duplicate a struct passwd.
543 */
544struct passwd *
528 write(tfd, "\n", 1) != 1)
529 goto err;
530 done:
531 free(line);
532 return (0);
533 err:
534 free(line);
535 return (-1);

--- 8 unchanged lines hidden (view full) ---

544
545 return (tempname);
546}
547
548/*
549 * Duplicate a struct passwd.
550 */
551struct passwd *
545pw_dup(struct passwd *pw)
552pw_dup(const struct passwd *pw)
546{
547 struct passwd *npw;
553{
554 struct passwd *npw;
548 size_t len;
555 ssize_t len;
549
556
550 len = sizeof *npw +
557 len = sizeof(*npw) +
551 (pw->pw_name ? strlen(pw->pw_name) + 1 : 0) +
552 (pw->pw_passwd ? strlen(pw->pw_passwd) + 1 : 0) +
553 (pw->pw_class ? strlen(pw->pw_class) + 1 : 0) +
554 (pw->pw_gecos ? strlen(pw->pw_gecos) + 1 : 0) +
555 (pw->pw_dir ? strlen(pw->pw_dir) + 1 : 0) +
556 (pw->pw_shell ? strlen(pw->pw_shell) + 1 : 0);
558 (pw->pw_name ? strlen(pw->pw_name) + 1 : 0) +
559 (pw->pw_passwd ? strlen(pw->pw_passwd) + 1 : 0) +
560 (pw->pw_class ? strlen(pw->pw_class) + 1 : 0) +
561 (pw->pw_gecos ? strlen(pw->pw_gecos) + 1 : 0) +
562 (pw->pw_dir ? strlen(pw->pw_dir) + 1 : 0) +
563 (pw->pw_shell ? strlen(pw->pw_shell) + 1 : 0);
557 if ((npw = malloc(len)) == NULL)
564 if ((npw = malloc((size_t)len)) == NULL)
558 return (NULL);
565 return (NULL);
559 memcpy(npw, pw, sizeof *npw);
560 len = sizeof *npw;
566 memcpy(npw, pw, sizeof(*npw));
567 len = sizeof(*npw);
561 if (pw->pw_name) {
562 npw->pw_name = ((char *)npw) + len;
563 len += sprintf(npw->pw_name, "%s", pw->pw_name) + 1;
564 }
565 if (pw->pw_passwd) {
566 npw->pw_passwd = ((char *)npw) + len;
567 len += sprintf(npw->pw_passwd, "%s", pw->pw_passwd) + 1;
568 }

--- 40 unchanged lines hidden ---
568 if (pw->pw_name) {
569 npw->pw_name = ((char *)npw) + len;
570 len += sprintf(npw->pw_name, "%s", pw->pw_name) + 1;
571 }
572 if (pw->pw_passwd) {
573 npw->pw_passwd = ((char *)npw) + len;
574 len += sprintf(npw->pw_passwd, "%s", pw->pw_passwd) + 1;
575 }

--- 40 unchanged lines hidden ---