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 --- |