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