1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 #pragma ident "%Z%%M% %I% %E% SMI" 23 24 /* 25 * Copyright 1994-2003 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 /* 30 * Beware those who enter here. 31 * The logic may appear hairy, but it's been ARCed. 32 * See /shared/sac/PSARC/1995/122/mail 33 */ 34 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <ctype.h> 38 #include <unistd.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <stdio.h> 42 #include <errno.h> 43 #include <syslog.h> 44 #include <pwd.h> 45 #include <shadow.h> 46 #include <signal.h> 47 #include <crypt.h> 48 #include <rpc/rpc.h> 49 #include <rpcsvc/yppasswd.h> 50 #include <utmpx.h> 51 #include <nss_dbdefs.h> 52 53 #define STRSIZE 100 54 #define FINGERSIZE (4 * STRSIZE - 4) 55 #define SHELLSIZE (STRSIZE - 2) 56 #define UTUSERLEN (sizeof (((struct utmpx *)0)->ut_user)) 57 58 /* Prototypes */ 59 extern bool_t validloginshell(char *sh, char *arg, int); 60 extern int validstr(char *str, size_t size); 61 extern int yplckpwdf(); 62 extern int ypulckpwdf(); 63 64 void 65 changepasswd(SVCXPRT *transp) 66 { 67 /* 68 * Put these numeric constants into const variables so 69 * a) they're visible in a debugger 70 * b) the compiler can play it's cool games with em 71 */ 72 static const int cryptpwsize = CRYPT_MAXCIPHERTEXTLEN; 73 static const int fingersize = FINGERSIZE; 74 static const int shellsize = SHELLSIZE; 75 76 struct yppasswd yppwd; 77 struct passwd newpw, opwd; 78 struct spwd ospwd; 79 struct sigaction sa, osa1, osa2, osa3; 80 struct stat pwstat, spstat, adjstat; 81 82 char newpasswdfile[FILENAME_MAX]; 83 char newshadowfile[FILENAME_MAX]; 84 char newadjunctfile[FILENAME_MAX]; 85 char tmppasswdfile[FILENAME_MAX]; 86 char tmpshadowfile[FILENAME_MAX]; 87 char tmpadjunctfile[FILENAME_MAX]; 88 char pwbuf[NSS_LINELEN_PASSWD], spbuf[NSS_LINELEN_SHADOW]; 89 char adjbuf[BUFSIZ+1], adjbuf_new[BUFSIZ+1], cmdbuf[BUFSIZ]; 90 char adj_encrypt[CRYPT_MAXCIPHERTEXTLEN + 1]; 91 /* 92 * The adj_crypt_* pointers are used to point into adjbuf 93 * NOT adj_encrypt 94 */ 95 char *adj_crypt_begin, *adj_crypt_end; 96 char name[UTUSERLEN + sizeof (":")]; 97 char *p; 98 99 FILE *opwfp = NULL, *ospfp = NULL, *oadjfp = NULL, 100 *npwfp = NULL, *nspfp = NULL, *nadjfp = NULL; 101 int npwfd = -1, nspfd = -1, nadjfd = -1; 102 103 int i, ans, chsh, chpw, chgecos, namelen; 104 int gotadjunct = 0, gotshadow = 0, gotpasswd = 0; 105 int doneflag = 0, root_on_master = 0; 106 pid_t retval; 107 108 time_t now; 109 110 long pwpos = 0, sppos = 0; 111 112 /* Globals :-( */ 113 extern int single, nogecos, noshell, nopw, mflag, Mstart, Argc; 114 extern char **Argv; 115 extern char passwd_file[], shadow_file[], adjunct_file[]; 116 extern int useadjunct; 117 extern int useshadow; 118 119 /* Clean out yppwd */ 120 memset(&yppwd, 0, sizeof (struct yppasswd)); 121 122 /* Get the RPC args */ 123 if (!svc_getargs(transp, xdr_yppasswd, (caddr_t)&yppwd)) { 124 svcerr_decode(transp); 125 return; 126 } 127 128 /* Perform basic validation */ 129 if (/* (!validstr(yppwd.oldpass, PWSIZE)) || */ /* see PR:nis/38 */ 130 (!validstr(yppwd.newpw.pw_passwd, cryptpwsize)) || 131 (!validstr(yppwd.newpw.pw_name, UTUSERLEN)) || 132 (!validstr(yppwd.newpw.pw_gecos, fingersize)) || 133 (!validstr(yppwd.newpw.pw_shell, shellsize))) { 134 svcerr_decode(transp); 135 return; 136 } 137 138 /* 139 * Special case: root on the master server can change other users' 140 * passwords without first entering the old password. We need to 141 * ensure that this is indeed root on the master server. (bug 1253949) 142 */ 143 if (strcmp(transp->xp_netid, "ticlts") == 0) { 144 svc_local_cred_t cred; 145 if (!svc_get_local_cred(transp, &cred)) { 146 syslog(LOG_ERR, "yppasswdd: Couldn't get " 147 "local user credentials.\n"); 148 } else if (cred.ruid == 0) 149 root_on_master = 1; 150 } 151 152 newpw = yppwd.newpw; 153 strcpy(name, newpw.pw_name); 154 strcat(name, ":"); 155 namelen = strlen(name); 156 ans = 2; 157 chsh = chpw = chgecos = 0; 158 159 /* Get all the filenames straight */ 160 strcpy(newpasswdfile, passwd_file); 161 strcat(newpasswdfile, ".ptmp"); 162 strcpy(newshadowfile, shadow_file); 163 strcat(newshadowfile, ".ptmp"); 164 strcpy(newadjunctfile, adjunct_file); 165 strcat(newadjunctfile, ".ptmp"); 166 167 memset(&sa, 0, sizeof (struct sigaction)); 168 sa.sa_handler = SIG_IGN; 169 sigaction(SIGTSTP, &sa, (struct sigaction *)0); 170 sigaction(SIGHUP, &sa, &osa1); 171 sigaction(SIGINT, &sa, &osa2); 172 sigaction(SIGQUIT, &sa, &osa3); 173 174 /* Lock, then open the passwd and shadow files */ 175 176 if (yplckpwdf() < 0) { 177 syslog(LOG_ERR, 178 "yppasswdd: Password file(s) busy. " 179 "Try again later.\n"); 180 ans = 8; 181 goto cleanup; 182 } 183 184 if ((opwfp = fopen(passwd_file, "r")) == NULL) { 185 syslog(LOG_ERR, "yppasswdd: Could not open %s\n", passwd_file); 186 goto cleanup; 187 } 188 189 fstat(fileno(opwfp), &pwstat); 190 191 if (useshadow) { 192 if ((ospfp = fopen(shadow_file, "r")) == NULL) { 193 syslog(LOG_ERR, 194 "yppasswdd: Could not open %s\n", shadow_file); 195 goto cleanup; 196 } 197 198 fstat(fileno(ospfp), &spstat); 199 } 200 201 if (useadjunct) { 202 if ((oadjfp = fopen(adjunct_file, "r")) == NULL) { 203 syslog(LOG_ERR, 204 "yppasswdd: Could not open %s\n", 205 adjunct_file); 206 goto cleanup; 207 } 208 209 fstat(fileno(oadjfp), &adjstat); 210 } 211 212 /* 213 * Open the new passwd and shadow tmp files, 214 * first with open and then create a FILE * with fdopen() 215 */ 216 if ((npwfd = open(newpasswdfile, O_WRONLY | O_CREAT | O_EXCL, 217 pwstat.st_mode)) < 0) { 218 if (errno == EEXIST) { 219 syslog(LOG_WARNING, 220 "yppasswdd: passwd file busy - try again\n"); 221 ans = 8; 222 } else { 223 syslog(LOG_ERR, "yppasswdd: %s: %m", 224 newpasswdfile); 225 ans = 9; 226 } 227 goto cleanup; 228 } 229 230 fchown(npwfd, pwstat.st_uid, pwstat.st_gid); 231 232 if ((npwfp = fdopen(npwfd, "w")) == NULL) { 233 syslog(LOG_ERR, 234 "yppasswdd: fdopen() on %s failed\n", newpasswdfile); 235 goto cleanup; 236 } 237 238 if (useshadow) { 239 if ((nspfd = open(newshadowfile, O_WRONLY | O_CREAT | O_EXCL, 240 spstat.st_mode)) < 0) { 241 if (errno == EEXIST) { 242 syslog(LOG_WARNING, 243 "yppasswdd: shadow file busy - try again\n"); 244 ans = 8; 245 } else { 246 syslog(LOG_ERR, "yppasswdd: %s: %m", 247 newshadowfile); 248 ans = 9; 249 } 250 goto cleanup; 251 } 252 253 fchown(nspfd, spstat.st_uid, spstat.st_gid); 254 255 if ((nspfp = fdopen(nspfd, "w")) == NULL) { 256 syslog(LOG_ERR, 257 "yppasswdd: fdopen() on %s failed\n", 258 newshadowfile); 259 goto cleanup; 260 } 261 } 262 263 if (useadjunct) { 264 if ((nadjfd = open(newadjunctfile, O_WRONLY | O_CREAT | O_EXCL, 265 adjstat.st_mode)) < 0) { 266 if (errno == EEXIST) { 267 syslog(LOG_WARNING, 268 "yppasswdd: adjunct file busy - try again\n"); 269 ans = 8; 270 } else { 271 syslog(LOG_ERR, "yppasswdd: %s: %m", 272 newadjunctfile); 273 ans = 9; 274 } 275 goto cleanup; 276 } 277 278 fchown(nadjfd, adjstat.st_uid, adjstat.st_gid); 279 280 if ((nadjfp = fdopen(nadjfd, "w")) == NULL) { 281 syslog(LOG_ERR, 282 "yppasswdd: fdopen() on %s failed\n", 283 newadjunctfile); 284 goto cleanup; 285 } 286 } 287 288 /* 289 * The following code may not seem all that elegant, but my 290 * interpretation of the man pages relating to the passwd and 291 * shadow files would seem to indicate that there is no guarantee 292 * that the entries contained in those files will be in the same 293 * order... 294 * 295 * So here's the high level overview: 296 * 297 * Loop through the passwd file reading in lines and writing them 298 * out to the new file UNTIL we get to the correct entry. 299 * IF we have a shadow file, loop through it reading in lines and 300 * writing them out to the new file UNTIL we get to the correct 301 * entry. IF we have an adjunct file, loop through it reading in 302 * lines and writing them out to the new file UNTIL we get to the 303 * correct entry. 304 * 305 * Figure out what's changing, contruct the new passwd, shadow, 306 * and adjunct entries and spit em out to the temp files. 307 * At this point, set the done flag and leap back into the loop(s) 308 * until you're finished with the files and then leap to the 309 * section that installs the new files. 310 */ 311 312 loop_in_files: 313 /* While we find things in the passwd file */ 314 while (fgets(pwbuf, NSS_LINELEN_PASSWD, opwfp)) { 315 316 /* 317 * Is this the passwd entry we want? 318 * If not, then write it out to the new passwd temp file 319 * and remember our position. 320 */ 321 if (doneflag || strncmp(name, pwbuf, namelen)) { 322 if (fputs(pwbuf, npwfp) == EOF) { 323 syslog(LOG_ERR, 324 "yppasswdd: write to passwd file failed.\n"); 325 goto cleanup; 326 } 327 pwpos = ftell(opwfp); 328 continue; 329 } 330 gotpasswd = 1; 331 break; 332 } 333 334 /* no match */ 335 if (!gotpasswd) { 336 syslog(LOG_ERR, "yppasswdd: user %s does not exist\n", name); 337 goto cleanup; 338 } 339 340 /* While we find things in the shadow file */ 341 while (useshadow && fgets(spbuf, NSS_LINELEN_SHADOW, ospfp)) { 342 343 /* 344 * Is this the shadow entry that we want? 345 * If not, write it out to the new shadow temp file 346 * and remember our position. 347 */ 348 if (doneflag || strncmp(name, spbuf, namelen)) { 349 if (fputs(spbuf, nspfp) == EOF) { 350 syslog(LOG_ERR, 351 "yppasswdd: write to shadow file failed.\n"); 352 goto cleanup; 353 } 354 sppos = ftell(ospfp); 355 continue; 356 } 357 gotshadow = 1; 358 break; 359 } 360 361 /* While we find things in the adjunct file */ 362 while (useadjunct && fgets(adjbuf, BUFSIZ, oadjfp)) { 363 364 /* 365 * is this the adjunct entry that we want? 366 * If not, write it out to the new temp file 367 * and remember our position. 368 */ 369 if (doneflag || strncmp(name, adjbuf, namelen)) { 370 if (fputs(adjbuf, nadjfp) == EOF) { 371 syslog(LOG_ERR, 372 "yppasswdd: write to adjunct file failed.\n"); 373 goto cleanup; 374 } 375 continue; 376 } 377 gotadjunct = 1; 378 break; 379 } 380 381 if (doneflag) 382 goto install_files; 383 384 if (useshadow && !gotshadow) { 385 syslog(LOG_ERR, "yppasswdd: no passwd in shadow for %s\n", 386 newpw.pw_name); 387 ans = 4; 388 goto cleanup; 389 } 390 if (useadjunct && !gotadjunct) { 391 syslog(LOG_ERR, "yppasswdd: no passwd in adjunct for %s\n", 392 newpw.pw_name); 393 ans = 4; 394 goto cleanup; 395 } 396 397 /* 398 * Now that we've read in the correct passwd AND 399 * shadow lines, we'll rewind to the beginning of 400 * those lines and let the fget*ent() calls do 401 * the work. Since we are only working with the 402 * first two fields of the adjunct entry, leave 403 * it as a char array. 404 */ 405 fseek(opwfp, pwpos, SEEK_SET); 406 opwd = *fgetpwent(opwfp); 407 408 if (useshadow) { 409 fseek(ospfp, sppos, SEEK_SET); 410 ospwd = *fgetspent(ospfp); 411 } 412 413 p = newpw.pw_passwd; 414 if ((!nopw) && 415 p && *p && 416 !(*p++ == '#' && *p++ == '#' && 417 (strcmp(p, opwd.pw_name) == 0)) && 418 (strcmp(crypt(yppwd.oldpass, newpw.pw_passwd), 419 newpw.pw_passwd) != 0)) 420 chpw = 1; 421 422 if ((!noshell) && (strcmp(opwd.pw_shell, newpw.pw_shell) != 0)) { 423 if (single) 424 chpw = 0; 425 chsh = 1; 426 } 427 428 if ((!nogecos) && (strcmp(opwd.pw_gecos, newpw.pw_gecos) != 0)) { 429 if (single) { 430 chpw = 0; 431 chsh = 0; 432 } 433 chgecos = 1; 434 } 435 436 if (!(chpw + chsh + chgecos)) { 437 syslog(LOG_NOTICE, "yppasswdd: no change for %s\n", 438 newpw.pw_name); 439 ans = 3; 440 goto cleanup; 441 } 442 443 if (useshadow && !root_on_master) { 444 if (ospwd.sp_pwdp && *ospwd.sp_pwdp && 445 (strcmp(crypt(yppwd.oldpass, ospwd.sp_pwdp), 446 ospwd.sp_pwdp) != 0)) { 447 448 syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n", 449 newpw.pw_name); 450 ans = 7; 451 goto cleanup; 452 } 453 } else if (useadjunct) { 454 /* 455 * Clear the adj_encrypt array. Extract the encrypted passwd 456 * into adj_encrypt by setting adj_crypt_begin and 457 * adj_crypt_end to point at the first character of the 458 * encrypted passwd and the first character following the 459 * encrypted passwd in adjbuf, respectively, and copy the 460 * stuff between (there may not be anything) into adj_ecrypt. 461 * Then, check that adj_encrypt contains something and that 462 * the old passwd is correct. 463 */ 464 memset(adj_encrypt, 0, sizeof (adj_encrypt)); 465 adj_crypt_begin = adjbuf + namelen; 466 adj_crypt_end = strchr(adj_crypt_begin, ':'); 467 strncpy(adj_encrypt, adj_crypt_begin, 468 adj_crypt_end - adj_crypt_begin); 469 if (!root_on_master && *adj_encrypt && 470 (strcmp(crypt(yppwd.oldpass, adj_encrypt), 471 adj_encrypt) != 0)) { 472 473 syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n", 474 newpw.pw_name); 475 ans = 7; 476 goto cleanup; 477 } 478 } else { 479 if (!root_on_master && opwd.pw_passwd && *opwd.pw_passwd && 480 (strcmp(crypt(yppwd.oldpass, opwd.pw_passwd), 481 opwd.pw_passwd) != 0)) { 482 483 syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n", 484 newpw.pw_name); 485 ans = 7; 486 goto cleanup; 487 } 488 } 489 490 #ifdef DEBUG 491 printf("%d %d %d\n", chsh, chgecos, chpw); 492 493 printf("%s %s %s\n", 494 yppwd.newpw.pw_shell, 495 yppwd.newpw.pw_gecos, 496 yppwd.newpw.pw_passwd); 497 498 printf("%s %s %s\n", 499 opwd.pw_shell, 500 opwd.pw_gecos, 501 ospwd.sp_pwdp); 502 #endif 503 504 if (chsh && !validloginshell(opwd.pw_shell, newpw.pw_shell, 505 root_on_master)) { 506 goto cleanup; 507 } 508 509 /* security hole fix from original source */ 510 for (p = newpw.pw_name; (*p != '\0'); p++) 511 if ((*p == ':') || !(isprint(*p))) 512 *p = '$'; /* you lose buckwheat */ 513 for (p = newpw.pw_passwd; (*p != '\0'); p++) 514 if ((*p == ':') || !(isprint(*p))) 515 *p = '$'; /* you lose buckwheat */ 516 517 if (chgecos) 518 opwd.pw_gecos = newpw.pw_gecos; 519 520 if (chsh) 521 opwd.pw_shell = newpw.pw_shell; 522 523 /* 524 * If we're changing the shell or gecos fields and we're 525 * using a shadow or adjunct file or not changing the passwd 526 * then go ahead and update the passwd file. The case where 527 * the passwd is being changed and we are not using a shadow 528 * or adjunct file is handled later. 529 */ 530 if ((chsh || chgecos) && (useshadow || useadjunct || !chpw) && 531 putpwent(&opwd, npwfp)) { 532 533 syslog(LOG_ERR, "yppasswdd: putpwent failed: %s\n", 534 passwd_file); 535 goto cleanup; 536 } 537 538 if (chpw) { 539 if (useshadow) { 540 ospwd.sp_pwdp = newpw.pw_passwd; 541 now = DAY_NOW; 542 /* password aging - bug for bug compatibility */ 543 if (ospwd.sp_max != -1) { 544 if (now < ospwd.sp_lstchg + ospwd.sp_min) { 545 syslog(LOG_ERR, 546 "yppasswdd: Sorry: < %ld days since " 547 "the last change.\n", ospwd.sp_min); 548 goto cleanup; 549 } 550 } 551 ospwd.sp_lstchg = now; 552 if (putspent(&ospwd, nspfp)) { 553 syslog(LOG_ERR, 554 "yppasswdd: putspent failed: %s\n", 555 shadow_file); 556 goto cleanup; 557 } 558 } else if (useadjunct) { 559 sprintf(adjbuf_new, 560 "%s%s%s", name, newpw.pw_passwd, 561 adj_crypt_end); 562 if (fputs(adjbuf_new, nadjfp) == EOF) { 563 syslog(LOG_ERR, 564 "yppasswdd: write to adjunct failed: %s\n", 565 adjunct_file); 566 goto cleanup; 567 } 568 } else { 569 opwd.pw_passwd = newpw.pw_passwd; 570 if (putpwent(&opwd, npwfp)) { 571 syslog(LOG_ERR, 572 "yppasswdd: putpwent failed: %s\n", 573 passwd_file); 574 goto cleanup; 575 } 576 } 577 } 578 579 if (!doneflag) { 580 doneflag = 1; 581 goto loop_in_files; 582 } 583 584 install_files: 585 /* 586 * Critical section, nothing special needs to be done since we 587 * hold exclusive access to the *.ptmp files 588 */ 589 fflush(npwfp); 590 if (useshadow) 591 fflush(nspfp); 592 if (useadjunct) 593 fflush(nadjfp); 594 595 strcpy(tmppasswdfile, passwd_file); 596 strcat(tmppasswdfile, "-"); 597 if (useshadow) { 598 strcpy(tmpshadowfile, shadow_file); 599 strcat(tmpshadowfile, "-"); 600 } 601 if (useadjunct) { 602 strcpy(tmpadjunctfile, adjunct_file); 603 strcat(tmpadjunctfile, "-"); 604 } 605 606 if ((!useshadow && !useadjunct) || (chsh || chgecos)) { 607 if (rename(passwd_file, tmppasswdfile) < 0) { 608 syslog(LOG_CRIT, "yppasswdd: failed to backup " 609 "passwd file: %m"); 610 goto cleanup; 611 } else { 612 if (rename(newpasswdfile, passwd_file) < 0) { 613 syslog(LOG_CRIT, 614 "yppasswdd: failed to mv passwd: %m"); 615 if (rename(tmppasswdfile, passwd_file) < 0) { 616 syslog(LOG_CRIT, 617 "yppasswdd: failed to restore " 618 "backup of passwd file: %m"); 619 } 620 goto cleanup; 621 } 622 } 623 } 624 625 if (useshadow && chpw) { 626 if (rename(shadow_file, tmpshadowfile) < 0) { 627 syslog(LOG_CRIT, "yppasswdd: failed to back up " 628 "shadow file: %m"); 629 if (rename(tmppasswdfile, passwd_file) < 0) { 630 syslog(LOG_CRIT, 631 "yppasswdd: failed to restore " 632 "backup of passwd file: %m"); 633 } 634 goto cleanup; 635 } else { 636 if (rename(newshadowfile, shadow_file) < 0) { 637 syslog(LOG_CRIT, 638 "yppasswdd: failed to mv shadow: %m"); 639 if (rename(tmpshadowfile, shadow_file) < 0) { 640 syslog(LOG_CRIT, 641 "yppasswdd: failed to restore " 642 "backup of shadow file: %m"); 643 } 644 if (rename(tmppasswdfile, passwd_file) < 0) { 645 syslog(LOG_CRIT, 646 "yppasswdd: failed to restore " 647 "backup of passwd file: %m"); 648 } 649 goto cleanup; 650 } 651 } 652 } else if (useadjunct && chpw) { 653 if (rename(adjunct_file, tmpadjunctfile) < 0) { 654 syslog(LOG_CRIT, "yppasswdd: failed to back up " 655 "adjunct file: %m"); 656 if (rename(tmppasswdfile, passwd_file) < 0) { 657 syslog(LOG_CRIT, 658 "yppasswdd: failed to restore backup " 659 "of passwd: %m"); 660 } 661 goto cleanup; 662 } else { 663 if (rename(newadjunctfile, adjunct_file) < 0) { 664 syslog(LOG_CRIT, 665 "yppassdd: failed to mv adjunct: %m"); 666 if (rename(tmppasswdfile, passwd_file) < 0) { 667 syslog(LOG_CRIT, 668 "yppasswdd: failed to restore " 669 "backup of passwd file: %m"); 670 } 671 if (rename(tmpadjunctfile, adjunct_file) < 0) { 672 syslog(LOG_CRIT, 673 "yppasswdd: failed to restore " 674 "backup of adjunct file: %m"); 675 } 676 goto cleanup; 677 } 678 } 679 } 680 681 if (doneflag) 682 ans = 0; 683 /* End critical section */ 684 685 /* 686 * Here we have come only after the new files have been successfully 687 * renamed to original files. At this point, the temp files would still 688 * be existing we need to remove them from the /etc directory 689 */ 690 unlink(tmppasswdfile); 691 if (useshadow) 692 unlink(tmpshadowfile); 693 if (useadjunct) 694 unlink(tmpadjunctfile); 695 696 cleanup: 697 698 /* If we don't have opwfp, then we didn't do anything */ 699 if (opwfp) { 700 fclose(opwfp); 701 702 if (ospfp) { 703 fclose(ospfp); 704 } 705 706 if (oadjfp) { 707 fclose(oadjfp); 708 } 709 710 unlink(newpasswdfile); 711 /* These tests are cheaper than failing syscalls */ 712 if (useshadow) 713 unlink(newshadowfile); 714 if (useadjunct) 715 unlink(newadjunctfile); 716 717 if (npwfp) { 718 fclose(npwfp); 719 720 if (nspfp) { 721 fclose(nspfp); 722 } 723 if (nadjfp) { 724 fclose(nadjfp); 725 } 726 } 727 } 728 729 ypulckpwdf(); 730 731 if (doneflag && mflag) { 732 retval = fork(); 733 if (retval < 0) { 734 syslog(LOG_ERR, "yppasswdd: Fork failed %m"); 735 } else if (retval == 0) { 736 strcpy(cmdbuf, "/usr/ccs/bin/make"); 737 for (i = Mstart + 1; i < Argc; i++) { 738 strcat(cmdbuf, " "); 739 strcat(cmdbuf, Argv[i]); 740 } 741 742 #ifdef DEBUG 743 syslog(LOG_ERR, "yppasswdd: about to " 744 "execute %s\n", cmdbuf); 745 #else 746 if (yplckpwdf() < 0) { 747 syslog(LOG_ERR, "yppasswdd: Couldn't get the" 748 "lock to update the maps"); 749 } else { 750 setpgrp(); 751 system(cmdbuf); 752 ypulckpwdf(); 753 } 754 #endif 755 exit(0); 756 } 757 } 758 759 sigaction(SIGHUP, &osa1, (struct sigaction *)0); 760 sigaction(SIGINT, &osa2, (struct sigaction *)0); 761 sigaction(SIGQUIT, &osa3, (struct sigaction *)0); 762 763 if (!svc_sendreply(transp, xdr_int, (char *)&ans)) 764 syslog(LOG_WARNING, 765 "yppasswdd: couldn\'t reply to RPC call\n"); 766 } 767