xref: /titanic_52/usr/src/cmd/ypcmd/yppasswd/yppasswdd.c (revision a506a34ceb0e9dcc6c61bf0560202f8538928650)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*a506a34cSth160488  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <signal.h>
337c478bd9Sstevel@tonic-gate #include <fcntl.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <syslog.h>
377c478bd9Sstevel@tonic-gate #include <crypt.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
397c478bd9Sstevel@tonic-gate #include <tiuser.h>
407c478bd9Sstevel@tonic-gate #include <netdir.h>
417c478bd9Sstevel@tonic-gate #include <pwd.h>
427c478bd9Sstevel@tonic-gate #include <shadow.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #include <sys/wait.h>
467c478bd9Sstevel@tonic-gate #include <sys/resource.h>
477c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
487c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
497c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h>
507c478bd9Sstevel@tonic-gate #include <netconfig.h>
517c478bd9Sstevel@tonic-gate #include <deflt.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /* N2L includes */
547c478bd9Sstevel@tonic-gate #include <ndbm.h>
557c478bd9Sstevel@tonic-gate #include "shim.h"
567c478bd9Sstevel@tonic-gate #include "yptol.h"
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /* must match sizes in passwd */
597c478bd9Sstevel@tonic-gate #define	STRSIZE 100
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #define	DEFDIR "/etc/"
627c478bd9Sstevel@tonic-gate #define	MYPASSWD "passwd"
637c478bd9Sstevel@tonic-gate #define	MYSHADOW "shadow"
647c478bd9Sstevel@tonic-gate #define	DEFAULT_YPPASSWDD "/etc/default/yppasswdd"
657c478bd9Sstevel@tonic-gate #define	YPPASSWDD_STR "check_restricted_shell_name=1"
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /* The guts are in there */
68*a506a34cSth160488 extern void changepasswd(SVCXPRT *);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate static void	boilerplate(struct svc_req *rqstp, SVCXPRT *transp);
717c478bd9Sstevel@tonic-gate static void	unlimit(int lim);
727c478bd9Sstevel@tonic-gate bool_t		validloginshell(char *sh, char *arg, int);
737c478bd9Sstevel@tonic-gate int		validstr(char *str, size_t size);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate extern char  *getusershell(void);
767c478bd9Sstevel@tonic-gate extern void   setusershell(void);
777c478bd9Sstevel@tonic-gate extern void   endusershell(void);
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate int  Argc;
807c478bd9Sstevel@tonic-gate char **Argv;
817c478bd9Sstevel@tonic-gate int  mflag;			/* do a make */
827c478bd9Sstevel@tonic-gate int Mstart;
837c478bd9Sstevel@tonic-gate int single = 0;
847c478bd9Sstevel@tonic-gate int nogecos = 0;
857c478bd9Sstevel@tonic-gate int noshell = 0;
867c478bd9Sstevel@tonic-gate int nopw = 0;
877c478bd9Sstevel@tonic-gate int useadjunct = 0;
887c478bd9Sstevel@tonic-gate int useshadow = 0;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static char *defshell = "/bin/sh";
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /* These are the various reasons we might exit. */
937c478bd9Sstevel@tonic-gate enum exitstat {
947c478bd9Sstevel@tonic-gate     Esuccess,
957c478bd9Sstevel@tonic-gate     EminusDandfiles,
967c478bd9Sstevel@tonic-gate     Emissingdir,
977c478bd9Sstevel@tonic-gate     Emissingadjunct,
987c478bd9Sstevel@tonic-gate     Eaccesspasswd,
997c478bd9Sstevel@tonic-gate     Eaccessshadow,
1007c478bd9Sstevel@tonic-gate     Echdir,
1017c478bd9Sstevel@tonic-gate     Egetnetconfigent,
1027c478bd9Sstevel@tonic-gate     Et_open,
1037c478bd9Sstevel@tonic-gate     Enetdir_rsvdport,
1047c478bd9Sstevel@tonic-gate     Et_sync,
1057c478bd9Sstevel@tonic-gate     Et_info,
1067c478bd9Sstevel@tonic-gate     Esvc_create,
1077c478bd9Sstevel@tonic-gate     Esvc_reg,
1087c478bd9Sstevel@tonic-gate     Esvcrun_ret,
1097c478bd9Sstevel@tonic-gate     ElockFail,
1107c478bd9Sstevel@tonic-gate     EparseFail
1117c478bd9Sstevel@tonic-gate };
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate static char err_usage[] =
1147c478bd9Sstevel@tonic-gate "Usage:\n"
1157c478bd9Sstevel@tonic-gate "        rpc.yppasswdd [-D directory | passwd [passwd.adjunct]]\n"
1167c478bd9Sstevel@tonic-gate "                      [-nopw] [-nogecos]\n"
1177c478bd9Sstevel@tonic-gate "                      [-noshell] [-m arg1 arg2 ...]\n"
1187c478bd9Sstevel@tonic-gate "where\n"
1197c478bd9Sstevel@tonic-gate "        directory is the directory where the passwd, shadow and/or\n"
1207c478bd9Sstevel@tonic-gate "        passwd.adjunct files are found (/etc by default)\n"
1217c478bd9Sstevel@tonic-gate "        It should match the setting of PWDIR in /var/yp/Makefile\n\n"
1227c478bd9Sstevel@tonic-gate "        Alternatively, the old 4.1.x syntax is supported where\n"
1237c478bd9Sstevel@tonic-gate "        passwd is the path to the passwd file\n"
1247c478bd9Sstevel@tonic-gate "        passwd.adjunct is the patch to the passwd.adjunct file\n"
1257c478bd9Sstevel@tonic-gate "        NOTES:\n"
1267c478bd9Sstevel@tonic-gate "         1. The -D option and the passwd/passwd.adjunct arguments are\n"
1277c478bd9Sstevel@tonic-gate "            mutually exclusive\n"
1287c478bd9Sstevel@tonic-gate "         2. The old syntax deprecated and will be removed in a future\n"
1297c478bd9Sstevel@tonic-gate "            release\n"
1307c478bd9Sstevel@tonic-gate "         3. A shadow file found in the same directory as the passwd\n"
1317c478bd9Sstevel@tonic-gate "            will be assumed to contain the password information\n\n"
1327c478bd9Sstevel@tonic-gate "        arguments after -m are passed to make(1S) after password changes\n"
1337c478bd9Sstevel@tonic-gate "        -nopw passwords may not be changed remotely using passwd\n"
1347c478bd9Sstevel@tonic-gate "        -nogecos full name may not be changed remotely using passwd or chfn\n"
1357c478bd9Sstevel@tonic-gate "        -noshell shell may not be changed remotely using passwd or chsh\n";
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate char passwd_file[FILENAME_MAX], shadow_file[FILENAME_MAX];
1387c478bd9Sstevel@tonic-gate char lockfile[FILENAME_MAX], adjunct_file[FILENAME_MAX];
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate int
1417c478bd9Sstevel@tonic-gate main(int argc, char **argv)
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	SVCXPRT *transp4, *transp6, *transpl;
1447c478bd9Sstevel@tonic-gate 	struct netconfig *nconf4, *nconf6, *nconfl;
1457c478bd9Sstevel@tonic-gate 	int i, tli4, tli6, stat;
1467c478bd9Sstevel@tonic-gate 	int errorflag;
1477c478bd9Sstevel@tonic-gate 	int dfexcl; /* -D or files, not both flag */
1487c478bd9Sstevel@tonic-gate 	enum exitstat exitstatus = Esuccess;
1497c478bd9Sstevel@tonic-gate 	int connmaxrec = RPC_MAXDATASIZE;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	strcpy(passwd_file, DEFDIR MYPASSWD);
1527c478bd9Sstevel@tonic-gate 	strcpy(shadow_file, DEFDIR MYSHADOW);
1537c478bd9Sstevel@tonic-gate 	strcpy(lockfile, DEFDIR ".pwd.lock");
1547c478bd9Sstevel@tonic-gate 	strcpy(adjunct_file, DEFDIR "security/passwd.adjunct");
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	Argc = argc;
1577c478bd9Sstevel@tonic-gate 	Argv = argv;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	for (i = 1, errorflag = 0, dfexcl = 0; i < argc; i++) {
1607c478bd9Sstevel@tonic-gate 		if (argv[i][0] == '-' && argv[i][1] == 'm') {
1617c478bd9Sstevel@tonic-gate 		    if (access("/usr/ccs/bin/make", X_OK) < 0)
1627c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1637c478bd9Sstevel@tonic-gate 				"%s: /usr/ccs/bin/make is not available, "
1647c478bd9Sstevel@tonic-gate 				"ignoring -m option",
1657c478bd9Sstevel@tonic-gate 				argv[0]);
1667c478bd9Sstevel@tonic-gate 		    else {
1677c478bd9Sstevel@tonic-gate 			mflag++;
1687c478bd9Sstevel@tonic-gate 			Mstart = i;
1697c478bd9Sstevel@tonic-gate 			break;
1707c478bd9Sstevel@tonic-gate 		    }
1717c478bd9Sstevel@tonic-gate 		} else if (argv[i][0] == '-' && argv[i][1] == 'D') {
1727c478bd9Sstevel@tonic-gate 		    switch (dfexcl) {
1737c478bd9Sstevel@tonic-gate 		    case 0:
1747c478bd9Sstevel@tonic-gate 			if (++i < argc) {
1757c478bd9Sstevel@tonic-gate 			    strcpy(passwd_file, argv[i]);
1767c478bd9Sstevel@tonic-gate 			    strcpy(shadow_file, argv[i]);
1777c478bd9Sstevel@tonic-gate 			    strcpy(adjunct_file, argv[i]);
1787c478bd9Sstevel@tonic-gate 			    strcpy(lockfile, argv[i]);
1797c478bd9Sstevel@tonic-gate 			    if (argv[i][strlen(argv[i]) - 1] == '/') {
1807c478bd9Sstevel@tonic-gate 				strcat(passwd_file, MYPASSWD);
1817c478bd9Sstevel@tonic-gate 				strcat(shadow_file, MYSHADOW);
1827c478bd9Sstevel@tonic-gate 				strcat(lockfile, ".pwd.lock");
1837c478bd9Sstevel@tonic-gate 				strcat(adjunct_file, "security/passwd.adjunct");
1847c478bd9Sstevel@tonic-gate 			    } else {
1857c478bd9Sstevel@tonic-gate 				strcat(passwd_file, "/" MYPASSWD);
1867c478bd9Sstevel@tonic-gate 				strcat(shadow_file, "/" MYSHADOW);
1877c478bd9Sstevel@tonic-gate 				strcat(lockfile, "/.pwd.lock");
1887c478bd9Sstevel@tonic-gate 				strcat(adjunct_file,
1897c478bd9Sstevel@tonic-gate 					"/security/passwd.adjunct");
1907c478bd9Sstevel@tonic-gate 			    }
1917c478bd9Sstevel@tonic-gate 			    dfexcl++;
1927c478bd9Sstevel@tonic-gate 			} else {
1937c478bd9Sstevel@tonic-gate 			    fprintf(stderr,
1947c478bd9Sstevel@tonic-gate 				"rpc.yppasswdd: -D option requires a "
1957c478bd9Sstevel@tonic-gate 				"directory argument\n");
1967c478bd9Sstevel@tonic-gate 			    errorflag++;
1977c478bd9Sstevel@tonic-gate 			    exitstatus = Emissingdir;
1987c478bd9Sstevel@tonic-gate 			}
1997c478bd9Sstevel@tonic-gate 			break;
2007c478bd9Sstevel@tonic-gate 		    case 1:
2017c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2027c478bd9Sstevel@tonic-gate 				"rpc.yppasswdd: cannot specify passwd/"
2037c478bd9Sstevel@tonic-gate 				"passwd.adjunct pathnames AND use -D\n");
2047c478bd9Sstevel@tonic-gate 			errorflag++;
2057c478bd9Sstevel@tonic-gate 			dfexcl++;
2067c478bd9Sstevel@tonic-gate 			exitstatus = EminusDandfiles;
2077c478bd9Sstevel@tonic-gate 			break;
2087c478bd9Sstevel@tonic-gate 		    default:
2097c478bd9Sstevel@tonic-gate 			break;
2107c478bd9Sstevel@tonic-gate 		    }
2117c478bd9Sstevel@tonic-gate 	/* -single: Allow user to change only one of password,  */
2127c478bd9Sstevel@tonic-gate 	/*		shell, or full name at a time.  (WHY?)	*/
2137c478bd9Sstevel@tonic-gate 	/*	else if (strcmp(argv[i], "-single") == 0)	*/
2147c478bd9Sstevel@tonic-gate 	/*	    single = 1;					*/
2157c478bd9Sstevel@tonic-gate 	/*	else if (strcmp(argv[i], "-nosingle") == 0)	*/
2167c478bd9Sstevel@tonic-gate 	/*	    single = 0;					*/
2177c478bd9Sstevel@tonic-gate 		} else if (strcmp(argv[i], "-nogecos") == 0)
2187c478bd9Sstevel@tonic-gate 		    nogecos = 1;
2197c478bd9Sstevel@tonic-gate 		else if (strcmp(argv[i], "-nopw") == 0)
2207c478bd9Sstevel@tonic-gate 		    nopw = 1;
2217c478bd9Sstevel@tonic-gate 		else if (strcmp(argv[i], "-noshell") == 0)
2227c478bd9Sstevel@tonic-gate 		    noshell = 1;
2237c478bd9Sstevel@tonic-gate 		else if (argv[i][0] != '-') {
2247c478bd9Sstevel@tonic-gate 			/*
2257c478bd9Sstevel@tonic-gate 			 * If we find a shadow file, we warn that we're
2267c478bd9Sstevel@tonic-gate 			 * using it in addition to warning that the user
2277c478bd9Sstevel@tonic-gate 			 * it using a deprecated syntax.
2287c478bd9Sstevel@tonic-gate 			 */
2297c478bd9Sstevel@tonic-gate 		    errorflag++;
2307c478bd9Sstevel@tonic-gate 		    switch (dfexcl) {
2317c478bd9Sstevel@tonic-gate 		    case 0:
2327c478bd9Sstevel@tonic-gate 			strcpy(passwd_file, argv[i]);
2337c478bd9Sstevel@tonic-gate 			memset(shadow_file, 0, sizeof (shadow_file));
2347c478bd9Sstevel@tonic-gate 			strncpy(shadow_file, argv[i],
2357c478bd9Sstevel@tonic-gate 				strrchr(argv[i], '/') - argv[i] + 1);
2367c478bd9Sstevel@tonic-gate 			strcat(shadow_file, MYSHADOW);
2377c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2387c478bd9Sstevel@tonic-gate 				"rpc.yppasswdd: specifying the password file"
2397c478bd9Sstevel@tonic-gate 				" on the command line is \n"
2407c478bd9Sstevel@tonic-gate 				"               obsolete, "
2417c478bd9Sstevel@tonic-gate 				"consider using the -D option instead.\n");
2427c478bd9Sstevel@tonic-gate 			if (access(shadow_file, F_OK) == 0) {
2437c478bd9Sstevel@tonic-gate 			    fprintf(stderr,
2447c478bd9Sstevel@tonic-gate 				    "rpc.yppasswdd: found a shadow file in "
2457c478bd9Sstevel@tonic-gate 				    "the same directory as %s\n"
2467c478bd9Sstevel@tonic-gate 				    "               It will be used.\n",
2477c478bd9Sstevel@tonic-gate 				    passwd_file);
2487c478bd9Sstevel@tonic-gate 			}
2497c478bd9Sstevel@tonic-gate 			if (i + 1 < argc && argv[i+1][0] != '-') {
2507c478bd9Sstevel@tonic-gate 			    strcpy(adjunct_file, argv[++i]);
2517c478bd9Sstevel@tonic-gate 			    if (access(adjunct_file, F_OK) != 0) {
2527c478bd9Sstevel@tonic-gate 				fprintf(stderr,
2537c478bd9Sstevel@tonic-gate 					"rpc.yppasswdd: adjunct file %s "
2547c478bd9Sstevel@tonic-gate 					"not found\n",
2557c478bd9Sstevel@tonic-gate 					adjunct_file);
2567c478bd9Sstevel@tonic-gate 				exitstatus = Emissingadjunct;
2577c478bd9Sstevel@tonic-gate 			    }
2587c478bd9Sstevel@tonic-gate 			}
2597c478bd9Sstevel@tonic-gate 			dfexcl++;
2607c478bd9Sstevel@tonic-gate 			break;
2617c478bd9Sstevel@tonic-gate 		    case 1:
2627c478bd9Sstevel@tonic-gate 			fprintf(stderr,
2637c478bd9Sstevel@tonic-gate 				"rpc.yppasswdd: cannot specify passwd/"
2647c478bd9Sstevel@tonic-gate 				"passwd.adjunct pathnames AND use -D\n");
2657c478bd9Sstevel@tonic-gate 			dfexcl++;
2667c478bd9Sstevel@tonic-gate 			exitstatus = EminusDandfiles;
2677c478bd9Sstevel@tonic-gate 			break;
2687c478bd9Sstevel@tonic-gate 		    default:
2697c478bd9Sstevel@tonic-gate 			break;
2707c478bd9Sstevel@tonic-gate 		    }
2717c478bd9Sstevel@tonic-gate 		} else {
2727c478bd9Sstevel@tonic-gate 		    errorflag++;
2737c478bd9Sstevel@tonic-gate 		    fprintf(stderr,
2747c478bd9Sstevel@tonic-gate 			    "rpc.yppasswdd: unrecognized option %s ignored\n",
2757c478bd9Sstevel@tonic-gate 			    argv[i]);
2767c478bd9Sstevel@tonic-gate 		}
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	if (errorflag)
2807c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_usage);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	if (exitstatus)
2837c478bd9Sstevel@tonic-gate 		exit(exitstatus);
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	if (access(passwd_file, W_OK) < 0) {
2867c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rpc.yppasswdd: can't access %s\n",
2877c478bd9Sstevel@tonic-gate 			passwd_file);
2887c478bd9Sstevel@tonic-gate 		exitstatus = Eaccesspasswd;
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 	if (access(shadow_file, W_OK) == 0) {
2917c478bd9Sstevel@tonic-gate 		useshadow = 1;
2927c478bd9Sstevel@tonic-gate 	} else {
2937c478bd9Sstevel@tonic-gate 		/* We don't demand a shadow file unless we're looking at /etc */
2947c478bd9Sstevel@tonic-gate 		if (strcmp(DEFDIR MYSHADOW, shadow_file) == 0) {
2957c478bd9Sstevel@tonic-gate 		    fprintf(stderr, "rpc.yppasswdd: can't access %s\n",
2967c478bd9Sstevel@tonic-gate 				shadow_file);
2977c478bd9Sstevel@tonic-gate 		    exitstatus = Eaccessshadow;
2987c478bd9Sstevel@tonic-gate 		}
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 	if (access(adjunct_file, W_OK) == 0) {
3017c478bd9Sstevel@tonic-gate 		/* using an adjunct file */
3027c478bd9Sstevel@tonic-gate 		useadjunct = 1;
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	if (chdir("/var/yp") < 0) {
3067c478bd9Sstevel@tonic-gate 		fprintf(stderr, "rpc.yppasswdd: can't chdir to /var/yp\n");
3077c478bd9Sstevel@tonic-gate 		exitstatus = Echdir;
3087c478bd9Sstevel@tonic-gate 	}
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	if (exitstatus)
3117c478bd9Sstevel@tonic-gate 		exit(exitstatus);
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	if (errorflag)
3147c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\nProceeding.\n");
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	/*
3187c478bd9Sstevel@tonic-gate 	 * Initialize locking system.
3197c478bd9Sstevel@tonic-gate 	 * This is required for N2L version which accesses the DBM files.
3207c478bd9Sstevel@tonic-gate 	 * For the non N2L version this sets up some locking which, since non
3217c478bd9Sstevel@tonic-gate 	 * N2L mode does not access the DBM files, will be unused.
3227c478bd9Sstevel@tonic-gate 	 *
3237c478bd9Sstevel@tonic-gate 	 * This also sets up yptol_mode.
3247c478bd9Sstevel@tonic-gate 	 */
3257c478bd9Sstevel@tonic-gate 	if (!init_lock_system(TRUE)) {
3267c478bd9Sstevel@tonic-gate 		fprintf(stderr,
3277c478bd9Sstevel@tonic-gate 			"rpc.yppasswdd: Cant initialize locking system\n");
3287c478bd9Sstevel@tonic-gate 		exit(ElockFail);
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate #ifndef	DEBUG
3327c478bd9Sstevel@tonic-gate 	/* Close everything, but stdin/stdout/stderr */
3337c478bd9Sstevel@tonic-gate 	closefrom(3);
3347c478bd9Sstevel@tonic-gate #endif
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 	if (yptol_mode) {
3377c478bd9Sstevel@tonic-gate 		stat = parseConfig(NULL, NTOL_MAP_FILE);
3387c478bd9Sstevel@tonic-gate 		if (stat == 1) {
3397c478bd9Sstevel@tonic-gate 			fprintf(stderr, "yppasswdd : NIS to LDAP mapping"
3407c478bd9Sstevel@tonic-gate 							" inactive.\n");
3417c478bd9Sstevel@tonic-gate 		} else if (stat != 0) {
3427c478bd9Sstevel@tonic-gate 			fprintf(stderr, "yppasswdd : Aborting after NIS to LDAP"
3437c478bd9Sstevel@tonic-gate 							" mapping error.\n");
3447c478bd9Sstevel@tonic-gate 			exit(EparseFail);
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate #ifndef	DEBUG
3497c478bd9Sstevel@tonic-gate 	/* Wack umask that we inherited from parent */
3507c478bd9Sstevel@tonic-gate 	umask(0);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/* Be a midwife to ourselves */
3537c478bd9Sstevel@tonic-gate 	if (fork())
3547c478bd9Sstevel@tonic-gate 		exit(Esuccess);
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/* Disassociation is hard to do, la la la */
3577c478bd9Sstevel@tonic-gate 	setpgrp();
3587c478bd9Sstevel@tonic-gate 	setsid();
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	/* Ignore stuff */
3617c478bd9Sstevel@tonic-gate 	signal(SIGHUP, SIG_IGN);
3627c478bd9Sstevel@tonic-gate 	signal(SIGINT, SIG_IGN);
3637c478bd9Sstevel@tonic-gate 	signal(SIGWINCH, SIG_IGN);
3647c478bd9Sstevel@tonic-gate 	signal(SIGTSTP, SIG_IGN);
3657c478bd9Sstevel@tonic-gate 	signal(SIGTTIN, SIG_IGN);
3667c478bd9Sstevel@tonic-gate 	signal(SIGTTOU, SIG_IGN);
3677c478bd9Sstevel@tonic-gate 	signal(SIGCHLD, SIG_IGN);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	/*
3707c478bd9Sstevel@tonic-gate 	 * Just in case that wasn't enough, let's fork
3717c478bd9Sstevel@tonic-gate 	 * again.  (per Stevens).
3727c478bd9Sstevel@tonic-gate 	 */
3737c478bd9Sstevel@tonic-gate 	if (fork())
3747c478bd9Sstevel@tonic-gate 		exit(Esuccess);
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	/*
3777c478bd9Sstevel@tonic-gate 	 * We need stdin, stdout, and stderr later when we
3787c478bd9Sstevel@tonic-gate 	 * fork a make(1).
3797c478bd9Sstevel@tonic-gate 	 */
3807c478bd9Sstevel@tonic-gate 	freopen("/dev/null", "r+", stdin);
3817c478bd9Sstevel@tonic-gate 	freopen("/dev/null", "r+", stdout);
3827c478bd9Sstevel@tonic-gate 	freopen("/dev/null", "r+", stderr);
3837c478bd9Sstevel@tonic-gate #endif
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	openlog("yppasswdd", LOG_CONS | LOG_PID, LOG_AUTH);
3867c478bd9Sstevel@tonic-gate 	unlimit(RLIMIT_CPU);
3877c478bd9Sstevel@tonic-gate 	unlimit(RLIMIT_FSIZE);
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	/*
3907c478bd9Sstevel@tonic-gate 	 * Set non-blocking mode and maximum record size for
3917c478bd9Sstevel@tonic-gate 	 * connection oriented RPC transports.
3927c478bd9Sstevel@tonic-gate 	 */
3937c478bd9Sstevel@tonic-gate 	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
3947c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO, "unable to set maximum RPC record size");
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 	nconf4 = getnetconfigent("udp");
3987c478bd9Sstevel@tonic-gate 	nconf6 = getnetconfigent("udp6");
3997c478bd9Sstevel@tonic-gate 	if (nconf4 == 0 && nconf6 == 0) {
4007c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "udp/udp6 transport not supported\n");
4017c478bd9Sstevel@tonic-gate 		exit(Egetnetconfigent);
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	tli4 = (nconf4 != 0) ? t_open(nconf4->nc_device, O_RDWR, NULL) : -1;
4057c478bd9Sstevel@tonic-gate 	tli6 = (nconf6 != 0) ? t_open(nconf6->nc_device, O_RDWR, NULL) : -1;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	if (tli4 == -1 && tli6 == -1) {
4087c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can\'t open TLI endpoint(s)\n");
4097c478bd9Sstevel@tonic-gate 		exit(Et_open);
4107c478bd9Sstevel@tonic-gate 	}
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	if (tli4 != -1) {
4137c478bd9Sstevel@tonic-gate 		if (netdir_options(nconf4, ND_SET_RESERVEDPORT, tli4, NULL)) {
4147c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "could not set reserved port: %s\n",
4157c478bd9Sstevel@tonic-gate 				netdir_sperror());
4167c478bd9Sstevel@tonic-gate 			exit(Enetdir_rsvdport);
4177c478bd9Sstevel@tonic-gate 		}
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 	if (tli6 != -1) {
4207c478bd9Sstevel@tonic-gate 		if (netdir_options(nconf6, ND_SET_RESERVEDPORT, tli6, NULL)) {
4217c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "could not set reserved port: %s\n",
4227c478bd9Sstevel@tonic-gate 				netdir_sperror());
4237c478bd9Sstevel@tonic-gate 			exit(Enetdir_rsvdport);
4247c478bd9Sstevel@tonic-gate 		}
4257c478bd9Sstevel@tonic-gate 	}
4267c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4277c478bd9Sstevel@tonic-gate 	{
4287c478bd9Sstevel@tonic-gate 		int i, tli[2];
4297c478bd9Sstevel@tonic-gate 		char *label[2] = {"udp", "udp6"};
4307c478bd9Sstevel@tonic-gate 		int state;
4317c478bd9Sstevel@tonic-gate 		struct t_info tinfo;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 		tli[0] = tli4;
4347c478bd9Sstevel@tonic-gate 		tli[1] = tli6;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 		for (i = 0; i < sizeof (tli)/sizeof (tli[0]); i++) {
4377c478bd9Sstevel@tonic-gate 			fprintf(stderr, "transport %s, fd = %d\n",
4387c478bd9Sstevel@tonic-gate 				tli[i], label[i]);
4397c478bd9Sstevel@tonic-gate 			if ((state = t_sync(tli[i])) < 0) {
4407c478bd9Sstevel@tonic-gate 				fprintf(stderr, "t_sync failed: %s\n",
4417c478bd9Sstevel@tonic-gate 					t_errlist[t_errno]);
4427c478bd9Sstevel@tonic-gate 				exit(Et_sync);
4437c478bd9Sstevel@tonic-gate 			}
4447c478bd9Sstevel@tonic-gate 			if (t_getinfo(tli[i], &tinfo) < 0) {
4457c478bd9Sstevel@tonic-gate 				fprintf(stderr, "t_getinfo failed: %s\n",
4467c478bd9Sstevel@tonic-gate 					t_errlist[t_errno]);
4477c478bd9Sstevel@tonic-gate 				exit(Et_info);
4487c478bd9Sstevel@tonic-gate 			}
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 			switch (state) {
4517c478bd9Sstevel@tonic-gate 			case T_UNBND:
4527c478bd9Sstevel@tonic-gate 				fprintf(stderr, "TLI is unbound\n");
4537c478bd9Sstevel@tonic-gate 				break;
4547c478bd9Sstevel@tonic-gate 			case T_IDLE:
4557c478bd9Sstevel@tonic-gate 				fprintf(stderr, "TLI is idle\n");
4567c478bd9Sstevel@tonic-gate 				break;
4577c478bd9Sstevel@tonic-gate 			case T_INREL:
4587c478bd9Sstevel@tonic-gate 				fprintf(stderr,
4597c478bd9Sstevel@tonic-gate 					"other side wants to release\n");
4607c478bd9Sstevel@tonic-gate 				break;
4617c478bd9Sstevel@tonic-gate 			case T_INCON:
4627c478bd9Sstevel@tonic-gate 				fprintf(stderr, "T_INCON\n");
4637c478bd9Sstevel@tonic-gate 				break;
4647c478bd9Sstevel@tonic-gate 			case T_DATAXFER:
4657c478bd9Sstevel@tonic-gate 				fprintf(stderr, "T_DATAXFER\n");
4667c478bd9Sstevel@tonic-gate 				break;
4677c478bd9Sstevel@tonic-gate 			default:
4687c478bd9Sstevel@tonic-gate 				fprintf(stderr, "no state info, state = %d\n",
4697c478bd9Sstevel@tonic-gate 					state);
4707c478bd9Sstevel@tonic-gate 			}
4717c478bd9Sstevel@tonic-gate 		}
4727c478bd9Sstevel@tonic-gate 	}
4737c478bd9Sstevel@tonic-gate #endif
4747c478bd9Sstevel@tonic-gate 	if (tli4 != -1) {
4757c478bd9Sstevel@tonic-gate 		rpcb_unset((ulong_t)YPPASSWDPROG, (ulong_t)YPPASSWDVERS,
4767c478bd9Sstevel@tonic-gate 			nconf4);
4777c478bd9Sstevel@tonic-gate 		transp4 = svc_tli_create(tli4, nconf4, NULL, 0, 0);
4787c478bd9Sstevel@tonic-gate 	} else {
4797c478bd9Sstevel@tonic-gate 		transp4 = 0;
4807c478bd9Sstevel@tonic-gate 	}
4817c478bd9Sstevel@tonic-gate 	if (tli6 != -1) {
4827c478bd9Sstevel@tonic-gate 		rpcb_unset((ulong_t)YPPASSWDPROG, (ulong_t)YPPASSWDVERS,
4837c478bd9Sstevel@tonic-gate 			nconf6);
4847c478bd9Sstevel@tonic-gate 		transp6 = svc_tli_create(tli6, nconf6, NULL, 0, 0);
4857c478bd9Sstevel@tonic-gate 	} else {
4867c478bd9Sstevel@tonic-gate 		transp6 = 0;
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 	if (transp4 == 0 && transp6 == 0) {
4897c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: couldn't create an RPC server\n");
4907c478bd9Sstevel@tonic-gate 		exit(Esvc_create);
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 	if (transp4 && !svc_reg(transp4, (ulong_t)YPPASSWDPROG,
4937c478bd9Sstevel@tonic-gate 			(ulong_t)YPPASSWDVERS, boilerplate, nconf4)) {
4947c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: couldn't register yppasswdd\n");
4957c478bd9Sstevel@tonic-gate 		exit(Esvc_reg);
4967c478bd9Sstevel@tonic-gate 	}
4977c478bd9Sstevel@tonic-gate 	if (transp6 && !svc_reg(transp6, (ulong_t)YPPASSWDPROG,
4987c478bd9Sstevel@tonic-gate 			(ulong_t)YPPASSWDVERS, boilerplate, nconf6)) {
4997c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: couldn't register yppasswdd\n");
5007c478bd9Sstevel@tonic-gate 		exit(Esvc_reg);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	/*
5047c478bd9Sstevel@tonic-gate 	 * Create a loopback RPC service for secure authentication of local
5057c478bd9Sstevel@tonic-gate 	 * principals -- we need this for accepting passwd updates from
5067c478bd9Sstevel@tonic-gate 	 * root on the master server.
5077c478bd9Sstevel@tonic-gate 	 */
5087c478bd9Sstevel@tonic-gate 	if ((nconfl = getnetconfigent("ticlts")) == NULL) {
5097c478bd9Sstevel@tonic-gate 	    syslog(LOG_ERR, "transport ticlts not supported\n");
5107c478bd9Sstevel@tonic-gate 	    exit(Egetnetconfigent);
5117c478bd9Sstevel@tonic-gate 	}
5127c478bd9Sstevel@tonic-gate 	rpcb_unset((ulong_t)YPPASSWDPROG, (ulong_t)YPPASSWDVERS, nconfl);
5137c478bd9Sstevel@tonic-gate 	transpl = svc_tli_create(RPC_ANYFD, nconfl, NULL, 0, 0);
5147c478bd9Sstevel@tonic-gate 	if (transpl == NULL) {
5157c478bd9Sstevel@tonic-gate 	    syslog(LOG_ERR,
5167c478bd9Sstevel@tonic-gate 		"yppasswdd: couldn't create an loopback RPC server\n");
5177c478bd9Sstevel@tonic-gate 	    exit(Esvc_create);
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 	if (!svc_reg(transpl, (ulong_t)YPPASSWDPROG, (ulong_t)YPPASSWDVERS,
5207c478bd9Sstevel@tonic-gate 			boilerplate, nconfl)) {
5217c478bd9Sstevel@tonic-gate 	    syslog(LOG_ERR, "yppasswdd: couldn't register yppasswdd\n");
5227c478bd9Sstevel@tonic-gate 	    exit(Esvc_reg);
5237c478bd9Sstevel@tonic-gate 	}
5247c478bd9Sstevel@tonic-gate 	__rpc_negotiate_uid(transpl->xp_fd);
5257c478bd9Sstevel@tonic-gate 	freenetconfigent(nconf4);
5267c478bd9Sstevel@tonic-gate 	freenetconfigent(nconf6);
5277c478bd9Sstevel@tonic-gate 	freenetconfigent(nconfl);
5287c478bd9Sstevel@tonic-gate 	svc_run();
5297c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, "yppasswdd: svc_run shouldn't have returned\n");
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	return (Esvcrun_ret);
5327c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate static void
5367c478bd9Sstevel@tonic-gate boilerplate(struct svc_req *rqstp, SVCXPRT *transp)
5377c478bd9Sstevel@tonic-gate {
5387c478bd9Sstevel@tonic-gate 	switch (rqstp->rq_proc) {
5397c478bd9Sstevel@tonic-gate 	case NULLPROC:
5407c478bd9Sstevel@tonic-gate 		if (!svc_sendreply(transp, xdr_void, (char *)0))
5417c478bd9Sstevel@tonic-gate 		    syslog(LOG_WARNING,
5427c478bd9Sstevel@tonic-gate 			"yppasswdd: couldn't reply to RPC call\n");
5437c478bd9Sstevel@tonic-gate 		break;
5447c478bd9Sstevel@tonic-gate 	case YPPASSWDPROC_UPDATE:
5457c478bd9Sstevel@tonic-gate 		if (yptol_mode)
5467c478bd9Sstevel@tonic-gate 			shim_changepasswd(transp);
5477c478bd9Sstevel@tonic-gate 		else
5487c478bd9Sstevel@tonic-gate 			changepasswd(transp);
5497c478bd9Sstevel@tonic-gate 		break;
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate int
5547c478bd9Sstevel@tonic-gate validstr(char *str, size_t size)
5557c478bd9Sstevel@tonic-gate {
5567c478bd9Sstevel@tonic-gate 	char c;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	if (str == NULL || strlen(str) > size || strchr(str, ':'))
5597c478bd9Sstevel@tonic-gate 		return (0);
5607c478bd9Sstevel@tonic-gate 	while (c = *str++) {
5617c478bd9Sstevel@tonic-gate 		if (iscntrl(c))
5627c478bd9Sstevel@tonic-gate 		    return (0);
5637c478bd9Sstevel@tonic-gate 	}
5647c478bd9Sstevel@tonic-gate 	return (1);
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate bool_t
5687c478bd9Sstevel@tonic-gate validloginshell(char *pw_shell, char *arg, int privileged)
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate 	static char newshell[STRSIZE];
5717c478bd9Sstevel@tonic-gate 	char *cp, *valid;
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	if (pw_shell == 0 || *pw_shell == '\0')
5747c478bd9Sstevel@tonic-gate 		pw_shell = defshell;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	if ((defopen(DEFAULT_YPPASSWDD)) == 0) {
5777c478bd9Sstevel@tonic-gate 		if ((defread(YPPASSWDD_STR)) != NULL) {
5787c478bd9Sstevel@tonic-gate 			cp = strrchr(pw_shell, '/');
5797c478bd9Sstevel@tonic-gate 			if (cp)
5807c478bd9Sstevel@tonic-gate 				cp++;
5817c478bd9Sstevel@tonic-gate 			else
5827c478bd9Sstevel@tonic-gate 				cp = pw_shell;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 			if (*cp == 'r') {
5857c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
5867c478bd9Sstevel@tonic-gate 					"yppasswdd: cannot change "
5877c478bd9Sstevel@tonic-gate 					"from restricted shell %s\n",
5887c478bd9Sstevel@tonic-gate 					pw_shell);
5897c478bd9Sstevel@tonic-gate 				return (0);
5907c478bd9Sstevel@tonic-gate 			}
5917c478bd9Sstevel@tonic-gate 		}
5927c478bd9Sstevel@tonic-gate 		(void) defopen((char *)NULL);
5937c478bd9Sstevel@tonic-gate 	}
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	for (valid = getusershell(); valid; valid = getusershell())
5967c478bd9Sstevel@tonic-gate 		if (strcmp(pw_shell, valid) == 0)
5977c478bd9Sstevel@tonic-gate 		    break;
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 	if (valid == NULL && !privileged) {
6007c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "yppasswdd: Current shell is not valid: %s\n",
6017c478bd9Sstevel@tonic-gate 			pw_shell);
6027c478bd9Sstevel@tonic-gate 		endusershell();
6037c478bd9Sstevel@tonic-gate 		return (0);
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	if (arg != 0) {
6077c478bd9Sstevel@tonic-gate 		strncpy(newshell, arg, sizeof (newshell) - 1);
6087c478bd9Sstevel@tonic-gate 		newshell[sizeof (newshell) - 1] = 0;
6097c478bd9Sstevel@tonic-gate 	} else {
6107c478bd9Sstevel@tonic-gate 		endusershell();
6117c478bd9Sstevel@tonic-gate 		return (0);
6127c478bd9Sstevel@tonic-gate 	}
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	/*
6157c478bd9Sstevel@tonic-gate 	 * Allow user to give shell name w/o preceding pathname.
6167c478bd9Sstevel@tonic-gate 	 */
6177c478bd9Sstevel@tonic-gate 	setusershell();
6187c478bd9Sstevel@tonic-gate 	for (valid = getusershell(); valid; valid = getusershell()) {
6197c478bd9Sstevel@tonic-gate 		if (newshell[0] == '/') {
6207c478bd9Sstevel@tonic-gate 		    cp = valid;
6217c478bd9Sstevel@tonic-gate 		} else {
6227c478bd9Sstevel@tonic-gate 		    cp = strrchr(valid, '/');
6237c478bd9Sstevel@tonic-gate 		    if (cp == 0)
6247c478bd9Sstevel@tonic-gate 			cp = valid;
6257c478bd9Sstevel@tonic-gate 		    else
6267c478bd9Sstevel@tonic-gate 			cp++;
6277c478bd9Sstevel@tonic-gate 		}
6287c478bd9Sstevel@tonic-gate 		if (strcmp(newshell, cp) == 0)
6297c478bd9Sstevel@tonic-gate 		    break;
6307c478bd9Sstevel@tonic-gate 	}
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate 	if (valid == 0) {
6337c478bd9Sstevel@tonic-gate 		if (!privileged || newshell[0] != '/') {
6347c478bd9Sstevel@tonic-gate 			syslog(LOG_WARNING,
6357c478bd9Sstevel@tonic-gate 				"%s is unacceptable as a new shell.\n",
6367c478bd9Sstevel@tonic-gate 				newshell);
6377c478bd9Sstevel@tonic-gate 			endusershell();
6387c478bd9Sstevel@tonic-gate 			return (0);
6397c478bd9Sstevel@tonic-gate 		}
6407c478bd9Sstevel@tonic-gate 		valid = newshell;
6417c478bd9Sstevel@tonic-gate 	}
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	if (access(valid, X_OK) < 0) {
6447c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING, "%s is unavailable.\n", valid);
6457c478bd9Sstevel@tonic-gate 		endusershell();
6467c478bd9Sstevel@tonic-gate 		return (0);
6477c478bd9Sstevel@tonic-gate 	}
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate 	strncpy(newshell, valid, sizeof (newshell));
6507c478bd9Sstevel@tonic-gate 	pw_shell =  newshell;
6517c478bd9Sstevel@tonic-gate 	endusershell();
6527c478bd9Sstevel@tonic-gate 	return (1);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate static void
6567c478bd9Sstevel@tonic-gate unlimit(int lim)
6577c478bd9Sstevel@tonic-gate {
6587c478bd9Sstevel@tonic-gate 	struct rlimit rlim;
6597c478bd9Sstevel@tonic-gate 	rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
6607c478bd9Sstevel@tonic-gate 	setrlimit(lim, &rlim);
6617c478bd9Sstevel@tonic-gate }
662