login.c revision 38374
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
489615Sdes *
589615Sdes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
789615Sdes * are met:
889615Sdes * 1. Redistributions of source code must retain the above copyright
989615Sdes *    notice, this list of conditions and the following disclaimer.
1089615Sdes * 2. Redistributions in binary form must reproduce the above copyright
1189615Sdes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#if 0
351590Srgrimesstatic char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif
391590Srgrimes
401590Srgrimes#ifndef lint
4187628Sdwmalone#if 0
4287628Sdwmalonestatic char sccsid[] = "@(#)login.c	8.4 (Berkeley) 4/2/94";
4387628Sdwmalone#endif
4487628Sdwmalonestatic const char rcsid[] =
4587628Sdwmalone	"$Id: login.c,v 1.37 1998/07/31 07:22:31 bde Exp $";
4687628Sdwmalone#endif /* not lint */
4787233Smarkm
4887233Smarkm/*
4987233Smarkm * login [ name ]
501590Srgrimes * login -h hostname	(for telnetd, etc.)
511590Srgrimes * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
521590Srgrimes */
531590Srgrimes
541590Srgrimes#include <sys/copyright.h>
551590Srgrimes#include <sys/param.h>
5687233Smarkm#include <sys/stat.h>
5787180Smarkm#include <sys/time.h>
5887180Smarkm#include <sys/resource.h>
591590Srgrimes#include <sys/file.h>
601590Srgrimes#include <netinet/in.h>
611590Srgrimes#include <arpa/inet.h>
6287180Smarkm
631590Srgrimes#include <err.h>
641590Srgrimes#include <errno.h>
651590Srgrimes#include <grp.h>
661590Srgrimes#include <netdb.h>
6740102Smarkm#include <pwd.h>
6841079Sjdp#include <setjmp.h>
691590Srgrimes#include <signal.h>
701590Srgrimes#include <stdio.h>
711590Srgrimes#include <stdlib.h>
721590Srgrimes#include <string.h>
731590Srgrimes#include <syslog.h>
741590Srgrimes#include <ttyent.h>
751590Srgrimes#include <unistd.h>
761590Srgrimes#include <utmp.h>
771590Srgrimes
781590Srgrimes#ifdef LOGIN_CAP
7941279Sjdp#include <login_cap.h>
8091714Sdes#else /* Undef AUTH as well */
813702Spst#undef LOGIN_CAP_AUTH
8287173Smarkm#endif
831590Srgrimes
841590Srgrimes/*
8589994Sdes * If LOGIN_CAP_AUTH is activated:
8689994Sdes * kerberose & skey logins are runtime selected via login
8789994Sdes * login_getstyle() and authentication types for login classes
8889994Sdes * The actual login itself is handled via /usr/libexec/login_<style>
8989994Sdes * Valid styles are determined by the auth-type=style,style entries
9089994Sdes * in the login class.
9189994Sdes */
9289994Sdes#ifdef LOGIN_CAP_AUTH
9389994Sdes#undef KERBEROS
9489994Sdes#undef SKEY
9589994Sdes#endif /* LOGIN_CAP_AUTH */
9689994Sdes
9789994Sdes#ifdef	SKEY
9889994Sdes#include <skey.h>
991590Srgrimes#endif /* SKEY */
10087173Smarkm
10187173Smarkm#include "pathnames.h"
10287173Smarkm
10376786Sobrienvoid	 badlogin __P((char *));
10476786Sobrienvoid	 checknologin __P((void));
10589994Sdesvoid	 dolastlog __P((int));
10687173Smarkmvoid	 getloginname __P((void));
10789994Sdesvoid	 motd __P((char *));
10889994Sdesint	 rootterm __P((char *));
1091590Srgrimesvoid	 sigint __P((int));
1101590Srgrimesvoid	 sleepexit __P((int));
1111590Srgrimesvoid	 refused __P((char *,char *,int));
1121590Srgrimeschar	*stypeof __P((char *));
1131590Srgrimesvoid	 timedout __P((int));
11489994Sdesint	 login_access __P((char *, char *));
1151590Srgrimesvoid     login_fbtab __P((char *, uid_t, gid_t));
11642272Seivind#ifdef KERBEROS
11789994Sdesint	 klogin __P((struct passwd *, char *, char *, char *));
11842272Seivind#endif
11989994Sdes
12089994Sdesextern void login __P((struct utmp *));
1211590Srgrimesextern void trimdomain __P((char *, int));
12289994Sdesstatic void usage __P((void));
12389994Sdes
12489994Sdes#define	TTYGRPNAME	"tty"		/* name of group to own ttys */
12589994Sdes#define	DEFAULT_BACKOFF	3
12689994Sdes#define	DEFAULT_RETRIES	10
12789994Sdes
12889994Sdes/*
12989994Sdes * This bounds the time given to login.  Not a define so it can
13089994Sdes * be patched on machines where it's too small.
13189994Sdes */
13289994Sdesu_int	timeout = 300;
13389994Sdes
13489994Sdes#ifdef KERBEROS
13589994Sdesint	notickets = 1;
13689994Sdesint	noticketsdontcomplain = 1;
13789994Sdeschar	*instance;
13889994Sdeschar	*krbtkfile_env;
13989994Sdesint	authok;
14089994Sdes#endif
14189994Sdes
14294203Srustruct	passwd *pwd;
14389994Sdesint	failures;
14494203Sruchar	*term, *envinit[1], *hostname, *username, *tty;
14589994Sdeschar    full_hostname[MAXHOSTNAMELEN];
14689994Sdes
14789994Sdesint
14889994Sdesmain(argc, argv)
14989994Sdes	int argc;
15089994Sdes	char *argv[];
15189994Sdes{
15291714Sdes	extern char **environ;
15389994Sdes	struct group *gr;
15489994Sdes	struct stat st;
15589994Sdes	struct timeval tp;
15689994Sdes	struct utmp utmp;
15789994Sdes	int rootok, retries, backoff;
1581590Srgrimes	int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
15989994Sdes	int changepass;
1601590Srgrimes	time_t warntime;
1611590Srgrimes	uid_t uid, euid;
1621590Srgrimes	char *domain, *p, *ep, *salt, *ttyn;
16389994Sdes	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
16489994Sdes	char localhost[MAXHOSTNAMELEN];
16535559Speter	char *shell = NULL;
16646007Sache#ifdef LOGIN_CAP
16789994Sdes	login_cap_t *lc = NULL;
16845431Sbrian#ifdef LOGIN_CAP_AUTH
16942272Seivind	char *style, *authtype;
17094203Sru	char *auth_method = NULL;
17198960Sache	char *instance = NULL;
17294203Sru	int authok;
17321528Sdavidn#endif /* LOGIN_CAP_AUTH */
174146867Smaxim#endif /* LOGIN_CAP */
17574874Smarkm#ifdef SKEY
176165152Scsjp	int permit_passwd = 0;
177155312Swsalamon#endif /* SKEY */
178165152Scsjp
1791590Srgrimes	(void)signal(SIGALRM, timedout);
18042272Seivind	(void)alarm(timeout);
18142272Seivind	(void)signal(SIGQUIT, SIG_IGN);
18276942Sguido	(void)signal(SIGINT, SIG_IGN);
18342272Seivind	(void)setpriority(PRIO_PROCESS, 0, 0);
18442272Seivind
18589994Sdes	openlog("login", LOG_ODELAY, LOG_AUTH);
18676788Sobrien
18776788Sobrien	/*
18889994Sdes	 * -p is used by getty to tell login not to destroy the environment
18942272Seivind	 * -f is used to skip a second login authentication
1901590Srgrimes	 * -h is used by other servers to pass the name of the remote
1911590Srgrimes	 *    host to login so that it may be placed in utmp and wtmp
1921590Srgrimes	 */
1931590Srgrimes	*full_hostname = '\0';
1941590Srgrimes	domain = NULL;
1951590Srgrimes	term = NULL;
1961590Srgrimes	if (gethostname(localhost, sizeof(localhost)) < 0)
19735557Speter		syslog(LOG_ERR, "couldn't get local hostname: %m");
19846007Sache	else
19989994Sdes		domain = strchr(localhost, '.');
20024360Simp
2011590Srgrimes	fflag = hflag = pflag = 0;
2021590Srgrimes	uid = getuid();
2031590Srgrimes	euid = geteuid();
2041590Srgrimes	while ((ch = getopt(argc, argv, "fh:p")) != -1)
2051590Srgrimes		switch (ch) {
20689994Sdes		case 'f':
2071590Srgrimes			fflag = 1;
20889994Sdes			break;
20981555Smike		case 'h':
21081555Smike			if (uid)
21189994Sdes				errx(1, "-h option: %s", strerror(EPERM));
2121590Srgrimes			hflag = 1;
2131590Srgrimes			strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
2141590Srgrimes			if (domain && (p = strchr(optarg, '.')) &&
2151590Srgrimes			    strcasecmp(p, domain) == 0)
2161590Srgrimes				*p = 0;
2171590Srgrimes
2181590Srgrimes			trimdomain(optarg, UT_HOSTSIZE );
21989994Sdes
2201590Srgrimes			if (strlen(optarg) > UT_HOSTSIZE) {
22127605Scharnier				struct hostent *hp = gethostbyname(optarg);
2221590Srgrimes
2231590Srgrimes				if (hp != NULL) {
2241590Srgrimes					struct in_addr in;
2251590Srgrimes
22689994Sdes					memmove(&in, hp->h_addr, sizeof(in));
22789994Sdes					optarg = strdup(inet_ntoa(in));
22889994Sdes				} else
22989994Sdes					optarg = "invalid hostname";
2301590Srgrimes			}
23189994Sdes			hostname = optarg;
2321590Srgrimes			break;
23389994Sdes		case 'p':
2341590Srgrimes			pflag = 1;
235107585Sdes			break;
236107585Sdes		case '?':
2371590Srgrimes		default:
2381590Srgrimes			if (!uid)
2391590Srgrimes				syslog(LOG_ERR, "invalid flag %c", ch);
24089994Sdes			usage();
24189994Sdes		}
24289994Sdes	argc -= optind;
2431590Srgrimes	argv += optind;
2441590Srgrimes
2451590Srgrimes	if (*argv) {
2461590Srgrimes		username = *argv;
2471590Srgrimes		ask = 0;
24823985Sdavidn	} else
2491590Srgrimes		ask = 1;
2501590Srgrimes
2511590Srgrimes	for (cnt = getdtablesize(); cnt > 2; cnt--)
2521590Srgrimes		(void)close(cnt);
25323985Sdavidn
25423985Sdavidn	ttyn = ttyname(STDIN_FILENO);
25523985Sdavidn	if (ttyn == NULL || *ttyn == '\0') {
25623985Sdavidn		(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
257114010Sdes		ttyn = tname;
25889994Sdes	}
25976786Sobrien	if ((tty = strrchr(ttyn, '/')) != NULL)
26087173Smarkm		++tty;
26189994Sdes	else
26289994Sdes		tty = ttyn;
26389994Sdes
26489994Sdes#ifdef LOGIN_CAP_AUTH
26523985Sdavidn	authtype = hostname ? "rlogin" : "login";
26623985Sdavidn#endif
26721528Sdavidn#ifdef LOGIN_CAP
26889994Sdes	/*
26989994Sdes	 * Get "login-retries" & "login-backoff" from default class
27089994Sdes	 */
2711590Srgrimes	lc = login_getclass(NULL);
2721590Srgrimes	retries = login_getcapnum(lc, "login-retries", DEFAULT_RETRIES, DEFAULT_RETRIES);
2731590Srgrimes	backoff = login_getcapnum(lc, "login-backoff", DEFAULT_BACKOFF, DEFAULT_BACKOFF);
27489994Sdes	login_close(lc);
27589994Sdes	lc = NULL;
27689994Sdes#else
27789994Sdes	retries = DEFAULT_RETRIES;
2781590Srgrimes	backoff = DEFAULT_BACKOFF;
2791590Srgrimes#endif
28021528Sdavidn
2811590Srgrimes	for (cnt = 0;; ask = 1) {
2821590Srgrimes		if (ask) {
2831590Srgrimes			fflag = 0;
2841590Srgrimes			getloginname();
2851590Srgrimes		}
28689994Sdes		rootlogin = 0;
2871590Srgrimes		rootok = rootterm(tty); /* Default (auth may change) */
28889994Sdes#ifdef LOGIN_CAP_AUTH
2891590Srgrimes		authok = 0;
2901590Srgrimes		if (auth_method = strchr(username, ':')) {
29123985Sdavidn			*auth_method = '\0';
29289994Sdes			auth_method++;
2931590Srgrimes			if (*auth_method == '\0')
29489994Sdes				auth_method = NULL;
29589994Sdes		}
29689994Sdes		/*
297165152Scsjp		 * We need to do this regardless of whether
298155312Swsalamon		 * kerberos is available.
299165152Scsjp		 */
30089994Sdes		if ((instance = strchr(username, '.')) != NULL) {
3013205Spst			if (strncmp(instance, ".root", 5) == 0)
30289994Sdes				rootlogin = 1;
30389994Sdes			*instance++ = '\0';
30489994Sdes		} else
305165152Scsjp			instance = "";
306155312Swsalamon#else /* !LOGIN_CAP_AUTH */
307165152Scsjp#ifdef KERBEROS
30889994Sdes		if ((instance = strchr(username, '.')) != NULL) {
30989994Sdes			if (strncmp(instance, ".root", 5) == 0)
310110966Sdes				rootlogin = 1;
31189994Sdes			*instance++ = '\0';
31289994Sdes		} else
313165152Scsjp			instance = "";
314155312Swsalamon#endif /* KERBEROS */
315165152Scsjp#endif /* LOGIN_CAP_AUTH */
31689994Sdes
31789994Sdes		if (strlen(username) > UT_NAMESIZE)
31897376Sdes			username[UT_NAMESIZE] = '\0';
31989994Sdes
32041279Sjdp		/*
32141279Sjdp		 * Note if trying multiple user names; log failures for
3221590Srgrimes		 * previous user name, but don't bother logging one failure
3231590Srgrimes		 * for nonexistent name (mistyped username).
32489994Sdes		 */
32589994Sdes		if (failures && strcmp(tbuf, username)) {
32689994Sdes			if (failures > (pwd ? 0 : 1))
3271590Srgrimes				badlogin(tbuf);
32889994Sdes			failures = 0;
32989994Sdes		}
33089994Sdes		(void)strncpy(tbuf, username, sizeof tbuf-1);
33189994Sdes		tbuf[sizeof tbuf-1] = '\0';
332165152Scsjp
333155312Swsalamon		if ((pwd = getpwnam(username)) != NULL)
334165152Scsjp			salt = pwd->pw_passwd;
33589994Sdes		else
33689994Sdes			salt = "xx";
33789994Sdes
33889994Sdes#ifdef LOGIN_CAP
33989994Sdes		/*
3401590Srgrimes		 * Establish the class now, before we might goto
3411590Srgrimes		 * within the next block. pwd can be NULL since it
34289994Sdes		 * falls back to the "default" class if it is.
34389994Sdes		 */
34489994Sdes		if (pwd != NULL)
34589994Sdes			(void)seteuid(rootlogin ? 0 : pwd->pw_uid);
34697376Sdes		lc = login_getpwclass(pwd);
347155312Swsalamon		seteuid(euid);
348155312Swsalamon#endif /* LOGIN_CAP */
349155312Swsalamon
350155312Swsalamon		/*
351165152Scsjp		 * if we have a valid account name, and it doesn't have a
352155312Swsalamon		 * password, or the -f option was specified and the caller
353165152Scsjp		 * is root or the caller isn't changing their uid, don't
354155312Swsalamon		 * authenticate.
3551590Srgrimes		 */
3561590Srgrimes		rval = 1;
35723985Sdavidn		if (pwd != NULL) {
358157215Scognet			if (pwd->pw_uid == 0)
359157215Scognet				rootlogin = 1;
36023985Sdavidn
36189994Sdes			if (fflag && (uid == (uid_t)0 ||
36289994Sdes				      uid == (uid_t)pwd->pw_uid)) {
36323985Sdavidn				/* already authenticated */
36423985Sdavidn				break;
36523985Sdavidn			} else if (pwd->pw_passwd[0] == '\0') {
3661590Srgrimes				if (!rootlogin || rootok) {
36789994Sdes					/* pretend password okay */
3681590Srgrimes					rval = 0;
36938374Sjkoshy					goto ttycheck;
3701590Srgrimes				}
3711590Srgrimes			}
3721590Srgrimes		}
3731590Srgrimes
3741590Srgrimes		fflag = 0;
37576942Sguido
3761590Srgrimes		(void)setpriority(PRIO_PROCESS, 0, -4);
3771590Srgrimes
3781590Srgrimes#ifdef LOGIN_CAP_AUTH
379165152Scsjp		/*
380155312Swsalamon		 * This hands off authorization to an authorization program,
381155312Swsalamon		 * depending on the styles available for the "auth-login",
382155312Swsalamon		 * auth-rlogin (or default) authorization styles.
383165152Scsjp		 * We do this regardless of whether an account exists so that
384155312Swsalamon		 * the remote user cannot tell a "real" from an invented
38541279Sjdp		 * account name. If we don't have an account we just fall
38641279Sjdp		 * back to the first method for the "default" class.
38741279Sjdp		 */
38841279Sjdp		if (!(style = login_getstyle(lc, auth_method, authtype))) {
389146867Smaxim
39041279Sjdp			/*
391146867Smaxim			 * No available authorization method
392146867Smaxim			 */
39397376Sdes			rval = 1;
39483519Srwatson			(void)printf("No auth method available for %s.\n",
39583519Srwatson				     authtype);
39683519Srwatson		} else {
39783519Srwatson
39883519Srwatson			/*
39983519Srwatson			 * Put back the kerberos instance, if any was given.
40083519Srwatson			 * Don't worry about the non-kerberos case here, since
40146007Sache			 * if kerberos is not available or not selected and an
40235557Speter			 * instance is given at the login prompt, su or rlogin -l,
40321528Sdavidn			 * then anything else should fail as well.
40426021Spst			 */
40523985Sdavidn			if (*instance)
40697376Sdes				*(instance - 1) = '.';
40723985Sdavidn
40823985Sdavidn			rval = authenticate(username,
40923985Sdavidn					    lc ? lc->lc_class : "default",
41087173Smarkm					    style, authtype);
41187173Smarkm			/* Junk it again */
41287173Smarkm			if (*instance)
41389994Sdes				*(instance - 1) = '\0';
41487173Smarkm		}
4151590Srgrimes
41635557Speter		if (!rval) {
41746007Sache			char * approvep;
418125055Sfjoe
41921528Sdavidn			/*
420125055Sfjoe			 * If authentication succeeds, run any approval
421125055Sfjoe			 * program, if applicable for this class.
422125055Sfjoe			 */
42397376Sdes			approvep = login_getcapstr(lc, "approve", NULL, NULL);
42497376Sdes			rval = 1; /* Assume bad login again */
42523985Sdavidn
42687173Smarkm			if (approvep==NULL ||
42787173Smarkm			    auth_script(approvep, approvep, username,
42887173Smarkm					lc->lc_class, 0) == 0) {
42989994Sdes				int     r;
43087173Smarkm
43123985Sdavidn				r = auth_scan(AUTH_OKAY);
43223985Sdavidn				/*
43323985Sdavidn				 * See what the authorize program says
43481555Smike				 */
43589994Sdes				if (r != 0) {
43623985Sdavidn					rval = 0;
43721528Sdavidn
4382224Sguido					if (!rootok && (r & AUTH_ROOTOKAY))
4392224Sguido						rootok = 1; /* root approved */
4402224Sguido					else
4412224Sguido						rootlogin = 0;
4422224Sguido
4432224Sguido					if (!authok && (r & AUTH_SECURE))
4442224Sguido						authok = 1; /* secure */
44550124Simp				}
44650124Simp			}
44750124Simp		}
44850124Simp#else /* !LOGIN_CAP_AUTH */
44950124Simp#ifdef SKEY
450102141Simp		permit_passwd = skeyaccess(username, tty,
451102141Simp					   hostname ? full_hostname : NULL,
452102141Simp					   NULL);
453102141Simp		p = skey_getpass("Password:", pwd, permit_passwd);
454102141Simp		ep = skey_crypt(p, salt, pwd, permit_passwd);
455102141Simp#else /* !SKEY */
456102141Simp		p = getpass("Password:");
45750124Simp		ep = crypt(p, salt);
458102141Simp#endif/* SKEY */
459102141Simp
460102141Simp		if (pwd) {
46189994Sdes			if (!p[0] && pwd->pw_passwd[0])
46250124Simp				ep = ":";
463102141Simp#ifdef KERBEROS
464114048Srwatson#ifdef SKEY
4651590Srgrimes			/*
46623985Sdavidn			 * Do not allow user to type in kerberos password
46723985Sdavidn			 * over the net (actually, this is ok for encrypted
46823985Sdavidn			 * links, but we have no way of determining if the
46923985Sdavidn			 * link is encrypted.
47023985Sdavidn			 */
47189994Sdes			if (!permit_passwd) {
4721590Srgrimes				rval = 1;		/* failed */
4731590Srgrimes			} else
4743205Spst#endif /* SKEY */
4753205Spst			rval = klogin(pwd, instance, localhost, p);
47689994Sdes			if (rval != 0 && rootlogin && pwd->pw_uid != 0)
47789994Sdes				rootlogin = 0;
4783205Spst			if (rval == 0)
47989994Sdes				authok = 1; /* kerberos authenticated ok */
48023985Sdavidn			else if (rval == 1) /* fallback to unix passwd */
48189994Sdes				rval = strcmp(ep, pwd->pw_passwd);
48223985Sdavidn#else /* !KERBEROS */
48323985Sdavidn			rval = strcmp(ep, pwd->pw_passwd);
48423985Sdavidn#endif /* KERBEROS */
48521528Sdavidn		}
48621528Sdavidn
48723985Sdavidn		/* clear entered password */
48889994Sdes		memset(p, 0, strlen(p));
48989994Sdes#endif /* LOGIN_CAP_AUTH */
49023985Sdavidn
49189994Sdes		(void)setpriority(PRIO_PROCESS, 0, 0);
49289994Sdes
49323985Sdavidn#ifdef LOGIN_CAP_AUTH
49489994Sdes		if (rval)
49523985Sdavidn			auth_rmfiles();
49623985Sdavidn#endif
49776788Sobrien	ttycheck:
49823985Sdavidn		/*
49923985Sdavidn		 * If trying to log in as root without Kerberos,
50023985Sdavidn		 * but with insecure terminal, refuse the login attempt.
50189994Sdes		 */
50289994Sdes		if (pwd && !rval) {
50323985Sdavidn#if defined(KERBEROS) || defined(LOGIN_CAP_AUTH)
50489994Sdes			if (authok == 0 && rootlogin && !rootok)
50521528Sdavidn#else
50621528Sdavidn			if (rootlogin && !rootok)
50789994Sdes#endif
50889994Sdes				refused(NULL, "NOROOT", 0);
50921528Sdavidn			else	/* valid password & authenticated */
51023985Sdavidn				break;
51174874Smarkm		}
51274874Smarkm
51374874Smarkm		(void)printf("Login incorrect\n");
51497376Sdes		failures++;
51589994Sdes
51674874Smarkm		/*
51774874Smarkm		 * we allow up to 'retry' (10) tries,
51889994Sdes		 * but after 'backoff' (3) we start backing off
51989994Sdes		 */
52089994Sdes		if (++cnt > backoff) {
52189994Sdes			if (cnt >= retries) {
52289994Sdes				badlogin(username);
52389994Sdes				sleepexit(1);
52497376Sdes			}
52589994Sdes			sleep((u_int)((cnt - backoff) * 5));
52689994Sdes		}
52789994Sdes	}
52889994Sdes
52989994Sdes	/* committed to login -- turn off timeout */
53089994Sdes	(void)alarm((u_int)0);
53174874Smarkm
53289994Sdes	endpwent();
53389994Sdes
53489994Sdes	/* if user not super-user, check for disabled logins */
53589994Sdes#ifdef LOGIN_CAP
53689994Sdes	if (!rootlogin)
53789994Sdes		auth_checknologin(lc);
53889994Sdes#else
53989994Sdes	if (!rootlogin)
54074874Smarkm		checknologin();
54189994Sdes#endif
54289994Sdes
54374874Smarkm#ifdef LOGIN_CAP
544110549Sdes	quietlog = login_getcapbool(lc, "hushlogin", 0);
545107585Sdes#else
546110549Sdes	quietlog = 0;
54789994Sdes#endif
54874874Smarkm	(void)seteuid(rootlogin ? 0 : pwd->pw_uid);
54974874Smarkm	if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) {
55074874Smarkm#ifdef LOGIN_CAP
55189994Sdes		if (login_getcapbool(lc, "requirehome", 0))
55221528Sdavidn			refused("Home directory not available", "HOMEDIR", 1);
55397376Sdes#endif
55489994Sdes		if (chdir("/") < 0)
55589994Sdes			refused("Cannot find root directory", "ROOTDIR", 1);
55689994Sdes		pwd->pw_dir = "/";
55789994Sdes		if (!quietlog || *pwd->pw_dir)
55889994Sdes			printf("No home directory.\nLogging in with home = \"/\".\n");
55989994Sdes	}
56089994Sdes	(void)seteuid(euid);
56189994Sdes	if (!quietlog)
56291714Sdes		quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
56389994Sdes
56489994Sdes	if (pwd->pw_change || pwd->pw_expire)
56589994Sdes		(void)gettimeofday(&tp, (struct timezone *)NULL);
56689994Sdes
56789994Sdes#define DEFAULT_WARN  (2L * 7L * 86400L)  /* Two weeks */
56889994Sdes
56941279Sjdp#ifdef LOGIN_CAP
57097376Sdes	warntime = login_getcaptime(lc, "warnpassword",
57189994Sdes				    DEFAULT_WARN, DEFAULT_WARN);
57241279Sjdp#else
57341279Sjdp	warntime = DEFAULT_WARN;
57474874Smarkm#endif
57597376Sdes
57621528Sdavidn	changepass=0;
5773205Spst	if (pwd->pw_change) {
57821528Sdavidn		if (tp.tv_sec >= pwd->pw_change) {
57923148Sache			(void)printf("Sorry -- your password has expired.\n");
58021528Sdavidn			changepass=1;
58198960Sache			syslog(LOG_INFO,
58298990Sache			       "%s Password expired - forcing change",
58398960Sache			       pwd->pw_name);
58498960Sache		} else if (pwd->pw_change - tp.tv_sec < warntime && !quietlog)
58598960Sache		    (void)printf("Warning: your password expires on %s",
58641279Sjdp				 ctime(&pwd->pw_change));
58741279Sjdp	}
58821528Sdavidn
58921528Sdavidn#ifdef LOGIN_CAP
5901590Srgrimes	warntime = login_getcaptime(lc, "warnexpire",
59194203Sru				    DEFAULT_WARN, DEFAULT_WARN);
59223985Sdavidn#else
59323985Sdavidn	warntime = DEFAULT_WARN;
59489994Sdes#endif
59589994Sdes
59623985Sdavidn	if (pwd->pw_expire) {
59723985Sdavidn		if (tp.tv_sec >= pwd->pw_expire) {
59823985Sdavidn			refused("Sorry -- your account has expired",
59921528Sdavidn				"EXPIRED", 1);
60089994Sdes		} else if (pwd->pw_expire - tp.tv_sec < warntime && !quietlog)
60189994Sdes		    (void)printf("Warning: your account expires on %s",
60289994Sdes				 ctime(&pwd->pw_expire));
60389994Sdes	}
60423985Sdavidn
605146867Smaxim#ifdef LOGIN_CAP
606146867Smaxim	if (lc != NULL) {
607100825Sdwmalone		if (hostname) {
608100825Sdwmalone			struct hostent *hp = gethostbyname(full_hostname);
60986450Srwatson
610100825Sdwmalone			if (hp == NULL)
611100825Sdwmalone				optarg = NULL;
612100825Sdwmalone			else {
61386450Srwatson				struct in_addr in;
61489994Sdes				memmove(&in, hp->h_addr, sizeof(in));
615100825Sdwmalone				optarg = strdup(inet_ntoa(in));
61686450Srwatson			}
61786450Srwatson			if (!auth_hostok(lc, full_hostname, optarg))
61889994Sdes				refused("Permission denied", "HOST", 1);
619100825Sdwmalone		}
62086450Srwatson
6211590Srgrimes		if (!auth_ttyok(lc, tty))
6221590Srgrimes			refused("Permission denied", "TTY", 1);
623146867Smaxim
62421528Sdavidn		if (!auth_timeok(lc, time(NULL)))
6253205Spst			refused("Logins not available right now", "TIME", 1);
6261590Srgrimes	}
6271590Srgrimes        shell=login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell);
6281590Srgrimes#else /* !LOGIN_CAP */
6291590Srgrimes       shell=pwd->pw_shell;
6301590Srgrimes#endif /* LOGIN_CAP */
63123985Sdavidn	if (*pwd->pw_shell == '\0')
63223985Sdavidn		pwd->pw_shell = _PATH_BSHELL;
63323985Sdavidn	if (*shell == '\0')   /* Not overridden */
63489994Sdes		shell = pwd->pw_shell;
63589994Sdes	if ((shell = strdup(shell)) == NULL) {
63681555Smike		syslog(LOG_NOTICE, "memory allocation error");
63781555Smike		sleepexit(1);
63881555Smike	}
63989994Sdes
64089994Sdes#ifdef LOGIN_ACCESS
64181555Smike	if (login_access(pwd->pw_name, hostname ? full_hostname : tty) == 0)
64223985Sdavidn		refused("Permission denied", "ACCESS", 1);
64389994Sdes#endif /* LOGIN_ACCESS */
64421528Sdavidn
64597376Sdes	/* Nothing else left to fail -- really log in. */
64689994Sdes	memset((void *)&utmp, 0, sizeof(utmp));
64789994Sdes	(void)time(&utmp.ut_time);
64889994Sdes	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
6491590Srgrimes	if (hostname)
6501590Srgrimes		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
65141279Sjdp	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
65241279Sjdp	login(&utmp);
65341279Sjdp
65441279Sjdp	dolastlog(quietlog);
65541279Sjdp
65641279Sjdp	/*
65741279Sjdp	 * Set device protections, depending on what terminal the
65841279Sjdp	 * user is logged in. This feature is used on Suns to give
65989994Sdes	 * console users better privacy.
66041279Sjdp	 */
66141279Sjdp	login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);
66241279Sjdp
66341279Sjdp	(void)chown(ttyn, pwd->pw_uid,
66441279Sjdp		    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
66589994Sdes
66689994Sdes	/*
66741279Sjdp	 * Preserve TERM if it happens to be already set.
66841279Sjdp	 */
66941279Sjdp	if ((term = getenv("TERM")) != NULL)
67041279Sjdp		term = strdup(term);
67141279Sjdp
67241279Sjdp	/*
67341279Sjdp	 * Exclude cons/vt/ptys only, assume dialup otherwise
67441279Sjdp	 * TODO: Make dialup tty determination a library call
67541279Sjdp	 * for consistency (finger etc.)
67641279Sjdp	 */
67741279Sjdp	if (hostname==NULL && isdialuptty(tty))
67841279Sjdp		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
67941279Sjdp
68041279Sjdp#ifdef KERBEROS
68141279Sjdp	if (!quietlog && notickets == 1 && !noticketsdontcomplain)
68241279Sjdp		(void)printf("Warning: no Kerberos tickets issued.\n");
68341279Sjdp#endif
68441279Sjdp
68541279Sjdp#ifdef LOGALL
68689994Sdes	/*
68789994Sdes	 * Syslog each successful login, so we don't have to watch hundreds
68889994Sdes	 * of wtmp or lastlogin files.
68941279Sjdp	 */
69041279Sjdp	if (hostname)
69189994Sdes		syslog(LOG_INFO, "login from %s on %s as %s",
69289994Sdes		       full_hostname, tty, pwd->pw_name);
69389994Sdes	else
69441279Sjdp		syslog(LOG_INFO, "login on %s as %s",
69541279Sjdp		       tty, pwd->pw_name);
69641279Sjdp#endif
69741279Sjdp
69841279Sjdp	/*
69941279Sjdp	 * If fflag is on, assume caller/authenticator has logged root login.
70041279Sjdp	 */
70141279Sjdp	if (rootlogin && fflag == 0)
70241279Sjdp	{
70341279Sjdp		if (hostname)
70489994Sdes			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
70541279Sjdp			       username, tty, full_hostname);
70641279Sjdp		else
70741279Sjdp			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s",
70874874Smarkm			       username, tty);
70974874Smarkm	}
71089994Sdes
71189994Sdes	/*
71289994Sdes	 * Destroy environment unless user has requested its preservation.
71389994Sdes	 * We need to do this before setusercontext() because that may
71489994Sdes	 * set or reset some environment variables.
71589994Sdes	 */
71689994Sdes	if (!pflag)
71789994Sdes		environ = envinit;
71889994Sdes
71974874Smarkm	/*
72074874Smarkm	 * We don't need to be root anymore, so
72189994Sdes	 * set the user and session context
72289994Sdes	 */
72389994Sdes#ifdef LOGIN_CAP
72474874Smarkm	if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL) != 0) {
72589994Sdes                syslog(LOG_ERR, "setusercontext() failed - exiting");
72674874Smarkm		exit(1);
72741279Sjdp	}
72874874Smarkm#else
72974874Smarkm     	if (setlogin(pwd->pw_name) < 0)
73089994Sdes                syslog(LOG_ERR, "setlogin() failure: %m");
73174874Smarkm
73274874Smarkm	(void)setgid(pwd->pw_gid);
73389994Sdes	initgroups(username, pwd->pw_gid);
73441279Sjdp	(void)setuid(rootlogin ? 0 : pwd->pw_uid);
73572215Snectar#endif
73689994Sdes
73789994Sdes	(void)setenv("SHELL", pwd->pw_shell, 1);
73889994Sdes	(void)setenv("HOME", pwd->pw_dir, 1);
73989994Sdes	if (term != NULL && *term != '\0')
74087177Smarkm		(void)setenv("TERM", term, 1);	/* Preset overrides */
74172215Snectar	else {
74289994Sdes		(void)setenv("TERM", stypeof(tty), 0);	/* Fallback doesn't */
74389994Sdes	}
74472215Snectar	(void)setenv("LOGNAME", pwd->pw_name, 1);
74589994Sdes	(void)setenv("USER", pwd->pw_name, 1);
74689994Sdes	(void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0);
74789994Sdes#ifdef KERBEROS
748169177Sache	if (krbtkfile_env)
749169177Sache		(void)setenv("KRBTKFILE", krbtkfile_env, 1);
75089994Sdes#endif
75172215Snectar#if LOGIN_CAP_AUTH
75272215Snectar	auth_env();
75372215Snectar#endif
75472215Snectar
75589994Sdes#ifdef LOGIN_CAP
75672215Snectar	if (!quietlog) {
75772215Snectar		char	*cw;
75872215Snectar
75972215Snectar		cw = login_getcapstr(lc, "copyright", NULL, NULL);
76089994Sdes		if (cw != NULL && access(cw, F_OK) == 0)
76172215Snectar			motd(cw);
76272215Snectar		else
76389994Sdes		    (void)printf("%s\n\t%s %s\n",
76472215Snectar	"Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
76572215Snectar	"The Regents of the University of California. ",
76672215Snectar	"All rights reserved.");
76772215Snectar
76872215Snectar		(void)printf("\n");
769171195Sscf
77072215Snectar		cw = login_getcapstr(lc, "welcome", NULL, NULL);
77172215Snectar		if (cw == NULL || access(cw, F_OK) != 0)
77272215Snectar			cw = _PATH_MOTDFILE;
773171195Sscf		motd(cw);
77489994Sdes
77572215Snectar		cw = getenv("MAIL");	/* $MAIL may have been set by class */
77689994Sdes		if (cw != NULL) {
77772215Snectar			strncpy(tbuf, cw, sizeof(tbuf));
77872215Snectar			tbuf[sizeof(tbuf)-1] = '\0';
77972215Snectar		} else
78089994Sdes			snprintf(tbuf, sizeof(tbuf), "%s/%s",
78172215Snectar				 _PATH_MAILDIR, pwd->pw_name);
782171195Sscf#else
783171195Sscf	if (!quietlog) {
784171195Sscf		    (void)printf("%s\n\t%s %s\n",
78589994Sdes	"Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
78672215Snectar	"The Regents of the University of California. ",
78741279Sjdp	"All rights reserved.");
78827605Scharnier		motd(_PATH_MOTDFILE);
78987177Smarkm		snprintf(tbuf, sizeof(tbuf), "%s/%s",
79027605Scharnier			 _PATH_MAILDIR, pwd->pw_name);
79176791Sobrien#endif
79227605Scharnier		if (stat(tbuf, &st) == 0 && st.st_size != 0)
79327605Scharnier			(void)printf("You have %smail.\n",
79427605Scharnier				     (st.st_mtime > st.st_atime) ? "new " : "");
7951590Srgrimes	}
79623985Sdavidn
79789994Sdes#ifdef LOGIN_CAP
79874874Smarkm	login_close(lc);
79989994Sdes#endif
80087177Smarkm
8011590Srgrimes	(void)signal(SIGALRM, SIG_DFL);
80289994Sdes	(void)signal(SIGQUIT, SIG_DFL);
8031590Srgrimes	(void)signal(SIGINT, SIG_DFL);
8041590Srgrimes	(void)signal(SIGTSTP, SIG_IGN);
80589994Sdes
80689994Sdes	if (changepass) {
80789994Sdes		if (system(_PATH_CHPASS) != 0)
80889994Sdes			sleepexit(1);
80981555Smike	}
8101590Srgrimes
8111590Srgrimes	/*
8121590Srgrimes	 * Login shells have a leading '-' in front of argv[0]
81389994Sdes	 */
8141590Srgrimes	tbuf[0] = '-';
81589994Sdes	(void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell);
8161590Srgrimes
8171590Srgrimes	execlp(shell, tbuf, 0);
81889994Sdes	err(1, "%s", shell);
81997376Sdes}
82089994Sdes
82189994Sdesstatic void
82289994Sdesusage()
82389994Sdes{
82489994Sdes	(void)fprintf(stderr, "usage: login [-fp] [-h hostname] [username]\n");
82589994Sdes	exit(1);
8261590Srgrimes}
82789994Sdes
8281590Srgrimes/*
8291590Srgrimes * Allow for authentication style and/or kerberos instance
83089994Sdes * */
83189994Sdes
83289994Sdes#define	NBUFSIZ		UT_NAMESIZE + 64
83389994Sdes
83489994Sdesvoid
83589994Sdesgetloginname()
8361590Srgrimes{
83721528Sdavidn	int ch;
83821528Sdavidn	char *p;
83921528Sdavidn	static char nbuf[NBUFSIZ];
84089994Sdes
84189994Sdes	for (;;) {
84289994Sdes		(void)printf("login: ");
84389994Sdes		for (p = nbuf; (ch = getchar()) != '\n'; ) {
84489994Sdes			if (ch == EOF) {
84521528Sdavidn				badlogin(username);
8461590Srgrimes				exit(0);
84789994Sdes			}
84889994Sdes			if (p < nbuf + (NBUFSIZ - 1))
8491590Srgrimes				*p++ = ch;
85089994Sdes		}
85189994Sdes		if (p > nbuf)
85221528Sdavidn			if (nbuf[0] == '-')
8531590Srgrimes				(void)fprintf(stderr,
85489994Sdes				    "login names may not start with '-'.\n");
85589994Sdes			else {
85689994Sdes				*p = '\0';
85789994Sdes				username = nbuf;
85889994Sdes				break;
85989994Sdes			}
86089994Sdes	}
86189994Sdes}
86289994Sdes
8631590Srgrimesint
8641590Srgrimesrootterm(ttyn)
86589994Sdes	char *ttyn;
86689994Sdes{
86789994Sdes	struct ttyent *t;
86889994Sdes
86989994Sdes	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
87089994Sdes}
87189994Sdes
87289994Sdesvolatile int motdinterrupt;
87389994Sdes
87489994Sdes/* ARGSUSED */
8751590Srgrimesvoid
87676788Sobriensigint(signo)
87742272Seivind	int signo;
8781590Srgrimes{
8791590Srgrimes	motdinterrupt = 1;
880105164Sphk}
88189994Sdes
8821590Srgrimesvoid
8831590Srgrimesmotd(motdfile)
8841590Srgrimes	char *motdfile;
8851590Srgrimes{
88689994Sdes	int fd, nchars;
8871590Srgrimes	sig_t oldint;
88889994Sdes	char tbuf[256];
8891590Srgrimes
8901590Srgrimes	if ((fd = open(motdfile, O_RDONLY, 0)) < 0)
89189994Sdes		return;
8921590Srgrimes	motdinterrupt = 0;
8931590Srgrimes	oldint = signal(SIGINT, sigint);
8941590Srgrimes	while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0 && !motdinterrupt)
8951590Srgrimes		(void)write(fileno(stdout), tbuf, nchars);
8961590Srgrimes	(void)signal(SIGINT, oldint);
8971590Srgrimes	(void)close(fd);
8981590Srgrimes}
89942272Seivind
9001590Srgrimes/* ARGSUSED */
9011590Srgrimesvoid
90287173Smarkmtimedout(signo)
90389994Sdes	int signo;
9041590Srgrimes{
9051590Srgrimes	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
90623985Sdavidn	exit(0);
90781555Smike}
90881555Smike
90981555Smike#ifndef LOGIN_CAP
91081555Smikevoid
91181555Smikechecknologin()
91298960Sache{
9131590Srgrimes	int fd, nchars;
9141590Srgrimes	char tbuf[8192];
915105164Sphk
91689994Sdes	if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
91723985Sdavidn		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
91823985Sdavidn			(void)write(fileno(stdout), tbuf, nchars);
91923985Sdavidn		sleepexit(0);
92023985Sdavidn	}
92189994Sdes}
92223985Sdavidn#endif
92389994Sdes
92423985Sdavidnvoid
92523985Sdavidndolastlog(quiet)
92676788Sobrien	int quiet;
92723985Sdavidn{
92889994Sdes	struct lastlog ll;
92923985Sdavidn	int fd;
93023985Sdavidn
93189994Sdes	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
93289994Sdes		(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
93389994Sdes		if (!quiet) {
934105164Sphk			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
93589994Sdes			    ll.ll_time != 0) {
9361590Srgrimes				(void)printf("Last login: %.*s ",
93789994Sdes				    24-5, (char *)ctime(&ll.ll_time));
93889994Sdes				if (*ll.ll_host != '\0')
93923985Sdavidn					(void)printf("from %.*s\n",
94089994Sdes					    (int)sizeof(ll.ll_host),
94189994Sdes					    ll.ll_host);
94289994Sdes				else
943105164Sphk					(void)printf("on %.*s\n",
94489994Sdes					    (int)sizeof(ll.ll_line),
94589994Sdes					    ll.ll_line);
94689994Sdes			}
94789994Sdes			(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
94889994Sdes		}
94989994Sdes		memset((void *)&ll, 0, sizeof(ll));
95089994Sdes		(void)time(&ll.ll_time);
95189994Sdes		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
95289994Sdes		if (hostname)
95389994Sdes			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
95489994Sdes		(void)write(fd, (char *)&ll, sizeof(ll));
95589994Sdes		(void)close(fd);
95689994Sdes	}
95789994Sdes}
95889994Sdes
95989994Sdesvoid
96089994Sdesbadlogin(name)
96189994Sdes	char *name;
96289994Sdes{
96389994Sdes
96489994Sdes	if (failures == 0)
96589994Sdes		return;
96689994Sdes	if (hostname) {
96789994Sdes		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
96889994Sdes		    failures, failures > 1 ? "S" : "", full_hostname);
96989994Sdes		syslog(LOG_AUTHPRIV|LOG_NOTICE,
97089994Sdes		    "%d LOGIN FAILURE%s FROM %s, %s",
97189994Sdes		    failures, failures > 1 ? "S" : "", full_hostname, name);
97289994Sdes	} else {
973165152Scsjp		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
974157215Scognet		    failures, failures > 1 ? "S" : "", tty);
975157215Scognet		syslog(LOG_AUTHPRIV|LOG_NOTICE,
976165152Scsjp		    "%d LOGIN FAILURE%s ON %s, %s",
97789994Sdes		    failures, failures > 1 ? "S" : "", tty, name);
9781590Srgrimes	}
9791590Srgrimes}
980
981#undef	UNKNOWN
982#define	UNKNOWN	"su"
983
984char *
985stypeof(ttyid)
986	char *ttyid;
987{
988
989	struct ttyent *t;
990
991	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
992}
993
994void
995refused(msg, rtype, lout)
996	char *msg;
997	char *rtype;
998	int lout;
999{
1000
1001	if (msg != NULL)
1002	    printf("%s.\n", msg);
1003	if (hostname)
1004		syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) FROM %s ON TTY %s",
1005		       pwd->pw_name, rtype, full_hostname, tty);
1006	else
1007		syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) ON TTY %s",
1008		       pwd->pw_name, rtype, tty);
1009	if (lout)
1010		sleepexit(1);
1011}
1012
1013void
1014sleepexit(eval)
1015	int eval;
1016{
1017
1018	(void)sleep(5);
1019	exit(eval);
1020}
1021