xref: /titanic_44/usr/src/cmd/login/login.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
28*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
29*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*
32*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
33*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
34*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
35*7c478bd9Sstevel@tonic-gate  *
36*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
37*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
38*7c478bd9Sstevel@tonic-gate  * contributors.
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
42*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /*
49*7c478bd9Sstevel@tonic-gate  * For a complete reference to login(1), see the manual page.  However,
50*7c478bd9Sstevel@tonic-gate  * login has accreted some intentionally undocumented options, which are
51*7c478bd9Sstevel@tonic-gate  * explained here:
52*7c478bd9Sstevel@tonic-gate  *
53*7c478bd9Sstevel@tonic-gate  * -a: This legacy flag appears to be unused.
54*7c478bd9Sstevel@tonic-gate  *
55*7c478bd9Sstevel@tonic-gate  * -f <username>: This flag was introduced by PSARC 1995/039 in support
56*7c478bd9Sstevel@tonic-gate  *    of Kerberos.  But it's not used by Sun's Kerberos implementation.
57*7c478bd9Sstevel@tonic-gate  *    It is however employed by zlogin(1), since it allows one to tell
58*7c478bd9Sstevel@tonic-gate  *    login: "This user is authenticated."  In the case of zlogin that's
59*7c478bd9Sstevel@tonic-gate  *    true because the zone always trusts the global zone.
60*7c478bd9Sstevel@tonic-gate  *
61*7c478bd9Sstevel@tonic-gate  * -z <zonename>: This flag is passed to login when zlogin(1) executes a
62*7c478bd9Sstevel@tonic-gate  *    zone login.  This tells login(1) to skip it's normal CONSOLE check
63*7c478bd9Sstevel@tonic-gate  *    (i.e. that the root login must be on /dev/console) and tells us the
64*7c478bd9Sstevel@tonic-gate  *    name of the zone from which the login is occuring.
65*7c478bd9Sstevel@tonic-gate  */
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
68*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
69*7c478bd9Sstevel@tonic-gate #include <unistd.h>	/* For logfile locking */
70*7c478bd9Sstevel@tonic-gate #include <signal.h>
71*7c478bd9Sstevel@tonic-gate #include <stdio.h>
72*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
73*7c478bd9Sstevel@tonic-gate #include <string.h>
74*7c478bd9Sstevel@tonic-gate #include <deflt.h>
75*7c478bd9Sstevel@tonic-gate #include <grp.h>
76*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
77*7c478bd9Sstevel@tonic-gate #include <lastlog.h>
78*7c478bd9Sstevel@tonic-gate #include <termio.h>
79*7c478bd9Sstevel@tonic-gate #include <utmpx.h>
80*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
81*7c478bd9Sstevel@tonic-gate #include <wait.h>
82*7c478bd9Sstevel@tonic-gate #include <errno.h>
83*7c478bd9Sstevel@tonic-gate #include <ctype.h>
84*7c478bd9Sstevel@tonic-gate #include <syslog.h>
85*7c478bd9Sstevel@tonic-gate #include <ulimit.h>
86*7c478bd9Sstevel@tonic-gate #include <libgen.h>
87*7c478bd9Sstevel@tonic-gate #include <pwd.h>
88*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
89*7c478bd9Sstevel@tonic-gate #include <strings.h>
90*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
91*7c478bd9Sstevel@tonic-gate #include <zone.h>
92*7c478bd9Sstevel@tonic-gate #include "login_audit.h"
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate #include <krb5_repository.h>
95*7c478bd9Sstevel@tonic-gate /*
96*7c478bd9Sstevel@tonic-gate  *
97*7c478bd9Sstevel@tonic-gate  *	    *** Defines, Macros, and String Constants  ***
98*7c478bd9Sstevel@tonic-gate  *
99*7c478bd9Sstevel@tonic-gate  *
100*7c478bd9Sstevel@tonic-gate  */
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate #define	ISSUEFILE "/etc/issue"	/* file to print before prompt */
103*7c478bd9Sstevel@tonic-gate #define	NOLOGIN	"/etc/nologin"	/* file to lock users out during shutdown */
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  * These need to be defined for UTMPX management.
107*7c478bd9Sstevel@tonic-gate  * If we add in the utility functions later, we
108*7c478bd9Sstevel@tonic-gate  * can remove them.
109*7c478bd9Sstevel@tonic-gate  */
110*7c478bd9Sstevel@tonic-gate #define	__UPDATE_ENTRY	1
111*7c478bd9Sstevel@tonic-gate #define	__LOGIN		2
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate  * Intervals to sleep after failed login
115*7c478bd9Sstevel@tonic-gate  */
116*7c478bd9Sstevel@tonic-gate #ifndef	SLEEPTIME
117*7c478bd9Sstevel@tonic-gate #define	SLEEPTIME 4	/* sleeptime before login incorrect msg */
118*7c478bd9Sstevel@tonic-gate #endif
119*7c478bd9Sstevel@tonic-gate static int	Sleeptime = SLEEPTIME;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate  * seconds login disabled after allowable number of unsuccessful attempts
123*7c478bd9Sstevel@tonic-gate  */
124*7c478bd9Sstevel@tonic-gate #ifndef	DISABLETIME
125*7c478bd9Sstevel@tonic-gate #define	DISABLETIME	20
126*7c478bd9Sstevel@tonic-gate #endif
127*7c478bd9Sstevel@tonic-gate static int	Disabletime = DISABLETIME;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate #define	MAXTRYS		5
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate static int	retry = MAXTRYS;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate /*
134*7c478bd9Sstevel@tonic-gate  * Login logging support
135*7c478bd9Sstevel@tonic-gate  */
136*7c478bd9Sstevel@tonic-gate #define	LOGINLOG	"/var/adm/loginlog"	/* login log file */
137*7c478bd9Sstevel@tonic-gate #define	LNAME_SIZE	20	/* size of logged logname */
138*7c478bd9Sstevel@tonic-gate #define	TTYN_SIZE	15	/* size of logged tty name */
139*7c478bd9Sstevel@tonic-gate #define	TIME_SIZE	30	/* size of logged time string */
140*7c478bd9Sstevel@tonic-gate #define	ENT_SIZE	(LNAME_SIZE + TTYN_SIZE + TIME_SIZE + 3)
141*7c478bd9Sstevel@tonic-gate #define	L_WAITTIME	5	/* waittime for log file to unlock */
142*7c478bd9Sstevel@tonic-gate #define	LOGTRYS		10	/* depth of 'try' logging */
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /*
145*7c478bd9Sstevel@tonic-gate  * String manipulation macros: SCPYN, SCPYL, EQN and ENVSTRNCAT
146*7c478bd9Sstevel@tonic-gate  * SCPYL is the safer version of SCPYN
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate #define	SCPYL(a, b)	(void) strlcpy(a, b, sizeof (a))
149*7c478bd9Sstevel@tonic-gate #define	SCPYN(a, b)	(void) strncpy(a, b, sizeof (a))
150*7c478bd9Sstevel@tonic-gate #define	EQN(a, b)	(strncmp(a, b, sizeof (a)-1) == 0)
151*7c478bd9Sstevel@tonic-gate #define	ENVSTRNCAT(to, from) {int deflen; deflen = strlen(to); \
152*7c478bd9Sstevel@tonic-gate 	(void) strncpy((to)+ deflen, (from), sizeof (to) - (1 + deflen)); }
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate /*
155*7c478bd9Sstevel@tonic-gate  * Other macros
156*7c478bd9Sstevel@tonic-gate  */
157*7c478bd9Sstevel@tonic-gate #define	NMAX	sizeof (((struct utmpx *)0)->ut_name)
158*7c478bd9Sstevel@tonic-gate #define	HMAX	sizeof (((struct utmpx *)0)->ut_host)
159*7c478bd9Sstevel@tonic-gate #define	min(a, b)	(((a) < (b)) ? (a) : (b))
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate /*
162*7c478bd9Sstevel@tonic-gate  * Various useful files and string constants
163*7c478bd9Sstevel@tonic-gate  */
164*7c478bd9Sstevel@tonic-gate #define	SHELL		"/usr/bin/sh"
165*7c478bd9Sstevel@tonic-gate #define	SHELL2		"/sbin/sh"
166*7c478bd9Sstevel@tonic-gate #define	SUBLOGIN	"<!sublogin>"
167*7c478bd9Sstevel@tonic-gate #define	LASTLOG		"/var/adm/lastlog"
168*7c478bd9Sstevel@tonic-gate #define	PROG_NAME	"login"
169*7c478bd9Sstevel@tonic-gate #define	HUSHLOGIN	".hushlogin"
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
172*7c478bd9Sstevel@tonic-gate /*
173*7c478bd9Sstevel@tonic-gate  * Array and Buffer sizes
174*7c478bd9Sstevel@tonic-gate  */
175*7c478bd9Sstevel@tonic-gate #define	PBUFSIZE 8	/* max significant characters in a password */
176*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
177*7c478bd9Sstevel@tonic-gate #define	MAXARGS 63	/* change value below if changing this */
178*7c478bd9Sstevel@tonic-gate #define	MAXARGSWIDTH 2	/* log10(MAXARGS) */
179*7c478bd9Sstevel@tonic-gate #define	MAXENV 1024
180*7c478bd9Sstevel@tonic-gate #define	MAXLINE 2048
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate /*
183*7c478bd9Sstevel@tonic-gate  * Miscellaneous constants
184*7c478bd9Sstevel@tonic-gate  */
185*7c478bd9Sstevel@tonic-gate #define	ROOTUID		0
186*7c478bd9Sstevel@tonic-gate #define	ERROR		1
187*7c478bd9Sstevel@tonic-gate #define	OK		0
188*7c478bd9Sstevel@tonic-gate #define	LOG_ERROR	1
189*7c478bd9Sstevel@tonic-gate #define	DONT_LOG_ERROR	0
190*7c478bd9Sstevel@tonic-gate #define	TRUE		1
191*7c478bd9Sstevel@tonic-gate #define	FALSE		0
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * Counters for counting the number of failed login attempts
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate static int trys = 0;
197*7c478bd9Sstevel@tonic-gate static int count = 1;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate /*
200*7c478bd9Sstevel@tonic-gate  * error value for login_exit() audit output (0 == no audit record)
201*7c478bd9Sstevel@tonic-gate  */
202*7c478bd9Sstevel@tonic-gate static int	audit_error = 0;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate  * Externs a plenty
206*7c478bd9Sstevel@tonic-gate  */
207*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
208*7c478bd9Sstevel@tonic-gate extern	int	getsecretkey();
209*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate /*
212*7c478bd9Sstevel@tonic-gate  * The current user name
213*7c478bd9Sstevel@tonic-gate  */
214*7c478bd9Sstevel@tonic-gate static	char	user_name[NMAX];
215*7c478bd9Sstevel@tonic-gate static	char	minusnam[16] = "-";
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * locale environments to be passed to shells.
219*7c478bd9Sstevel@tonic-gate  */
220*7c478bd9Sstevel@tonic-gate static char *localeenv[] = {
221*7c478bd9Sstevel@tonic-gate 	"LANG",
222*7c478bd9Sstevel@tonic-gate 	"LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE",
223*7c478bd9Sstevel@tonic-gate 	"LC_MONETARY", "LC_MESSAGES", "LC_ALL", 0};
224*7c478bd9Sstevel@tonic-gate static int locale_envmatch(char *, char *);
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate /*
227*7c478bd9Sstevel@tonic-gate  * Environment variable support
228*7c478bd9Sstevel@tonic-gate  */
229*7c478bd9Sstevel@tonic-gate static	char	shell[256] = { "SHELL=" };
230*7c478bd9Sstevel@tonic-gate static	char	home[MAXPATHLEN] = { "HOME=" };
231*7c478bd9Sstevel@tonic-gate static	char	term[64] = { "TERM=" };
232*7c478bd9Sstevel@tonic-gate static	char	logname[30] = { "LOGNAME=" };
233*7c478bd9Sstevel@tonic-gate static	char	timez[100] = { "TZ=" };
234*7c478bd9Sstevel@tonic-gate static	char	hertz[10] = { "HZ=" };
235*7c478bd9Sstevel@tonic-gate static	char	path[MAXPATHLEN] = { "PATH=" };
236*7c478bd9Sstevel@tonic-gate static	char	*newenv[10+MAXARGS] =
237*7c478bd9Sstevel@tonic-gate 	{home, path, logname, hertz, term, 0, 0};
238*7c478bd9Sstevel@tonic-gate static	char	**envinit = newenv;
239*7c478bd9Sstevel@tonic-gate static	int	basicenv;
240*7c478bd9Sstevel@tonic-gate static	char	*zero = (char *)0;
241*7c478bd9Sstevel@tonic-gate static	char 	**envp;
242*7c478bd9Sstevel@tonic-gate #ifndef	NO_MAIL
243*7c478bd9Sstevel@tonic-gate static	char	mail[30] = { "MAIL=/var/mail/" };
244*7c478bd9Sstevel@tonic-gate #endif
245*7c478bd9Sstevel@tonic-gate extern char **environ;
246*7c478bd9Sstevel@tonic-gate static	char inputline[MAXLINE];
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate #define	MAX_ID_LEN 256
249*7c478bd9Sstevel@tonic-gate #define	MAX_REPOSITORY_LEN 256
250*7c478bd9Sstevel@tonic-gate #define	MAX_PAMSERVICE_LEN 256
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate static char identity[MAX_ID_LEN];
253*7c478bd9Sstevel@tonic-gate static char repository[MAX_REPOSITORY_LEN];
254*7c478bd9Sstevel@tonic-gate static char progname[MAX_PAMSERVICE_LEN];
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate  * Strings used to prompt the user.
259*7c478bd9Sstevel@tonic-gate  */
260*7c478bd9Sstevel@tonic-gate static	char	loginmsg[] = "login: ";
261*7c478bd9Sstevel@tonic-gate static	char	passwdmsg[] = "Password:";
262*7c478bd9Sstevel@tonic-gate static	char	incorrectmsg[] = "Login incorrect\n";
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
265*7c478bd9Sstevel@tonic-gate /*
266*7c478bd9Sstevel@tonic-gate  * Password file support
267*7c478bd9Sstevel@tonic-gate  */
268*7c478bd9Sstevel@tonic-gate static	struct	passwd *pwd = NULL;
269*7c478bd9Sstevel@tonic-gate static	char	remote_host[HMAX];
270*7c478bd9Sstevel@tonic-gate static	char	zone_name[ZONENAME_MAX];
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate /*
273*7c478bd9Sstevel@tonic-gate  * Illegal passwd entries.
274*7c478bd9Sstevel@tonic-gate  */
275*7c478bd9Sstevel@tonic-gate static	struct	passwd nouser = { "", "no:password", ~ROOTUID };
276*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate /*
279*7c478bd9Sstevel@tonic-gate  * Log file support
280*7c478bd9Sstevel@tonic-gate  */
281*7c478bd9Sstevel@tonic-gate static	char	*log_entry[LOGTRYS];
282*7c478bd9Sstevel@tonic-gate static	int	writelog = 0;
283*7c478bd9Sstevel@tonic-gate static	int	lastlogok = 0;
284*7c478bd9Sstevel@tonic-gate static	struct lastlog ll;
285*7c478bd9Sstevel@tonic-gate static	int	dosyslog = 0;
286*7c478bd9Sstevel@tonic-gate static	int	flogin = MAXTRYS;	/* flag for SYSLOG_FAILED_LOGINS */
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate /*
289*7c478bd9Sstevel@tonic-gate  * Default file toggles
290*7c478bd9Sstevel@tonic-gate  */
291*7c478bd9Sstevel@tonic-gate static	char	*Pndefault	= "/etc/default/login";
292*7c478bd9Sstevel@tonic-gate static	char	*Altshell	= NULL;
293*7c478bd9Sstevel@tonic-gate static	char	*Console	= NULL;
294*7c478bd9Sstevel@tonic-gate static	int	Passreqflag	= 0;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate #define	DEFUMASK	022
297*7c478bd9Sstevel@tonic-gate static	mode_t	Umask		= DEFUMASK;
298*7c478bd9Sstevel@tonic-gate static	char 	*Def_tz		= NULL;
299*7c478bd9Sstevel@tonic-gate static	char 	*tmp_tz		= NULL;
300*7c478bd9Sstevel@tonic-gate static	char 	*Def_hertz	= NULL;
301*7c478bd9Sstevel@tonic-gate #define	SET_FSIZ	2			/* ulimit() command arg */
302*7c478bd9Sstevel@tonic-gate static	long	Def_ulimit	= 0;
303*7c478bd9Sstevel@tonic-gate #define	MAX_TIMEOUT	(15 * 60)
304*7c478bd9Sstevel@tonic-gate #define	DEF_TIMEOUT	(5 * 60)
305*7c478bd9Sstevel@tonic-gate static	unsigned Def_timeout	= DEF_TIMEOUT;
306*7c478bd9Sstevel@tonic-gate static	char	*Def_path	= NULL;
307*7c478bd9Sstevel@tonic-gate static	char	*Def_supath	= NULL;
308*7c478bd9Sstevel@tonic-gate #define	DEF_PATH	"/usr/bin:" 	/* same as PATH */
309*7c478bd9Sstevel@tonic-gate #define	DEF_SUPATH	"/usr/sbin:/usr/bin" /* same as ROOTPATH */
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate /*
312*7c478bd9Sstevel@tonic-gate  * Defaults for updating expired passwords
313*7c478bd9Sstevel@tonic-gate  */
314*7c478bd9Sstevel@tonic-gate #define	DEF_ATTEMPTS	3
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate /*
317*7c478bd9Sstevel@tonic-gate  * ttyprompt will point to the environment variable TTYPROMPT.
318*7c478bd9Sstevel@tonic-gate  * TTYPROMPT is set by ttymon if ttymon already wrote out the prompt.
319*7c478bd9Sstevel@tonic-gate  */
320*7c478bd9Sstevel@tonic-gate static	char	*ttyprompt = NULL;
321*7c478bd9Sstevel@tonic-gate static	char 	*ttyn = NULL;
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate /*
324*7c478bd9Sstevel@tonic-gate  * Pass inherited environment.  Used by telnetd in support of the telnet
325*7c478bd9Sstevel@tonic-gate  * ENVIRON option.
326*7c478bd9Sstevel@tonic-gate  */
327*7c478bd9Sstevel@tonic-gate static	boolean_t pflag = B_FALSE;
328*7c478bd9Sstevel@tonic-gate static  boolean_t uflag = B_FALSE;
329*7c478bd9Sstevel@tonic-gate static  boolean_t Rflag = B_FALSE;
330*7c478bd9Sstevel@tonic-gate static  boolean_t sflag = B_FALSE;
331*7c478bd9Sstevel@tonic-gate static  boolean_t Uflag = B_FALSE;
332*7c478bd9Sstevel@tonic-gate static  boolean_t tflag = B_FALSE;
333*7c478bd9Sstevel@tonic-gate static	boolean_t hflag = B_FALSE;
334*7c478bd9Sstevel@tonic-gate static  boolean_t rflag = B_FALSE;
335*7c478bd9Sstevel@tonic-gate static  boolean_t zflag = B_FALSE;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate /*
338*7c478bd9Sstevel@tonic-gate  * Remote login support
339*7c478bd9Sstevel@tonic-gate  */
340*7c478bd9Sstevel@tonic-gate static	char	rusername[NMAX+1], lusername[NMAX+1];
341*7c478bd9Sstevel@tonic-gate static	char	terminal[MAXPATHLEN];
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
344*7c478bd9Sstevel@tonic-gate /*
345*7c478bd9Sstevel@tonic-gate  * Pre-authentication flag support
346*7c478bd9Sstevel@tonic-gate  */
347*7c478bd9Sstevel@tonic-gate static	int	fflag;
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate static char ** getargs(char *);
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate static int login_conv(int, struct pam_message **,
352*7c478bd9Sstevel@tonic-gate     struct pam_response **, void *);
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate static struct pam_conv pam_conv = {login_conv, NULL};
355*7c478bd9Sstevel@tonic-gate static pam_handle_t *pamh;	/* Authentication handle */
356*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate /*
359*7c478bd9Sstevel@tonic-gate  * Function declarations
360*7c478bd9Sstevel@tonic-gate  */
361*7c478bd9Sstevel@tonic-gate static	void	turn_on_logging(void);
362*7c478bd9Sstevel@tonic-gate static	void	defaults(void);
363*7c478bd9Sstevel@tonic-gate static	void	usage(void);
364*7c478bd9Sstevel@tonic-gate static	void	process_rlogin(void);
365*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
366*7c478bd9Sstevel@tonic-gate static	void	login_authenticate();
367*7c478bd9Sstevel@tonic-gate static	void	setup_credentials(void);
368*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
369*7c478bd9Sstevel@tonic-gate static	void	adjust_nice(void);
370*7c478bd9Sstevel@tonic-gate static	void	update_utmpx_entry(int);
371*7c478bd9Sstevel@tonic-gate static	void	establish_user_environment(char **);
372*7c478bd9Sstevel@tonic-gate static	void	print_banner(void);
373*7c478bd9Sstevel@tonic-gate static	void	display_last_login_time(void);
374*7c478bd9Sstevel@tonic-gate static	void	exec_the_shell(void);
375*7c478bd9Sstevel@tonic-gate static	int	process_chroot_logins(void);
376*7c478bd9Sstevel@tonic-gate static 	void	chdir_to_dir_user(void);
377*7c478bd9Sstevel@tonic-gate static	void	check_log(void);
378*7c478bd9Sstevel@tonic-gate static	void	validate_account(void);
379*7c478bd9Sstevel@tonic-gate static	void	doremoteterm(char *);
380*7c478bd9Sstevel@tonic-gate static	int	get_options(int, char **);
381*7c478bd9Sstevel@tonic-gate static	void	getstr(char *, int, char *);
382*7c478bd9Sstevel@tonic-gate static 	int	legalenvvar(char *);
383*7c478bd9Sstevel@tonic-gate static	void	check_for_console(void);
384*7c478bd9Sstevel@tonic-gate static	void	check_for_dueling_unix(char *);
385*7c478bd9Sstevel@tonic-gate static	void	get_user_name(void);
386*7c478bd9Sstevel@tonic-gate static	uint_t	get_audit_id(void);
387*7c478bd9Sstevel@tonic-gate static	void	login_exit(int);
388*7c478bd9Sstevel@tonic-gate static	int	logins_disabled(char *);
389*7c478bd9Sstevel@tonic-gate static	void	log_bad_attempts(void);
390*7c478bd9Sstevel@tonic-gate static	int	is_number(char *);
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
393*7c478bd9Sstevel@tonic-gate /*
394*7c478bd9Sstevel@tonic-gate  *			*** main ***
395*7c478bd9Sstevel@tonic-gate  *
396*7c478bd9Sstevel@tonic-gate  *	The primary flow of control is directed in this routine.
397*7c478bd9Sstevel@tonic-gate  *	Control moves in line from top to bottom calling subfunctions
398*7c478bd9Sstevel@tonic-gate  *	which perform the bulk of the work.  Many of these calls exit
399*7c478bd9Sstevel@tonic-gate  *	when a fatal error is encountered and do not return to main.
400*7c478bd9Sstevel@tonic-gate  *
401*7c478bd9Sstevel@tonic-gate  *
402*7c478bd9Sstevel@tonic-gate  */
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate void
405*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char **renvp)
406*7c478bd9Sstevel@tonic-gate {
407*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
408*7c478bd9Sstevel@tonic-gate 	int sublogin;
409*7c478bd9Sstevel@tonic-gate 	int pam_rc;
410*7c478bd9Sstevel@tonic-gate 
411*7c478bd9Sstevel@tonic-gate 	/*
412*7c478bd9Sstevel@tonic-gate 	 * Set up Defaults and flags
413*7c478bd9Sstevel@tonic-gate 	 */
414*7c478bd9Sstevel@tonic-gate 	defaults();
415*7c478bd9Sstevel@tonic-gate 	SCPYL(progname, PROG_NAME);
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	/*
418*7c478bd9Sstevel@tonic-gate 	 * Set up default umask
419*7c478bd9Sstevel@tonic-gate 	 */
420*7c478bd9Sstevel@tonic-gate 	if (Umask > ((mode_t)0777))
421*7c478bd9Sstevel@tonic-gate 		Umask = DEFUMASK;
422*7c478bd9Sstevel@tonic-gate 	(void) umask(Umask);
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 	/*
425*7c478bd9Sstevel@tonic-gate 	 * Set up default timeouts and delays
426*7c478bd9Sstevel@tonic-gate 	 */
427*7c478bd9Sstevel@tonic-gate 	if (Def_timeout > MAX_TIMEOUT)
428*7c478bd9Sstevel@tonic-gate 		Def_timeout = MAX_TIMEOUT;
429*7c478bd9Sstevel@tonic-gate 	if (Sleeptime < 0 || Sleeptime > 5)
430*7c478bd9Sstevel@tonic-gate 		Sleeptime = SLEEPTIME;
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	(void) alarm(Def_timeout);
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	/*
435*7c478bd9Sstevel@tonic-gate 	 * Ignore SIGQUIT and SIGINT and set nice to 0
436*7c478bd9Sstevel@tonic-gate 	 */
437*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGQUIT, SIG_IGN);
438*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, SIG_IGN);
439*7c478bd9Sstevel@tonic-gate 	(void) nice(0);
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate 	/*
442*7c478bd9Sstevel@tonic-gate 	 * Set flag to disable the pid check if you find that you are
443*7c478bd9Sstevel@tonic-gate 	 * a subsystem login.
444*7c478bd9Sstevel@tonic-gate 	 */
445*7c478bd9Sstevel@tonic-gate 	sublogin = 0;
446*7c478bd9Sstevel@tonic-gate 	if (*renvp && strcmp(*renvp, SUBLOGIN) == 0)
447*7c478bd9Sstevel@tonic-gate 		sublogin = 1;
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate 	/*
450*7c478bd9Sstevel@tonic-gate 	 * Parse Arguments
451*7c478bd9Sstevel@tonic-gate 	 */
452*7c478bd9Sstevel@tonic-gate 	if (get_options(argc, argv) == -1) {
453*7c478bd9Sstevel@tonic-gate 		usage();
454*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_VALUE_BAD_CMD;
455*7c478bd9Sstevel@tonic-gate 		login_exit(1);
456*7c478bd9Sstevel@tonic-gate 	}
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	/*
459*7c478bd9Sstevel@tonic-gate 	 * if devicename is not passed as argument, call ttyname(0)
460*7c478bd9Sstevel@tonic-gate 	 */
461*7c478bd9Sstevel@tonic-gate 	if (ttyn == NULL) {
462*7c478bd9Sstevel@tonic-gate 		ttyn = ttyname(0);
463*7c478bd9Sstevel@tonic-gate 		if (ttyn == NULL)
464*7c478bd9Sstevel@tonic-gate 			ttyn = "/dev/???";
465*7c478bd9Sstevel@tonic-gate 	}
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
468*7c478bd9Sstevel@tonic-gate 	/*
469*7c478bd9Sstevel@tonic-gate 	 * Call pam_start to initiate a PAM authentication operation
470*7c478bd9Sstevel@tonic-gate 	 */
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 	if ((pam_rc = pam_start(progname, user_name, &pam_conv, &pamh))
473*7c478bd9Sstevel@tonic-gate 	    != PAM_SUCCESS) {
474*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_PAM + pam_rc;
475*7c478bd9Sstevel@tonic-gate 		login_exit(1);
476*7c478bd9Sstevel@tonic-gate 	}
477*7c478bd9Sstevel@tonic-gate 	if ((pam_rc = pam_set_item(pamh, PAM_TTY, ttyn)) != PAM_SUCCESS) {
478*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_PAM + pam_rc;
479*7c478bd9Sstevel@tonic-gate 		login_exit(1);
480*7c478bd9Sstevel@tonic-gate 	}
481*7c478bd9Sstevel@tonic-gate 	if ((pam_rc = pam_set_item(pamh, PAM_RHOST, remote_host)) !=
482*7c478bd9Sstevel@tonic-gate 	    PAM_SUCCESS) {
483*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_PAM + pam_rc;
484*7c478bd9Sstevel@tonic-gate 		login_exit(1);
485*7c478bd9Sstevel@tonic-gate 	}
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	/*
488*7c478bd9Sstevel@tonic-gate 	 * We currently only support special handling of the KRB5 PAM repository
489*7c478bd9Sstevel@tonic-gate 	 */
490*7c478bd9Sstevel@tonic-gate 	if ((Rflag && strlen(repository)) &&
491*7c478bd9Sstevel@tonic-gate 	    strcmp(repository, KRB5_REPOSITORY_NAME) == 0 &&
492*7c478bd9Sstevel@tonic-gate 	    (uflag && strlen(identity))) {
493*7c478bd9Sstevel@tonic-gate 		krb5_repository_data_t krb5_data;
494*7c478bd9Sstevel@tonic-gate 		pam_repository_t pam_rep_data;
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate 		krb5_data.principal = identity;
497*7c478bd9Sstevel@tonic-gate 		krb5_data.flags = SUNW_PAM_KRB5_ALREADY_AUTHENTICATED;
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 		pam_rep_data.type = repository;
500*7c478bd9Sstevel@tonic-gate 		pam_rep_data.scope = (void *)&krb5_data;
501*7c478bd9Sstevel@tonic-gate 		pam_rep_data.scope_len = sizeof (krb5_data);
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 		(void) pam_set_item(pamh, PAM_REPOSITORY,
504*7c478bd9Sstevel@tonic-gate 		    (void *)&pam_rep_data);
505*7c478bd9Sstevel@tonic-gate 	}
506*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	/*
509*7c478bd9Sstevel@tonic-gate 	 * Open the log file which contains a record of successful and failed
510*7c478bd9Sstevel@tonic-gate 	 * login attempts
511*7c478bd9Sstevel@tonic-gate 	 */
512*7c478bd9Sstevel@tonic-gate 	turn_on_logging();
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	/*
515*7c478bd9Sstevel@tonic-gate 	 * say "hi" to syslogd ..
516*7c478bd9Sstevel@tonic-gate 	 */
517*7c478bd9Sstevel@tonic-gate 	openlog("login", 0, LOG_AUTH);
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate 	/*
520*7c478bd9Sstevel@tonic-gate 	 * Do special processing for -r (rlogin) flag
521*7c478bd9Sstevel@tonic-gate 	 */
522*7c478bd9Sstevel@tonic-gate 	if (rflag)
523*7c478bd9Sstevel@tonic-gate 		process_rlogin();
524*7c478bd9Sstevel@tonic-gate 
525*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
526*7c478bd9Sstevel@tonic-gate 	/*
527*7c478bd9Sstevel@tonic-gate 	 * validate user
528*7c478bd9Sstevel@tonic-gate 	 */
529*7c478bd9Sstevel@tonic-gate 	/* we are already authenticated. fill in what we must, then continue */
530*7c478bd9Sstevel@tonic-gate 	if (fflag) {
531*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
532*7c478bd9Sstevel@tonic-gate 		if ((pwd = getpwnam(user_name)) == NULL) {
533*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_VALUE_USERNAME;
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 			log_bad_attempts();
536*7c478bd9Sstevel@tonic-gate 			(void) printf("Login failed: unknown user '%s'.\n",
537*7c478bd9Sstevel@tonic-gate 			    user_name);
538*7c478bd9Sstevel@tonic-gate 			login_exit(1);
539*7c478bd9Sstevel@tonic-gate 		}
540*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
541*7c478bd9Sstevel@tonic-gate 	} else {
542*7c478bd9Sstevel@tonic-gate 		/*
543*7c478bd9Sstevel@tonic-gate 		 * Perform the primary login authentication activity.
544*7c478bd9Sstevel@tonic-gate 		 */
545*7c478bd9Sstevel@tonic-gate 		login_authenticate();
546*7c478bd9Sstevel@tonic-gate 	}
547*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate 	/* change root login, then we exec another login and try again */
550*7c478bd9Sstevel@tonic-gate 	if (process_chroot_logins() != OK)
551*7c478bd9Sstevel@tonic-gate 		login_exit(1);
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 	/*
554*7c478bd9Sstevel@tonic-gate 	 * If root login and not on system console then call exit(2)
555*7c478bd9Sstevel@tonic-gate 	 */
556*7c478bd9Sstevel@tonic-gate 	check_for_console();
557*7c478bd9Sstevel@tonic-gate 
558*7c478bd9Sstevel@tonic-gate 	/*
559*7c478bd9Sstevel@tonic-gate 	 * Check to see if a shutdown is in progress, if it is and
560*7c478bd9Sstevel@tonic-gate 	 * we are not root then throw the user off the system
561*7c478bd9Sstevel@tonic-gate 	 */
562*7c478bd9Sstevel@tonic-gate 	if (logins_disabled(user_name) == TRUE) {
563*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_VALUE_LOGIN_DISABLED;
564*7c478bd9Sstevel@tonic-gate 		login_exit(1);
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	if (pwd->pw_uid == 0) {
568*7c478bd9Sstevel@tonic-gate 		if (Def_supath != NULL)
569*7c478bd9Sstevel@tonic-gate 			Def_path = Def_supath;
570*7c478bd9Sstevel@tonic-gate 		else
571*7c478bd9Sstevel@tonic-gate 			Def_path = DEF_SUPATH;
572*7c478bd9Sstevel@tonic-gate 	}
573*7c478bd9Sstevel@tonic-gate 
574*7c478bd9Sstevel@tonic-gate 	/*
575*7c478bd9Sstevel@tonic-gate 	 * Check account expiration and passwd aging
576*7c478bd9Sstevel@tonic-gate 	 */
577*7c478bd9Sstevel@tonic-gate 	validate_account();
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 	/*
580*7c478bd9Sstevel@tonic-gate 	 * We only get here if we've been authenticated.
581*7c478bd9Sstevel@tonic-gate 	 */
582*7c478bd9Sstevel@tonic-gate 	/*
583*7c478bd9Sstevel@tonic-gate 	 * NOTE: telnetd and rlogind rely upon this updating of utmpx
584*7c478bd9Sstevel@tonic-gate 	 * to indicate that the authentication completed  successfully,
585*7c478bd9Sstevel@tonic-gate 	 * pam_open_session was called and therefore they are required to
586*7c478bd9Sstevel@tonic-gate 	 * call pam_close_session.
587*7c478bd9Sstevel@tonic-gate 	 */
588*7c478bd9Sstevel@tonic-gate 	update_utmpx_entry(sublogin);
589*7c478bd9Sstevel@tonic-gate 
590*7c478bd9Sstevel@tonic-gate 	/*
591*7c478bd9Sstevel@tonic-gate 	 * Now we set up the environment for the new user, which includes
592*7c478bd9Sstevel@tonic-gate 	 * the users ulimit, nice value, ownership of this tty, uid, gid,
593*7c478bd9Sstevel@tonic-gate 	 * and environment variables.
594*7c478bd9Sstevel@tonic-gate 	 */
595*7c478bd9Sstevel@tonic-gate 	if (Def_ulimit > 0L && ulimit(SET_FSIZ, Def_ulimit) < 0L)
596*7c478bd9Sstevel@tonic-gate 		(void) printf("Could not set ULIMIT to %ld\n", Def_ulimit);
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 	/* di_devperm_login() sends detailed errors to syslog */
599*7c478bd9Sstevel@tonic-gate 	if (di_devperm_login((const char *)ttyn, pwd->pw_uid, pwd->pw_gid,
600*7c478bd9Sstevel@tonic-gate 	    NULL) == -1) {
601*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "error processing /etc/logindevperm,"
602*7c478bd9Sstevel@tonic-gate 		    " see syslog for more details\n");
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	adjust_nice();		/* passwd file can specify nice value */
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
608*7c478bd9Sstevel@tonic-gate 	setup_credentials();	/* Set uid/gid - exits on failure */
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	/*
611*7c478bd9Sstevel@tonic-gate 	 * Set up the basic environment for the exec.  This includes
612*7c478bd9Sstevel@tonic-gate 	 * HOME, PATH, LOGNAME, SHELL, TERM, TZ, HZ, and MAIL.
613*7c478bd9Sstevel@tonic-gate 	 */
614*7c478bd9Sstevel@tonic-gate 	chdir_to_dir_user();
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	establish_user_environment(renvp);
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	(void) pam_end(pamh, PAM_SUCCESS);	/* Done using PAM */
619*7c478bd9Sstevel@tonic-gate 	pamh = NULL;
620*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 	if (pwd->pw_uid == 0) {
623*7c478bd9Sstevel@tonic-gate 		if (dosyslog) {
624*7c478bd9Sstevel@tonic-gate 			if (remote_host[0]) {
625*7c478bd9Sstevel@tonic-gate 			    syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
626*7c478bd9Sstevel@tonic-gate 			    ttyn, HMAX, remote_host);
627*7c478bd9Sstevel@tonic-gate 			} else
628*7c478bd9Sstevel@tonic-gate 				syslog(LOG_NOTICE, "ROOT LOGIN %s", ttyn);
629*7c478bd9Sstevel@tonic-gate 		}
630*7c478bd9Sstevel@tonic-gate 	}
631*7c478bd9Sstevel@tonic-gate 	closelog();
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGQUIT, SIG_DFL);
634*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, SIG_DFL);
635*7c478bd9Sstevel@tonic-gate 
636*7c478bd9Sstevel@tonic-gate 	/*
637*7c478bd9Sstevel@tonic-gate 	 * Display some useful information to the new user like the banner
638*7c478bd9Sstevel@tonic-gate 	 * and last login time if not a quiet login.
639*7c478bd9Sstevel@tonic-gate 	 */
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 	if (access(HUSHLOGIN, F_OK) != 0) {
642*7c478bd9Sstevel@tonic-gate 		print_banner();
643*7c478bd9Sstevel@tonic-gate 		display_last_login_time();
644*7c478bd9Sstevel@tonic-gate 	}
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 	/*
647*7c478bd9Sstevel@tonic-gate 	 * Set SIGXCPU and SIGXFSZ to default disposition.
648*7c478bd9Sstevel@tonic-gate 	 * Shells inherit signal disposition from parent.
649*7c478bd9Sstevel@tonic-gate 	 * And the shells should have default dispositions
650*7c478bd9Sstevel@tonic-gate 	 * for the two below signals.
651*7c478bd9Sstevel@tonic-gate 	 */
652*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGXCPU, SIG_DFL);
653*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGXFSZ, SIG_DFL);
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 	/*
656*7c478bd9Sstevel@tonic-gate 	 * Now fire off the shell of choice
657*7c478bd9Sstevel@tonic-gate 	 */
658*7c478bd9Sstevel@tonic-gate 	exec_the_shell();
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate 	/*
661*7c478bd9Sstevel@tonic-gate 	 * All done
662*7c478bd9Sstevel@tonic-gate 	 */
663*7c478bd9Sstevel@tonic-gate 	login_exit(1);
664*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
665*7c478bd9Sstevel@tonic-gate }
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate /*
669*7c478bd9Sstevel@tonic-gate  *			*** Utility functions ***
670*7c478bd9Sstevel@tonic-gate  */
671*7c478bd9Sstevel@tonic-gate 
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate 
674*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
675*7c478bd9Sstevel@tonic-gate /*
676*7c478bd9Sstevel@tonic-gate  * donothing & catch	- Signal catching functions
677*7c478bd9Sstevel@tonic-gate  */
678*7c478bd9Sstevel@tonic-gate 
679*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
680*7c478bd9Sstevel@tonic-gate static void
681*7c478bd9Sstevel@tonic-gate donothing(int sig)
682*7c478bd9Sstevel@tonic-gate {
683*7c478bd9Sstevel@tonic-gate 	if (pamh)
684*7c478bd9Sstevel@tonic-gate 		(void) pam_end(pamh, PAM_ABORT);
685*7c478bd9Sstevel@tonic-gate }
686*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate #ifdef notdef
689*7c478bd9Sstevel@tonic-gate static	int	intrupt;
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
692*7c478bd9Sstevel@tonic-gate static void
693*7c478bd9Sstevel@tonic-gate catch(int sig)
694*7c478bd9Sstevel@tonic-gate {
695*7c478bd9Sstevel@tonic-gate 	++intrupt;
696*7c478bd9Sstevel@tonic-gate }
697*7c478bd9Sstevel@tonic-gate #endif
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate /*
700*7c478bd9Sstevel@tonic-gate  *			*** Bad login logging support ***
701*7c478bd9Sstevel@tonic-gate  */
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate /*
704*7c478bd9Sstevel@tonic-gate  * badlogin() 		- log to the log file 'trys'
705*7c478bd9Sstevel@tonic-gate  *			  unsuccessful attempts
706*7c478bd9Sstevel@tonic-gate  */
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate static void
709*7c478bd9Sstevel@tonic-gate badlogin(void)
710*7c478bd9Sstevel@tonic-gate {
711*7c478bd9Sstevel@tonic-gate 	int retval, count1, fildes;
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	/*
714*7c478bd9Sstevel@tonic-gate 	 * Tries to open the log file. If succeed, lock it and write
715*7c478bd9Sstevel@tonic-gate 	 * in the failed attempts
716*7c478bd9Sstevel@tonic-gate 	 */
717*7c478bd9Sstevel@tonic-gate 	if ((fildes = open(LOGINLOG, O_APPEND|O_WRONLY)) != -1) {
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 		(void) sigset(SIGALRM, donothing);
720*7c478bd9Sstevel@tonic-gate 		(void) alarm(L_WAITTIME);
721*7c478bd9Sstevel@tonic-gate 		retval = lockf(fildes, F_LOCK, 0L);
722*7c478bd9Sstevel@tonic-gate 		(void) alarm(0);
723*7c478bd9Sstevel@tonic-gate 		(void) sigset(SIGALRM, SIG_DFL);
724*7c478bd9Sstevel@tonic-gate 		if (retval == 0) {
725*7c478bd9Sstevel@tonic-gate 			for (count1 = 0; count1 < trys; count1++)
726*7c478bd9Sstevel@tonic-gate 				(void) write(fildes, log_entry[count1],
727*7c478bd9Sstevel@tonic-gate 				    (unsigned)strlen(log_entry[count1]));
728*7c478bd9Sstevel@tonic-gate 			(void) lockf(fildes, F_ULOCK, 0L);
729*7c478bd9Sstevel@tonic-gate 		}
730*7c478bd9Sstevel@tonic-gate 		(void) close(fildes);
731*7c478bd9Sstevel@tonic-gate 	}
732*7c478bd9Sstevel@tonic-gate }
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate /*
736*7c478bd9Sstevel@tonic-gate  * log_bad_attempts 	- log each bad login attempt - called from
737*7c478bd9Sstevel@tonic-gate  *			  login_authenticate.  Exits when the maximum attempt
738*7c478bd9Sstevel@tonic-gate  *			  count is exceeded.
739*7c478bd9Sstevel@tonic-gate  */
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate static void
742*7c478bd9Sstevel@tonic-gate log_bad_attempts(void)
743*7c478bd9Sstevel@tonic-gate {
744*7c478bd9Sstevel@tonic-gate 	time_t timenow;
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 	if (trys >= LOGTRYS)
747*7c478bd9Sstevel@tonic-gate 		return;
748*7c478bd9Sstevel@tonic-gate 	if (writelog) {
749*7c478bd9Sstevel@tonic-gate 		(void) time(&timenow);
750*7c478bd9Sstevel@tonic-gate 		(void) strncat(log_entry[trys], user_name, LNAME_SIZE);
751*7c478bd9Sstevel@tonic-gate 		(void) strncat(log_entry[trys], ":", (size_t)1);
752*7c478bd9Sstevel@tonic-gate 		(void) strncat(log_entry[trys], ttyn, TTYN_SIZE);
753*7c478bd9Sstevel@tonic-gate 		(void) strncat(log_entry[trys], ":", (size_t)1);
754*7c478bd9Sstevel@tonic-gate 		(void) strncat(log_entry[trys], ctime(&timenow),
755*7c478bd9Sstevel@tonic-gate 				TIME_SIZE);
756*7c478bd9Sstevel@tonic-gate 		trys++;
757*7c478bd9Sstevel@tonic-gate 	}
758*7c478bd9Sstevel@tonic-gate 	if (count > flogin) {
759*7c478bd9Sstevel@tonic-gate 		if ((pwd = getpwnam(user_name)) != NULL) {
760*7c478bd9Sstevel@tonic-gate 			if (remote_host[0]) {
761*7c478bd9Sstevel@tonic-gate 				syslog(LOG_NOTICE,
762*7c478bd9Sstevel@tonic-gate 				    "Login failure on %s from %.*s, "
763*7c478bd9Sstevel@tonic-gate 				    "%.*s", ttyn, HMAX, remote_host,
764*7c478bd9Sstevel@tonic-gate 				    NMAX, user_name);
765*7c478bd9Sstevel@tonic-gate 			} else {
766*7c478bd9Sstevel@tonic-gate 				syslog(LOG_NOTICE,
767*7c478bd9Sstevel@tonic-gate 				    "Login failure on %s, %.*s",
768*7c478bd9Sstevel@tonic-gate 				    ttyn, NMAX, user_name);
769*7c478bd9Sstevel@tonic-gate 			}
770*7c478bd9Sstevel@tonic-gate 		} else 	{
771*7c478bd9Sstevel@tonic-gate 			if (remote_host[0]) {
772*7c478bd9Sstevel@tonic-gate 				syslog(LOG_NOTICE,
773*7c478bd9Sstevel@tonic-gate 				    "Login failure on %s from %.*s",
774*7c478bd9Sstevel@tonic-gate 				    ttyn, HMAX, remote_host);
775*7c478bd9Sstevel@tonic-gate 			} else {
776*7c478bd9Sstevel@tonic-gate 				syslog(LOG_NOTICE,
777*7c478bd9Sstevel@tonic-gate 				    "Login failure on %s", ttyn);
778*7c478bd9Sstevel@tonic-gate 			}
779*7c478bd9Sstevel@tonic-gate 		}
780*7c478bd9Sstevel@tonic-gate 	}
781*7c478bd9Sstevel@tonic-gate }
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate /*
785*7c478bd9Sstevel@tonic-gate  * turn_on_logging 	- if the logfile exist, turn on attempt logging and
786*7c478bd9Sstevel@tonic-gate  *			  initialize the string storage area
787*7c478bd9Sstevel@tonic-gate  */
788*7c478bd9Sstevel@tonic-gate 
789*7c478bd9Sstevel@tonic-gate static void
790*7c478bd9Sstevel@tonic-gate turn_on_logging(void)
791*7c478bd9Sstevel@tonic-gate {
792*7c478bd9Sstevel@tonic-gate 	struct stat dbuf;
793*7c478bd9Sstevel@tonic-gate 	int i;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	if (stat(LOGINLOG, &dbuf) == 0) {
796*7c478bd9Sstevel@tonic-gate 		writelog = 1;
797*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < LOGTRYS; i++) {
798*7c478bd9Sstevel@tonic-gate 			if (!(log_entry[i] = malloc((size_t)ENT_SIZE))) {
799*7c478bd9Sstevel@tonic-gate 				writelog = 0;
800*7c478bd9Sstevel@tonic-gate 				break;
801*7c478bd9Sstevel@tonic-gate 			}
802*7c478bd9Sstevel@tonic-gate 			*log_entry[i] = '\0';
803*7c478bd9Sstevel@tonic-gate 		}
804*7c478bd9Sstevel@tonic-gate 	}
805*7c478bd9Sstevel@tonic-gate }
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
809*7c478bd9Sstevel@tonic-gate /*
810*7c478bd9Sstevel@tonic-gate  * login_conv():
811*7c478bd9Sstevel@tonic-gate  *	This is the conv (conversation) function called from
812*7c478bd9Sstevel@tonic-gate  *	a PAM authentication module to print error messages
813*7c478bd9Sstevel@tonic-gate  *	or garner information from the user.
814*7c478bd9Sstevel@tonic-gate  */
815*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
816*7c478bd9Sstevel@tonic-gate static int
817*7c478bd9Sstevel@tonic-gate login_conv(int num_msg, struct pam_message **msg,
818*7c478bd9Sstevel@tonic-gate     struct pam_response **response, void *appdata_ptr)
819*7c478bd9Sstevel@tonic-gate {
820*7c478bd9Sstevel@tonic-gate 	struct pam_message	*m;
821*7c478bd9Sstevel@tonic-gate 	struct pam_response	*r;
822*7c478bd9Sstevel@tonic-gate 	char 			*temp;
823*7c478bd9Sstevel@tonic-gate 	int			k, i;
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 	if (num_msg <= 0)
826*7c478bd9Sstevel@tonic-gate 		return (PAM_CONV_ERR);
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	*response = calloc(num_msg, sizeof (struct pam_response));
829*7c478bd9Sstevel@tonic-gate 	if (*response == NULL)
830*7c478bd9Sstevel@tonic-gate 		return (PAM_BUF_ERR);
831*7c478bd9Sstevel@tonic-gate 
832*7c478bd9Sstevel@tonic-gate 	k = num_msg;
833*7c478bd9Sstevel@tonic-gate 	m = *msg;
834*7c478bd9Sstevel@tonic-gate 	r = *response;
835*7c478bd9Sstevel@tonic-gate 	while (k--) {
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 		switch (m->msg_style) {
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_OFF:
840*7c478bd9Sstevel@tonic-gate 			temp = getpassphrase(m->msg);
841*7c478bd9Sstevel@tonic-gate 			if (temp != NULL) {
842*7c478bd9Sstevel@tonic-gate 				r->resp = strdup(temp);
843*7c478bd9Sstevel@tonic-gate 				if (r->resp == NULL) {
844*7c478bd9Sstevel@tonic-gate 					/* free responses */
845*7c478bd9Sstevel@tonic-gate 					r = *response;
846*7c478bd9Sstevel@tonic-gate 					for (i = 0; i < num_msg; i++, r++) {
847*7c478bd9Sstevel@tonic-gate 						if (r->resp)
848*7c478bd9Sstevel@tonic-gate 							free(r->resp);
849*7c478bd9Sstevel@tonic-gate 					}
850*7c478bd9Sstevel@tonic-gate 					free(*response);
851*7c478bd9Sstevel@tonic-gate 					*response = NULL;
852*7c478bd9Sstevel@tonic-gate 					return (PAM_BUF_ERR);
853*7c478bd9Sstevel@tonic-gate 				}
854*7c478bd9Sstevel@tonic-gate 			}
855*7c478bd9Sstevel@tonic-gate 
856*7c478bd9Sstevel@tonic-gate 			m++;
857*7c478bd9Sstevel@tonic-gate 			r++;
858*7c478bd9Sstevel@tonic-gate 			break;
859*7c478bd9Sstevel@tonic-gate 
860*7c478bd9Sstevel@tonic-gate 		case PAM_PROMPT_ECHO_ON:
861*7c478bd9Sstevel@tonic-gate 			if (m->msg != NULL)
862*7c478bd9Sstevel@tonic-gate 				(void) fputs(m->msg, stdout);
863*7c478bd9Sstevel@tonic-gate 			r->resp = calloc(1, PAM_MAX_RESP_SIZE);
864*7c478bd9Sstevel@tonic-gate 			if (r->resp == NULL) {
865*7c478bd9Sstevel@tonic-gate 				/* free responses */
866*7c478bd9Sstevel@tonic-gate 				r = *response;
867*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < num_msg; i++, r++) {
868*7c478bd9Sstevel@tonic-gate 					if (r->resp)
869*7c478bd9Sstevel@tonic-gate 						free(r->resp);
870*7c478bd9Sstevel@tonic-gate 				}
871*7c478bd9Sstevel@tonic-gate 				free(*response);
872*7c478bd9Sstevel@tonic-gate 				*response = NULL;
873*7c478bd9Sstevel@tonic-gate 				return (PAM_BUF_ERR);
874*7c478bd9Sstevel@tonic-gate 			}
875*7c478bd9Sstevel@tonic-gate 			/*
876*7c478bd9Sstevel@tonic-gate 			 * The response might include environment variables
877*7c478bd9Sstevel@tonic-gate 			 * information. We should store that information in
878*7c478bd9Sstevel@tonic-gate 			 * envp if there is any; otherwise, envp is set to
879*7c478bd9Sstevel@tonic-gate 			 * NULL.
880*7c478bd9Sstevel@tonic-gate 			 */
881*7c478bd9Sstevel@tonic-gate 			bzero((void *)inputline, MAXLINE);
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 			envp = getargs(inputline);
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate 			/* If we read in any input, process it. */
886*7c478bd9Sstevel@tonic-gate 			if (inputline[0] != '\0') {
887*7c478bd9Sstevel@tonic-gate 				int len;
888*7c478bd9Sstevel@tonic-gate 
889*7c478bd9Sstevel@tonic-gate 				if (envp != (char **)NULL)
890*7c478bd9Sstevel@tonic-gate 					/*
891*7c478bd9Sstevel@tonic-gate 					 * If getargs() did not return NULL,
892*7c478bd9Sstevel@tonic-gate 					 * *envp is the first string in
893*7c478bd9Sstevel@tonic-gate 					 * inputline. envp++ makes envp point
894*7c478bd9Sstevel@tonic-gate 					 * to environment variables information
895*7c478bd9Sstevel@tonic-gate 					 *  or be NULL.
896*7c478bd9Sstevel@tonic-gate 					 */
897*7c478bd9Sstevel@tonic-gate 					envp++;
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 				(void) strncpy(r->resp, inputline,
900*7c478bd9Sstevel@tonic-gate 					PAM_MAX_RESP_SIZE-1);
901*7c478bd9Sstevel@tonic-gate 				r->resp[PAM_MAX_RESP_SIZE-1] = NULL;
902*7c478bd9Sstevel@tonic-gate 				len = strlen(r->resp);
903*7c478bd9Sstevel@tonic-gate 				if (r->resp[len-1] == '\n')
904*7c478bd9Sstevel@tonic-gate 					r->resp[len-1] = '\0';
905*7c478bd9Sstevel@tonic-gate 			} else {
906*7c478bd9Sstevel@tonic-gate 				login_exit(1);
907*7c478bd9Sstevel@tonic-gate 			}
908*7c478bd9Sstevel@tonic-gate 			m++;
909*7c478bd9Sstevel@tonic-gate 			r++;
910*7c478bd9Sstevel@tonic-gate 			break;
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 		case PAM_ERROR_MSG:
913*7c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
914*7c478bd9Sstevel@tonic-gate 				(void) fputs(m->msg, stderr);
915*7c478bd9Sstevel@tonic-gate 				(void) fputs("\n", stderr);
916*7c478bd9Sstevel@tonic-gate 			}
917*7c478bd9Sstevel@tonic-gate 			m++;
918*7c478bd9Sstevel@tonic-gate 			r++;
919*7c478bd9Sstevel@tonic-gate 			break;
920*7c478bd9Sstevel@tonic-gate 		case PAM_TEXT_INFO:
921*7c478bd9Sstevel@tonic-gate 			if (m->msg != NULL) {
922*7c478bd9Sstevel@tonic-gate 				(void) fputs(m->msg, stdout);
923*7c478bd9Sstevel@tonic-gate 				(void) fputs("\n", stdout);
924*7c478bd9Sstevel@tonic-gate 			}
925*7c478bd9Sstevel@tonic-gate 			m++;
926*7c478bd9Sstevel@tonic-gate 			r++;
927*7c478bd9Sstevel@tonic-gate 			break;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 		default:
930*7c478bd9Sstevel@tonic-gate 			break;
931*7c478bd9Sstevel@tonic-gate 		}
932*7c478bd9Sstevel@tonic-gate 	}
933*7c478bd9Sstevel@tonic-gate 	return (PAM_SUCCESS);
934*7c478bd9Sstevel@tonic-gate }
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate /*
937*7c478bd9Sstevel@tonic-gate  * verify_passwd - Authenticates the user.
938*7c478bd9Sstevel@tonic-gate  *	Returns: PAM_SUCCESS if authentication successful,
939*7c478bd9Sstevel@tonic-gate  *		 PAM error code if authentication fails.
940*7c478bd9Sstevel@tonic-gate  */
941*7c478bd9Sstevel@tonic-gate 
942*7c478bd9Sstevel@tonic-gate static int
943*7c478bd9Sstevel@tonic-gate verify_passwd()
944*7c478bd9Sstevel@tonic-gate {
945*7c478bd9Sstevel@tonic-gate 	int error;
946*7c478bd9Sstevel@tonic-gate 	char *user;
947*7c478bd9Sstevel@tonic-gate 	int flag = 0;
948*7c478bd9Sstevel@tonic-gate 
949*7c478bd9Sstevel@tonic-gate 	/*
950*7c478bd9Sstevel@tonic-gate 	 * PAM authenticates the user for us.
951*7c478bd9Sstevel@tonic-gate 	 */
952*7c478bd9Sstevel@tonic-gate 	if ((error = pam_authenticate(pamh, flag)) != PAM_SUCCESS) {
953*7c478bd9Sstevel@tonic-gate 		return (error);
954*7c478bd9Sstevel@tonic-gate 	}
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate 	/* get the user_name from the pam handle */
957*7c478bd9Sstevel@tonic-gate 	(void) pam_get_item(pamh, PAM_USER, (void**)&user);
958*7c478bd9Sstevel@tonic-gate 
959*7c478bd9Sstevel@tonic-gate 	if (user == NULL || *user == '\0')
960*7c478bd9Sstevel@tonic-gate 		return (PAM_SYSTEM_ERR);
961*7c478bd9Sstevel@tonic-gate 
962*7c478bd9Sstevel@tonic-gate 	SCPYL(user_name, user);
963*7c478bd9Sstevel@tonic-gate 	check_for_dueling_unix(user_name);
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	if ((pwd = getpwnam(user_name)) == NULL) {
966*7c478bd9Sstevel@tonic-gate 		return (PAM_SYSTEM_ERR);
967*7c478bd9Sstevel@tonic-gate 	}
968*7c478bd9Sstevel@tonic-gate 
969*7c478bd9Sstevel@tonic-gate 	return (error);
970*7c478bd9Sstevel@tonic-gate }
971*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate /*
974*7c478bd9Sstevel@tonic-gate  * quotec		- Called by getargs
975*7c478bd9Sstevel@tonic-gate  */
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate static int
978*7c478bd9Sstevel@tonic-gate quotec(void)
979*7c478bd9Sstevel@tonic-gate {
980*7c478bd9Sstevel@tonic-gate 	int c, i, num;
981*7c478bd9Sstevel@tonic-gate 
982*7c478bd9Sstevel@tonic-gate 	switch (c = getc(stdin)) {
983*7c478bd9Sstevel@tonic-gate 
984*7c478bd9Sstevel@tonic-gate 		case 'n':
985*7c478bd9Sstevel@tonic-gate 			c = '\n';
986*7c478bd9Sstevel@tonic-gate 			break;
987*7c478bd9Sstevel@tonic-gate 
988*7c478bd9Sstevel@tonic-gate 		case 'r':
989*7c478bd9Sstevel@tonic-gate 			c = '\r';
990*7c478bd9Sstevel@tonic-gate 			break;
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate 		case 'v':
993*7c478bd9Sstevel@tonic-gate 			c = '\013';
994*7c478bd9Sstevel@tonic-gate 			break;
995*7c478bd9Sstevel@tonic-gate 
996*7c478bd9Sstevel@tonic-gate 		case 'b':
997*7c478bd9Sstevel@tonic-gate 			c = '\b';
998*7c478bd9Sstevel@tonic-gate 			break;
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 		case 't':
1001*7c478bd9Sstevel@tonic-gate 			c = '\t';
1002*7c478bd9Sstevel@tonic-gate 			break;
1003*7c478bd9Sstevel@tonic-gate 
1004*7c478bd9Sstevel@tonic-gate 		case 'f':
1005*7c478bd9Sstevel@tonic-gate 			c = '\f';
1006*7c478bd9Sstevel@tonic-gate 			break;
1007*7c478bd9Sstevel@tonic-gate 
1008*7c478bd9Sstevel@tonic-gate 		case '0':
1009*7c478bd9Sstevel@tonic-gate 		case '1':
1010*7c478bd9Sstevel@tonic-gate 		case '2':
1011*7c478bd9Sstevel@tonic-gate 		case '3':
1012*7c478bd9Sstevel@tonic-gate 		case '4':
1013*7c478bd9Sstevel@tonic-gate 		case '5':
1014*7c478bd9Sstevel@tonic-gate 		case '6':
1015*7c478bd9Sstevel@tonic-gate 		case '7':
1016*7c478bd9Sstevel@tonic-gate 			for (num = 0, i = 0; i < 3; i++) {
1017*7c478bd9Sstevel@tonic-gate 				num = num * 8 + (c - '0');
1018*7c478bd9Sstevel@tonic-gate 				if ((c = getc(stdin)) < '0' || c > '7')
1019*7c478bd9Sstevel@tonic-gate 					break;
1020*7c478bd9Sstevel@tonic-gate 			}
1021*7c478bd9Sstevel@tonic-gate 			(void) ungetc(c, stdin);
1022*7c478bd9Sstevel@tonic-gate 			c = num & 0377;
1023*7c478bd9Sstevel@tonic-gate 			break;
1024*7c478bd9Sstevel@tonic-gate 
1025*7c478bd9Sstevel@tonic-gate 		default:
1026*7c478bd9Sstevel@tonic-gate 			break;
1027*7c478bd9Sstevel@tonic-gate 	}
1028*7c478bd9Sstevel@tonic-gate 	return (c);
1029*7c478bd9Sstevel@tonic-gate }
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate /*
1032*7c478bd9Sstevel@tonic-gate  * getargs		- returns an input line.  Exits if EOF encountered.
1033*7c478bd9Sstevel@tonic-gate  */
1034*7c478bd9Sstevel@tonic-gate #define	WHITESPACE	0
1035*7c478bd9Sstevel@tonic-gate #define	ARGUMENT	1
1036*7c478bd9Sstevel@tonic-gate 
1037*7c478bd9Sstevel@tonic-gate static char **
1038*7c478bd9Sstevel@tonic-gate getargs(char *input_line)
1039*7c478bd9Sstevel@tonic-gate {
1040*7c478bd9Sstevel@tonic-gate 	static char envbuf[MAXLINE];
1041*7c478bd9Sstevel@tonic-gate 	static char *args[MAXARGS];
1042*7c478bd9Sstevel@tonic-gate 	char *ptr, **answer;
1043*7c478bd9Sstevel@tonic-gate 	int c;
1044*7c478bd9Sstevel@tonic-gate 	int state;
1045*7c478bd9Sstevel@tonic-gate 	char *p = input_line;
1046*7c478bd9Sstevel@tonic-gate 
1047*7c478bd9Sstevel@tonic-gate 	ptr = envbuf;
1048*7c478bd9Sstevel@tonic-gate 	answer = &args[0];
1049*7c478bd9Sstevel@tonic-gate 	state = WHITESPACE;
1050*7c478bd9Sstevel@tonic-gate 
1051*7c478bd9Sstevel@tonic-gate 	while ((c = getc(stdin)) != EOF && answer < &args[MAXARGS-1]) {
1052*7c478bd9Sstevel@tonic-gate 
1053*7c478bd9Sstevel@tonic-gate 		*(input_line++) = c;
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 		switch (c) {
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 		case '\n':
1058*7c478bd9Sstevel@tonic-gate 			if (ptr == &envbuf[0])
1059*7c478bd9Sstevel@tonic-gate 				return ((char **)NULL);
1060*7c478bd9Sstevel@tonic-gate 			*input_line = *ptr = '\0';
1061*7c478bd9Sstevel@tonic-gate 			*answer = NULL;
1062*7c478bd9Sstevel@tonic-gate 			return (&args[0]);
1063*7c478bd9Sstevel@tonic-gate 
1064*7c478bd9Sstevel@tonic-gate 		case ' ':
1065*7c478bd9Sstevel@tonic-gate 		case '\t':
1066*7c478bd9Sstevel@tonic-gate 			if (state == ARGUMENT) {
1067*7c478bd9Sstevel@tonic-gate 				*ptr++ = '\0';
1068*7c478bd9Sstevel@tonic-gate 				state = WHITESPACE;
1069*7c478bd9Sstevel@tonic-gate 			}
1070*7c478bd9Sstevel@tonic-gate 			break;
1071*7c478bd9Sstevel@tonic-gate 
1072*7c478bd9Sstevel@tonic-gate 		case '\\':
1073*7c478bd9Sstevel@tonic-gate 			c = quotec();
1074*7c478bd9Sstevel@tonic-gate 
1075*7c478bd9Sstevel@tonic-gate 		default:
1076*7c478bd9Sstevel@tonic-gate 			if (state == WHITESPACE) {
1077*7c478bd9Sstevel@tonic-gate 				*answer++ = ptr;
1078*7c478bd9Sstevel@tonic-gate 				state = ARGUMENT;
1079*7c478bd9Sstevel@tonic-gate 			}
1080*7c478bd9Sstevel@tonic-gate 			*ptr++ = c;
1081*7c478bd9Sstevel@tonic-gate 		}
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate 		/* Attempt at overflow, exit */
1084*7c478bd9Sstevel@tonic-gate 		if (input_line - p >= MAXLINE - 1 ||
1085*7c478bd9Sstevel@tonic-gate 		    ptr >= &envbuf[sizeof (envbuf) - 1]) {
1086*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_VALUE_INPUT_OVERFLOW;
1087*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1088*7c478bd9Sstevel@tonic-gate 		}
1089*7c478bd9Sstevel@tonic-gate 	}
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate 	/*
1092*7c478bd9Sstevel@tonic-gate 	 * If we left loop because an EOF was received or we've overflown
1093*7c478bd9Sstevel@tonic-gate 	 * args[], exit immediately.
1094*7c478bd9Sstevel@tonic-gate 	 */
1095*7c478bd9Sstevel@tonic-gate 	login_exit(0);
1096*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
1097*7c478bd9Sstevel@tonic-gate }
1098*7c478bd9Sstevel@tonic-gate 
1099*7c478bd9Sstevel@tonic-gate /*
1100*7c478bd9Sstevel@tonic-gate  * get_user_name	- Gets the user name either passed in, or from the
1101*7c478bd9Sstevel@tonic-gate  *			  login: prompt.
1102*7c478bd9Sstevel@tonic-gate  */
1103*7c478bd9Sstevel@tonic-gate 
1104*7c478bd9Sstevel@tonic-gate static void
1105*7c478bd9Sstevel@tonic-gate get_user_name()
1106*7c478bd9Sstevel@tonic-gate {
1107*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
1108*7c478bd9Sstevel@tonic-gate 
1109*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(ISSUEFILE, "r")) != NULL) {
1110*7c478bd9Sstevel@tonic-gate 		char    *ptr, buffer[BUFSIZ];
1111*7c478bd9Sstevel@tonic-gate 		while ((ptr = fgets(buffer, sizeof (buffer),
1112*7c478bd9Sstevel@tonic-gate 					fp)) != NULL) {
1113*7c478bd9Sstevel@tonic-gate 			(void) fputs(ptr, stdout);
1114*7c478bd9Sstevel@tonic-gate 		}
1115*7c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
1116*7c478bd9Sstevel@tonic-gate 	}
1117*7c478bd9Sstevel@tonic-gate 
1118*7c478bd9Sstevel@tonic-gate 	/*
1119*7c478bd9Sstevel@tonic-gate 	 * if TTYPROMPT is not set, use our own prompt
1120*7c478bd9Sstevel@tonic-gate 	 * otherwise, use ttyprompt. We just set PAM_USER_PROMPT
1121*7c478bd9Sstevel@tonic-gate 	 * and let the module do the prompting.
1122*7c478bd9Sstevel@tonic-gate 	 */
1123*7c478bd9Sstevel@tonic-gate 
1124*7c478bd9Sstevel@tonic-gate 	if ((ttyprompt == NULL) || (*ttyprompt == '\0'))
1125*7c478bd9Sstevel@tonic-gate 		(void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)loginmsg);
1126*7c478bd9Sstevel@tonic-gate 	else
1127*7c478bd9Sstevel@tonic-gate 		(void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)ttyprompt);
1128*7c478bd9Sstevel@tonic-gate 
1129*7c478bd9Sstevel@tonic-gate 	envp = &zero; /* XXX: is this right? */
1130*7c478bd9Sstevel@tonic-gate }
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate /*
1134*7c478bd9Sstevel@tonic-gate  * Check_for_dueling_unix   -	Check to see if the another login is talking
1135*7c478bd9Sstevel@tonic-gate  *				to the line we've got open as a login port
1136*7c478bd9Sstevel@tonic-gate  *				Exits if we're talking to another unix system
1137*7c478bd9Sstevel@tonic-gate  */
1138*7c478bd9Sstevel@tonic-gate 
1139*7c478bd9Sstevel@tonic-gate static void
1140*7c478bd9Sstevel@tonic-gate check_for_dueling_unix(char *inputline)
1141*7c478bd9Sstevel@tonic-gate {
1142*7c478bd9Sstevel@tonic-gate 	if (EQN(loginmsg, inputline) || EQN(passwdmsg, inputline) ||
1143*7c478bd9Sstevel@tonic-gate 	    EQN(incorrectmsg, inputline)) {
1144*7c478bd9Sstevel@tonic-gate 		(void) printf("Looking at a login line.\n");
1145*7c478bd9Sstevel@tonic-gate 		login_exit(8);
1146*7c478bd9Sstevel@tonic-gate 	}
1147*7c478bd9Sstevel@tonic-gate }
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate /*
1150*7c478bd9Sstevel@tonic-gate  * logins_disabled - 	if the file /etc/nologin exists and the user is not
1151*7c478bd9Sstevel@tonic-gate  *			root then do not permit them to login
1152*7c478bd9Sstevel@tonic-gate  */
1153*7c478bd9Sstevel@tonic-gate static int
1154*7c478bd9Sstevel@tonic-gate logins_disabled(char *user_name)
1155*7c478bd9Sstevel@tonic-gate {
1156*7c478bd9Sstevel@tonic-gate 	FILE	*nlfd;
1157*7c478bd9Sstevel@tonic-gate 	int	c;
1158*7c478bd9Sstevel@tonic-gate 	if (!EQN("root", user_name) &&
1159*7c478bd9Sstevel@tonic-gate 			((nlfd = fopen(NOLOGIN, "r")) != (FILE *)NULL)) {
1160*7c478bd9Sstevel@tonic-gate 		while ((c = getc(nlfd)) != EOF)
1161*7c478bd9Sstevel@tonic-gate 			(void) putchar(c);
1162*7c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
1163*7c478bd9Sstevel@tonic-gate 		(void) sleep(5);
1164*7c478bd9Sstevel@tonic-gate 		return (TRUE);
1165*7c478bd9Sstevel@tonic-gate 	}
1166*7c478bd9Sstevel@tonic-gate 	return (FALSE);
1167*7c478bd9Sstevel@tonic-gate }
1168*7c478bd9Sstevel@tonic-gate 
1169*7c478bd9Sstevel@tonic-gate /*
1170*7c478bd9Sstevel@tonic-gate  * check_for_console -  Checks if we're getting a root login on the
1171*7c478bd9Sstevel@tonic-gate  *			console, or a login from the global zone.  Exits if not.
1172*7c478bd9Sstevel@tonic-gate  *
1173*7c478bd9Sstevel@tonic-gate  */
1174*7c478bd9Sstevel@tonic-gate static void
1175*7c478bd9Sstevel@tonic-gate check_for_console(void)
1176*7c478bd9Sstevel@tonic-gate {
1177*7c478bd9Sstevel@tonic-gate 	if (pwd != NULL && pwd->pw_uid == 0 && zflag == B_FALSE) {
1178*7c478bd9Sstevel@tonic-gate 		if ((Console != NULL) && (strcmp(ttyn, Console) != 0)) {
1179*7c478bd9Sstevel@tonic-gate 			(void) printf("Not on system console\n");
1180*7c478bd9Sstevel@tonic-gate 
1181*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_VALUE_CONSOLE;
1182*7c478bd9Sstevel@tonic-gate 			login_exit(10);
1183*7c478bd9Sstevel@tonic-gate 		}
1184*7c478bd9Sstevel@tonic-gate 	}
1185*7c478bd9Sstevel@tonic-gate }
1186*7c478bd9Sstevel@tonic-gate 
1187*7c478bd9Sstevel@tonic-gate /*
1188*7c478bd9Sstevel@tonic-gate  * List of environment variables or environment variable prefixes that should
1189*7c478bd9Sstevel@tonic-gate  * not be propagated across logins, such as when the login -p option is used.
1190*7c478bd9Sstevel@tonic-gate  */
1191*7c478bd9Sstevel@tonic-gate static const char *const illegal[] = {
1192*7c478bd9Sstevel@tonic-gate 	"SHELL=",
1193*7c478bd9Sstevel@tonic-gate 	"HOME=",
1194*7c478bd9Sstevel@tonic-gate 	"LOGNAME=",
1195*7c478bd9Sstevel@tonic-gate #ifndef	NO_MAIL
1196*7c478bd9Sstevel@tonic-gate 	"MAIL=",
1197*7c478bd9Sstevel@tonic-gate #endif
1198*7c478bd9Sstevel@tonic-gate 	"CDPATH=",
1199*7c478bd9Sstevel@tonic-gate 	"IFS=",
1200*7c478bd9Sstevel@tonic-gate 	"PATH=",
1201*7c478bd9Sstevel@tonic-gate 	"LD_",
1202*7c478bd9Sstevel@tonic-gate 	"SMF_",
1203*7c478bd9Sstevel@tonic-gate 	NULL
1204*7c478bd9Sstevel@tonic-gate };
1205*7c478bd9Sstevel@tonic-gate 
1206*7c478bd9Sstevel@tonic-gate /*
1207*7c478bd9Sstevel@tonic-gate  * legalenvvar		- Is it legal to insert this environmental variable?
1208*7c478bd9Sstevel@tonic-gate  */
1209*7c478bd9Sstevel@tonic-gate 
1210*7c478bd9Sstevel@tonic-gate static int
1211*7c478bd9Sstevel@tonic-gate legalenvvar(char *s)
1212*7c478bd9Sstevel@tonic-gate {
1213*7c478bd9Sstevel@tonic-gate 	const char *const *p;
1214*7c478bd9Sstevel@tonic-gate 
1215*7c478bd9Sstevel@tonic-gate 	for (p = &illegal[0]; *p; p++) {
1216*7c478bd9Sstevel@tonic-gate 		if (strncmp(s, *p, strlen(*p)) == 0)
1217*7c478bd9Sstevel@tonic-gate 			return (0);
1218*7c478bd9Sstevel@tonic-gate 	}
1219*7c478bd9Sstevel@tonic-gate 
1220*7c478bd9Sstevel@tonic-gate 	return (1);
1221*7c478bd9Sstevel@tonic-gate }
1222*7c478bd9Sstevel@tonic-gate 
1223*7c478bd9Sstevel@tonic-gate 
1224*7c478bd9Sstevel@tonic-gate /*
1225*7c478bd9Sstevel@tonic-gate  * getstr		- Get a string from standard input
1226*7c478bd9Sstevel@tonic-gate  *			  Calls exit if read(2) fails.
1227*7c478bd9Sstevel@tonic-gate  */
1228*7c478bd9Sstevel@tonic-gate 
1229*7c478bd9Sstevel@tonic-gate static void
1230*7c478bd9Sstevel@tonic-gate getstr(char *buf, int cnt, char *err)
1231*7c478bd9Sstevel@tonic-gate {
1232*7c478bd9Sstevel@tonic-gate 	char c;
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate 	do {
1235*7c478bd9Sstevel@tonic-gate 		if (read(0, &c, 1) != 1)
1236*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1237*7c478bd9Sstevel@tonic-gate 		*buf++ = c;
1238*7c478bd9Sstevel@tonic-gate 	} while (--cnt > 1 && c != 0);
1239*7c478bd9Sstevel@tonic-gate 
1240*7c478bd9Sstevel@tonic-gate 	*buf = 0;
1241*7c478bd9Sstevel@tonic-gate 	err = err; 	/* For lint */
1242*7c478bd9Sstevel@tonic-gate }
1243*7c478bd9Sstevel@tonic-gate 
1244*7c478bd9Sstevel@tonic-gate 
1245*7c478bd9Sstevel@tonic-gate /*
1246*7c478bd9Sstevel@tonic-gate  * defaults 		- read defaults
1247*7c478bd9Sstevel@tonic-gate  */
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate static void
1250*7c478bd9Sstevel@tonic-gate defaults(void)
1251*7c478bd9Sstevel@tonic-gate {
1252*7c478bd9Sstevel@tonic-gate 	int  flags;
1253*7c478bd9Sstevel@tonic-gate 	char *ptr;
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate 	if (defopen(Pndefault) == 0) {
1256*7c478bd9Sstevel@tonic-gate 		/*
1257*7c478bd9Sstevel@tonic-gate 		 * ignore case
1258*7c478bd9Sstevel@tonic-gate 		 */
1259*7c478bd9Sstevel@tonic-gate 		flags = defcntl(DC_GETFLAGS, 0);
1260*7c478bd9Sstevel@tonic-gate 		TURNOFF(flags, DC_CASE);
1261*7c478bd9Sstevel@tonic-gate 		(void) defcntl(DC_SETFLAGS, flags);
1262*7c478bd9Sstevel@tonic-gate 
1263*7c478bd9Sstevel@tonic-gate 		if ((Console = defread("CONSOLE=")) != NULL)
1264*7c478bd9Sstevel@tonic-gate 			Console = strdup(Console);
1265*7c478bd9Sstevel@tonic-gate 
1266*7c478bd9Sstevel@tonic-gate 		if ((Altshell = defread("ALTSHELL=")) != NULL)
1267*7c478bd9Sstevel@tonic-gate 			Altshell = strdup(Altshell);
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("PASSREQ=")) != NULL &&
1270*7c478bd9Sstevel@tonic-gate 		    strcasecmp("YES", ptr) == 0)
1271*7c478bd9Sstevel@tonic-gate 				Passreqflag = 1;
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 		if ((Def_tz = defread("TIMEZONE=")) != NULL)
1274*7c478bd9Sstevel@tonic-gate 			Def_tz = strdup(Def_tz);
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate 		if ((Def_hertz = defread("HZ=")) != NULL)
1277*7c478bd9Sstevel@tonic-gate 			Def_hertz = strdup(Def_hertz);
1278*7c478bd9Sstevel@tonic-gate 
1279*7c478bd9Sstevel@tonic-gate 		if ((Def_path   = defread("PATH=")) != NULL)
1280*7c478bd9Sstevel@tonic-gate 			Def_path = strdup(Def_path);
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 		if ((Def_supath = defread("SUPATH=")) != NULL)
1283*7c478bd9Sstevel@tonic-gate 			Def_supath = strdup(Def_supath);
1284*7c478bd9Sstevel@tonic-gate 
1285*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("ULIMIT=")) != NULL)
1286*7c478bd9Sstevel@tonic-gate 			Def_ulimit = atol(ptr);
1287*7c478bd9Sstevel@tonic-gate 
1288*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("TIMEOUT=")) != NULL)
1289*7c478bd9Sstevel@tonic-gate 			Def_timeout = (unsigned)atoi(ptr);
1290*7c478bd9Sstevel@tonic-gate 
1291*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("UMASK=")) != NULL)
1292*7c478bd9Sstevel@tonic-gate 			if (sscanf(ptr, "%lo", &Umask) != 1)
1293*7c478bd9Sstevel@tonic-gate 				Umask = DEFUMASK;
1294*7c478bd9Sstevel@tonic-gate 
1295*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("SLEEPTIME=")) != NULL) {
1296*7c478bd9Sstevel@tonic-gate 			if (is_number(ptr))
1297*7c478bd9Sstevel@tonic-gate 				Sleeptime = atoi(ptr);
1298*7c478bd9Sstevel@tonic-gate 		}
1299*7c478bd9Sstevel@tonic-gate 
1300*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("DISABLETIME=")) != NULL) {
1301*7c478bd9Sstevel@tonic-gate 			if (is_number(ptr))
1302*7c478bd9Sstevel@tonic-gate 				Disabletime = atoi(ptr);
1303*7c478bd9Sstevel@tonic-gate 		}
1304*7c478bd9Sstevel@tonic-gate 
1305*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("SYSLOG=")) != NULL)
1306*7c478bd9Sstevel@tonic-gate 			dosyslog = strcmp(ptr, "YES") == 0;
1307*7c478bd9Sstevel@tonic-gate 
1308*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("RETRIES=")) != NULL) {
1309*7c478bd9Sstevel@tonic-gate 			if (is_number(ptr))
1310*7c478bd9Sstevel@tonic-gate 				retry = atoi(ptr);
1311*7c478bd9Sstevel@tonic-gate 		}
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) {
1314*7c478bd9Sstevel@tonic-gate 			if (is_number(ptr))
1315*7c478bd9Sstevel@tonic-gate 				flogin = atoi(ptr);
1316*7c478bd9Sstevel@tonic-gate 			else
1317*7c478bd9Sstevel@tonic-gate 				flogin = retry;
1318*7c478bd9Sstevel@tonic-gate 		} else
1319*7c478bd9Sstevel@tonic-gate 			flogin = retry;
1320*7c478bd9Sstevel@tonic-gate 		(void) defopen((char *)NULL);
1321*7c478bd9Sstevel@tonic-gate 	}
1322*7c478bd9Sstevel@tonic-gate }
1323*7c478bd9Sstevel@tonic-gate 
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate /*
1326*7c478bd9Sstevel@tonic-gate  * get_options(argc, argv)
1327*7c478bd9Sstevel@tonic-gate  * 			- parse the cmd line.
1328*7c478bd9Sstevel@tonic-gate  *			- return 0 if successful, -1 if failed.
1329*7c478bd9Sstevel@tonic-gate  *			Calls login_exit() on misuse of -r, -h, and -z flags
1330*7c478bd9Sstevel@tonic-gate  */
1331*7c478bd9Sstevel@tonic-gate 
1332*7c478bd9Sstevel@tonic-gate static	int
1333*7c478bd9Sstevel@tonic-gate get_options(int argc, char *argv[])
1334*7c478bd9Sstevel@tonic-gate {
1335*7c478bd9Sstevel@tonic-gate 	int	c;
1336*7c478bd9Sstevel@tonic-gate 	int	errflg = 0;
1337*7c478bd9Sstevel@tonic-gate 	char    sflagname[NMAX+1];
1338*7c478bd9Sstevel@tonic-gate 	const 	char *flags_message = "Only one of -r, -h and -z allowed\n";
1339*7c478bd9Sstevel@tonic-gate 
1340*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "u:s:R:f:h:r:pad:t:U:z:")) != -1) {
1341*7c478bd9Sstevel@tonic-gate 		switch (c) {
1342*7c478bd9Sstevel@tonic-gate 		case 'a':
1343*7c478bd9Sstevel@tonic-gate 			break;
1344*7c478bd9Sstevel@tonic-gate 
1345*7c478bd9Sstevel@tonic-gate 		case 'd':
1346*7c478bd9Sstevel@tonic-gate 			/*
1347*7c478bd9Sstevel@tonic-gate 			 * Must be root to pass in device name
1348*7c478bd9Sstevel@tonic-gate 			 * otherwise we exit() as punishment for trying.
1349*7c478bd9Sstevel@tonic-gate 			 */
1350*7c478bd9Sstevel@tonic-gate 			if (getuid() != 0 || geteuid() != 0) {
1351*7c478bd9Sstevel@tonic-gate 				audit_error = ADT_FAIL_VALUE_DEVICE_PERM;
1352*7c478bd9Sstevel@tonic-gate 				login_exit(1);	/* sigh */
1353*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
1354*7c478bd9Sstevel@tonic-gate 			}
1355*7c478bd9Sstevel@tonic-gate 			ttyn = optarg;
1356*7c478bd9Sstevel@tonic-gate 			break;
1357*7c478bd9Sstevel@tonic-gate 
1358*7c478bd9Sstevel@tonic-gate 		case 'h':
1359*7c478bd9Sstevel@tonic-gate 			if (hflag || rflag || zflag) {
1360*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, flags_message);
1361*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1362*7c478bd9Sstevel@tonic-gate 			}
1363*7c478bd9Sstevel@tonic-gate 			hflag = B_TRUE;
1364*7c478bd9Sstevel@tonic-gate 			SCPYL(remote_host, optarg);
1365*7c478bd9Sstevel@tonic-gate 			if (argv[optind]) {
1366*7c478bd9Sstevel@tonic-gate 				if (argv[optind][0] != '-') {
1367*7c478bd9Sstevel@tonic-gate 					SCPYL(terminal, argv[optind]);
1368*7c478bd9Sstevel@tonic-gate 					optind++;
1369*7c478bd9Sstevel@tonic-gate 				} else {
1370*7c478bd9Sstevel@tonic-gate 					/*
1371*7c478bd9Sstevel@tonic-gate 					 * Allow "login -h hostname -" to
1372*7c478bd9Sstevel@tonic-gate 					 * skip setting up an username as "-".
1373*7c478bd9Sstevel@tonic-gate 					 */
1374*7c478bd9Sstevel@tonic-gate 					if (argv[optind][1] == '\0')
1375*7c478bd9Sstevel@tonic-gate 						optind++;
1376*7c478bd9Sstevel@tonic-gate 				}
1377*7c478bd9Sstevel@tonic-gate 
1378*7c478bd9Sstevel@tonic-gate 			}
1379*7c478bd9Sstevel@tonic-gate 			SCPYL(progname, "telnet");
1380*7c478bd9Sstevel@tonic-gate 			break;
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 		case 'r':
1383*7c478bd9Sstevel@tonic-gate 			if (hflag || rflag || zflag) {
1384*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, flags_message);
1385*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1386*7c478bd9Sstevel@tonic-gate 			}
1387*7c478bd9Sstevel@tonic-gate 			rflag = B_TRUE;
1388*7c478bd9Sstevel@tonic-gate 			SCPYL(remote_host, optarg);
1389*7c478bd9Sstevel@tonic-gate 			SCPYL(progname, "rlogin");
1390*7c478bd9Sstevel@tonic-gate 			break;
1391*7c478bd9Sstevel@tonic-gate 
1392*7c478bd9Sstevel@tonic-gate 		case 'p':
1393*7c478bd9Sstevel@tonic-gate 			pflag = B_TRUE;
1394*7c478bd9Sstevel@tonic-gate 			break;
1395*7c478bd9Sstevel@tonic-gate 
1396*7c478bd9Sstevel@tonic-gate 		case 'f':
1397*7c478bd9Sstevel@tonic-gate 			/*
1398*7c478bd9Sstevel@tonic-gate 			 * Must be root to bypass authentication
1399*7c478bd9Sstevel@tonic-gate 			 * otherwise we exit() as punishment for trying.
1400*7c478bd9Sstevel@tonic-gate 			 */
1401*7c478bd9Sstevel@tonic-gate 			if (getuid() != 0 || geteuid() != 0) {
1402*7c478bd9Sstevel@tonic-gate 				audit_error = ADT_FAIL_VALUE_AUTH_BYPASS;
1403*7c478bd9Sstevel@tonic-gate 
1404*7c478bd9Sstevel@tonic-gate 				login_exit(1);	/* sigh */
1405*7c478bd9Sstevel@tonic-gate 				/*NOTREACHED*/
1406*7c478bd9Sstevel@tonic-gate 			}
1407*7c478bd9Sstevel@tonic-gate 			/* save fflag user name for future use */
1408*7c478bd9Sstevel@tonic-gate 			SCPYL(user_name, optarg);
1409*7c478bd9Sstevel@tonic-gate 			fflag = B_TRUE;
1410*7c478bd9Sstevel@tonic-gate 			break;
1411*7c478bd9Sstevel@tonic-gate 		case 'u':
1412*7c478bd9Sstevel@tonic-gate 			if (!strlen(optarg)) {
1413*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1414*7c478bd9Sstevel@tonic-gate 					"Empty string supplied with -u\n");
1415*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1416*7c478bd9Sstevel@tonic-gate 			}
1417*7c478bd9Sstevel@tonic-gate 			SCPYL(identity, optarg);
1418*7c478bd9Sstevel@tonic-gate 			uflag = B_TRUE;
1419*7c478bd9Sstevel@tonic-gate 			break;
1420*7c478bd9Sstevel@tonic-gate 		case 's':
1421*7c478bd9Sstevel@tonic-gate 			if (!strlen(optarg)) {
1422*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1423*7c478bd9Sstevel@tonic-gate 					"Empty string supplied with -s\n");
1424*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1425*7c478bd9Sstevel@tonic-gate 			}
1426*7c478bd9Sstevel@tonic-gate 			SCPYL(sflagname, optarg);
1427*7c478bd9Sstevel@tonic-gate 			sflag = B_TRUE;
1428*7c478bd9Sstevel@tonic-gate 			break;
1429*7c478bd9Sstevel@tonic-gate 		case 'R':
1430*7c478bd9Sstevel@tonic-gate 			if (!strlen(optarg)) {
1431*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1432*7c478bd9Sstevel@tonic-gate 					"Empty string supplied with -R\n");
1433*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1434*7c478bd9Sstevel@tonic-gate 			}
1435*7c478bd9Sstevel@tonic-gate 			SCPYL(repository, optarg);
1436*7c478bd9Sstevel@tonic-gate 			Rflag =	B_TRUE;
1437*7c478bd9Sstevel@tonic-gate 			break;
1438*7c478bd9Sstevel@tonic-gate 		case 't':
1439*7c478bd9Sstevel@tonic-gate 			if (!strlen(optarg)) {
1440*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1441*7c478bd9Sstevel@tonic-gate 					"Empty string supplied with -t\n");
1442*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1443*7c478bd9Sstevel@tonic-gate 			}
1444*7c478bd9Sstevel@tonic-gate 			SCPYL(terminal, optarg);
1445*7c478bd9Sstevel@tonic-gate 			tflag = B_TRUE;
1446*7c478bd9Sstevel@tonic-gate 			break;
1447*7c478bd9Sstevel@tonic-gate 		case 'U':
1448*7c478bd9Sstevel@tonic-gate 			/*
1449*7c478bd9Sstevel@tonic-gate 			 * Kerberized rlogind may fork us with
1450*7c478bd9Sstevel@tonic-gate 			 * -U "" if the rlogin client used the "-a"
1451*7c478bd9Sstevel@tonic-gate 			 * option to send a NULL username.  This is done
1452*7c478bd9Sstevel@tonic-gate 			 * to force login to prompt for a user/password.
1453*7c478bd9Sstevel@tonic-gate 			 * However, if Kerberos auth was used, we dont need
1454*7c478bd9Sstevel@tonic-gate 			 * to prompt, so we will accept the option and
1455*7c478bd9Sstevel@tonic-gate 			 * handle the situation later.
1456*7c478bd9Sstevel@tonic-gate 			 */
1457*7c478bd9Sstevel@tonic-gate 			SCPYL(rusername, optarg);
1458*7c478bd9Sstevel@tonic-gate 			Uflag = B_TRUE;
1459*7c478bd9Sstevel@tonic-gate 			break;
1460*7c478bd9Sstevel@tonic-gate 		case 'z':
1461*7c478bd9Sstevel@tonic-gate 			if (hflag || rflag || zflag) {
1462*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, flags_message);
1463*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1464*7c478bd9Sstevel@tonic-gate 			}
1465*7c478bd9Sstevel@tonic-gate 			(void) snprintf(zone_name, sizeof (zone_name),
1466*7c478bd9Sstevel@tonic-gate 			    "zone:%s", optarg);
1467*7c478bd9Sstevel@tonic-gate 			SCPYL(progname, "zlogin");
1468*7c478bd9Sstevel@tonic-gate 			zflag = B_TRUE;
1469*7c478bd9Sstevel@tonic-gate 			break;
1470*7c478bd9Sstevel@tonic-gate 		default:
1471*7c478bd9Sstevel@tonic-gate 			errflg++;
1472*7c478bd9Sstevel@tonic-gate 			break;
1473*7c478bd9Sstevel@tonic-gate 		} 	/* end switch */
1474*7c478bd9Sstevel@tonic-gate 	} 		/* end while */
1475*7c478bd9Sstevel@tonic-gate 
1476*7c478bd9Sstevel@tonic-gate 	/*
1477*7c478bd9Sstevel@tonic-gate 	 * If the 's svcname' flag was used, override the progname
1478*7c478bd9Sstevel@tonic-gate 	 * value that is to be used in the pam_start call.
1479*7c478bd9Sstevel@tonic-gate 	 */
1480*7c478bd9Sstevel@tonic-gate 	if (sflag)
1481*7c478bd9Sstevel@tonic-gate 		SCPYL(progname, sflagname);
1482*7c478bd9Sstevel@tonic-gate 
1483*7c478bd9Sstevel@tonic-gate 	/*
1484*7c478bd9Sstevel@tonic-gate 	 * get the prompt set by ttymon
1485*7c478bd9Sstevel@tonic-gate 	 */
1486*7c478bd9Sstevel@tonic-gate 	ttyprompt = getenv("TTYPROMPT");
1487*7c478bd9Sstevel@tonic-gate 
1488*7c478bd9Sstevel@tonic-gate 	if ((ttyprompt != NULL) && (*ttyprompt != '\0')) {
1489*7c478bd9Sstevel@tonic-gate 		/*
1490*7c478bd9Sstevel@tonic-gate 		 * if ttyprompt is set, there should be data on
1491*7c478bd9Sstevel@tonic-gate 		 * the stream already.
1492*7c478bd9Sstevel@tonic-gate 		 */
1493*7c478bd9Sstevel@tonic-gate 		if ((envp = getargs(inputline)) != (char **)NULL) {
1494*7c478bd9Sstevel@tonic-gate 			/*
1495*7c478bd9Sstevel@tonic-gate 			 * don't get name if name passed as argument.
1496*7c478bd9Sstevel@tonic-gate 			 */
1497*7c478bd9Sstevel@tonic-gate 			SCPYL(user_name, *envp++);
1498*7c478bd9Sstevel@tonic-gate 		}
1499*7c478bd9Sstevel@tonic-gate 	} else if (optind < argc) {
1500*7c478bd9Sstevel@tonic-gate 		SCPYL(user_name, argv[optind]);
1501*7c478bd9Sstevel@tonic-gate 		(void) SCPYL(inputline, user_name);
1502*7c478bd9Sstevel@tonic-gate 		(void) strlcat(inputline, "   \n", sizeof (inputline));
1503*7c478bd9Sstevel@tonic-gate 		envp = &argv[optind+1];
1504*7c478bd9Sstevel@tonic-gate 
1505*7c478bd9Sstevel@tonic-gate 		if (!fflag)
1506*7c478bd9Sstevel@tonic-gate 			SCPYL(lusername, user_name);
1507*7c478bd9Sstevel@tonic-gate 	}
1508*7c478bd9Sstevel@tonic-gate 
1509*7c478bd9Sstevel@tonic-gate 	if (errflg)
1510*7c478bd9Sstevel@tonic-gate 		return (-1);
1511*7c478bd9Sstevel@tonic-gate 	return (0);
1512*7c478bd9Sstevel@tonic-gate }
1513*7c478bd9Sstevel@tonic-gate 
1514*7c478bd9Sstevel@tonic-gate /*
1515*7c478bd9Sstevel@tonic-gate  * usage		- Print usage message
1516*7c478bd9Sstevel@tonic-gate  *
1517*7c478bd9Sstevel@tonic-gate  */
1518*7c478bd9Sstevel@tonic-gate static void
1519*7c478bd9Sstevel@tonic-gate usage(void)
1520*7c478bd9Sstevel@tonic-gate {
1521*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
1522*7c478bd9Sstevel@tonic-gate 	    "usage:\n"
1523*7c478bd9Sstevel@tonic-gate 	    "    login [-p] [-d device] [-R repository] [-s service]\n"
1524*7c478bd9Sstevel@tonic-gate 	    "\t[-t terminal]  [-u identity] [-U ruser]\n"
1525*7c478bd9Sstevel@tonic-gate 	    "\t[-h hostname [terminal] | -r hostname] [name [environ]...]\n");
1526*7c478bd9Sstevel@tonic-gate 
1527*7c478bd9Sstevel@tonic-gate }
1528*7c478bd9Sstevel@tonic-gate 
1529*7c478bd9Sstevel@tonic-gate /*
1530*7c478bd9Sstevel@tonic-gate  * doremoteterm		- Sets the appropriate ioctls for a remote terminal
1531*7c478bd9Sstevel@tonic-gate  */
1532*7c478bd9Sstevel@tonic-gate static char	*speeds[] = {
1533*7c478bd9Sstevel@tonic-gate 	"0", "50", "75", "110", "134", "150", "200", "300",
1534*7c478bd9Sstevel@tonic-gate 	"600", "1200", "1800", "2400", "4800", "9600", "19200", "38400",
1535*7c478bd9Sstevel@tonic-gate 	"57600", "76800", "115200", "153600", "230400", "307200", "460800"
1536*7c478bd9Sstevel@tonic-gate };
1537*7c478bd9Sstevel@tonic-gate 
1538*7c478bd9Sstevel@tonic-gate #define	NSPEEDS	(sizeof (speeds) / sizeof (speeds[0]))
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate 
1541*7c478bd9Sstevel@tonic-gate static void
1542*7c478bd9Sstevel@tonic-gate doremoteterm(char *term)
1543*7c478bd9Sstevel@tonic-gate {
1544*7c478bd9Sstevel@tonic-gate 	struct termios tp;
1545*7c478bd9Sstevel@tonic-gate 	char *cp = strchr(term, '/'), **cpp;
1546*7c478bd9Sstevel@tonic-gate 	char *speed;
1547*7c478bd9Sstevel@tonic-gate 
1548*7c478bd9Sstevel@tonic-gate 	(void) ioctl(0, TCGETS, &tp);
1549*7c478bd9Sstevel@tonic-gate 
1550*7c478bd9Sstevel@tonic-gate 	if (cp) {
1551*7c478bd9Sstevel@tonic-gate 		*cp++ = '\0';
1552*7c478bd9Sstevel@tonic-gate 		speed = cp;
1553*7c478bd9Sstevel@tonic-gate 		cp = strchr(speed, '/');
1554*7c478bd9Sstevel@tonic-gate 
1555*7c478bd9Sstevel@tonic-gate 		if (cp)
1556*7c478bd9Sstevel@tonic-gate 			*cp++ = '\0';
1557*7c478bd9Sstevel@tonic-gate 
1558*7c478bd9Sstevel@tonic-gate 		for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
1559*7c478bd9Sstevel@tonic-gate 			if (strcmp(*cpp, speed) == 0) {
1560*7c478bd9Sstevel@tonic-gate 				(void) cfsetospeed(&tp, cpp-speeds);
1561*7c478bd9Sstevel@tonic-gate 				break;
1562*7c478bd9Sstevel@tonic-gate 			}
1563*7c478bd9Sstevel@tonic-gate 	}
1564*7c478bd9Sstevel@tonic-gate 
1565*7c478bd9Sstevel@tonic-gate 	tp.c_lflag |= ECHO|ICANON;
1566*7c478bd9Sstevel@tonic-gate 	tp.c_iflag |= IGNPAR|ICRNL;
1567*7c478bd9Sstevel@tonic-gate 
1568*7c478bd9Sstevel@tonic-gate 	(void) ioctl(0, TCSETS, &tp);
1569*7c478bd9Sstevel@tonic-gate 
1570*7c478bd9Sstevel@tonic-gate }
1571*7c478bd9Sstevel@tonic-gate 
1572*7c478bd9Sstevel@tonic-gate /*
1573*7c478bd9Sstevel@tonic-gate  * Process_rlogin		- Does the work that rlogin and telnet
1574*7c478bd9Sstevel@tonic-gate  *				  need done
1575*7c478bd9Sstevel@tonic-gate  */
1576*7c478bd9Sstevel@tonic-gate static void
1577*7c478bd9Sstevel@tonic-gate process_rlogin(void)
1578*7c478bd9Sstevel@tonic-gate {
1579*7c478bd9Sstevel@tonic-gate 	/*
1580*7c478bd9Sstevel@tonic-gate 	 * If a Kerberized rlogin was initiated, then these fields
1581*7c478bd9Sstevel@tonic-gate 	 * must be read by rlogin daemon itself and passed down via
1582*7c478bd9Sstevel@tonic-gate 	 * cmd line args.
1583*7c478bd9Sstevel@tonic-gate 	 */
1584*7c478bd9Sstevel@tonic-gate 	if (!Uflag && !strlen(rusername))
1585*7c478bd9Sstevel@tonic-gate 		getstr(rusername, sizeof (rusername), "remuser");
1586*7c478bd9Sstevel@tonic-gate 	if (!strlen(lusername))
1587*7c478bd9Sstevel@tonic-gate 		getstr(lusername, sizeof (lusername), "locuser");
1588*7c478bd9Sstevel@tonic-gate 	if (!tflag && !strlen(terminal))
1589*7c478bd9Sstevel@tonic-gate 		getstr(terminal, sizeof (terminal), "Terminal type");
1590*7c478bd9Sstevel@tonic-gate 
1591*7c478bd9Sstevel@tonic-gate 	if (strlen(terminal))
1592*7c478bd9Sstevel@tonic-gate 		doremoteterm(terminal);
1593*7c478bd9Sstevel@tonic-gate 
1594*7c478bd9Sstevel@tonic-gate 	/* fflag has precedence over stuff passed by rlogind */
1595*7c478bd9Sstevel@tonic-gate 	if (fflag || getuid()) {
1596*7c478bd9Sstevel@tonic-gate 		pwd = &nouser;
1597*7c478bd9Sstevel@tonic-gate 		return;
1598*7c478bd9Sstevel@tonic-gate 	} else {
1599*7c478bd9Sstevel@tonic-gate 		if (pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS)
1600*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1601*7c478bd9Sstevel@tonic-gate 
1602*7c478bd9Sstevel@tonic-gate 		pwd = getpwnam(lusername);
1603*7c478bd9Sstevel@tonic-gate 		if (pwd == NULL) {
1604*7c478bd9Sstevel@tonic-gate 			pwd = &nouser;
1605*7c478bd9Sstevel@tonic-gate 			return;
1606*7c478bd9Sstevel@tonic-gate 		}
1607*7c478bd9Sstevel@tonic-gate 	}
1608*7c478bd9Sstevel@tonic-gate 
1609*7c478bd9Sstevel@tonic-gate 	/*
1610*7c478bd9Sstevel@tonic-gate 	 * Update PAM on the user name
1611*7c478bd9Sstevel@tonic-gate 	 */
1612*7c478bd9Sstevel@tonic-gate 	if (strlen(lusername) &&
1613*7c478bd9Sstevel@tonic-gate 	    pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS)
1614*7c478bd9Sstevel@tonic-gate 		login_exit(1);
1615*7c478bd9Sstevel@tonic-gate 
1616*7c478bd9Sstevel@tonic-gate 	if (strlen(rusername) &&
1617*7c478bd9Sstevel@tonic-gate 	    pam_set_item(pamh, PAM_RUSER, rusername) != PAM_SUCCESS)
1618*7c478bd9Sstevel@tonic-gate 		login_exit(1);
1619*7c478bd9Sstevel@tonic-gate 
1620*7c478bd9Sstevel@tonic-gate 	SCPYL(user_name, lusername);
1621*7c478bd9Sstevel@tonic-gate 	envp = &zero;
1622*7c478bd9Sstevel@tonic-gate 	lusername[0] = '\0';
1623*7c478bd9Sstevel@tonic-gate }
1624*7c478bd9Sstevel@tonic-gate 
1625*7c478bd9Sstevel@tonic-gate /*
1626*7c478bd9Sstevel@tonic-gate  *		*** Account validation routines ***
1627*7c478bd9Sstevel@tonic-gate  *
1628*7c478bd9Sstevel@tonic-gate  */
1629*7c478bd9Sstevel@tonic-gate 
1630*7c478bd9Sstevel@tonic-gate /*
1631*7c478bd9Sstevel@tonic-gate  * validate_account		- This is the PAM version of validate.
1632*7c478bd9Sstevel@tonic-gate  */
1633*7c478bd9Sstevel@tonic-gate 
1634*7c478bd9Sstevel@tonic-gate static void
1635*7c478bd9Sstevel@tonic-gate validate_account(void)
1636*7c478bd9Sstevel@tonic-gate {
1637*7c478bd9Sstevel@tonic-gate 	int 	error;
1638*7c478bd9Sstevel@tonic-gate 	int	flag;
1639*7c478bd9Sstevel@tonic-gate 	int	tries;		/* new password retries */
1640*7c478bd9Sstevel@tonic-gate 
1641*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);	/* give user time to come up with password */
1642*7c478bd9Sstevel@tonic-gate 
1643*7c478bd9Sstevel@tonic-gate 	check_log();
1644*7c478bd9Sstevel@tonic-gate 
1645*7c478bd9Sstevel@tonic-gate 	if (Passreqflag)
1646*7c478bd9Sstevel@tonic-gate 		flag = PAM_DISALLOW_NULL_AUTHTOK;
1647*7c478bd9Sstevel@tonic-gate 	else
1648*7c478bd9Sstevel@tonic-gate 		flag = 0;
1649*7c478bd9Sstevel@tonic-gate 
1650*7c478bd9Sstevel@tonic-gate 	if ((error = pam_acct_mgmt(pamh, flag)) != PAM_SUCCESS) {
1651*7c478bd9Sstevel@tonic-gate 		if (error == PAM_NEW_AUTHTOK_REQD) {
1652*7c478bd9Sstevel@tonic-gate 			tries = 1;
1653*7c478bd9Sstevel@tonic-gate 			error = PAM_AUTHTOK_ERR;
1654*7c478bd9Sstevel@tonic-gate 			while (error == PAM_AUTHTOK_ERR &&
1655*7c478bd9Sstevel@tonic-gate 					tries <= DEF_ATTEMPTS) {
1656*7c478bd9Sstevel@tonic-gate 				if (tries > 1)
1657*7c478bd9Sstevel@tonic-gate 					(void) printf("Try again\n\n");
1658*7c478bd9Sstevel@tonic-gate 
1659*7c478bd9Sstevel@tonic-gate 				(void) printf("Choose a new password.\n");
1660*7c478bd9Sstevel@tonic-gate 
1661*7c478bd9Sstevel@tonic-gate 				error = pam_chauthtok(pamh, 0);
1662*7c478bd9Sstevel@tonic-gate 				if (error == PAM_TRY_AGAIN) {
1663*7c478bd9Sstevel@tonic-gate 					(void) sleep(1);
1664*7c478bd9Sstevel@tonic-gate 					error = pam_chauthtok(pamh, 0);
1665*7c478bd9Sstevel@tonic-gate 				}
1666*7c478bd9Sstevel@tonic-gate 				tries++;
1667*7c478bd9Sstevel@tonic-gate 			}
1668*7c478bd9Sstevel@tonic-gate 
1669*7c478bd9Sstevel@tonic-gate 			if (error != PAM_SUCCESS) {
1670*7c478bd9Sstevel@tonic-gate 				if (dosyslog)
1671*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1672*7c478bd9Sstevel@tonic-gate 						"change password failure: %s",
1673*7c478bd9Sstevel@tonic-gate 						pam_strerror(pamh, error));
1674*7c478bd9Sstevel@tonic-gate 				audit_error = ADT_FAIL_PAM + error;
1675*7c478bd9Sstevel@tonic-gate 				login_exit(1);
1676*7c478bd9Sstevel@tonic-gate 			} else {
1677*7c478bd9Sstevel@tonic-gate 				audit_success(ADT_passwd, pwd, zone_name);
1678*7c478bd9Sstevel@tonic-gate 			}
1679*7c478bd9Sstevel@tonic-gate 		} else {
1680*7c478bd9Sstevel@tonic-gate 			(void) printf(incorrectmsg);
1681*7c478bd9Sstevel@tonic-gate 
1682*7c478bd9Sstevel@tonic-gate 			if (dosyslog)
1683*7c478bd9Sstevel@tonic-gate 				syslog(LOG_CRIT,
1684*7c478bd9Sstevel@tonic-gate 					"login account failure: %s",
1685*7c478bd9Sstevel@tonic-gate 						pam_strerror(pamh, error));
1686*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_PAM + error;
1687*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1688*7c478bd9Sstevel@tonic-gate 		}
1689*7c478bd9Sstevel@tonic-gate 	}
1690*7c478bd9Sstevel@tonic-gate }
1691*7c478bd9Sstevel@tonic-gate 
1692*7c478bd9Sstevel@tonic-gate /*
1693*7c478bd9Sstevel@tonic-gate  * Check_log	- This is really a hack because PAM checks the log, but login
1694*7c478bd9Sstevel@tonic-gate  *		  wants to know if the log is okay and PAM doesn't have
1695*7c478bd9Sstevel@tonic-gate  *		  a module independent way of handing this info back.
1696*7c478bd9Sstevel@tonic-gate  */
1697*7c478bd9Sstevel@tonic-gate 
1698*7c478bd9Sstevel@tonic-gate static void
1699*7c478bd9Sstevel@tonic-gate check_log(void)
1700*7c478bd9Sstevel@tonic-gate {
1701*7c478bd9Sstevel@tonic-gate 	int fdl;
1702*7c478bd9Sstevel@tonic-gate 	long long offset;
1703*7c478bd9Sstevel@tonic-gate 
1704*7c478bd9Sstevel@tonic-gate 	offset = (long long) pwd->pw_uid * (long long) sizeof (struct lastlog);
1705*7c478bd9Sstevel@tonic-gate 
1706*7c478bd9Sstevel@tonic-gate 	if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
1707*7c478bd9Sstevel@tonic-gate 		if (llseek(fdl, offset, SEEK_SET) == offset &&
1708*7c478bd9Sstevel@tonic-gate 		    read(fdl, (char *)&ll, sizeof (ll)) == sizeof (ll) &&
1709*7c478bd9Sstevel@tonic-gate 		    ll.ll_time != 0)
1710*7c478bd9Sstevel@tonic-gate 			lastlogok = 1;
1711*7c478bd9Sstevel@tonic-gate 		(void) close(fdl);
1712*7c478bd9Sstevel@tonic-gate 	}
1713*7c478bd9Sstevel@tonic-gate }
1714*7c478bd9Sstevel@tonic-gate 
1715*7c478bd9Sstevel@tonic-gate /*
1716*7c478bd9Sstevel@tonic-gate  * chdir_to_dir_user	- Now chdir after setuid/setgid have happened to
1717*7c478bd9Sstevel@tonic-gate  *			  place us in the user's home directory just in
1718*7c478bd9Sstevel@tonic-gate  *			  case it was protected and the first chdir failed.
1719*7c478bd9Sstevel@tonic-gate  *			  No chdir errors should happen at this point because
1720*7c478bd9Sstevel@tonic-gate  *			  all failures should have happened on the first
1721*7c478bd9Sstevel@tonic-gate  *			  time around.
1722*7c478bd9Sstevel@tonic-gate  */
1723*7c478bd9Sstevel@tonic-gate 
1724*7c478bd9Sstevel@tonic-gate static void
1725*7c478bd9Sstevel@tonic-gate chdir_to_dir_user(void)
1726*7c478bd9Sstevel@tonic-gate {
1727*7c478bd9Sstevel@tonic-gate 	if (chdir(pwd->pw_dir) < 0) {
1728*7c478bd9Sstevel@tonic-gate 		if (chdir("/") < 0) {
1729*7c478bd9Sstevel@tonic-gate 			(void) printf("No directory!\n");
1730*7c478bd9Sstevel@tonic-gate 			/*
1731*7c478bd9Sstevel@tonic-gate 			 * This probably won't work since we can't get to /.
1732*7c478bd9Sstevel@tonic-gate 			 */
1733*7c478bd9Sstevel@tonic-gate 			if (dosyslog) {
1734*7c478bd9Sstevel@tonic-gate 				if (remote_host[0]) {
1735*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1736*7c478bd9Sstevel@tonic-gate 					    "LOGIN FAILURES ON %s FROM %.*s ",
1737*7c478bd9Sstevel@tonic-gate 					    " %.*s", ttyn, HMAX,
1738*7c478bd9Sstevel@tonic-gate 					    remote_host, NMAX, pwd->pw_name);
1739*7c478bd9Sstevel@tonic-gate 				} else {
1740*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1741*7c478bd9Sstevel@tonic-gate 					    "LOGIN FAILURES ON %s, %.*s",
1742*7c478bd9Sstevel@tonic-gate 					    ttyn, NMAX, pwd->pw_name);
1743*7c478bd9Sstevel@tonic-gate 				}
1744*7c478bd9Sstevel@tonic-gate 			}
1745*7c478bd9Sstevel@tonic-gate 			closelog();
1746*7c478bd9Sstevel@tonic-gate 			(void) sleep(Disabletime);
1747*7c478bd9Sstevel@tonic-gate 			exit(1);
1748*7c478bd9Sstevel@tonic-gate 		} else {
1749*7c478bd9Sstevel@tonic-gate 			(void) printf("No directory! Logging in with home=/\n");
1750*7c478bd9Sstevel@tonic-gate 			pwd->pw_dir = "/";
1751*7c478bd9Sstevel@tonic-gate 		}
1752*7c478bd9Sstevel@tonic-gate 	}
1753*7c478bd9Sstevel@tonic-gate }
1754*7c478bd9Sstevel@tonic-gate 
1755*7c478bd9Sstevel@tonic-gate 
1756*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
1757*7c478bd9Sstevel@tonic-gate /*
1758*7c478bd9Sstevel@tonic-gate  * login_authenticate	- Performs the main authentication work
1759*7c478bd9Sstevel@tonic-gate  *			  1. Prints the login prompt
1760*7c478bd9Sstevel@tonic-gate  *			  2. Requests and verifys the password
1761*7c478bd9Sstevel@tonic-gate  *			  3. Checks the port password
1762*7c478bd9Sstevel@tonic-gate  */
1763*7c478bd9Sstevel@tonic-gate 
1764*7c478bd9Sstevel@tonic-gate static void
1765*7c478bd9Sstevel@tonic-gate login_authenticate()
1766*7c478bd9Sstevel@tonic-gate {
1767*7c478bd9Sstevel@tonic-gate 	char *user;
1768*7c478bd9Sstevel@tonic-gate 	int err;
1769*7c478bd9Sstevel@tonic-gate 	int login_successful = 0;
1770*7c478bd9Sstevel@tonic-gate 
1771*7c478bd9Sstevel@tonic-gate 	do {
1772*7c478bd9Sstevel@tonic-gate 		/* if scheme broken, then nothing to do but quit */
1773*7c478bd9Sstevel@tonic-gate 		if (pam_get_item(pamh, PAM_USER, (void **)&user)
1774*7c478bd9Sstevel@tonic-gate 							!= PAM_SUCCESS)
1775*7c478bd9Sstevel@tonic-gate 			exit(1);
1776*7c478bd9Sstevel@tonic-gate 
1777*7c478bd9Sstevel@tonic-gate 		/*
1778*7c478bd9Sstevel@tonic-gate 		 * only get name from utility if it is not already
1779*7c478bd9Sstevel@tonic-gate 		 * supplied by pam_start or a pam_set_item.
1780*7c478bd9Sstevel@tonic-gate 		 */
1781*7c478bd9Sstevel@tonic-gate 		if (!user || !user[0]) {
1782*7c478bd9Sstevel@tonic-gate 			/* use call back to get user name */
1783*7c478bd9Sstevel@tonic-gate 			get_user_name();
1784*7c478bd9Sstevel@tonic-gate 		}
1785*7c478bd9Sstevel@tonic-gate 
1786*7c478bd9Sstevel@tonic-gate 		err = verify_passwd();
1787*7c478bd9Sstevel@tonic-gate 
1788*7c478bd9Sstevel@tonic-gate 		/*
1789*7c478bd9Sstevel@tonic-gate 		 * If root login and not on system console then call exit(2)
1790*7c478bd9Sstevel@tonic-gate 		 */
1791*7c478bd9Sstevel@tonic-gate 		check_for_console();
1792*7c478bd9Sstevel@tonic-gate 
1793*7c478bd9Sstevel@tonic-gate 		switch (err) {
1794*7c478bd9Sstevel@tonic-gate 		case PAM_SUCCESS:
1795*7c478bd9Sstevel@tonic-gate 		case PAM_NEW_AUTHTOK_REQD:
1796*7c478bd9Sstevel@tonic-gate 			/*
1797*7c478bd9Sstevel@tonic-gate 			 * Officially, pam_authenticate() shouldn't return this
1798*7c478bd9Sstevel@tonic-gate 			 * but it's probably the right thing to return if
1799*7c478bd9Sstevel@tonic-gate 			 * PAM_DISALLOW_NULL_AUTHTOK is set so the user will
1800*7c478bd9Sstevel@tonic-gate 			 * be forced to change password later in this code.
1801*7c478bd9Sstevel@tonic-gate 			 */
1802*7c478bd9Sstevel@tonic-gate 			count = 0;
1803*7c478bd9Sstevel@tonic-gate 			login_successful = 1;
1804*7c478bd9Sstevel@tonic-gate 			break;
1805*7c478bd9Sstevel@tonic-gate 		case PAM_MAXTRIES:
1806*7c478bd9Sstevel@tonic-gate 			count = retry;
1807*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
1808*7c478bd9Sstevel@tonic-gate 		case PAM_AUTH_ERR:
1809*7c478bd9Sstevel@tonic-gate 		case PAM_AUTHINFO_UNAVAIL:
1810*7c478bd9Sstevel@tonic-gate 		case PAM_USER_UNKNOWN:
1811*7c478bd9Sstevel@tonic-gate 			audit_failure(get_audit_id(), ADT_FAIL_PAM + err, pwd,
1812*7c478bd9Sstevel@tonic-gate 			    remote_host, ttyn, zone_name);
1813*7c478bd9Sstevel@tonic-gate 			log_bad_attempts();
1814*7c478bd9Sstevel@tonic-gate 			break;
1815*7c478bd9Sstevel@tonic-gate 		case PAM_ABORT:
1816*7c478bd9Sstevel@tonic-gate 			log_bad_attempts();
1817*7c478bd9Sstevel@tonic-gate 			(void) sleep(Disabletime);
1818*7c478bd9Sstevel@tonic-gate 			(void) printf(incorrectmsg);
1819*7c478bd9Sstevel@tonic-gate 
1820*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_PAM + err;
1821*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1822*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
1823*7c478bd9Sstevel@tonic-gate 		default:	/* Some other PAM error */
1824*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_PAM + err;
1825*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1826*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
1827*7c478bd9Sstevel@tonic-gate 		}
1828*7c478bd9Sstevel@tonic-gate 
1829*7c478bd9Sstevel@tonic-gate 		if (login_successful)
1830*7c478bd9Sstevel@tonic-gate 			break;
1831*7c478bd9Sstevel@tonic-gate 
1832*7c478bd9Sstevel@tonic-gate 		/* sleep after bad passwd */
1833*7c478bd9Sstevel@tonic-gate 		if (count)
1834*7c478bd9Sstevel@tonic-gate 			(void) sleep(Sleeptime);
1835*7c478bd9Sstevel@tonic-gate 		(void) printf(incorrectmsg);
1836*7c478bd9Sstevel@tonic-gate 		/* force name to be null in this case */
1837*7c478bd9Sstevel@tonic-gate 		if (pam_set_item(pamh, PAM_USER, NULL) != PAM_SUCCESS)
1838*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1839*7c478bd9Sstevel@tonic-gate 		if (pam_set_item(pamh, PAM_RUSER, NULL) != PAM_SUCCESS)
1840*7c478bd9Sstevel@tonic-gate 			login_exit(1);
1841*7c478bd9Sstevel@tonic-gate 	} while (count++ < retry);
1842*7c478bd9Sstevel@tonic-gate 
1843*7c478bd9Sstevel@tonic-gate 	if (count >= retry) {
1844*7c478bd9Sstevel@tonic-gate 		audit_failure(get_audit_id(), ADT_FAIL_VALUE_MAX_TRIES, pwd,
1845*7c478bd9Sstevel@tonic-gate 		    remote_host, ttyn, zone_name);
1846*7c478bd9Sstevel@tonic-gate 		/*
1847*7c478bd9Sstevel@tonic-gate 		 * If logging is turned on, output the
1848*7c478bd9Sstevel@tonic-gate 		 * string storage area to the log file,
1849*7c478bd9Sstevel@tonic-gate 		 * and sleep for Disabletime
1850*7c478bd9Sstevel@tonic-gate 		 * seconds before exiting.
1851*7c478bd9Sstevel@tonic-gate 		 */
1852*7c478bd9Sstevel@tonic-gate 		if (writelog)
1853*7c478bd9Sstevel@tonic-gate 			badlogin();
1854*7c478bd9Sstevel@tonic-gate 		if (dosyslog) {
1855*7c478bd9Sstevel@tonic-gate 			if ((pwd = getpwnam(user_name)) != NULL) {
1856*7c478bd9Sstevel@tonic-gate 				if (remote_host[0]) {
1857*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1858*7c478bd9Sstevel@tonic-gate 					"REPEATED LOGIN FAILURES ON %s FROM "
1859*7c478bd9Sstevel@tonic-gate 						"%.*s, %.*s",
1860*7c478bd9Sstevel@tonic-gate 					ttyn, HMAX, remote_host, NMAX,
1861*7c478bd9Sstevel@tonic-gate 					user_name);
1862*7c478bd9Sstevel@tonic-gate 				} else {
1863*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1864*7c478bd9Sstevel@tonic-gate 					"REPEATED LOGIN FAILURES ON %s, %.*s",
1865*7c478bd9Sstevel@tonic-gate 					ttyn, NMAX, user_name);
1866*7c478bd9Sstevel@tonic-gate 				}
1867*7c478bd9Sstevel@tonic-gate 			} else {
1868*7c478bd9Sstevel@tonic-gate 				if (remote_host[0]) {
1869*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1870*7c478bd9Sstevel@tonic-gate 					"REPEATED LOGIN FAILURES ON %s FROM "
1871*7c478bd9Sstevel@tonic-gate 					"%.*s",
1872*7c478bd9Sstevel@tonic-gate 					ttyn, HMAX, remote_host);
1873*7c478bd9Sstevel@tonic-gate 				} else {
1874*7c478bd9Sstevel@tonic-gate 					syslog(LOG_CRIT,
1875*7c478bd9Sstevel@tonic-gate 					"REPEATED LOGIN FAILURES ON %s", ttyn);
1876*7c478bd9Sstevel@tonic-gate 				}
1877*7c478bd9Sstevel@tonic-gate 			}
1878*7c478bd9Sstevel@tonic-gate 		}
1879*7c478bd9Sstevel@tonic-gate 		(void) sleep(Disabletime);
1880*7c478bd9Sstevel@tonic-gate 		exit(1);
1881*7c478bd9Sstevel@tonic-gate 	}
1882*7c478bd9Sstevel@tonic-gate 
1883*7c478bd9Sstevel@tonic-gate }
1884*7c478bd9Sstevel@tonic-gate 
1885*7c478bd9Sstevel@tonic-gate /*
1886*7c478bd9Sstevel@tonic-gate  * 			*** Credential Related routines ***
1887*7c478bd9Sstevel@tonic-gate  *
1888*7c478bd9Sstevel@tonic-gate  */
1889*7c478bd9Sstevel@tonic-gate 
1890*7c478bd9Sstevel@tonic-gate /*
1891*7c478bd9Sstevel@tonic-gate  * setup_credentials		- sets the group ID, initializes the groups
1892*7c478bd9Sstevel@tonic-gate  *				  and sets up the secretkey.
1893*7c478bd9Sstevel@tonic-gate  *				  Exits if a failure occurrs.
1894*7c478bd9Sstevel@tonic-gate  */
1895*7c478bd9Sstevel@tonic-gate 
1896*7c478bd9Sstevel@tonic-gate 
1897*7c478bd9Sstevel@tonic-gate /*
1898*7c478bd9Sstevel@tonic-gate  * setup_credentials		- PAM does all the work for us on this one.
1899*7c478bd9Sstevel@tonic-gate  */
1900*7c478bd9Sstevel@tonic-gate 
1901*7c478bd9Sstevel@tonic-gate static void
1902*7c478bd9Sstevel@tonic-gate setup_credentials(void)
1903*7c478bd9Sstevel@tonic-gate {
1904*7c478bd9Sstevel@tonic-gate 	int 	error = 0;
1905*7c478bd9Sstevel@tonic-gate 
1906*7c478bd9Sstevel@tonic-gate 	/* set the real (and effective) GID */
1907*7c478bd9Sstevel@tonic-gate 	if (setgid(pwd->pw_gid) == -1) {
1908*7c478bd9Sstevel@tonic-gate 		login_exit(1);
1909*7c478bd9Sstevel@tonic-gate 	}
1910*7c478bd9Sstevel@tonic-gate 
1911*7c478bd9Sstevel@tonic-gate 	/*
1912*7c478bd9Sstevel@tonic-gate 	 * Initialize the supplementary group access list.
1913*7c478bd9Sstevel@tonic-gate 	 */
1914*7c478bd9Sstevel@tonic-gate 	if ((user_name[0] == '\0') ||
1915*7c478bd9Sstevel@tonic-gate 	    (initgroups(user_name, pwd->pw_gid) == -1)) {
1916*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_VALUE_PROGRAM;
1917*7c478bd9Sstevel@tonic-gate 		login_exit(1);
1918*7c478bd9Sstevel@tonic-gate 	}
1919*7c478bd9Sstevel@tonic-gate 
1920*7c478bd9Sstevel@tonic-gate 	if ((error = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
1921*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_PAM + error;
1922*7c478bd9Sstevel@tonic-gate 		login_exit(error);
1923*7c478bd9Sstevel@tonic-gate 	}
1924*7c478bd9Sstevel@tonic-gate 
1925*7c478bd9Sstevel@tonic-gate 	/*
1926*7c478bd9Sstevel@tonic-gate 	 * Record successful login and fork process that records logout.
1927*7c478bd9Sstevel@tonic-gate 	 * We have to do this after setting credentials because pam_setcred()
1928*7c478bd9Sstevel@tonic-gate 	 * loads key audit info into the cred, but before setuid() so audit
1929*7c478bd9Sstevel@tonic-gate 	 * system calls will work.
1930*7c478bd9Sstevel@tonic-gate 	 */
1931*7c478bd9Sstevel@tonic-gate 	audit_success(get_audit_id(), pwd, zone_name);
1932*7c478bd9Sstevel@tonic-gate 
1933*7c478bd9Sstevel@tonic-gate 	/* set the real (and effective) UID */
1934*7c478bd9Sstevel@tonic-gate 	if (setuid(pwd->pw_uid) == -1) {
1935*7c478bd9Sstevel@tonic-gate 		login_exit(1);
1936*7c478bd9Sstevel@tonic-gate 	}
1937*7c478bd9Sstevel@tonic-gate 
1938*7c478bd9Sstevel@tonic-gate }
1939*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
1940*7c478bd9Sstevel@tonic-gate 
1941*7c478bd9Sstevel@tonic-gate static uint_t
1942*7c478bd9Sstevel@tonic-gate get_audit_id() {
1943*7c478bd9Sstevel@tonic-gate 	if (rflag)
1944*7c478bd9Sstevel@tonic-gate 		return (ADT_rlogin);
1945*7c478bd9Sstevel@tonic-gate 	else if (hflag)
1946*7c478bd9Sstevel@tonic-gate 		return (ADT_telnet);
1947*7c478bd9Sstevel@tonic-gate 	else if (zflag)
1948*7c478bd9Sstevel@tonic-gate 		return (ADT_zlogin);
1949*7c478bd9Sstevel@tonic-gate 
1950*7c478bd9Sstevel@tonic-gate 	return (ADT_login);
1951*7c478bd9Sstevel@tonic-gate }
1952*7c478bd9Sstevel@tonic-gate 
1953*7c478bd9Sstevel@tonic-gate /*
1954*7c478bd9Sstevel@tonic-gate  *
1955*7c478bd9Sstevel@tonic-gate  *		*** Routines to get a new user set up and running ***
1956*7c478bd9Sstevel@tonic-gate  *
1957*7c478bd9Sstevel@tonic-gate  *			Things to do when starting up a new user:
1958*7c478bd9Sstevel@tonic-gate  *				adjust_nice
1959*7c478bd9Sstevel@tonic-gate  *				update_utmpx_entry
1960*7c478bd9Sstevel@tonic-gate  *				establish_user_environment
1961*7c478bd9Sstevel@tonic-gate  *				print_banner
1962*7c478bd9Sstevel@tonic-gate  *				display_last_login_time
1963*7c478bd9Sstevel@tonic-gate  *				exec_the_shell
1964*7c478bd9Sstevel@tonic-gate  *
1965*7c478bd9Sstevel@tonic-gate  */
1966*7c478bd9Sstevel@tonic-gate 
1967*7c478bd9Sstevel@tonic-gate 
1968*7c478bd9Sstevel@tonic-gate /*
1969*7c478bd9Sstevel@tonic-gate  * adjust_nice		- Set the nice (process priority) value if the
1970*7c478bd9Sstevel@tonic-gate  *			  gecos value contains an appropriate value.
1971*7c478bd9Sstevel@tonic-gate  */
1972*7c478bd9Sstevel@tonic-gate 
1973*7c478bd9Sstevel@tonic-gate static void
1974*7c478bd9Sstevel@tonic-gate adjust_nice(void)
1975*7c478bd9Sstevel@tonic-gate {
1976*7c478bd9Sstevel@tonic-gate 	int pri, mflg, i;
1977*7c478bd9Sstevel@tonic-gate 
1978*7c478bd9Sstevel@tonic-gate 	if (strncmp("pri=", pwd->pw_gecos, 4) == 0) {
1979*7c478bd9Sstevel@tonic-gate 		pri = 0;
1980*7c478bd9Sstevel@tonic-gate 		mflg = 0;
1981*7c478bd9Sstevel@tonic-gate 		i = 4;
1982*7c478bd9Sstevel@tonic-gate 
1983*7c478bd9Sstevel@tonic-gate 		if (pwd->pw_gecos[i] == '-') {
1984*7c478bd9Sstevel@tonic-gate 			mflg++;
1985*7c478bd9Sstevel@tonic-gate 			i++;
1986*7c478bd9Sstevel@tonic-gate 		}
1987*7c478bd9Sstevel@tonic-gate 
1988*7c478bd9Sstevel@tonic-gate 		while (pwd->pw_gecos[i] >= '0' && pwd->pw_gecos[i] <= '9')
1989*7c478bd9Sstevel@tonic-gate 			pri = (pri * 10) + pwd->pw_gecos[i++] - '0';
1990*7c478bd9Sstevel@tonic-gate 
1991*7c478bd9Sstevel@tonic-gate 		if (mflg)
1992*7c478bd9Sstevel@tonic-gate 			pri = -pri;
1993*7c478bd9Sstevel@tonic-gate 
1994*7c478bd9Sstevel@tonic-gate 		(void) nice(pri);
1995*7c478bd9Sstevel@tonic-gate 	}
1996*7c478bd9Sstevel@tonic-gate }
1997*7c478bd9Sstevel@tonic-gate 
1998*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
1999*7c478bd9Sstevel@tonic-gate /*
2000*7c478bd9Sstevel@tonic-gate  * update_utmpx_entry	- Searchs for the correct utmpx entry, making an
2001*7c478bd9Sstevel@tonic-gate  *			  entry there if it finds one, otherwise exits.
2002*7c478bd9Sstevel@tonic-gate  */
2003*7c478bd9Sstevel@tonic-gate 
2004*7c478bd9Sstevel@tonic-gate static void
2005*7c478bd9Sstevel@tonic-gate update_utmpx_entry(int sublogin)
2006*7c478bd9Sstevel@tonic-gate {
2007*7c478bd9Sstevel@tonic-gate 	int	err;
2008*7c478bd9Sstevel@tonic-gate 	char	*user;
2009*7c478bd9Sstevel@tonic-gate 	static char	*errmsg	= "No utmpx entry. "
2010*7c478bd9Sstevel@tonic-gate 		"You must exec \"login\" from the lowest level \"shell\".";
2011*7c478bd9Sstevel@tonic-gate 	int	   tmplen;
2012*7c478bd9Sstevel@tonic-gate 	struct utmpx  *u = (struct utmpx *)0;
2013*7c478bd9Sstevel@tonic-gate 	struct utmpx  utmpx;
2014*7c478bd9Sstevel@tonic-gate 	char	  *ttyntail;
2015*7c478bd9Sstevel@tonic-gate 
2016*7c478bd9Sstevel@tonic-gate 	/*
2017*7c478bd9Sstevel@tonic-gate 	 * If we're not a sublogin then
2018*7c478bd9Sstevel@tonic-gate 	 * we'll get an error back if our PID doesn't match the PID of the
2019*7c478bd9Sstevel@tonic-gate 	 * entry we are updating, otherwise if its a sublogin the flags
2020*7c478bd9Sstevel@tonic-gate 	 * field is set to 0, which means we just write a matching entry
2021*7c478bd9Sstevel@tonic-gate 	 * (without checking the pid), or a new entry if an entry doesn't
2022*7c478bd9Sstevel@tonic-gate 	 * exist.
2023*7c478bd9Sstevel@tonic-gate 	 */
2024*7c478bd9Sstevel@tonic-gate 
2025*7c478bd9Sstevel@tonic-gate 	if ((err = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
2026*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_PAM + err;
2027*7c478bd9Sstevel@tonic-gate 		login_exit(1);
2028*7c478bd9Sstevel@tonic-gate 	}
2029*7c478bd9Sstevel@tonic-gate 
2030*7c478bd9Sstevel@tonic-gate 	if ((err = pam_get_item(pamh, PAM_USER, (void **) &user)) !=
2031*7c478bd9Sstevel@tonic-gate 	    PAM_SUCCESS) {
2032*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_PAM + err;
2033*7c478bd9Sstevel@tonic-gate 		login_exit(1);
2034*7c478bd9Sstevel@tonic-gate 	}
2035*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
2036*7c478bd9Sstevel@tonic-gate 
2037*7c478bd9Sstevel@tonic-gate 	(void) memset((void *)&utmpx, 0, sizeof (utmpx));
2038*7c478bd9Sstevel@tonic-gate 	(void) time(&utmpx.ut_tv.tv_sec);
2039*7c478bd9Sstevel@tonic-gate 	utmpx.ut_pid = getpid();
2040*7c478bd9Sstevel@tonic-gate 
2041*7c478bd9Sstevel@tonic-gate 	if (rflag || hflag) {
2042*7c478bd9Sstevel@tonic-gate 		SCPYN(utmpx.ut_host, remote_host);
2043*7c478bd9Sstevel@tonic-gate 		tmplen = strlen(remote_host) + 1;
2044*7c478bd9Sstevel@tonic-gate 		if (tmplen < sizeof (utmpx.ut_host))
2045*7c478bd9Sstevel@tonic-gate 			utmpx.ut_syslen = tmplen;
2046*7c478bd9Sstevel@tonic-gate 		else
2047*7c478bd9Sstevel@tonic-gate 			utmpx.ut_syslen = sizeof (utmpx.ut_host);
2048*7c478bd9Sstevel@tonic-gate 	} else if (zflag) {
2049*7c478bd9Sstevel@tonic-gate 		/*
2050*7c478bd9Sstevel@tonic-gate 		 * If this is a login from another zone, put the
2051*7c478bd9Sstevel@tonic-gate 		 * zone:<zonename> string in the utmpx entry.
2052*7c478bd9Sstevel@tonic-gate 		 */
2053*7c478bd9Sstevel@tonic-gate 		SCPYN(utmpx.ut_host, zone_name);
2054*7c478bd9Sstevel@tonic-gate 		tmplen = strlen(zone_name) + 1;
2055*7c478bd9Sstevel@tonic-gate 		if (tmplen < sizeof (utmpx.ut_host))
2056*7c478bd9Sstevel@tonic-gate 			utmpx.ut_syslen = tmplen;
2057*7c478bd9Sstevel@tonic-gate 		else
2058*7c478bd9Sstevel@tonic-gate 			utmpx.ut_syslen = sizeof (utmpx.ut_host);
2059*7c478bd9Sstevel@tonic-gate 	} else {
2060*7c478bd9Sstevel@tonic-gate 		utmpx.ut_syslen = 0;
2061*7c478bd9Sstevel@tonic-gate 	}
2062*7c478bd9Sstevel@tonic-gate 
2063*7c478bd9Sstevel@tonic-gate 	SCPYN(utmpx.ut_user, user);
2064*7c478bd9Sstevel@tonic-gate 
2065*7c478bd9Sstevel@tonic-gate 	/* skip over "/dev/" */
2066*7c478bd9Sstevel@tonic-gate 	ttyntail = basename(ttyn);
2067*7c478bd9Sstevel@tonic-gate 
2068*7c478bd9Sstevel@tonic-gate 	while ((u = getutxent()) != NULL) {
2069*7c478bd9Sstevel@tonic-gate 		if ((u->ut_type == INIT_PROCESS ||
2070*7c478bd9Sstevel@tonic-gate 			u->ut_type == LOGIN_PROCESS ||
2071*7c478bd9Sstevel@tonic-gate 			u->ut_type == USER_PROCESS) &&
2072*7c478bd9Sstevel@tonic-gate 			((sublogin && strncmp(u->ut_line, ttyntail,
2073*7c478bd9Sstevel@tonic-gate 			sizeof (u->ut_line)) == 0) ||
2074*7c478bd9Sstevel@tonic-gate 			u->ut_pid == utmpx.ut_pid)) {
2075*7c478bd9Sstevel@tonic-gate 			SCPYN(utmpx.ut_line, (ttyn+sizeof ("/dev/")-1));
2076*7c478bd9Sstevel@tonic-gate 			(void) memcpy(utmpx.ut_id, u->ut_id,
2077*7c478bd9Sstevel@tonic-gate 			    sizeof (utmpx.ut_id));
2078*7c478bd9Sstevel@tonic-gate 			utmpx.ut_exit.e_exit = u->ut_exit.e_exit;
2079*7c478bd9Sstevel@tonic-gate 			utmpx.ut_type = USER_PROCESS;
2080*7c478bd9Sstevel@tonic-gate 			(void) pututxline(&utmpx);
2081*7c478bd9Sstevel@tonic-gate 			break;
2082*7c478bd9Sstevel@tonic-gate 		}
2083*7c478bd9Sstevel@tonic-gate 	}
2084*7c478bd9Sstevel@tonic-gate 	endutxent();
2085*7c478bd9Sstevel@tonic-gate 
2086*7c478bd9Sstevel@tonic-gate 	if (u == (struct utmpx *)NULL) {
2087*7c478bd9Sstevel@tonic-gate 		if (!sublogin) {
2088*7c478bd9Sstevel@tonic-gate 			/*
2089*7c478bd9Sstevel@tonic-gate 			 * no utmpx entry already setup
2090*7c478bd9Sstevel@tonic-gate 			 * (init or rlogind/telnetd)
2091*7c478bd9Sstevel@tonic-gate 			 */
2092*7c478bd9Sstevel@tonic-gate 			(void) puts(errmsg);
2093*7c478bd9Sstevel@tonic-gate 
2094*7c478bd9Sstevel@tonic-gate 			audit_error = ADT_FAIL_VALUE_PROGRAM;
2095*7c478bd9Sstevel@tonic-gate 			login_exit(1);
2096*7c478bd9Sstevel@tonic-gate 		}
2097*7c478bd9Sstevel@tonic-gate 	} else {
2098*7c478bd9Sstevel@tonic-gate 		/* Now attempt to write out this entry to the wtmp file if */
2099*7c478bd9Sstevel@tonic-gate 		/* we were successful in getting it from the utmpx file and */
2100*7c478bd9Sstevel@tonic-gate 		/* the wtmp file exists.				   */
2101*7c478bd9Sstevel@tonic-gate 		updwtmpx(WTMPX_FILE, &utmpx);
2102*7c478bd9Sstevel@tonic-gate 	}
2103*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
2104*7c478bd9Sstevel@tonic-gate }
2105*7c478bd9Sstevel@tonic-gate 
2106*7c478bd9Sstevel@tonic-gate 
2107*7c478bd9Sstevel@tonic-gate 
2108*7c478bd9Sstevel@tonic-gate /*
2109*7c478bd9Sstevel@tonic-gate  * process_chroot_logins 	- Chroots to the specified subdirectory and
2110*7c478bd9Sstevel@tonic-gate  *				  re executes login.
2111*7c478bd9Sstevel@tonic-gate  */
2112*7c478bd9Sstevel@tonic-gate 
2113*7c478bd9Sstevel@tonic-gate static int
2114*7c478bd9Sstevel@tonic-gate process_chroot_logins(void)
2115*7c478bd9Sstevel@tonic-gate {
2116*7c478bd9Sstevel@tonic-gate 	/*
2117*7c478bd9Sstevel@tonic-gate 	 * If the shell field starts with a '*', do a chroot to the home
2118*7c478bd9Sstevel@tonic-gate 	 * directory and perform a new login.
2119*7c478bd9Sstevel@tonic-gate 	 */
2120*7c478bd9Sstevel@tonic-gate 
2121*7c478bd9Sstevel@tonic-gate 	if (*pwd->pw_shell == '*') {
2122*7c478bd9Sstevel@tonic-gate 		(void) pam_end(pamh, PAM_SUCCESS);	/* Done using PAM */
2123*7c478bd9Sstevel@tonic-gate 		pamh = NULL;				/* really done */
2124*7c478bd9Sstevel@tonic-gate 		if (chroot(pwd->pw_dir) < 0) {
2125*7c478bd9Sstevel@tonic-gate 			(void) printf("No Root Directory\n");
2126*7c478bd9Sstevel@tonic-gate 
2127*7c478bd9Sstevel@tonic-gate 			audit_failure(get_audit_id(),
2128*7c478bd9Sstevel@tonic-gate 			    ADT_FAIL_VALUE_CHDIR_FAILED,
2129*7c478bd9Sstevel@tonic-gate 			    pwd, remote_host, ttyn, zone_name);
2130*7c478bd9Sstevel@tonic-gate 
2131*7c478bd9Sstevel@tonic-gate 			return (ERROR);
2132*7c478bd9Sstevel@tonic-gate 		}
2133*7c478bd9Sstevel@tonic-gate 		/*
2134*7c478bd9Sstevel@tonic-gate 		 * Set the environment flag <!sublogin> so that the next login
2135*7c478bd9Sstevel@tonic-gate 		 * knows that it is a sublogin.
2136*7c478bd9Sstevel@tonic-gate 		 */
2137*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
2138*7c478bd9Sstevel@tonic-gate 		envinit[0] = SUBLOGIN;
2139*7c478bd9Sstevel@tonic-gate 		envinit[1] = (char *)NULL;
2140*7c478bd9Sstevel@tonic-gate 		(void) printf("Subsystem root: %s\n", pwd->pw_dir);
2141*7c478bd9Sstevel@tonic-gate 		(void) execle("/usr/bin/login", "login", (char *)0,
2142*7c478bd9Sstevel@tonic-gate 			&envinit[0]);
2143*7c478bd9Sstevel@tonic-gate 		(void) execle("/etc/login", "login", (char *)0, &envinit[0]);
2144*7c478bd9Sstevel@tonic-gate 		(void) printf("No /usr/bin/login or /etc/login on root\n");
2145*7c478bd9Sstevel@tonic-gate 
2146*7c478bd9Sstevel@tonic-gate 		audit_error = ADT_FAIL_VALUE_PROGRAM;
2147*7c478bd9Sstevel@tonic-gate 
2148*7c478bd9Sstevel@tonic-gate 		login_exit(1);
2149*7c478bd9Sstevel@tonic-gate 	}
2150*7c478bd9Sstevel@tonic-gate 	return (OK);
2151*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */
2152*7c478bd9Sstevel@tonic-gate }
2153*7c478bd9Sstevel@tonic-gate 
2154*7c478bd9Sstevel@tonic-gate /*
2155*7c478bd9Sstevel@tonic-gate  * establish_user_environment	- Set up the new users enviornment
2156*7c478bd9Sstevel@tonic-gate  */
2157*7c478bd9Sstevel@tonic-gate 
2158*7c478bd9Sstevel@tonic-gate static void
2159*7c478bd9Sstevel@tonic-gate establish_user_environment(char **renvp)
2160*7c478bd9Sstevel@tonic-gate {
2161*7c478bd9Sstevel@tonic-gate 	int i, j, k, l_index, length, idx = 0;
2162*7c478bd9Sstevel@tonic-gate 	char *endptr;
2163*7c478bd9Sstevel@tonic-gate 	char **lenvp;
2164*7c478bd9Sstevel@tonic-gate 	char **pam_env;
2165*7c478bd9Sstevel@tonic-gate 
2166*7c478bd9Sstevel@tonic-gate 	lenvp = environ;
2167*7c478bd9Sstevel@tonic-gate 	while (*lenvp++)
2168*7c478bd9Sstevel@tonic-gate 		;
2169*7c478bd9Sstevel@tonic-gate 
2170*7c478bd9Sstevel@tonic-gate 	/* count the number of PAM environment variables set by modules */
2171*7c478bd9Sstevel@tonic-gate 	if ((pam_env = pam_getenvlist(pamh)) != 0) {
2172*7c478bd9Sstevel@tonic-gate 		for (idx = 0; pam_env[idx] != 0; idx++)
2173*7c478bd9Sstevel@tonic-gate 				;
2174*7c478bd9Sstevel@tonic-gate 	}
2175*7c478bd9Sstevel@tonic-gate 
2176*7c478bd9Sstevel@tonic-gate 	envinit = (char **)calloc(lenvp - environ + 10
2177*7c478bd9Sstevel@tonic-gate 		+ MAXARGS + idx, sizeof (char *));
2178*7c478bd9Sstevel@tonic-gate 	if (envinit == NULL) {
2179*7c478bd9Sstevel@tonic-gate 		(void) printf("Calloc failed - out of swap space.\n");
2180*7c478bd9Sstevel@tonic-gate 		login_exit(8);
2181*7c478bd9Sstevel@tonic-gate 	}
2182*7c478bd9Sstevel@tonic-gate 
2183*7c478bd9Sstevel@tonic-gate 	/*
2184*7c478bd9Sstevel@tonic-gate 	 * add PAM environment variables first so they
2185*7c478bd9Sstevel@tonic-gate 	 * can be overwritten at login's discretion.
2186*7c478bd9Sstevel@tonic-gate 	 * check for illegal environment variables.
2187*7c478bd9Sstevel@tonic-gate 	 */
2188*7c478bd9Sstevel@tonic-gate 	idx = 0;	basicenv = 0;
2189*7c478bd9Sstevel@tonic-gate 	if (pam_env != 0) {
2190*7c478bd9Sstevel@tonic-gate 		while (pam_env[idx] != 0) {
2191*7c478bd9Sstevel@tonic-gate 			if (legalenvvar(pam_env[idx])) {
2192*7c478bd9Sstevel@tonic-gate 				envinit[basicenv] = pam_env[idx];
2193*7c478bd9Sstevel@tonic-gate 				basicenv++;
2194*7c478bd9Sstevel@tonic-gate 			}
2195*7c478bd9Sstevel@tonic-gate 			idx++;
2196*7c478bd9Sstevel@tonic-gate 		}
2197*7c478bd9Sstevel@tonic-gate 	}
2198*7c478bd9Sstevel@tonic-gate 	(void) memcpy(&envinit[basicenv], newenv, sizeof (newenv));
2199*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */
2200*7c478bd9Sstevel@tonic-gate 
2201*7c478bd9Sstevel@tonic-gate 	/* Set up environment */
2202*7c478bd9Sstevel@tonic-gate 	if (rflag) {
2203*7c478bd9Sstevel@tonic-gate 		ENVSTRNCAT(term, terminal);
2204*7c478bd9Sstevel@tonic-gate 	} else if (hflag) {
2205*7c478bd9Sstevel@tonic-gate 		if (strlen(terminal)) {
2206*7c478bd9Sstevel@tonic-gate 			ENVSTRNCAT(term, terminal);
2207*7c478bd9Sstevel@tonic-gate 		}
2208*7c478bd9Sstevel@tonic-gate 	} else {
2209*7c478bd9Sstevel@tonic-gate 		char *tp = getenv("TERM");
2210*7c478bd9Sstevel@tonic-gate 
2211*7c478bd9Sstevel@tonic-gate 		if ((tp != NULL) && (*tp != '\0'))
2212*7c478bd9Sstevel@tonic-gate 			ENVSTRNCAT(term, tp);
2213*7c478bd9Sstevel@tonic-gate 	}
2214*7c478bd9Sstevel@tonic-gate 
2215*7c478bd9Sstevel@tonic-gate 	ENVSTRNCAT(logname, pwd->pw_name);
2216*7c478bd9Sstevel@tonic-gate 
2217*7c478bd9Sstevel@tonic-gate 	/*
2218*7c478bd9Sstevel@tonic-gate 	 * There are three places to get timezone info.  init.c sets
2219*7c478bd9Sstevel@tonic-gate 	 * TZ if the file /etc/TIMEZONE contains a value for TZ.
2220*7c478bd9Sstevel@tonic-gate 	 * login.c looks in the file /etc/default/login for a
2221*7c478bd9Sstevel@tonic-gate 	 * variable called TIMEZONE being set.  If TIMEZONE has a
2222*7c478bd9Sstevel@tonic-gate 	 *  value, TZ is set to that value; no environment variable
2223*7c478bd9Sstevel@tonic-gate 	 * TIMEZONE is set, only TZ.  If neither of these methods
2224*7c478bd9Sstevel@tonic-gate 	 * work to set TZ, then the library routines  will default
2225*7c478bd9Sstevel@tonic-gate 	 * to using the file /usr/lib/locale/TZ/localtime.
2226*7c478bd9Sstevel@tonic-gate 	 *
2227*7c478bd9Sstevel@tonic-gate 	 * There is a priority set up here.  If /etc/TIMEZONE has
2228*7c478bd9Sstevel@tonic-gate 	 * a value for TZ, that value remains top priority.  If the
2229*7c478bd9Sstevel@tonic-gate 	 * file /etc/default/login has TIMEZONE set, that has second
2230*7c478bd9Sstevel@tonic-gate 	 * highest priority not overriding the value of TZ in
2231*7c478bd9Sstevel@tonic-gate 	 * /etc/TIMEZONE.  The reason for this priority is that the
2232*7c478bd9Sstevel@tonic-gate 	 * file /etc/TIMEZONE is supposed to be sourced by
2233*7c478bd9Sstevel@tonic-gate 	 * /etc/profile.  We are doing the "sourcing" prematurely in
2234*7c478bd9Sstevel@tonic-gate 	 * init.c.  Additionally, a login C shell doesn't source the
2235*7c478bd9Sstevel@tonic-gate 	 * file /etc/profile thus not sourcing /etc/TIMEZONE thus not
2236*7c478bd9Sstevel@tonic-gate 	 * allowing an adminstrator to globally set TZ for all users
2237*7c478bd9Sstevel@tonic-gate 	 */
2238*7c478bd9Sstevel@tonic-gate 	if (Def_tz != NULL)	/* Is there a TZ from defaults/login? */
2239*7c478bd9Sstevel@tonic-gate 		tmp_tz = Def_tz;
2240*7c478bd9Sstevel@tonic-gate 
2241*7c478bd9Sstevel@tonic-gate 	if ((Def_tz = getenv("TZ")) != NULL) {
2242*7c478bd9Sstevel@tonic-gate 		ENVSTRNCAT(timez, Def_tz);
2243*7c478bd9Sstevel@tonic-gate 	} else if (tmp_tz != NULL) {
2244*7c478bd9Sstevel@tonic-gate 		Def_tz = tmp_tz;
2245*7c478bd9Sstevel@tonic-gate 		ENVSTRNCAT(timez, Def_tz);
2246*7c478bd9Sstevel@tonic-gate 	}
2247*7c478bd9Sstevel@tonic-gate 
2248*7c478bd9Sstevel@tonic-gate 	if (Def_hertz == NULL)
2249*7c478bd9Sstevel@tonic-gate 		(void) sprintf(hertz + strlen(hertz), "%lu", HZ);
2250*7c478bd9Sstevel@tonic-gate 	else
2251*7c478bd9Sstevel@tonic-gate 		ENVSTRNCAT(hertz, Def_hertz);
2252*7c478bd9Sstevel@tonic-gate 
2253*7c478bd9Sstevel@tonic-gate 	if (Def_path == NULL)
2254*7c478bd9Sstevel@tonic-gate 		(void) strlcat(path, DEF_PATH, sizeof (path));
2255*7c478bd9Sstevel@tonic-gate 	else
2256*7c478bd9Sstevel@tonic-gate 		ENVSTRNCAT(path, Def_path);
2257*7c478bd9Sstevel@tonic-gate 
2258*7c478bd9Sstevel@tonic-gate 	ENVSTRNCAT(home, pwd->pw_dir);
2259*7c478bd9Sstevel@tonic-gate 
2260*7c478bd9Sstevel@tonic-gate 	/*
2261*7c478bd9Sstevel@tonic-gate 	 * Find the end of the basic environment
2262*7c478bd9Sstevel@tonic-gate 	 */
2263*7c478bd9Sstevel@tonic-gate 	for (basicenv = 0; envinit[basicenv] != NULL; basicenv++)
2264*7c478bd9Sstevel@tonic-gate 		;
2265*7c478bd9Sstevel@tonic-gate 
2266*7c478bd9Sstevel@tonic-gate 	/*
2267*7c478bd9Sstevel@tonic-gate 	 * If TZ has a value, add it.
2268*7c478bd9Sstevel@tonic-gate 	 */
2269*7c478bd9Sstevel@tonic-gate 	if (strcmp(timez, "TZ=") != 0)
2270*7c478bd9Sstevel@tonic-gate 		envinit[basicenv++] = timez;
2271*7c478bd9Sstevel@tonic-gate 
2272*7c478bd9Sstevel@tonic-gate 	if (*pwd->pw_shell == '\0') {
2273*7c478bd9Sstevel@tonic-gate 		/*
2274*7c478bd9Sstevel@tonic-gate 		 * If possible, use the primary default shell,
2275*7c478bd9Sstevel@tonic-gate 		 * otherwise, use the secondary one.
2276*7c478bd9Sstevel@tonic-gate 		 */
2277*7c478bd9Sstevel@tonic-gate 		if (access(SHELL, X_OK) == 0)
2278*7c478bd9Sstevel@tonic-gate 			pwd->pw_shell = SHELL;
2279*7c478bd9Sstevel@tonic-gate 		else
2280*7c478bd9Sstevel@tonic-gate 			pwd->pw_shell = SHELL2;
2281*7c478bd9Sstevel@tonic-gate 	} else if (Altshell != NULL && strcmp(Altshell, "YES") == 0) {
2282*7c478bd9Sstevel@tonic-gate 		envinit[basicenv++] = shell;
2283*7c478bd9Sstevel@tonic-gate 		ENVSTRNCAT(shell, pwd->pw_shell);
2284*7c478bd9Sstevel@tonic-gate 	}
2285*7c478bd9Sstevel@tonic-gate 
2286*7c478bd9Sstevel@tonic-gate #ifndef	NO_MAIL
2287*7c478bd9Sstevel@tonic-gate 	envinit[basicenv++] = mail;
2288*7c478bd9Sstevel@tonic-gate 	(void) strlcat(mail, pwd->pw_name, sizeof (mail));
2289*7c478bd9Sstevel@tonic-gate #endif
2290*7c478bd9Sstevel@tonic-gate 
2291*7c478bd9Sstevel@tonic-gate 	/*
2292*7c478bd9Sstevel@tonic-gate 	 * Pick up locale environment variables, if any.
2293*7c478bd9Sstevel@tonic-gate 	 */
2294*7c478bd9Sstevel@tonic-gate 	lenvp = renvp;
2295*7c478bd9Sstevel@tonic-gate 	while (*lenvp != NULL) {
2296*7c478bd9Sstevel@tonic-gate 		j = 0;
2297*7c478bd9Sstevel@tonic-gate 		while (localeenv[j] != 0) {
2298*7c478bd9Sstevel@tonic-gate 			/*
2299*7c478bd9Sstevel@tonic-gate 			 * locale_envmatch() returns 1 if
2300*7c478bd9Sstevel@tonic-gate 			 * *lenvp is localenev[j] and valid.
2301*7c478bd9Sstevel@tonic-gate 			 */
2302*7c478bd9Sstevel@tonic-gate 			if (locale_envmatch(localeenv[j], *lenvp) == 1) {
2303*7c478bd9Sstevel@tonic-gate 				envinit[basicenv++] = *lenvp;
2304*7c478bd9Sstevel@tonic-gate 				break;
2305*7c478bd9Sstevel@tonic-gate 			}
2306*7c478bd9Sstevel@tonic-gate 			j++;
2307*7c478bd9Sstevel@tonic-gate 		}
2308*7c478bd9Sstevel@tonic-gate 		lenvp++;
2309*7c478bd9Sstevel@tonic-gate 	}
2310*7c478bd9Sstevel@tonic-gate 
2311*7c478bd9Sstevel@tonic-gate 	/*
2312*7c478bd9Sstevel@tonic-gate 	 * If '-p' flag, then try to pass on allowable environment
2313*7c478bd9Sstevel@tonic-gate 	 * variables.  Note that by processing this first, what is
2314*7c478bd9Sstevel@tonic-gate 	 * passed on the final "login:" line may over-ride the invocation
2315*7c478bd9Sstevel@tonic-gate 	 * values.  XXX is this correct?
2316*7c478bd9Sstevel@tonic-gate 	 */
2317*7c478bd9Sstevel@tonic-gate 	if (pflag) {
2318*7c478bd9Sstevel@tonic-gate 		for (lenvp = renvp; *lenvp; lenvp++) {
2319*7c478bd9Sstevel@tonic-gate 			if (!legalenvvar(*lenvp)) {
2320*7c478bd9Sstevel@tonic-gate 				continue;
2321*7c478bd9Sstevel@tonic-gate 			}
2322*7c478bd9Sstevel@tonic-gate 			/*
2323*7c478bd9Sstevel@tonic-gate 			 * If this isn't 'xxx=yyy', skip it.  XXX
2324*7c478bd9Sstevel@tonic-gate 			 */
2325*7c478bd9Sstevel@tonic-gate 			if ((endptr = strchr(*lenvp, '=')) == NULL) {
2326*7c478bd9Sstevel@tonic-gate 				continue;
2327*7c478bd9Sstevel@tonic-gate 			}
2328*7c478bd9Sstevel@tonic-gate 			length = endptr + 1 - *lenvp;
2329*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < basicenv; j++) {
2330*7c478bd9Sstevel@tonic-gate 				if (strncmp(envinit[j], *lenvp, length) == 0) {
2331*7c478bd9Sstevel@tonic-gate 					/*
2332*7c478bd9Sstevel@tonic-gate 					 * Replace previously established value
2333*7c478bd9Sstevel@tonic-gate 					 */
2334*7c478bd9Sstevel@tonic-gate 					envinit[j] = *lenvp;
2335*7c478bd9Sstevel@tonic-gate 					break;
2336*7c478bd9Sstevel@tonic-gate 				}
2337*7c478bd9Sstevel@tonic-gate 			}
2338*7c478bd9Sstevel@tonic-gate 			if (j == basicenv) {
2339*7c478bd9Sstevel@tonic-gate 				/*
2340*7c478bd9Sstevel@tonic-gate 				 * It's a new definition, so add it at the end.
2341*7c478bd9Sstevel@tonic-gate 				 */
2342*7c478bd9Sstevel@tonic-gate 				envinit[basicenv++] = *lenvp;
2343*7c478bd9Sstevel@tonic-gate 			}
2344*7c478bd9Sstevel@tonic-gate 		}
2345*7c478bd9Sstevel@tonic-gate 	}
2346*7c478bd9Sstevel@tonic-gate 
2347*7c478bd9Sstevel@tonic-gate 	/*
2348*7c478bd9Sstevel@tonic-gate 	 * Add in all the environment variables picked up from the
2349*7c478bd9Sstevel@tonic-gate 	 * argument list to "login" or from the user response to the
2350*7c478bd9Sstevel@tonic-gate 	 * "login" request, if any.
2351*7c478bd9Sstevel@tonic-gate 	 */
2352*7c478bd9Sstevel@tonic-gate 
2353*7c478bd9Sstevel@tonic-gate 	if (envp == NULL)
2354*7c478bd9Sstevel@tonic-gate 		goto switch_env;	/* done */
2355*7c478bd9Sstevel@tonic-gate 
2356*7c478bd9Sstevel@tonic-gate 	for (j = 0, k = 0, l_index = 0;
2357*7c478bd9Sstevel@tonic-gate 		*envp != NULL && j < (MAXARGS-1);
2358*7c478bd9Sstevel@tonic-gate 		j++, envp++) {
2359*7c478bd9Sstevel@tonic-gate 
2360*7c478bd9Sstevel@tonic-gate 		/*
2361*7c478bd9Sstevel@tonic-gate 		 * Scan each string provided.  If it doesn't have the
2362*7c478bd9Sstevel@tonic-gate 		 * format xxx=yyy, then add the string "Ln=" to the beginning.
2363*7c478bd9Sstevel@tonic-gate 		 */
2364*7c478bd9Sstevel@tonic-gate 		if ((endptr = strchr(*envp, '=')) == NULL) {
2365*7c478bd9Sstevel@tonic-gate 			/*
2366*7c478bd9Sstevel@tonic-gate 			 * This much to be malloc'd:
2367*7c478bd9Sstevel@tonic-gate 			 *   strlen(*envp) + 1 char for 'L' +
2368*7c478bd9Sstevel@tonic-gate 			 *   MAXARGSWIDTH + 1 char for '=' + 1 for null char;
2369*7c478bd9Sstevel@tonic-gate 			 *
2370*7c478bd9Sstevel@tonic-gate 			 * total = strlen(*envp) + MAXARGSWIDTH + 3
2371*7c478bd9Sstevel@tonic-gate 			 */
2372*7c478bd9Sstevel@tonic-gate 			int total = strlen(*envp) + MAXARGSWIDTH + 3;
2373*7c478bd9Sstevel@tonic-gate 			envinit[basicenv+k] = malloc(total);
2374*7c478bd9Sstevel@tonic-gate 			if (envinit[basicenv+k] == NULL) {
2375*7c478bd9Sstevel@tonic-gate 				(void) printf("%s: malloc failed\n", PROG_NAME);
2376*7c478bd9Sstevel@tonic-gate 				login_exit(1);
2377*7c478bd9Sstevel@tonic-gate 			}
2378*7c478bd9Sstevel@tonic-gate 			(void) snprintf(envinit[basicenv+k], total, "L%d=%s",
2379*7c478bd9Sstevel@tonic-gate 				l_index, *envp);
2380*7c478bd9Sstevel@tonic-gate 
2381*7c478bd9Sstevel@tonic-gate 			k++;
2382*7c478bd9Sstevel@tonic-gate 			l_index++;
2383*7c478bd9Sstevel@tonic-gate 		} else  {
2384*7c478bd9Sstevel@tonic-gate 			if (!legalenvvar(*envp)) { /* this env var permited? */
2385*7c478bd9Sstevel@tonic-gate 				continue;
2386*7c478bd9Sstevel@tonic-gate 			} else {
2387*7c478bd9Sstevel@tonic-gate 
2388*7c478bd9Sstevel@tonic-gate 				/*
2389*7c478bd9Sstevel@tonic-gate 				 * Check to see whether this string replaces
2390*7c478bd9Sstevel@tonic-gate 				 * any previously defined string
2391*7c478bd9Sstevel@tonic-gate 				 */
2392*7c478bd9Sstevel@tonic-gate 				for (i = 0, length = endptr + 1 - *envp;
2393*7c478bd9Sstevel@tonic-gate 					i < basicenv + k; i++) {
2394*7c478bd9Sstevel@tonic-gate 				    if (strncmp(*envp, envinit[i], length)
2395*7c478bd9Sstevel@tonic-gate 						== 0) {
2396*7c478bd9Sstevel@tonic-gate 					envinit[i] = *envp;
2397*7c478bd9Sstevel@tonic-gate 					break;
2398*7c478bd9Sstevel@tonic-gate 				    }
2399*7c478bd9Sstevel@tonic-gate 				}
2400*7c478bd9Sstevel@tonic-gate 
2401*7c478bd9Sstevel@tonic-gate 				/*
2402*7c478bd9Sstevel@tonic-gate 				 * If it doesn't, place it at the end of
2403*7c478bd9Sstevel@tonic-gate 				 * environment array.
2404*7c478bd9Sstevel@tonic-gate 				 */
2405*7c478bd9Sstevel@tonic-gate 				if (i == basicenv+k) {
2406*7c478bd9Sstevel@tonic-gate 					envinit[basicenv+k] = *envp;
2407*7c478bd9Sstevel@tonic-gate 					k++;
2408*7c478bd9Sstevel@tonic-gate 				}
2409*7c478bd9Sstevel@tonic-gate 			}
2410*7c478bd9Sstevel@tonic-gate 		}
2411*7c478bd9Sstevel@tonic-gate 	}		/* for (j = 0 ... ) */
2412*7c478bd9Sstevel@tonic-gate 
2413*7c478bd9Sstevel@tonic-gate switch_env:
2414*7c478bd9Sstevel@tonic-gate 	/*
2415*7c478bd9Sstevel@tonic-gate 	 * Switch to the new environment.
2416*7c478bd9Sstevel@tonic-gate 	 */
2417*7c478bd9Sstevel@tonic-gate 	environ = envinit;
2418*7c478bd9Sstevel@tonic-gate }
2419*7c478bd9Sstevel@tonic-gate 
2420*7c478bd9Sstevel@tonic-gate /*
2421*7c478bd9Sstevel@tonic-gate  * print_banner		- Print the banner at start up
2422*7c478bd9Sstevel@tonic-gate  *			   Do not turn on DOBANNER ifdef.  This is not
2423*7c478bd9Sstevel@tonic-gate  *			   relevant to SunOS.
2424*7c478bd9Sstevel@tonic-gate  */
2425*7c478bd9Sstevel@tonic-gate 
2426*7c478bd9Sstevel@tonic-gate static void
2427*7c478bd9Sstevel@tonic-gate print_banner(void)
2428*7c478bd9Sstevel@tonic-gate {
2429*7c478bd9Sstevel@tonic-gate #ifdef DOBANNER
2430*7c478bd9Sstevel@tonic-gate 	uname(&un);
2431*7c478bd9Sstevel@tonic-gate #if i386
2432*7c478bd9Sstevel@tonic-gate 	(void) printf("UNIX System V/386 Release %s\n%s\n"
2433*7c478bd9Sstevel@tonic-gate 	    "Copyright (C) 1984, 1986, 1987, 1988 AT&T\n"
2434*7c478bd9Sstevel@tonic-gate 	    "Copyright (C) 1987, 1988 Microsoft Corp.\nAll Rights Reserved\n",
2435*7c478bd9Sstevel@tonic-gate 		un.release, un.nodename);
2436*7c478bd9Sstevel@tonic-gate #elif sun
2437*7c478bd9Sstevel@tonic-gate 	(void) printf("SunOS Release %s Sun Microsystems %s\n%s\n"
2438*7c478bd9Sstevel@tonic-gate 	    "Copyright (c) 1984, 1986, 1987, 1988 AT&T\n"
2439*7c478bd9Sstevel@tonic-gate 	    "Copyright (c) 1988, 1989, 1990, 1991 Sun Microsystems\n"
2440*7c478bd9Sstevel@tonic-gate 	    "All Rights Reserved\n",
2441*7c478bd9Sstevel@tonic-gate 		un.release, un.machine, un.nodename);
2442*7c478bd9Sstevel@tonic-gate #else
2443*7c478bd9Sstevel@tonic-gate 	(void) printf("UNIX System V Release %s AT&T %s\n%s\n"
2444*7c478bd9Sstevel@tonic-gate 	    "Copyright (c) 1984, 1986, 1987, 1988 AT&T\nAll Rights Reserved\n",
2445*7c478bd9Sstevel@tonic-gate 		un.release, un.machine, un.nodename);
2446*7c478bd9Sstevel@tonic-gate #endif /* i386 */
2447*7c478bd9Sstevel@tonic-gate #endif /* DOBANNER */
2448*7c478bd9Sstevel@tonic-gate }
2449*7c478bd9Sstevel@tonic-gate 
2450*7c478bd9Sstevel@tonic-gate /*
2451*7c478bd9Sstevel@tonic-gate  * display_last_login_time	- Advise the user the time and date
2452*7c478bd9Sstevel@tonic-gate  *				  that this login-id was last used.
2453*7c478bd9Sstevel@tonic-gate  */
2454*7c478bd9Sstevel@tonic-gate 
2455*7c478bd9Sstevel@tonic-gate static void
2456*7c478bd9Sstevel@tonic-gate display_last_login_time(void)
2457*7c478bd9Sstevel@tonic-gate {
2458*7c478bd9Sstevel@tonic-gate 	if (lastlogok) {
2459*7c478bd9Sstevel@tonic-gate 		(void) printf("Last login: %.*s ", 24-5, ctime(&ll.ll_time));
2460*7c478bd9Sstevel@tonic-gate 
2461*7c478bd9Sstevel@tonic-gate 		if (*ll.ll_host != '\0')
2462*7c478bd9Sstevel@tonic-gate 			(void) printf("from %.*s\n", sizeof (ll.ll_host),
2463*7c478bd9Sstevel@tonic-gate 					    ll.ll_host);
2464*7c478bd9Sstevel@tonic-gate 		else
2465*7c478bd9Sstevel@tonic-gate 			(void) printf("on %.*s\n", sizeof (ll.ll_line),
2466*7c478bd9Sstevel@tonic-gate 					    ll.ll_line);
2467*7c478bd9Sstevel@tonic-gate 	}
2468*7c478bd9Sstevel@tonic-gate }
2469*7c478bd9Sstevel@tonic-gate 
2470*7c478bd9Sstevel@tonic-gate /*
2471*7c478bd9Sstevel@tonic-gate  * exec_the_shell	- invoke the specified shell or start up program
2472*7c478bd9Sstevel@tonic-gate  */
2473*7c478bd9Sstevel@tonic-gate 
2474*7c478bd9Sstevel@tonic-gate static void
2475*7c478bd9Sstevel@tonic-gate exec_the_shell(void)
2476*7c478bd9Sstevel@tonic-gate {
2477*7c478bd9Sstevel@tonic-gate 	char *endptr;
2478*7c478bd9Sstevel@tonic-gate 	int i;
2479*7c478bd9Sstevel@tonic-gate 
2480*7c478bd9Sstevel@tonic-gate 	(void) strlcat(minusnam, basename(pwd->pw_shell),
2481*7c478bd9Sstevel@tonic-gate 		sizeof (minusnam));
2482*7c478bd9Sstevel@tonic-gate 
2483*7c478bd9Sstevel@tonic-gate 	/*
2484*7c478bd9Sstevel@tonic-gate 	 * Exec the shell
2485*7c478bd9Sstevel@tonic-gate 	 */
2486*7c478bd9Sstevel@tonic-gate 	(void) execl(pwd->pw_shell, minusnam, (char *)0);
2487*7c478bd9Sstevel@tonic-gate 
2488*7c478bd9Sstevel@tonic-gate 	/*
2489*7c478bd9Sstevel@tonic-gate 	 * pwd->pw_shell was not an executable object file, maybe it
2490*7c478bd9Sstevel@tonic-gate 	 * is a shell proceedure or a command line with arguments.
2491*7c478bd9Sstevel@tonic-gate 	 * If so, turn off the SHELL= environment variable.
2492*7c478bd9Sstevel@tonic-gate 	 */
2493*7c478bd9Sstevel@tonic-gate 	for (i = 0; envinit[i] != NULL; ++i) {
2494*7c478bd9Sstevel@tonic-gate 		if ((envinit[i] == shell) &&
2495*7c478bd9Sstevel@tonic-gate 		    ((endptr = strchr(shell, '=')) != NULL))
2496*7c478bd9Sstevel@tonic-gate 			(*++endptr) = '\0';
2497*7c478bd9Sstevel@tonic-gate 		}
2498*7c478bd9Sstevel@tonic-gate 
2499*7c478bd9Sstevel@tonic-gate 	if (access(pwd->pw_shell, R_OK|X_OK) == 0) {
2500*7c478bd9Sstevel@tonic-gate 		(void) execl(SHELL, "sh", pwd->pw_shell, (char *)0);
2501*7c478bd9Sstevel@tonic-gate 		(void) execl(SHELL2, "sh", pwd->pw_shell, (char *)0);
2502*7c478bd9Sstevel@tonic-gate 	}
2503*7c478bd9Sstevel@tonic-gate 
2504*7c478bd9Sstevel@tonic-gate 	(void) printf("No shell\n");
2505*7c478bd9Sstevel@tonic-gate }
2506*7c478bd9Sstevel@tonic-gate 
2507*7c478bd9Sstevel@tonic-gate /*
2508*7c478bd9Sstevel@tonic-gate  * login_exit		- Call exit()  and terminate.
2509*7c478bd9Sstevel@tonic-gate  *			  This function is here for PAM so cleanup can
2510*7c478bd9Sstevel@tonic-gate  *			  be done before the process exits.
2511*7c478bd9Sstevel@tonic-gate  */
2512*7c478bd9Sstevel@tonic-gate static void
2513*7c478bd9Sstevel@tonic-gate login_exit(int exit_code)
2514*7c478bd9Sstevel@tonic-gate {
2515*7c478bd9Sstevel@tonic-gate 	if (pamh)
2516*7c478bd9Sstevel@tonic-gate 		(void) pam_end(pamh, PAM_ABORT);
2517*7c478bd9Sstevel@tonic-gate 
2518*7c478bd9Sstevel@tonic-gate 	if (audit_error)
2519*7c478bd9Sstevel@tonic-gate 		audit_failure(get_audit_id(), audit_error,
2520*7c478bd9Sstevel@tonic-gate 		    pwd, remote_host, ttyn, zone_name);
2521*7c478bd9Sstevel@tonic-gate 
2522*7c478bd9Sstevel@tonic-gate 	exit(exit_code);
2523*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
2524*7c478bd9Sstevel@tonic-gate }
2525*7c478bd9Sstevel@tonic-gate 
2526*7c478bd9Sstevel@tonic-gate /*
2527*7c478bd9Sstevel@tonic-gate  * Check if lenv and penv matches or not.
2528*7c478bd9Sstevel@tonic-gate  */
2529*7c478bd9Sstevel@tonic-gate static int
2530*7c478bd9Sstevel@tonic-gate locale_envmatch(char *lenv, char *penv)
2531*7c478bd9Sstevel@tonic-gate {
2532*7c478bd9Sstevel@tonic-gate 	while ((*lenv == *penv) && *lenv && *penv != '=') {
2533*7c478bd9Sstevel@tonic-gate 		lenv++;
2534*7c478bd9Sstevel@tonic-gate 		penv++;
2535*7c478bd9Sstevel@tonic-gate 	}
2536*7c478bd9Sstevel@tonic-gate 
2537*7c478bd9Sstevel@tonic-gate 	/*
2538*7c478bd9Sstevel@tonic-gate 	 * '/' is eliminated for security reason.
2539*7c478bd9Sstevel@tonic-gate 	 */
2540*7c478bd9Sstevel@tonic-gate 	if (*lenv == '\0' && *penv == '=' && *(penv + 1) != '/')
2541*7c478bd9Sstevel@tonic-gate 		return (1);
2542*7c478bd9Sstevel@tonic-gate 	return (0);
2543*7c478bd9Sstevel@tonic-gate }
2544*7c478bd9Sstevel@tonic-gate 
2545*7c478bd9Sstevel@tonic-gate static int
2546*7c478bd9Sstevel@tonic-gate is_number(char *ptr)
2547*7c478bd9Sstevel@tonic-gate {
2548*7c478bd9Sstevel@tonic-gate 	while (*ptr != '\0') {
2549*7c478bd9Sstevel@tonic-gate 		if (!isdigit(*ptr))
2550*7c478bd9Sstevel@tonic-gate 			return (0);
2551*7c478bd9Sstevel@tonic-gate 		ptr++;
2552*7c478bd9Sstevel@tonic-gate 	}
2553*7c478bd9Sstevel@tonic-gate 	return (1);
2554*7c478bd9Sstevel@tonic-gate }
2555