xref: /titanic_41/usr/src/cmd/ypcmd/yppasswd/changepasswd.c (revision 07a8ec025876f68beb4970924130b58b7ee6fa69)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*07a8ec02SBen Chang  * Common Development and Distribution License (the "License").
6*07a8ec02SBen Chang  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*07a8ec02SBen Chang  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Beware those who enter here.
287c478bd9Sstevel@tonic-gate  * The logic may appear hairy, but it's been ARCed.
297c478bd9Sstevel@tonic-gate  * See /shared/sac/PSARC/1995/122/mail
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
357c478bd9Sstevel@tonic-gate #include <unistd.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <stdio.h>
397c478bd9Sstevel@tonic-gate #include <errno.h>
407c478bd9Sstevel@tonic-gate #include <syslog.h>
417c478bd9Sstevel@tonic-gate #include <pwd.h>
427c478bd9Sstevel@tonic-gate #include <shadow.h>
437c478bd9Sstevel@tonic-gate #include <signal.h>
447c478bd9Sstevel@tonic-gate #include <crypt.h>
457c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
467c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h>
477c478bd9Sstevel@tonic-gate #include <utmpx.h>
487c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	STRSIZE 100
517c478bd9Sstevel@tonic-gate #define	FINGERSIZE (4 * STRSIZE - 4)
527c478bd9Sstevel@tonic-gate #define	SHELLSIZE (STRSIZE - 2)
537c478bd9Sstevel@tonic-gate #define	UTUSERLEN (sizeof (((struct utmpx *)0)->ut_user))
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate /* Prototypes */
567c478bd9Sstevel@tonic-gate extern bool_t validloginshell(char *sh, char *arg, int);
577c478bd9Sstevel@tonic-gate extern int    validstr(char *str, size_t size);
587c478bd9Sstevel@tonic-gate extern int yplckpwdf();
597c478bd9Sstevel@tonic-gate extern int ypulckpwdf();
607c478bd9Sstevel@tonic-gate 
61*07a8ec02SBen Chang static char *
cryptoldpasswd(char * oldpass,char * salt,char * acctname)62*07a8ec02SBen Chang cryptoldpasswd(char *oldpass, char *salt, char *acctname)
63*07a8ec02SBen Chang {
64*07a8ec02SBen Chang 	char *oldpass_crypt = NULL;
65*07a8ec02SBen Chang 
66*07a8ec02SBen Chang 	if ((oldpass_crypt = crypt(oldpass, salt)) == NULL) {
67*07a8ec02SBen Chang 		if (errno == EINVAL) {
68*07a8ec02SBen Chang 			syslog(LOG_ERR,
69*07a8ec02SBen Chang 			    "yppasswdd: password not changed for \"%s\" - "
70*07a8ec02SBen Chang 			    "crypt module not supported on the master\n",
71*07a8ec02SBen Chang 			    acctname);
72*07a8ec02SBen Chang 		} else {
73*07a8ec02SBen Chang 			syslog(LOG_ERR,
74*07a8ec02SBen Chang 			    "yppasswdd: password not changed for \"%s\" - "
75*07a8ec02SBen Chang 			    "%s\n", acctname, strerror(errno));
76*07a8ec02SBen Chang 		}
77*07a8ec02SBen Chang 	}
78*07a8ec02SBen Chang 	return (oldpass_crypt);
79*07a8ec02SBen Chang }
80*07a8ec02SBen Chang 
817c478bd9Sstevel@tonic-gate void
changepasswd(SVCXPRT * transp)827c478bd9Sstevel@tonic-gate changepasswd(SVCXPRT *transp)
837c478bd9Sstevel@tonic-gate {
847c478bd9Sstevel@tonic-gate 	/*
857c478bd9Sstevel@tonic-gate 	 * Put these numeric constants into const variables so
867c478bd9Sstevel@tonic-gate 	 *   a) they're visible in a debugger
877c478bd9Sstevel@tonic-gate 	 *   b) the compiler can play it's cool games with em
887c478bd9Sstevel@tonic-gate 	 */
897c478bd9Sstevel@tonic-gate 	static const int cryptpwsize = CRYPT_MAXCIPHERTEXTLEN;
907c478bd9Sstevel@tonic-gate 	static const int fingersize = FINGERSIZE;
917c478bd9Sstevel@tonic-gate 	static const int shellsize = SHELLSIZE;
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	struct yppasswd yppwd;
947c478bd9Sstevel@tonic-gate 	struct passwd newpw, opwd;
957c478bd9Sstevel@tonic-gate 	struct spwd ospwd;
967c478bd9Sstevel@tonic-gate 	struct sigaction sa, osa1, osa2, osa3;
977c478bd9Sstevel@tonic-gate 	struct stat pwstat, spstat, adjstat;
98*07a8ec02SBen Chang 	char *oldpass_crypt = NULL;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	char newpasswdfile[FILENAME_MAX];
1017c478bd9Sstevel@tonic-gate 	char newshadowfile[FILENAME_MAX];
1027c478bd9Sstevel@tonic-gate 	char newadjunctfile[FILENAME_MAX];
1037c478bd9Sstevel@tonic-gate 	char tmppasswdfile[FILENAME_MAX];
1047c478bd9Sstevel@tonic-gate 	char tmpshadowfile[FILENAME_MAX];
1057c478bd9Sstevel@tonic-gate 	char tmpadjunctfile[FILENAME_MAX];
1067c478bd9Sstevel@tonic-gate 	char pwbuf[NSS_LINELEN_PASSWD], spbuf[NSS_LINELEN_SHADOW];
1077c478bd9Sstevel@tonic-gate 	char adjbuf[BUFSIZ+1], adjbuf_new[BUFSIZ+1], cmdbuf[BUFSIZ];
1087c478bd9Sstevel@tonic-gate 	char adj_encrypt[CRYPT_MAXCIPHERTEXTLEN + 1];
1097c478bd9Sstevel@tonic-gate 	/*
1107c478bd9Sstevel@tonic-gate 	 * The adj_crypt_* pointers are used to point into adjbuf
1117c478bd9Sstevel@tonic-gate 	 * NOT adj_encrypt
1127c478bd9Sstevel@tonic-gate 	 */
1137c478bd9Sstevel@tonic-gate 	char *adj_crypt_begin, *adj_crypt_end;
1147c478bd9Sstevel@tonic-gate 	char name[UTUSERLEN + sizeof (":")];
1157c478bd9Sstevel@tonic-gate 	char *p;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	FILE *opwfp = NULL, *ospfp = NULL, *oadjfp = NULL,
1187c478bd9Sstevel@tonic-gate 	    *npwfp = NULL, *nspfp = NULL, *nadjfp = NULL;
1197c478bd9Sstevel@tonic-gate 	int npwfd = -1, nspfd = -1, nadjfd = -1;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	int i, ans, chsh, chpw, chgecos, namelen;
1227c478bd9Sstevel@tonic-gate 	int gotadjunct = 0, gotshadow = 0, gotpasswd = 0;
1237c478bd9Sstevel@tonic-gate 	int doneflag = 0, root_on_master = 0;
1247c478bd9Sstevel@tonic-gate 	pid_t retval;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	time_t now;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	long pwpos = 0, sppos = 0;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/* Globals :-( */
1317c478bd9Sstevel@tonic-gate 	extern int single, nogecos, noshell, nopw, mflag, Mstart, Argc;
1327c478bd9Sstevel@tonic-gate 	extern char **Argv;
1337c478bd9Sstevel@tonic-gate 	extern char passwd_file[], shadow_file[], adjunct_file[];
1347c478bd9Sstevel@tonic-gate 	extern int useadjunct;
1357c478bd9Sstevel@tonic-gate 	extern int useshadow;
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/* Clean out yppwd */
1387c478bd9Sstevel@tonic-gate 	memset(&yppwd, 0, sizeof (struct yppasswd));
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	/* Get the RPC args */
1417c478bd9Sstevel@tonic-gate 	if (!svc_getargs(transp, xdr_yppasswd, (caddr_t)&yppwd)) {
1427c478bd9Sstevel@tonic-gate 		svcerr_decode(transp);
1437c478bd9Sstevel@tonic-gate 		return;
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	/* Perform basic validation */
1477c478bd9Sstevel@tonic-gate 	if (/* (!validstr(yppwd.oldpass, PWSIZE)) || */ /* see PR:nis/38 */
1487c478bd9Sstevel@tonic-gate 	    (!validstr(yppwd.newpw.pw_passwd, cryptpwsize)) ||
1497c478bd9Sstevel@tonic-gate 	    (!validstr(yppwd.newpw.pw_name, UTUSERLEN)) ||
1507c478bd9Sstevel@tonic-gate 	    (!validstr(yppwd.newpw.pw_gecos, fingersize)) ||
1517c478bd9Sstevel@tonic-gate 	    (!validstr(yppwd.newpw.pw_shell, shellsize))) {
1527c478bd9Sstevel@tonic-gate 		svcerr_decode(transp);
1537c478bd9Sstevel@tonic-gate 		return;
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	/*
1577c478bd9Sstevel@tonic-gate 	 * Special case: root on the master server can change other users'
1587c478bd9Sstevel@tonic-gate 	 * passwords without first entering the old password.  We need to
1597c478bd9Sstevel@tonic-gate 	 * ensure that this is indeed root on the master server. (bug 1253949)
1607c478bd9Sstevel@tonic-gate 	 */
1617c478bd9Sstevel@tonic-gate 	if (strcmp(transp->xp_netid, "ticlts") == 0) {
1627c478bd9Sstevel@tonic-gate 		svc_local_cred_t cred;
1637c478bd9Sstevel@tonic-gate 		if (!svc_get_local_cred(transp, &cred)) {
1647c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "yppasswdd: Couldn't get "
1657c478bd9Sstevel@tonic-gate 			    "local user credentials.\n");
1667c478bd9Sstevel@tonic-gate 		} else if (cred.ruid == 0)
1677c478bd9Sstevel@tonic-gate 			root_on_master = 1;
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	newpw = yppwd.newpw;
1717c478bd9Sstevel@tonic-gate 	strcpy(name, newpw.pw_name);
1727c478bd9Sstevel@tonic-gate 	strcat(name, ":");
1737c478bd9Sstevel@tonic-gate 	namelen = strlen(name);
1747c478bd9Sstevel@tonic-gate 	ans = 2;
1757c478bd9Sstevel@tonic-gate 	chsh = chpw = chgecos = 0;
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	/* Get all the filenames straight */
1787c478bd9Sstevel@tonic-gate 	strcpy(newpasswdfile, passwd_file);
1797c478bd9Sstevel@tonic-gate 	strcat(newpasswdfile, ".ptmp");
1807c478bd9Sstevel@tonic-gate 	strcpy(newshadowfile, shadow_file);
1817c478bd9Sstevel@tonic-gate 	strcat(newshadowfile, ".ptmp");
1827c478bd9Sstevel@tonic-gate 	strcpy(newadjunctfile, adjunct_file);
1837c478bd9Sstevel@tonic-gate 	strcat(newadjunctfile, ".ptmp");
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	memset(&sa, 0, sizeof (struct sigaction));
1867c478bd9Sstevel@tonic-gate 	sa.sa_handler = SIG_IGN;
1877c478bd9Sstevel@tonic-gate 	sigaction(SIGTSTP, &sa, (struct sigaction *)0);
1887c478bd9Sstevel@tonic-gate 	sigaction(SIGHUP,  &sa, &osa1);
1897c478bd9Sstevel@tonic-gate 	sigaction(SIGINT,  &sa, &osa2);
1907c478bd9Sstevel@tonic-gate 	sigaction(SIGQUIT, &sa, &osa3);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	/* Lock, then open the passwd and shadow files */
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate 	if (yplckpwdf() < 0) {
1957c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
1967c478bd9Sstevel@tonic-gate 		    "yppasswdd: Password file(s) busy. "
1977c478bd9Sstevel@tonic-gate 		    "Try again later.\n");
1987c478bd9Sstevel@tonic-gate 		ans = 8;
1997c478bd9Sstevel@tonic-gate 		goto cleanup;
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	if ((opwfp = fopen(passwd_file, "r")) == NULL) {
2037c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: Could not open %s\n", passwd_file);
2047c478bd9Sstevel@tonic-gate 		goto cleanup;
2057c478bd9Sstevel@tonic-gate 	}
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	fstat(fileno(opwfp), &pwstat);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	if (useshadow) {
2107c478bd9Sstevel@tonic-gate 		if ((ospfp = fopen(shadow_file, "r")) == NULL) {
2117c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
2127c478bd9Sstevel@tonic-gate 			    "yppasswdd: Could not open %s\n", shadow_file);
2137c478bd9Sstevel@tonic-gate 			goto cleanup;
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 		fstat(fileno(ospfp), &spstat);
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	if (useadjunct) {
2207c478bd9Sstevel@tonic-gate 		if ((oadjfp = fopen(adjunct_file, "r")) == NULL) {
2217c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
2227c478bd9Sstevel@tonic-gate 			    "yppasswdd: Could not open %s\n",
2237c478bd9Sstevel@tonic-gate 			    adjunct_file);
2247c478bd9Sstevel@tonic-gate 			goto cleanup;
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 		fstat(fileno(oadjfp), &adjstat);
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	/*
2317c478bd9Sstevel@tonic-gate 	 * Open the new passwd and shadow tmp files,
2327c478bd9Sstevel@tonic-gate 	 * first with open and then create a FILE * with fdopen()
2337c478bd9Sstevel@tonic-gate 	 */
2347c478bd9Sstevel@tonic-gate 	if ((npwfd = open(newpasswdfile, O_WRONLY | O_CREAT | O_EXCL,
2357c478bd9Sstevel@tonic-gate 	    pwstat.st_mode)) < 0) {
2367c478bd9Sstevel@tonic-gate 		if (errno == EEXIST) {
2377c478bd9Sstevel@tonic-gate 			syslog(LOG_WARNING,
2387c478bd9Sstevel@tonic-gate 			    "yppasswdd: passwd file busy - try again\n");
2397c478bd9Sstevel@tonic-gate 			ans = 8;
2407c478bd9Sstevel@tonic-gate 		} else {
2417c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "yppasswdd: %s: %m",
2427c478bd9Sstevel@tonic-gate 			    newpasswdfile);
2437c478bd9Sstevel@tonic-gate 			ans = 9;
2447c478bd9Sstevel@tonic-gate 		}
2457c478bd9Sstevel@tonic-gate 		goto cleanup;
2467c478bd9Sstevel@tonic-gate 	}
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	fchown(npwfd, pwstat.st_uid, pwstat.st_gid);
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	if ((npwfp = fdopen(npwfd, "w")) == NULL) {
2517c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
2527c478bd9Sstevel@tonic-gate 		    "yppasswdd: fdopen() on %s failed\n", newpasswdfile);
2537c478bd9Sstevel@tonic-gate 		goto cleanup;
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if (useshadow) {
2577c478bd9Sstevel@tonic-gate 		if ((nspfd = open(newshadowfile, O_WRONLY | O_CREAT | O_EXCL,
2587c478bd9Sstevel@tonic-gate 		    spstat.st_mode)) < 0) {
2597c478bd9Sstevel@tonic-gate 			if (errno == EEXIST) {
2607c478bd9Sstevel@tonic-gate 				syslog(LOG_WARNING,
261*07a8ec02SBen Chang 				    "yppasswdd: shadow file busy - try "
262*07a8ec02SBen Chang 				    "again\n");
2637c478bd9Sstevel@tonic-gate 				ans = 8;
2647c478bd9Sstevel@tonic-gate 			} else {
2657c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "yppasswdd: %s: %m",
2667c478bd9Sstevel@tonic-gate 				    newshadowfile);
2677c478bd9Sstevel@tonic-gate 				ans = 9;
2687c478bd9Sstevel@tonic-gate 			}
2697c478bd9Sstevel@tonic-gate 			goto cleanup;
2707c478bd9Sstevel@tonic-gate 		}
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 		fchown(nspfd, spstat.st_uid, spstat.st_gid);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 		if ((nspfp = fdopen(nspfd, "w")) == NULL) {
2757c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
2767c478bd9Sstevel@tonic-gate 			    "yppasswdd: fdopen() on %s failed\n",
2777c478bd9Sstevel@tonic-gate 			    newshadowfile);
2787c478bd9Sstevel@tonic-gate 			goto cleanup;
2797c478bd9Sstevel@tonic-gate 		}
2807c478bd9Sstevel@tonic-gate 	}
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (useadjunct) {
2837c478bd9Sstevel@tonic-gate 		if ((nadjfd = open(newadjunctfile, O_WRONLY | O_CREAT | O_EXCL,
2847c478bd9Sstevel@tonic-gate 		    adjstat.st_mode)) < 0) {
2857c478bd9Sstevel@tonic-gate 			if (errno == EEXIST) {
2867c478bd9Sstevel@tonic-gate 				syslog(LOG_WARNING,
287*07a8ec02SBen Chang 				    "yppasswdd: adjunct file busy - try "
288*07a8ec02SBen Chang 				    "again\n");
2897c478bd9Sstevel@tonic-gate 				ans = 8;
2907c478bd9Sstevel@tonic-gate 			} else {
2917c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "yppasswdd: %s: %m",
2927c478bd9Sstevel@tonic-gate 				    newadjunctfile);
2937c478bd9Sstevel@tonic-gate 				ans = 9;
2947c478bd9Sstevel@tonic-gate 			}
2957c478bd9Sstevel@tonic-gate 			goto cleanup;
2967c478bd9Sstevel@tonic-gate 		}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 		fchown(nadjfd, adjstat.st_uid, adjstat.st_gid);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		if ((nadjfp = fdopen(nadjfd, "w")) == NULL) {
3017c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
3027c478bd9Sstevel@tonic-gate 			    "yppasswdd: fdopen() on %s failed\n",
3037c478bd9Sstevel@tonic-gate 			    newadjunctfile);
3047c478bd9Sstevel@tonic-gate 			goto cleanup;
3057c478bd9Sstevel@tonic-gate 		}
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	/*
3097c478bd9Sstevel@tonic-gate 	 * The following code may not seem all that elegant, but my
3107c478bd9Sstevel@tonic-gate 	 * interpretation of the man pages relating to the passwd and
3117c478bd9Sstevel@tonic-gate 	 * shadow files would seem to indicate that there is no guarantee
3127c478bd9Sstevel@tonic-gate 	 * that the entries contained in those files will be in the same
3137c478bd9Sstevel@tonic-gate 	 * order...
3147c478bd9Sstevel@tonic-gate 	 *
3157c478bd9Sstevel@tonic-gate 	 * So here's the high level overview:
3167c478bd9Sstevel@tonic-gate 	 *
3177c478bd9Sstevel@tonic-gate 	 *    Loop through the passwd file reading in lines and writing them
3187c478bd9Sstevel@tonic-gate 	 *    out to the new file UNTIL we get to the correct entry.
3197c478bd9Sstevel@tonic-gate 	 *    IF we have a shadow file, loop through it reading in lines and
3207c478bd9Sstevel@tonic-gate 	 *    writing them out to the new file UNTIL we get to the correct
3217c478bd9Sstevel@tonic-gate 	 *    entry. IF we have an adjunct file, loop through it reading in
3227c478bd9Sstevel@tonic-gate 	 *    lines and writing them out to the new file UNTIL we get to the
3237c478bd9Sstevel@tonic-gate 	 *    correct entry.
3247c478bd9Sstevel@tonic-gate 	 *
3257c478bd9Sstevel@tonic-gate 	 *    Figure out what's changing, contruct the new passwd, shadow,
3267c478bd9Sstevel@tonic-gate 	 *    and adjunct entries and spit em out to the temp files.
3277c478bd9Sstevel@tonic-gate 	 *    At this point, set the done flag and leap back into the loop(s)
3287c478bd9Sstevel@tonic-gate 	 *    until you're finished with the files and then leap to the
3297c478bd9Sstevel@tonic-gate 	 *    section that installs the new files.
3307c478bd9Sstevel@tonic-gate 	 */
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate loop_in_files:
3337c478bd9Sstevel@tonic-gate 	/* While we find things in the passwd file */
3347c478bd9Sstevel@tonic-gate 	while (fgets(pwbuf, NSS_LINELEN_PASSWD, opwfp)) {
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 		/*
3377c478bd9Sstevel@tonic-gate 		 * Is this the passwd entry we want?
3387c478bd9Sstevel@tonic-gate 		 * If not, then write it out to the new passwd temp file
3397c478bd9Sstevel@tonic-gate 		 * and remember our position.
3407c478bd9Sstevel@tonic-gate 		 */
3417c478bd9Sstevel@tonic-gate 		if (doneflag || strncmp(name, pwbuf, namelen)) {
3427c478bd9Sstevel@tonic-gate 			if (fputs(pwbuf, npwfp) == EOF) {
3437c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
344*07a8ec02SBen Chang 				    "yppasswdd: write to passwd file "
345*07a8ec02SBen Chang 				    "failed.\n");
3467c478bd9Sstevel@tonic-gate 				goto cleanup;
3477c478bd9Sstevel@tonic-gate 			}
3487c478bd9Sstevel@tonic-gate 			pwpos = ftell(opwfp);
3497c478bd9Sstevel@tonic-gate 			continue;
3507c478bd9Sstevel@tonic-gate 		}
3517c478bd9Sstevel@tonic-gate 		gotpasswd = 1;
3527c478bd9Sstevel@tonic-gate 		break;
3537c478bd9Sstevel@tonic-gate 	}
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	/* no match */
3567c478bd9Sstevel@tonic-gate 	if (!gotpasswd) {
3577c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: user %s does not exist\n", name);
3587c478bd9Sstevel@tonic-gate 		goto cleanup;
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	/* While we find things in the shadow file */
3627c478bd9Sstevel@tonic-gate 	while (useshadow && fgets(spbuf, NSS_LINELEN_SHADOW, ospfp)) {
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 		/*
3657c478bd9Sstevel@tonic-gate 		 * Is this the shadow entry that we want?
3667c478bd9Sstevel@tonic-gate 		 * If not, write it out to the new shadow temp file
3677c478bd9Sstevel@tonic-gate 		 * and remember our position.
3687c478bd9Sstevel@tonic-gate 		 */
3697c478bd9Sstevel@tonic-gate 		if (doneflag || strncmp(name, spbuf, namelen)) {
3707c478bd9Sstevel@tonic-gate 			if (fputs(spbuf, nspfp) == EOF) {
3717c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
372*07a8ec02SBen Chang 				    "yppasswdd: write to shadow file "
373*07a8ec02SBen Chang 				    "failed.\n");
3747c478bd9Sstevel@tonic-gate 				goto cleanup;
3757c478bd9Sstevel@tonic-gate 			}
3767c478bd9Sstevel@tonic-gate 			sppos = ftell(ospfp);
3777c478bd9Sstevel@tonic-gate 			continue;
3787c478bd9Sstevel@tonic-gate 		}
3797c478bd9Sstevel@tonic-gate 		gotshadow = 1;
3807c478bd9Sstevel@tonic-gate 		break;
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	/* While we find things in the adjunct file */
3847c478bd9Sstevel@tonic-gate 	while (useadjunct && fgets(adjbuf, BUFSIZ, oadjfp)) {
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 		/*
3877c478bd9Sstevel@tonic-gate 		 * is this the adjunct entry that we want?
3887c478bd9Sstevel@tonic-gate 		 * If not, write it out to the new temp file
3897c478bd9Sstevel@tonic-gate 		 * and remember our position.
3907c478bd9Sstevel@tonic-gate 		 */
3917c478bd9Sstevel@tonic-gate 		if (doneflag || strncmp(name, adjbuf, namelen)) {
3927c478bd9Sstevel@tonic-gate 			if (fputs(adjbuf, nadjfp) == EOF) {
3937c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
394*07a8ec02SBen Chang 				    "yppasswdd: write to adjunct file "
395*07a8ec02SBen Chang 				    "failed.\n");
3967c478bd9Sstevel@tonic-gate 				goto cleanup;
3977c478bd9Sstevel@tonic-gate 			}
3987c478bd9Sstevel@tonic-gate 			continue;
3997c478bd9Sstevel@tonic-gate 		}
4007c478bd9Sstevel@tonic-gate 		gotadjunct = 1;
4017c478bd9Sstevel@tonic-gate 		break;
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	if (doneflag)
4057c478bd9Sstevel@tonic-gate 		goto install_files;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	if (useshadow && !gotshadow) {
4087c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: no passwd in shadow for %s\n",
4097c478bd9Sstevel@tonic-gate 		    newpw.pw_name);
4107c478bd9Sstevel@tonic-gate 		ans = 4;
4117c478bd9Sstevel@tonic-gate 		goto cleanup;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 	if (useadjunct && !gotadjunct) {
4147c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: no passwd in adjunct for %s\n",
4157c478bd9Sstevel@tonic-gate 		    newpw.pw_name);
4167c478bd9Sstevel@tonic-gate 		ans = 4;
4177c478bd9Sstevel@tonic-gate 		goto cleanup;
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	/*
4217c478bd9Sstevel@tonic-gate 	 * Now that we've read in the correct passwd AND
4227c478bd9Sstevel@tonic-gate 	 * shadow lines, we'll rewind to the beginning of
4237c478bd9Sstevel@tonic-gate 	 * those lines and let the fget*ent() calls do
4247c478bd9Sstevel@tonic-gate 	 * the work.  Since we are only working with the
4257c478bd9Sstevel@tonic-gate 	 * first two fields of the adjunct entry, leave
4267c478bd9Sstevel@tonic-gate 	 * it as a char array.
4277c478bd9Sstevel@tonic-gate 	 */
4287c478bd9Sstevel@tonic-gate 	fseek(opwfp, pwpos, SEEK_SET);
4297c478bd9Sstevel@tonic-gate 	opwd  = *fgetpwent(opwfp);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	if (useshadow) {
4327c478bd9Sstevel@tonic-gate 		fseek(ospfp, sppos, SEEK_SET);
4337c478bd9Sstevel@tonic-gate 		ospwd = *fgetspent(ospfp);
4347c478bd9Sstevel@tonic-gate 	}
4357c478bd9Sstevel@tonic-gate 
436*07a8ec02SBen Chang 	oldpass_crypt = cryptoldpasswd(yppwd.oldpass, newpw.pw_passwd,
437*07a8ec02SBen Chang 	    newpw.pw_name);
438*07a8ec02SBen Chang 	if (oldpass_crypt == NULL) {
439*07a8ec02SBen Chang 		ans = 3;
440*07a8ec02SBen Chang 		goto cleanup;
441*07a8ec02SBen Chang 	}
4427c478bd9Sstevel@tonic-gate 	p = newpw.pw_passwd;
4437c478bd9Sstevel@tonic-gate 	if ((!nopw) &&
4447c478bd9Sstevel@tonic-gate 	    p && *p &&
445*07a8ec02SBen Chang 	    !((*p++ == '#') && (*p++ == '#') &&
4467c478bd9Sstevel@tonic-gate 	    (strcmp(p, opwd.pw_name) == 0)) &&
447*07a8ec02SBen Chang 	    (strcmp(oldpass_crypt, newpw.pw_passwd) != 0))
4487c478bd9Sstevel@tonic-gate 		chpw = 1;
449*07a8ec02SBen Chang 	oldpass_crypt = NULL;
4507c478bd9Sstevel@tonic-gate 
4517c478bd9Sstevel@tonic-gate 	if ((!noshell) && (strcmp(opwd.pw_shell, newpw.pw_shell) != 0)) {
4527c478bd9Sstevel@tonic-gate 		if (single)
4537c478bd9Sstevel@tonic-gate 			chpw = 0;
4547c478bd9Sstevel@tonic-gate 		chsh = 1;
4557c478bd9Sstevel@tonic-gate 	}
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	if ((!nogecos) && (strcmp(opwd.pw_gecos, newpw.pw_gecos) != 0)) {
4587c478bd9Sstevel@tonic-gate 		if (single) {
4597c478bd9Sstevel@tonic-gate 			chpw = 0;
4607c478bd9Sstevel@tonic-gate 			chsh = 0;
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 		chgecos = 1;
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	if (!(chpw + chsh + chgecos)) {
4667c478bd9Sstevel@tonic-gate 		syslog(LOG_NOTICE, "yppasswdd: no change for %s\n",
4677c478bd9Sstevel@tonic-gate 		    newpw.pw_name);
4687c478bd9Sstevel@tonic-gate 		ans = 3;
4697c478bd9Sstevel@tonic-gate 		goto cleanup;
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	if (useshadow && !root_on_master) {
473*07a8ec02SBen Chang 		oldpass_crypt = cryptoldpasswd(yppwd.oldpass, ospwd.sp_pwdp,
474*07a8ec02SBen Chang 		    newpw.pw_name);
475*07a8ec02SBen Chang 		if (oldpass_crypt == NULL)
476*07a8ec02SBen Chang 			goto cleanup;
4777c478bd9Sstevel@tonic-gate 		if (ospwd.sp_pwdp && *ospwd.sp_pwdp &&
478*07a8ec02SBen Chang 		    (strcmp(oldpass_crypt, ospwd.sp_pwdp) != 0)) {
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 			syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n",
4817c478bd9Sstevel@tonic-gate 			    newpw.pw_name);
4827c478bd9Sstevel@tonic-gate 			ans = 7;
4837c478bd9Sstevel@tonic-gate 			goto cleanup;
4847c478bd9Sstevel@tonic-gate 		}
4857c478bd9Sstevel@tonic-gate 	} else if (useadjunct) {
4867c478bd9Sstevel@tonic-gate 		/*
4877c478bd9Sstevel@tonic-gate 		 * Clear the adj_encrypt array.  Extract the encrypted passwd
4887c478bd9Sstevel@tonic-gate 		 * into adj_encrypt by setting adj_crypt_begin and
4897c478bd9Sstevel@tonic-gate 		 * adj_crypt_end to point at the first character of the
4907c478bd9Sstevel@tonic-gate 		 * encrypted passwd and the first character following the
4917c478bd9Sstevel@tonic-gate 		 * encrypted passwd in adjbuf, respectively, and copy the
4927c478bd9Sstevel@tonic-gate 		 * stuff between (there may not be anything) into adj_ecrypt.
4937c478bd9Sstevel@tonic-gate 		 * Then, check that adj_encrypt contains something and that
4947c478bd9Sstevel@tonic-gate 		 * the old passwd is correct.
4957c478bd9Sstevel@tonic-gate 		 */
4967c478bd9Sstevel@tonic-gate 		memset(adj_encrypt, 0, sizeof (adj_encrypt));
4977c478bd9Sstevel@tonic-gate 		adj_crypt_begin = adjbuf + namelen;
4987c478bd9Sstevel@tonic-gate 		adj_crypt_end = strchr(adj_crypt_begin, ':');
4997c478bd9Sstevel@tonic-gate 		strncpy(adj_encrypt, adj_crypt_begin,
5007c478bd9Sstevel@tonic-gate 		    adj_crypt_end - adj_crypt_begin);
501*07a8ec02SBen Chang 		oldpass_crypt = cryptoldpasswd(yppwd.oldpass, adj_encrypt,
502*07a8ec02SBen Chang 		    newpw.pw_name);
503*07a8ec02SBen Chang 		if (oldpass_crypt == NULL)
504*07a8ec02SBen Chang 			goto cleanup;
5057c478bd9Sstevel@tonic-gate 		if (!root_on_master && *adj_encrypt &&
506*07a8ec02SBen Chang 		    (strcmp(oldpass_crypt, adj_encrypt) != 0)) {
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 			syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n",
5097c478bd9Sstevel@tonic-gate 			    newpw.pw_name);
5107c478bd9Sstevel@tonic-gate 			ans = 7;
5117c478bd9Sstevel@tonic-gate 			goto cleanup;
5127c478bd9Sstevel@tonic-gate 		}
5137c478bd9Sstevel@tonic-gate 	} else {
514*07a8ec02SBen Chang 		oldpass_crypt = cryptoldpasswd(yppwd.oldpass, opwd.pw_passwd,
515*07a8ec02SBen Chang 		    newpw.pw_name);
516*07a8ec02SBen Chang 		if (oldpass_crypt == NULL)
517*07a8ec02SBen Chang 			goto cleanup;
5187c478bd9Sstevel@tonic-gate 		if (!root_on_master && opwd.pw_passwd && *opwd.pw_passwd &&
519*07a8ec02SBen Chang 		    (strcmp(oldpass_crypt, opwd.pw_passwd) != 0)) {
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 			syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n",
5227c478bd9Sstevel@tonic-gate 			    newpw.pw_name);
5237c478bd9Sstevel@tonic-gate 			ans = 7;
5247c478bd9Sstevel@tonic-gate 			goto cleanup;
5257c478bd9Sstevel@tonic-gate 		}
5267c478bd9Sstevel@tonic-gate 	}
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate #ifdef DEBUG
5297c478bd9Sstevel@tonic-gate 	printf("%d %d %d\n", chsh, chgecos, chpw);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	printf("%s %s %s\n",
5327c478bd9Sstevel@tonic-gate 	    yppwd.newpw.pw_shell,
5337c478bd9Sstevel@tonic-gate 	    yppwd.newpw.pw_gecos,
5347c478bd9Sstevel@tonic-gate 	    yppwd.newpw.pw_passwd);
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	printf("%s %s %s\n",
5377c478bd9Sstevel@tonic-gate 	    opwd.pw_shell,
5387c478bd9Sstevel@tonic-gate 	    opwd.pw_gecos,
5397c478bd9Sstevel@tonic-gate 	    ospwd.sp_pwdp);
5407c478bd9Sstevel@tonic-gate #endif
5417c478bd9Sstevel@tonic-gate 
542*07a8ec02SBen Chang 	if (chsh &&
543*07a8ec02SBen Chang 	    !validloginshell(opwd.pw_shell, newpw.pw_shell, root_on_master)) {
5447c478bd9Sstevel@tonic-gate 		goto cleanup;
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	/* security hole fix from original source */
5487c478bd9Sstevel@tonic-gate 	for (p = newpw.pw_name; (*p != '\0'); p++)
5497c478bd9Sstevel@tonic-gate 		if ((*p == ':') || !(isprint(*p)))
5507c478bd9Sstevel@tonic-gate 			*p = '$';	/* you lose buckwheat */
5517c478bd9Sstevel@tonic-gate 	for (p = newpw.pw_passwd; (*p != '\0'); p++)
5527c478bd9Sstevel@tonic-gate 		if ((*p == ':') || !(isprint(*p)))
5537c478bd9Sstevel@tonic-gate 			*p = '$';	/* you lose buckwheat */
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	if (chgecos)
5567c478bd9Sstevel@tonic-gate 		opwd.pw_gecos = newpw.pw_gecos;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	if (chsh)
5597c478bd9Sstevel@tonic-gate 		opwd.pw_shell = newpw.pw_shell;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	/*
5627c478bd9Sstevel@tonic-gate 	 * If we're changing the shell or gecos fields and we're
5637c478bd9Sstevel@tonic-gate 	 * using a shadow or adjunct file or not changing the passwd
5647c478bd9Sstevel@tonic-gate 	 * then go ahead and update the passwd file.  The case where
5657c478bd9Sstevel@tonic-gate 	 * the passwd is being changed and we are not using a shadow
5667c478bd9Sstevel@tonic-gate 	 * or adjunct file is handled later.
5677c478bd9Sstevel@tonic-gate 	 */
5687c478bd9Sstevel@tonic-gate 	if ((chsh || chgecos) && (useshadow || useadjunct || !chpw) &&
5697c478bd9Sstevel@tonic-gate 	    putpwent(&opwd, npwfp)) {
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: putpwent failed: %s\n",
5727c478bd9Sstevel@tonic-gate 		    passwd_file);
5737c478bd9Sstevel@tonic-gate 		goto cleanup;
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	if (chpw) {
5777c478bd9Sstevel@tonic-gate 		if (useshadow) {
5787c478bd9Sstevel@tonic-gate 			ospwd.sp_pwdp = newpw.pw_passwd;
5797c478bd9Sstevel@tonic-gate 			now = DAY_NOW;
5807c478bd9Sstevel@tonic-gate 			/* password aging - bug for bug compatibility */
5817c478bd9Sstevel@tonic-gate 			if (ospwd.sp_max != -1) {
5827c478bd9Sstevel@tonic-gate 				if (now < ospwd.sp_lstchg + ospwd.sp_min) {
5837c478bd9Sstevel@tonic-gate 					syslog(LOG_ERR,
584*07a8ec02SBen Chang 					    "yppasswdd: Sorry: < %ld days "
585*07a8ec02SBen Chang 					    "since the last change.\n",
586*07a8ec02SBen Chang 					    ospwd.sp_min);
5877c478bd9Sstevel@tonic-gate 					goto cleanup;
5887c478bd9Sstevel@tonic-gate 				}
5897c478bd9Sstevel@tonic-gate 			}
5907c478bd9Sstevel@tonic-gate 			ospwd.sp_lstchg = now;
5917c478bd9Sstevel@tonic-gate 			if (putspent(&ospwd, nspfp)) {
5927c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
5937c478bd9Sstevel@tonic-gate 				    "yppasswdd: putspent failed: %s\n",
5947c478bd9Sstevel@tonic-gate 				    shadow_file);
5957c478bd9Sstevel@tonic-gate 				goto cleanup;
5967c478bd9Sstevel@tonic-gate 			}
5977c478bd9Sstevel@tonic-gate 		} else if (useadjunct) {
5987c478bd9Sstevel@tonic-gate 			sprintf(adjbuf_new,
599*07a8ec02SBen Chang 			    "%s%s%s", name, newpw.pw_passwd, adj_crypt_end);
6007c478bd9Sstevel@tonic-gate 			if (fputs(adjbuf_new, nadjfp) == EOF) {
6017c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
6027c478bd9Sstevel@tonic-gate 				    "yppasswdd: write to adjunct failed: %s\n",
6037c478bd9Sstevel@tonic-gate 				    adjunct_file);
6047c478bd9Sstevel@tonic-gate 				goto cleanup;
6057c478bd9Sstevel@tonic-gate 			}
6067c478bd9Sstevel@tonic-gate 		} else {
6077c478bd9Sstevel@tonic-gate 			opwd.pw_passwd = newpw.pw_passwd;
6087c478bd9Sstevel@tonic-gate 			if (putpwent(&opwd, npwfp)) {
6097c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
6107c478bd9Sstevel@tonic-gate 				    "yppasswdd: putpwent failed: %s\n",
6117c478bd9Sstevel@tonic-gate 				    passwd_file);
6127c478bd9Sstevel@tonic-gate 				goto cleanup;
6137c478bd9Sstevel@tonic-gate 			}
6147c478bd9Sstevel@tonic-gate 		}
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	if (!doneflag) {
6187c478bd9Sstevel@tonic-gate 		doneflag = 1;
6197c478bd9Sstevel@tonic-gate 		goto loop_in_files;
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate install_files:
6237c478bd9Sstevel@tonic-gate 	/*
6247c478bd9Sstevel@tonic-gate 	 * Critical section, nothing special needs to be done since we
6257c478bd9Sstevel@tonic-gate 	 * hold exclusive access to the *.ptmp files
6267c478bd9Sstevel@tonic-gate 	 */
6277c478bd9Sstevel@tonic-gate 	fflush(npwfp);
6287c478bd9Sstevel@tonic-gate 	if (useshadow)
6297c478bd9Sstevel@tonic-gate 		fflush(nspfp);
6307c478bd9Sstevel@tonic-gate 	if (useadjunct)
6317c478bd9Sstevel@tonic-gate 		fflush(nadjfp);
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 	strcpy(tmppasswdfile, passwd_file);
6347c478bd9Sstevel@tonic-gate 	strcat(tmppasswdfile, "-");
6357c478bd9Sstevel@tonic-gate 	if (useshadow) {
6367c478bd9Sstevel@tonic-gate 		strcpy(tmpshadowfile, shadow_file);
6377c478bd9Sstevel@tonic-gate 		strcat(tmpshadowfile, "-");
6387c478bd9Sstevel@tonic-gate 	}
6397c478bd9Sstevel@tonic-gate 	if (useadjunct) {
6407c478bd9Sstevel@tonic-gate 		strcpy(tmpadjunctfile, adjunct_file);
6417c478bd9Sstevel@tonic-gate 		strcat(tmpadjunctfile, "-");
6427c478bd9Sstevel@tonic-gate 	}
6437c478bd9Sstevel@tonic-gate 
6447c478bd9Sstevel@tonic-gate 	if ((!useshadow && !useadjunct) || (chsh || chgecos)) {
6457c478bd9Sstevel@tonic-gate 		if (rename(passwd_file, tmppasswdfile) < 0) {
6467c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, "yppasswdd: failed to backup "
6477c478bd9Sstevel@tonic-gate 			    "passwd file: %m");
6487c478bd9Sstevel@tonic-gate 			goto cleanup;
6497c478bd9Sstevel@tonic-gate 		} else {
6507c478bd9Sstevel@tonic-gate 			if (rename(newpasswdfile, passwd_file) < 0) {
6517c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
6527c478bd9Sstevel@tonic-gate 				    "yppasswdd: failed to mv passwd: %m");
6537c478bd9Sstevel@tonic-gate 				if (rename(tmppasswdfile, passwd_file) < 0) {
6547c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
6557c478bd9Sstevel@tonic-gate 					    "yppasswdd: failed to restore "
6567c478bd9Sstevel@tonic-gate 					    "backup of passwd file: %m");
6577c478bd9Sstevel@tonic-gate 				}
6587c478bd9Sstevel@tonic-gate 				goto cleanup;
6597c478bd9Sstevel@tonic-gate 			}
6607c478bd9Sstevel@tonic-gate 		}
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	if (useshadow && chpw) {
6647c478bd9Sstevel@tonic-gate 		if (rename(shadow_file, tmpshadowfile) < 0) {
6657c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, "yppasswdd: failed to back up "
6667c478bd9Sstevel@tonic-gate 			    "shadow file: %m");
6677c478bd9Sstevel@tonic-gate 			if (rename(tmppasswdfile, passwd_file) < 0) {
6687c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
6697c478bd9Sstevel@tonic-gate 				    "yppasswdd: failed to restore "
6707c478bd9Sstevel@tonic-gate 				    "backup of passwd file: %m");
6717c478bd9Sstevel@tonic-gate 			}
6727c478bd9Sstevel@tonic-gate 			goto cleanup;
6737c478bd9Sstevel@tonic-gate 		} else {
6747c478bd9Sstevel@tonic-gate 			if (rename(newshadowfile, shadow_file) < 0) {
6757c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
6767c478bd9Sstevel@tonic-gate 				    "yppasswdd: failed to mv shadow: %m");
6777c478bd9Sstevel@tonic-gate 				if (rename(tmpshadowfile, shadow_file) < 0) {
6787c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
6797c478bd9Sstevel@tonic-gate 					    "yppasswdd: failed to restore "
6807c478bd9Sstevel@tonic-gate 					    "backup of shadow file: %m");
6817c478bd9Sstevel@tonic-gate 				}
6827c478bd9Sstevel@tonic-gate 				if (rename(tmppasswdfile, passwd_file) < 0) {
6837c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
6847c478bd9Sstevel@tonic-gate 					    "yppasswdd: failed to restore "
6857c478bd9Sstevel@tonic-gate 					    "backup of passwd file: %m");
6867c478bd9Sstevel@tonic-gate 				}
6877c478bd9Sstevel@tonic-gate 				goto cleanup;
6887c478bd9Sstevel@tonic-gate 			}
6897c478bd9Sstevel@tonic-gate 		}
6907c478bd9Sstevel@tonic-gate 	} else if (useadjunct && chpw) {
6917c478bd9Sstevel@tonic-gate 		if (rename(adjunct_file, tmpadjunctfile) < 0) {
6927c478bd9Sstevel@tonic-gate 			syslog(LOG_CRIT, "yppasswdd: failed to back up "
6937c478bd9Sstevel@tonic-gate 			    "adjunct file: %m");
6947c478bd9Sstevel@tonic-gate 			if (rename(tmppasswdfile, passwd_file) < 0) {
6957c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
6967c478bd9Sstevel@tonic-gate 				    "yppasswdd: failed to restore backup "
6977c478bd9Sstevel@tonic-gate 				    "of passwd: %m");
6987c478bd9Sstevel@tonic-gate 			}
6997c478bd9Sstevel@tonic-gate 			goto cleanup;
7007c478bd9Sstevel@tonic-gate 		} else {
7017c478bd9Sstevel@tonic-gate 			if (rename(newadjunctfile, adjunct_file) < 0) {
7027c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
7037c478bd9Sstevel@tonic-gate 				    "yppassdd: failed to mv adjunct: %m");
7047c478bd9Sstevel@tonic-gate 				if (rename(tmppasswdfile, passwd_file) < 0) {
7057c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
7067c478bd9Sstevel@tonic-gate 					    "yppasswdd: failed to restore "
7077c478bd9Sstevel@tonic-gate 					    "backup of passwd file: %m");
7087c478bd9Sstevel@tonic-gate 				}
7097c478bd9Sstevel@tonic-gate 				if (rename(tmpadjunctfile, adjunct_file) < 0) {
7107c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
7117c478bd9Sstevel@tonic-gate 					    "yppasswdd: failed to restore "
7127c478bd9Sstevel@tonic-gate 					    "backup of adjunct file: %m");
7137c478bd9Sstevel@tonic-gate 				}
7147c478bd9Sstevel@tonic-gate 				goto cleanup;
7157c478bd9Sstevel@tonic-gate 			}
7167c478bd9Sstevel@tonic-gate 		}
7177c478bd9Sstevel@tonic-gate 	}
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	if (doneflag)
7207c478bd9Sstevel@tonic-gate 		ans = 0;
7217c478bd9Sstevel@tonic-gate 	/* End critical section */
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 	/*
7247c478bd9Sstevel@tonic-gate 	 *  Here we have come only after the new files have been successfully
7257c478bd9Sstevel@tonic-gate 	 * renamed to original files. At this point, the temp files would still
7267c478bd9Sstevel@tonic-gate 	 * be existing we need to remove them from the /etc directory
7277c478bd9Sstevel@tonic-gate 	 */
7287c478bd9Sstevel@tonic-gate 	unlink(tmppasswdfile);
7297c478bd9Sstevel@tonic-gate 	if (useshadow)
7307c478bd9Sstevel@tonic-gate 		unlink(tmpshadowfile);
7317c478bd9Sstevel@tonic-gate 	if (useadjunct)
7327c478bd9Sstevel@tonic-gate 		unlink(tmpadjunctfile);
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate cleanup:
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	/* If we don't have opwfp, then we didn't do anything */
7377c478bd9Sstevel@tonic-gate 	if (opwfp) {
7387c478bd9Sstevel@tonic-gate 		fclose(opwfp);
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 		if (ospfp) {
7417c478bd9Sstevel@tonic-gate 			fclose(ospfp);
7427c478bd9Sstevel@tonic-gate 		}
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 		if (oadjfp) {
7457c478bd9Sstevel@tonic-gate 			fclose(oadjfp);
7467c478bd9Sstevel@tonic-gate 		}
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 		unlink(newpasswdfile);
7497c478bd9Sstevel@tonic-gate 		/* These tests are cheaper than failing syscalls */
7507c478bd9Sstevel@tonic-gate 		if (useshadow)
7517c478bd9Sstevel@tonic-gate 			unlink(newshadowfile);
7527c478bd9Sstevel@tonic-gate 		if (useadjunct)
7537c478bd9Sstevel@tonic-gate 			unlink(newadjunctfile);
7547c478bd9Sstevel@tonic-gate 
7557c478bd9Sstevel@tonic-gate 		if (npwfp) {
7567c478bd9Sstevel@tonic-gate 			fclose(npwfp);
7577c478bd9Sstevel@tonic-gate 
7587c478bd9Sstevel@tonic-gate 			if (nspfp) {
7597c478bd9Sstevel@tonic-gate 				fclose(nspfp);
7607c478bd9Sstevel@tonic-gate 			}
7617c478bd9Sstevel@tonic-gate 			if (nadjfp) {
7627c478bd9Sstevel@tonic-gate 				fclose(nadjfp);
7637c478bd9Sstevel@tonic-gate 			}
7647c478bd9Sstevel@tonic-gate 		}
7657c478bd9Sstevel@tonic-gate 	}
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 	ypulckpwdf();
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	if (doneflag && mflag) {
7707c478bd9Sstevel@tonic-gate 		retval = fork();
7717c478bd9Sstevel@tonic-gate 		if (retval < 0) {
7727c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "yppasswdd: Fork failed %m");
7737c478bd9Sstevel@tonic-gate 		} else if (retval == 0) {
7747c478bd9Sstevel@tonic-gate 			strcpy(cmdbuf, "/usr/ccs/bin/make");
7757c478bd9Sstevel@tonic-gate 			for (i = Mstart + 1; i < Argc; i++) {
7767c478bd9Sstevel@tonic-gate 				strcat(cmdbuf, " ");
7777c478bd9Sstevel@tonic-gate 				strcat(cmdbuf, Argv[i]);
7787c478bd9Sstevel@tonic-gate 			}
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate #ifdef DEBUG
7817c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "yppasswdd: about to "
7827c478bd9Sstevel@tonic-gate 			    "execute %s\n", cmdbuf);
7837c478bd9Sstevel@tonic-gate #else
7847c478bd9Sstevel@tonic-gate 			if (yplckpwdf() < 0) {
7857c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR, "yppasswdd: Couldn't get the "
7867c478bd9Sstevel@tonic-gate 				    "lock to update the maps");
7877c478bd9Sstevel@tonic-gate 			} else {
7887c478bd9Sstevel@tonic-gate 				setpgrp();
7897c478bd9Sstevel@tonic-gate 				system(cmdbuf);
7907c478bd9Sstevel@tonic-gate 				ypulckpwdf();
7917c478bd9Sstevel@tonic-gate 			}
7927c478bd9Sstevel@tonic-gate #endif
7937c478bd9Sstevel@tonic-gate 			exit(0);
7947c478bd9Sstevel@tonic-gate 		}
7957c478bd9Sstevel@tonic-gate 	}
7967c478bd9Sstevel@tonic-gate 
7977c478bd9Sstevel@tonic-gate 	sigaction(SIGHUP,  &osa1, (struct sigaction *)0);
7987c478bd9Sstevel@tonic-gate 	sigaction(SIGINT,  &osa2, (struct sigaction *)0);
7997c478bd9Sstevel@tonic-gate 	sigaction(SIGQUIT, &osa3, (struct sigaction *)0);
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	if (!svc_sendreply(transp, xdr_int, (char *)&ans))
8027c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING,
8037c478bd9Sstevel@tonic-gate 		    "yppasswdd: couldn\'t reply to RPC call\n");
8047c478bd9Sstevel@tonic-gate }
805