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