Home | History | Annotate | Line # | Download | only in login
login.c revision 1.50
      1  1.49       mjl /*     $NetBSD: login.c,v 1.50 2000/01/13 06:52:47 mjl Exp $       */
      2  1.12       jtc 
      3   1.1       cgd /*-
      4  1.12       jtc  * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
      5  1.10    brezak  *	The Regents of the University of California.  All rights reserved.
      6   1.1       cgd  *
      7   1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8   1.1       cgd  * modification, are permitted provided that the following conditions
      9   1.1       cgd  * are met:
     10   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     16   1.1       cgd  *    must display the following acknowledgement:
     17   1.1       cgd  *	This product includes software developed by the University of
     18   1.1       cgd  *	California, Berkeley and its contributors.
     19   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     20   1.1       cgd  *    may be used to endorse or promote products derived from this software
     21   1.1       cgd  *    without specific prior written permission.
     22   1.1       cgd  *
     23   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33   1.1       cgd  * SUCH DAMAGE.
     34   1.1       cgd  */
     35   1.1       cgd 
     36  1.24     lukem #include <sys/cdefs.h>
     37   1.1       cgd #ifndef lint
     38  1.24     lukem __COPYRIGHT(
     39  1.12       jtc "@(#) Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994\n\
     40  1.24     lukem 	The Regents of the University of California.  All rights reserved.\n");
     41   1.1       cgd #endif /* not lint */
     42   1.1       cgd 
     43   1.1       cgd #ifndef lint
     44  1.12       jtc #if 0
     45  1.12       jtc static char sccsid[] = "@(#)login.c	8.4 (Berkeley) 4/2/94";
     46  1.12       jtc #endif
     47  1.49       mjl __RCSID("$NetBSD: login.c,v 1.50 2000/01/13 06:52:47 mjl Exp $");
     48   1.1       cgd #endif /* not lint */
     49   1.1       cgd 
     50   1.1       cgd /*
     51   1.1       cgd  * login [ name ]
     52   1.1       cgd  * login -h hostname	(for telnetd, etc.)
     53   1.1       cgd  * login -f name	(for pre-authenticated login: datakit, xterm, etc.)
     54   1.1       cgd  */
     55   1.1       cgd 
     56   1.1       cgd #include <sys/param.h>
     57   1.1       cgd #include <sys/stat.h>
     58   1.1       cgd #include <sys/time.h>
     59   1.1       cgd #include <sys/resource.h>
     60   1.1       cgd #include <sys/file.h>
     61  1.38       mrg #include <sys/wait.h>
     62   1.1       cgd 
     63  1.12       jtc #include <err.h>
     64   1.5       cgd #include <errno.h>
     65   1.1       cgd #include <grp.h>
     66   1.1       cgd #include <pwd.h>
     67  1.12       jtc #include <setjmp.h>
     68  1.12       jtc #include <signal.h>
     69  1.19     veego #include <stdio.h>
     70   1.5       cgd #include <stdlib.h>
     71   1.1       cgd #include <string.h>
     72  1.12       jtc #include <syslog.h>
     73  1.36    kleink #include <time.h>
     74  1.12       jtc #include <ttyent.h>
     75  1.12       jtc #include <tzfile.h>
     76  1.12       jtc #include <unistd.h>
     77  1.12       jtc #include <utmp.h>
     78  1.13       jtc #include <util.h>
     79  1.29   mycroft #ifdef SKEY
     80  1.29   mycroft #include <skey.h>
     81  1.29   mycroft #endif
     82  1.25   mycroft #ifdef KERBEROS5
     83  1.45  christos #include <krb5/krb5.h>
     84  1.45  christos #include <kerberosIV/com_err.h>
     85  1.25   mycroft #endif
     86  1.48       mjl #ifdef LOGIN_CAP
     87  1.48       mjl #include <login_cap.h>
     88  1.48       mjl #endif
     89  1.25   mycroft 
     90   1.1       cgd #include "pathnames.h"
     91   1.1       cgd 
     92   1.5       cgd void	 badlogin __P((char *));
     93  1.48       mjl void	 checknologin __P((char *));
     94   1.5       cgd void	 dolastlog __P((int));
     95   1.5       cgd void	 getloginname __P((void));
     96  1.24     lukem int	 main __P((int, char *[]));
     97  1.48       mjl void	 motd __P((char *));
     98   1.5       cgd int	 rootterm __P((char *));
     99   1.5       cgd void	 sigint __P((int));
    100   1.5       cgd void	 sleepexit __P((int));
    101  1.39   mycroft const	 char *stypeof __P((const char *));
    102   1.5       cgd void	 timedout __P((int));
    103  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    104   1.5       cgd int	 klogin __P((struct passwd *, char *, char *, char *));
    105  1.12       jtc void	 kdestroy __P((void));
    106  1.12       jtc void	 dofork __P((void));
    107   1.5       cgd #endif
    108  1.44     aidan #ifdef KERBEROS5
    109  1.44     aidan int	k5_read_creds __P((char*));
    110  1.44     aidan int	k5_write_creds __P((void));
    111  1.44     aidan #endif
    112  1.12       jtc 
    113   1.1       cgd #define	TTYGRPNAME	"tty"		/* name of group to own ttys */
    114   1.1       cgd 
    115  1.50       mjl #define DEFAULT_BACKOFF 3
    116  1.50       mjl #define DEFAULT_RETRIES 10
    117  1.48       mjl 
    118   1.1       cgd /*
    119   1.1       cgd  * This bounds the time given to login.  Not a define so it can
    120   1.1       cgd  * be patched on machines where it's too small.
    121   1.1       cgd  */
    122  1.12       jtc u_int	timeout = 300;
    123   1.5       cgd 
    124  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    125   1.1       cgd int	notickets = 1;
    126   1.1       cgd char	*instance;
    127  1.12       jtc char	*krbtkfile_env;
    128   1.1       cgd #endif
    129  1.25   mycroft #ifdef KERBEROS5
    130  1.25   mycroft extern krb5_context kcontext;
    131  1.44     aidan extern int	have_forward;
    132  1.46     aidan extern int	use_krb5;
    133  1.25   mycroft #endif
    134   1.1       cgd 
    135   1.1       cgd struct	passwd *pwd;
    136   1.1       cgd int	failures;
    137   1.1       cgd char	term[64], *envinit[1], *hostname, *username, *tty;
    138   1.1       cgd 
    139  1.34   thorpej static const char copyrightstr[] = "\
    140  1.47     billc Copyright (c) 1996, 1997, 1998, 1999, 2000
    141  1.34   thorpej \tThe NetBSD Foundation, Inc.  All rights reserved.
    142  1.34   thorpej Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
    143  1.34   thorpej \tThe Regents of the University of California.  All rights reserved.\n\n";
    144  1.34   thorpej 
    145   1.5       cgd int
    146   1.1       cgd main(argc, argv)
    147   1.1       cgd 	int argc;
    148   1.5       cgd 	char *argv[];
    149   1.1       cgd {
    150   1.5       cgd 	extern char **environ;
    151   1.5       cgd 	struct group *gr;
    152   1.5       cgd 	struct stat st;
    153   1.5       cgd 	struct timeval tp;
    154   1.5       cgd 	struct utmp utmp;
    155  1.29   mycroft 	int ask, ch, cnt, fflag, hflag, pflag, sflag, quietlog, rootlogin, rval;
    156  1.44     aidan 	int Fflag;
    157  1.33   hubertf 	uid_t uid, saved_uid;
    158  1.35   hubertf 	gid_t saved_gid, saved_gids[NGROUPS_MAX];
    159  1.35   hubertf 	int nsaved_gids;
    160  1.39   mycroft 	char *domain, *p, *ttyn, *pwprompt;
    161  1.39   mycroft 	const char *salt;
    162   1.1       cgd 	char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
    163  1.37       mrg 	char localhost[MAXHOSTNAMELEN + 1];
    164  1.29   mycroft 	int need_chpass, require_chpass;
    165  1.48       mjl 	int login_retries = DEFAULT_RETRIES,
    166  1.48       mjl 	    login_backoff = DEFAULT_BACKOFF;
    167  1.48       mjl 	time_t pw_warntime = _PASSWORD_WARNDAYS * SECSPERDAY;
    168  1.25   mycroft #ifdef KERBEROS5
    169  1.25   mycroft 	krb5_error_code kerror;
    170  1.25   mycroft #endif
    171  1.48       mjl #ifdef LOGIN_CAP
    172  1.49       mjl 	char *shell = NULL;
    173  1.48       mjl 	login_cap_t *lc = NULL;
    174  1.48       mjl #endif
    175   1.1       cgd 
    176  1.20     lukem 	tbuf[0] = '\0';
    177  1.20     lukem 	rval = 0;
    178  1.20     lukem 	pwprompt = NULL;
    179  1.29   mycroft 	need_chpass = require_chpass = 0;
    180  1.20     lukem 
    181   1.1       cgd 	(void)signal(SIGALRM, timedout);
    182  1.12       jtc 	(void)alarm(timeout);
    183   1.1       cgd 	(void)signal(SIGQUIT, SIG_IGN);
    184   1.1       cgd 	(void)signal(SIGINT, SIG_IGN);
    185   1.1       cgd 	(void)setpriority(PRIO_PROCESS, 0, 0);
    186   1.1       cgd 
    187   1.1       cgd 	openlog("login", LOG_ODELAY, LOG_AUTH);
    188   1.1       cgd 
    189   1.1       cgd 	/*
    190   1.1       cgd 	 * -p is used by getty to tell login not to destroy the environment
    191   1.5       cgd 	 * -f is used to skip a second login authentication
    192   1.1       cgd 	 * -h is used by other servers to pass the name of the remote
    193   1.1       cgd 	 *    host to login so that it may be placed in utmp and wtmp
    194  1.20     lukem 	 * -s is used to force use of S/Key or equivalent.
    195   1.1       cgd 	 */
    196   1.1       cgd 	domain = NULL;
    197   1.1       cgd 	if (gethostname(localhost, sizeof(localhost)) < 0)
    198   1.1       cgd 		syslog(LOG_ERR, "couldn't get local hostname: %m");
    199   1.1       cgd 	else
    200  1.12       jtc 		domain = strchr(localhost, '.');
    201  1.37       mrg 	localhost[sizeof(localhost) - 1] = '\0';
    202   1.1       cgd 
    203  1.44     aidan 	Fflag = fflag = hflag = pflag = sflag = 0;
    204  1.44     aidan #ifdef KERBEROS5
    205  1.44     aidan 	have_forward = 0;
    206  1.46     aidan 	use_krb5 = 1;
    207  1.44     aidan #endif
    208   1.1       cgd 	uid = getuid();
    209  1.44     aidan 	while ((ch = getopt(argc, argv, "Ffh:ps")) != -1)
    210   1.1       cgd 		switch (ch) {
    211  1.44     aidan 		case 'F':
    212  1.44     aidan 			Fflag = 1;
    213  1.44     aidan 			/* FALLTHROUGH */
    214   1.1       cgd 		case 'f':
    215   1.1       cgd 			fflag = 1;
    216   1.1       cgd 			break;
    217   1.1       cgd 		case 'h':
    218  1.12       jtc 			if (uid)
    219  1.12       jtc 				errx(1, "-h option: %s", strerror(EPERM));
    220   1.1       cgd 			hflag = 1;
    221  1.23     mikel 			if (domain && (p = strchr(optarg, '.')) != NULL &&
    222   1.1       cgd 			    strcasecmp(p, domain) == 0)
    223   1.1       cgd 				*p = 0;
    224   1.1       cgd 			hostname = optarg;
    225   1.1       cgd 			break;
    226   1.1       cgd 		case 'p':
    227   1.1       cgd 			pflag = 1;
    228   1.1       cgd 			break;
    229  1.20     lukem 		case 's':
    230  1.29   mycroft 			sflag = 1;
    231  1.20     lukem 			break;
    232  1.29   mycroft 		default:
    233   1.1       cgd 		case '?':
    234   1.1       cgd 			(void)fprintf(stderr,
    235  1.29   mycroft 			    "usage: login [-fps] [-h hostname] [username]\n");
    236   1.1       cgd 			exit(1);
    237   1.1       cgd 		}
    238   1.1       cgd 	argc -= optind;
    239   1.1       cgd 	argv += optind;
    240   1.5       cgd 
    241   1.1       cgd 	if (*argv) {
    242   1.1       cgd 		username = *argv;
    243   1.1       cgd 		ask = 0;
    244   1.1       cgd 	} else
    245   1.1       cgd 		ask = 1;
    246   1.1       cgd 
    247   1.1       cgd 	for (cnt = getdtablesize(); cnt > 2; cnt--)
    248   1.5       cgd 		(void)close(cnt);
    249   1.1       cgd 
    250   1.5       cgd 	ttyn = ttyname(STDIN_FILENO);
    251   1.1       cgd 	if (ttyn == NULL || *ttyn == '\0') {
    252   1.5       cgd 		(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
    253   1.1       cgd 		ttyn = tname;
    254   1.1       cgd 	}
    255  1.23     mikel 	if ((tty = strrchr(ttyn, '/')) != NULL)
    256   1.1       cgd 		++tty;
    257   1.1       cgd 	else
    258   1.1       cgd 		tty = ttyn;
    259  1.25   mycroft 
    260  1.48       mjl #ifdef LOGIN_CAP
    261  1.48       mjl 	/* Get "login-retries" and "login-backoff" from default class */
    262  1.48       mjl 	if((lc = login_getclass(NULL)))
    263  1.48       mjl 		{
    264  1.48       mjl 		login_retries = (int) login_getcapnum(lc, "login-retries",
    265  1.48       mjl 					DEFAULT_RETRIES, DEFAULT_RETRIES);
    266  1.48       mjl 		login_backoff = (int) login_getcapnum(lc, "login-backoff",
    267  1.48       mjl 					DEFAULT_BACKOFF, DEFAULT_BACKOFF);
    268  1.48       mjl 		login_close(lc);
    269  1.48       mjl 		lc = NULL;
    270  1.48       mjl 		}
    271  1.48       mjl #endif
    272  1.48       mjl 
    273  1.25   mycroft #ifdef KERBEROS5
    274  1.25   mycroft 	kerror = krb5_init_context(&kcontext);
    275  1.25   mycroft 	if (kerror) {
    276  1.25   mycroft 		syslog(LOG_NOTICE, "%s when initializing Kerberos context",
    277  1.25   mycroft 		    error_message(kerror));
    278  1.46     aidan 		use_krb5 = 0;
    279  1.25   mycroft 	}
    280  1.25   mycroft #endif KERBEROS5
    281   1.1       cgd 
    282   1.1       cgd 	for (cnt = 0;; ask = 1) {
    283  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    284  1.10    brezak 	        kdestroy();
    285  1.10    brezak #endif
    286   1.1       cgd 		if (ask) {
    287   1.1       cgd 			fflag = 0;
    288   1.1       cgd 			getloginname();
    289   1.1       cgd 		}
    290   1.5       cgd 		rootlogin = 0;
    291  1.29   mycroft #ifdef KERBEROS
    292  1.29   mycroft 		if ((instance = strchr(username, '.')) != NULL)
    293   1.1       cgd 			*instance++ = '\0';
    294  1.29   mycroft 		else
    295   1.1       cgd 			instance = "";
    296   1.1       cgd #endif
    297  1.10    brezak #ifdef KERBEROS5
    298  1.29   mycroft 		if ((instance = strchr(username, '/')) != NULL)
    299  1.10    brezak 			*instance++ = '\0';
    300  1.29   mycroft 		else
    301  1.10    brezak 			instance = "";
    302  1.10    brezak #endif
    303  1.16  sommerfe 		if (strlen(username) > MAXLOGNAME)
    304  1.16  sommerfe 			username[MAXLOGNAME] = '\0';
    305   1.1       cgd 
    306   1.1       cgd 		/*
    307   1.1       cgd 		 * Note if trying multiple user names; log failures for
    308   1.1       cgd 		 * previous user name, but don't bother logging one failure
    309   1.1       cgd 		 * for nonexistent name (mistyped username).
    310   1.1       cgd 		 */
    311   1.1       cgd 		if (failures && strcmp(tbuf, username)) {
    312   1.1       cgd 			if (failures > (pwd ? 0 : 1))
    313   1.1       cgd 				badlogin(tbuf);
    314   1.1       cgd 			failures = 0;
    315   1.1       cgd 		}
    316  1.17       mrg 		(void)strncpy(tbuf, username, sizeof(tbuf) - 1);
    317  1.38       mrg 		tbuf[sizeof(tbuf) - 1] = '\0';
    318   1.1       cgd 
    319  1.23     mikel 		if ((pwd = getpwnam(username)) != NULL)
    320   1.1       cgd 			salt = pwd->pw_passwd;
    321   1.1       cgd 		else
    322   1.1       cgd 			salt = "xx";
    323   1.1       cgd 
    324  1.48       mjl #ifdef LOGIN_CAP
    325  1.48       mjl 		/*
    326  1.48       mjl 		 * Establish the class now, before we might goto
    327  1.48       mjl 		 * within the next block. pwd can be NULL since it
    328  1.48       mjl                  * falls back to the "default" class if it is.
    329  1.48       mjl                  */
    330  1.48       mjl 		if (pwd != NULL)
    331  1.48       mjl                 	lc = login_getclass(pwd->pw_class);
    332  1.48       mjl #endif
    333   1.1       cgd 		/*
    334   1.1       cgd 		 * if we have a valid account name, and it doesn't have a
    335   1.1       cgd 		 * password, or the -f option was specified and the caller
    336   1.1       cgd 		 * is root or the caller isn't changing their uid, don't
    337   1.1       cgd 		 * authenticate.
    338   1.1       cgd 		 */
    339   1.7   mycroft 		if (pwd) {
    340   1.7   mycroft 			if (pwd->pw_uid == 0)
    341   1.7   mycroft 				rootlogin = 1;
    342   1.7   mycroft 
    343   1.8   mycroft 			if (fflag && (uid == 0 || uid == pwd->pw_uid)) {
    344   1.7   mycroft 				/* already authenticated */
    345  1.44     aidan #ifdef KERBEROS5
    346  1.44     aidan 				if (Fflag)
    347  1.44     aidan 					k5_read_creds(username);
    348  1.44     aidan #endif
    349   1.7   mycroft 				break;
    350   1.7   mycroft 			} else if (pwd->pw_passwd[0] == '\0') {
    351   1.7   mycroft 				/* pretend password okay */
    352   1.7   mycroft 				rval = 0;
    353   1.7   mycroft 				goto ttycheck;
    354   1.7   mycroft 			}
    355   1.7   mycroft 		}
    356   1.7   mycroft 
    357   1.1       cgd 		fflag = 0;
    358   1.1       cgd 
    359   1.1       cgd 		(void)setpriority(PRIO_PROCESS, 0, -4);
    360   1.1       cgd 
    361  1.27   mycroft #ifdef SKEY
    362  1.29   mycroft 		if (skey_haskey(username) == 0) {
    363  1.29   mycroft 			static char skprompt[80];
    364  1.29   mycroft 			char *skinfo = skey_keyinfo(username);
    365  1.20     lukem 
    366  1.29   mycroft 			(void)snprintf(skprompt, sizeof(skprompt)-1,
    367  1.29   mycroft 			    "Password [%s]:",
    368  1.29   mycroft 			    skinfo ? skinfo : "error getting challenge");
    369  1.29   mycroft 			pwprompt = skprompt;
    370  1.29   mycroft 		} else
    371  1.27   mycroft #endif
    372  1.29   mycroft 			pwprompt = "Password:";
    373  1.27   mycroft 
    374  1.29   mycroft 		p = getpass(pwprompt);
    375   1.1       cgd 
    376  1.29   mycroft 		if (pwd == NULL) {
    377  1.29   mycroft 			rval = 1;
    378  1.29   mycroft 			goto skip;
    379  1.29   mycroft 		}
    380  1.29   mycroft #ifdef KERBEROS
    381  1.29   mycroft 		if (klogin(pwd, instance, localhost, p) == 0) {
    382  1.29   mycroft 			rval = 0;
    383  1.29   mycroft 			goto skip;
    384  1.29   mycroft 		}
    385   1.1       cgd #endif
    386  1.29   mycroft #ifdef KERBEROS5
    387  1.29   mycroft 		if (klogin(pwd, instance, localhost, p) == 0) {
    388  1.29   mycroft 			rval = 0;
    389  1.29   mycroft 			goto skip;
    390   1.1       cgd 		}
    391  1.29   mycroft #endif
    392  1.20     lukem #ifdef SKEY
    393  1.29   mycroft 		if (skey_haskey(username) == 0 &&
    394  1.29   mycroft 		    skey_passcheck(username, p) != -1) {
    395  1.29   mycroft 			rval = 0;
    396  1.29   mycroft 			goto skip;
    397  1.29   mycroft 		}
    398  1.20     lukem #endif
    399  1.29   mycroft 		if (!sflag && *pwd->pw_passwd != '\0' &&
    400  1.29   mycroft 		    !strcmp(crypt(p, pwd->pw_passwd), pwd->pw_passwd)) {
    401  1.29   mycroft 			rval = 0;
    402  1.29   mycroft 			require_chpass = 1;
    403  1.29   mycroft 			goto skip;
    404  1.29   mycroft 		}
    405  1.29   mycroft 		rval = 1;
    406  1.29   mycroft 
    407  1.29   mycroft 	skip:
    408  1.29   mycroft 		memset(p, 0, strlen(p));
    409   1.1       cgd 
    410   1.1       cgd 		(void)setpriority(PRIO_PROCESS, 0, 0);
    411   1.1       cgd 
    412   1.7   mycroft 	ttycheck:
    413   1.1       cgd 		/*
    414   1.1       cgd 		 * If trying to log in as root without Kerberos,
    415   1.1       cgd 		 * but with insecure terminal, refuse the login attempt.
    416   1.1       cgd 		 */
    417   1.7   mycroft 		if (pwd && !rval && rootlogin && !rootterm(tty)) {
    418   1.1       cgd 			(void)fprintf(stderr,
    419   1.1       cgd 			    "%s login refused on this terminal.\n",
    420   1.1       cgd 			    pwd->pw_name);
    421   1.1       cgd 			if (hostname)
    422   1.1       cgd 				syslog(LOG_NOTICE,
    423   1.1       cgd 				    "LOGIN %s REFUSED FROM %s ON TTY %s",
    424   1.1       cgd 				    pwd->pw_name, hostname, tty);
    425   1.1       cgd 			else
    426   1.1       cgd 				syslog(LOG_NOTICE,
    427   1.1       cgd 				    "LOGIN %s REFUSED ON TTY %s",
    428   1.1       cgd 				     pwd->pw_name, tty);
    429   1.1       cgd 			continue;
    430   1.1       cgd 		}
    431   1.1       cgd 
    432   1.1       cgd 		if (pwd && !rval)
    433   1.1       cgd 			break;
    434   1.1       cgd 
    435   1.1       cgd 		(void)printf("Login incorrect\n");
    436   1.1       cgd 		failures++;
    437  1.48       mjl 		cnt++;
    438   1.1       cgd 		/* we allow 10 tries, but after 3 we start backing off */
    439  1.50       mjl 		if (cnt > login_backoff) {
    440  1.48       mjl 			if (cnt >= login_retries) {
    441   1.1       cgd 				badlogin(username);
    442   1.1       cgd 				sleepexit(1);
    443   1.1       cgd 			}
    444   1.1       cgd 			sleep((u_int)((cnt - 3) * 5));
    445   1.1       cgd 		}
    446   1.1       cgd 	}
    447   1.1       cgd 
    448   1.1       cgd 	/* committed to login -- turn off timeout */
    449   1.1       cgd 	(void)alarm((u_int)0);
    450   1.1       cgd 
    451   1.1       cgd 	endpwent();
    452   1.1       cgd 
    453   1.1       cgd 	/* if user not super-user, check for disabled logins */
    454  1.48       mjl #ifdef LOGIN_CAP
    455  1.48       mjl         if (!rootlogin || login_getcapbool(lc, "ignorenologin", 0)) {
    456  1.48       mjl 		char *fname;
    457  1.48       mjl 
    458  1.48       mjl 		fname = login_getcapstr(lc, "nologin", NULL, NULL);
    459  1.48       mjl                 checknologin(fname);
    460  1.48       mjl 	}
    461  1.48       mjl #else
    462  1.48       mjl         if (!rootlogin)
    463  1.48       mjl                 checknologin(NULL);
    464  1.48       mjl #endif
    465   1.1       cgd 
    466  1.48       mjl #ifdef LOGIN_CAP
    467  1.48       mjl         quietlog = login_getcapbool(lc, "hushlogin", 0);
    468  1.48       mjl #else
    469  1.48       mjl         quietlog = 0;
    470  1.48       mjl #endif
    471  1.33   hubertf 	/* Temporarily give up special privileges so we can change */
    472  1.33   hubertf 	/* into NFS-mounted homes that are exported for non-root */
    473  1.33   hubertf 	/* access and have mode 7x0 */
    474  1.33   hubertf 	saved_uid = geteuid();
    475  1.35   hubertf 	saved_gid = getegid();
    476  1.35   hubertf 	nsaved_gids = getgroups(NGROUPS_MAX, saved_gids);
    477  1.35   hubertf 
    478  1.35   hubertf 	(void)setegid(pwd->pw_gid);
    479  1.35   hubertf 	initgroups(username, pwd->pw_gid);
    480  1.35   hubertf 	(void)seteuid(pwd->pw_uid);
    481  1.33   hubertf 
    482   1.1       cgd 	if (chdir(pwd->pw_dir) < 0) {
    483  1.48       mjl #ifdef LOGIN_CAP
    484  1.48       mjl                 if (login_getcapbool(lc, "requirehome", 0)) {
    485  1.48       mjl 			(void) printf("Home directory %s required\n", pwd->pw_dir);
    486  1.48       mjl                         sleepexit(1);
    487  1.48       mjl 		}
    488  1.48       mjl #endif
    489   1.1       cgd 		(void)printf("No home directory %s!\n", pwd->pw_dir);
    490   1.1       cgd 		if (chdir("/"))
    491   1.1       cgd 			exit(0);
    492   1.1       cgd 		pwd->pw_dir = "/";
    493   1.1       cgd 		(void)printf("Logging in with home = \"/\".\n");
    494   1.1       cgd 	}
    495   1.1       cgd 
    496  1.48       mjl 	if(!quietlog)
    497  1.48       mjl 		quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
    498  1.33   hubertf 
    499  1.33   hubertf 	/* regain special privileges */
    500  1.33   hubertf 	(void)seteuid(saved_uid);
    501  1.35   hubertf 	setgroups(nsaved_gids, saved_gids);
    502  1.35   hubertf 	(void)setegid(saved_gid);
    503   1.1       cgd 
    504  1.48       mjl #ifdef LOGIN_CAP
    505  1.48       mjl         pw_warntime = login_getcaptime(lc, "password-warn",
    506  1.48       mjl                                     _PASSWORD_WARNDAYS * SECSPERDAY,
    507  1.48       mjl                                     _PASSWORD_WARNDAYS * SECSPERDAY);
    508  1.48       mjl #endif
    509  1.48       mjl 
    510   1.1       cgd 	if (pwd->pw_change || pwd->pw_expire)
    511   1.1       cgd 		(void)gettimeofday(&tp, (struct timezone *)NULL);
    512  1.40      ross 	if (pwd->pw_expire) {
    513   1.1       cgd 		if (tp.tv_sec >= pwd->pw_expire) {
    514   1.1       cgd 			(void)printf("Sorry -- your account has expired.\n");
    515   1.1       cgd 			sleepexit(1);
    516  1.48       mjl 		} else if (pwd->pw_expire - tp.tv_sec < pw_warntime &&
    517  1.48       mjl 			   !quietlog)
    518   1.1       cgd 			(void)printf("Warning: your account expires on %s",
    519   1.1       cgd 			    ctime(&pwd->pw_expire));
    520  1.40      ross 	}
    521  1.40      ross 	if (pwd->pw_change) {
    522  1.30   mycroft 		if (pwd->pw_change == _PASSWORD_CHGNOW)
    523  1.30   mycroft 			need_chpass = 1;
    524  1.31   mycroft 		else if (tp.tv_sec >= pwd->pw_change) {
    525  1.31   mycroft 			(void)printf("Sorry -- your password has expired.\n");
    526  1.31   mycroft 			sleepexit(1);
    527  1.48       mjl 		} else if (pwd->pw_change - tp.tv_sec < pw_warntime &&
    528  1.48       mjl 			   !quietlog)
    529  1.30   mycroft 			(void)printf("Warning: your password expires on %s",
    530  1.30   mycroft 			    ctime(&pwd->pw_change));
    531   1.1       cgd 
    532  1.40      ross 	}
    533   1.5       cgd 	/* Nothing else left to fail -- really log in. */
    534  1.12       jtc 	memset((void *)&utmp, 0, sizeof(utmp));
    535   1.5       cgd 	(void)time(&utmp.ut_time);
    536   1.5       cgd 	(void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
    537   1.5       cgd 	if (hostname)
    538   1.5       cgd 		(void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
    539   1.5       cgd 	(void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
    540   1.5       cgd 	login(&utmp);
    541   1.1       cgd 
    542   1.1       cgd 	dolastlog(quietlog);
    543   1.1       cgd 
    544   1.1       cgd 	(void)chown(ttyn, pwd->pw_uid,
    545   1.1       cgd 	    (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
    546  1.15       gwr 
    547  1.15       gwr 	if (ttyaction(ttyn, "login", pwd->pw_name))
    548  1.15       gwr 		(void)printf("Warning: ttyaction failed.\n");
    549  1.15       gwr 
    550  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    551  1.10    brezak 	/* Fork so that we can call kdestroy */
    552  1.10    brezak 	if (krbtkfile_env)
    553  1.29   mycroft 		dofork();
    554  1.10    brezak #endif
    555  1.48       mjl #ifdef LOGIN_CAP
    556  1.50       mjl 	if(lc) {
    557  1.50       mjl 		if (setusercontext(lc, pwd, pwd->pw_uid,
    558  1.50       mjl 		    LOGIN_SETALL & ~LOGIN_SETPATH) != 0) {
    559  1.50       mjl 			syslog(LOG_ERR, "setusercontext failed");
    560  1.50       mjl 			exit(1);
    561  1.50       mjl 		}
    562  1.48       mjl 	}
    563  1.50       mjl 	else
    564  1.50       mjl #endif
    565  1.50       mjl 	{
    566   1.1       cgd 	(void)setgid(pwd->pw_gid);
    567   1.1       cgd 
    568   1.1       cgd 	initgroups(username, pwd->pw_gid);
    569  1.48       mjl 
    570  1.48       mjl 	if (setlogin(pwd->pw_name) < 0)
    571  1.48       mjl 		syslog(LOG_ERR, "setlogin() failure: %m");
    572  1.48       mjl 
    573  1.48       mjl 	/* Discard permissions last so can't get killed and drop core. */
    574  1.48       mjl 	if (rootlogin)
    575  1.48       mjl 		(void)setuid(0);
    576  1.48       mjl 	else
    577  1.48       mjl 		(void)setuid(pwd->pw_uid);
    578  1.50       mjl 	}
    579  1.48       mjl 
    580   1.1       cgd 
    581   1.1       cgd 	if (*pwd->pw_shell == '\0')
    582   1.1       cgd 		pwd->pw_shell = _PATH_BSHELL;
    583  1.48       mjl #ifdef LOGIN_CAP
    584  1.48       mjl 	if((shell = login_getcapstr(lc, "shell", NULL, NULL))) {
    585  1.48       mjl 		if(!(shell = strdup(shell))) {
    586  1.48       mjl                 	syslog(LOG_NOTICE, "Cannot alloc mem");
    587  1.48       mjl                 	sleepexit(1);
    588  1.48       mjl 		}
    589  1.48       mjl 		pwd->pw_shell = shell;
    590  1.48       mjl 	}
    591  1.48       mjl #endif
    592  1.48       mjl 
    593   1.5       cgd 	/* Destroy environment unless user has requested its preservation. */
    594   1.1       cgd 	if (!pflag)
    595   1.1       cgd 		environ = envinit;
    596   1.1       cgd 	(void)setenv("HOME", pwd->pw_dir, 1);
    597   1.1       cgd 	(void)setenv("SHELL", pwd->pw_shell, 1);
    598  1.48       mjl 	if (term[0] == '\0') {
    599  1.48       mjl 		char *tt = (char *) stypeof(tty);
    600  1.48       mjl #ifdef LOGIN_CAP
    601  1.48       mjl 		if(!tt)
    602  1.48       mjl 			tt = login_getcapstr(lc, "term", NULL, NULL);
    603  1.48       mjl #endif
    604  1.48       mjl 		/* unknown term -> "su" */
    605  1.48       mjl 		(void)strncpy(term, tt ? tt : "su", sizeof(term));
    606  1.48       mjl 		}
    607   1.1       cgd 	(void)setenv("TERM", term, 0);
    608   1.1       cgd 	(void)setenv("LOGNAME", pwd->pw_name, 1);
    609   1.1       cgd 	(void)setenv("USER", pwd->pw_name, 1);
    610  1.48       mjl #ifdef LOGIN_CAP
    611  1.48       mjl 	setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH);
    612  1.48       mjl #else
    613   1.1       cgd 	(void)setenv("PATH", _PATH_DEFPATH, 0);
    614  1.48       mjl #endif
    615   1.1       cgd #ifdef KERBEROS
    616   1.1       cgd 	if (krbtkfile_env)
    617   1.1       cgd 		(void)setenv("KRBTKFILE", krbtkfile_env, 1);
    618   1.1       cgd #endif
    619  1.10    brezak #ifdef KERBEROS5
    620  1.10    brezak 	if (krbtkfile_env)
    621  1.10    brezak 		(void)setenv("KRB5CCNAME", krbtkfile_env, 1);
    622  1.10    brezak #endif
    623   1.1       cgd 
    624  1.12       jtc 	if (tty[sizeof("tty")-1] == 'd')
    625  1.12       jtc 		syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
    626  1.12       jtc 
    627   1.5       cgd 	/* If fflag is on, assume caller/authenticator has logged root login. */
    628  1.40      ross 	if (rootlogin && fflag == 0) {
    629   1.1       cgd 		if (hostname)
    630   1.1       cgd 			syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
    631   1.1       cgd 			    username, tty, hostname);
    632   1.1       cgd 		else
    633  1.40      ross 			syslog(LOG_NOTICE,
    634  1.40      ross 				"ROOT LOGIN (%s) ON %s", username, tty);
    635  1.40      ross 	}
    636   1.1       cgd 
    637  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    638   1.1       cgd 	if (!quietlog && notickets == 1)
    639   1.1       cgd 		(void)printf("Warning: no Kerberos tickets issued.\n");
    640   1.1       cgd #endif
    641   1.1       cgd 
    642   1.1       cgd 	if (!quietlog) {
    643  1.48       mjl 		char    *fname;
    644  1.48       mjl #ifdef LOGIN_CAP
    645  1.48       mjl 
    646  1.48       mjl 		fname = login_getcapstr(lc, "copyright", NULL, NULL);
    647  1.48       mjl 		if (fname && access(fname, F_OK) == 0)
    648  1.48       mjl 			motd(fname);
    649  1.48       mjl 		else
    650  1.48       mjl #endif
    651  1.48       mjl 			(void)printf(copyrightstr);
    652  1.48       mjl 
    653  1.48       mjl #ifdef LOGIN_CAP
    654  1.48       mjl                 fname = login_getcapstr(lc, "welcome", NULL, NULL);
    655  1.48       mjl                 if (fname == NULL || access(fname, F_OK) != 0)
    656  1.48       mjl #endif
    657  1.48       mjl                         fname = _PATH_MOTDFILE;
    658  1.48       mjl                 motd(fname);
    659  1.48       mjl 
    660   1.5       cgd 		(void)snprintf(tbuf,
    661   1.5       cgd 		    sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
    662   1.1       cgd 		if (stat(tbuf, &st) == 0 && st.st_size != 0)
    663   1.1       cgd 			(void)printf("You have %smail.\n",
    664   1.1       cgd 			    (st.st_mtime > st.st_atime) ? "new " : "");
    665   1.1       cgd 	}
    666   1.1       cgd 
    667  1.48       mjl #ifdef LOGIN_CAP
    668  1.48       mjl 	login_close(lc);
    669  1.48       mjl #endif
    670  1.48       mjl 
    671   1.1       cgd 	(void)signal(SIGALRM, SIG_DFL);
    672   1.1       cgd 	(void)signal(SIGQUIT, SIG_DFL);
    673   1.1       cgd 	(void)signal(SIGINT, SIG_DFL);
    674   1.1       cgd 	(void)signal(SIGTSTP, SIG_IGN);
    675   1.1       cgd 
    676   1.1       cgd 	tbuf[0] = '-';
    677  1.17       mrg 	(void)strncpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
    678  1.17       mrg 	    p + 1 : pwd->pw_shell, sizeof(tbuf) - 2);
    679   1.1       cgd 
    680  1.24     lukem 	/* Wait to change password until we're unprivileged */
    681  1.24     lukem 	if (need_chpass) {
    682  1.29   mycroft 		if (!require_chpass)
    683  1.24     lukem 			(void)printf(
    684  1.24     lukem "Warning: your password has expired. Please change it as soon as possible.\n");
    685  1.29   mycroft 		else {
    686  1.38       mrg 			int	status;
    687  1.38       mrg 
    688  1.29   mycroft 			(void)printf(
    689  1.24     lukem 		    "Your password has expired. Please choose a new one.\n");
    690  1.38       mrg 			switch (fork()) {
    691  1.38       mrg 			case -1:
    692  1.38       mrg 				warn("fork");
    693  1.29   mycroft 				sleepexit(1);
    694  1.38       mrg 			case 0:
    695  1.38       mrg 				execl(_PATH_BINPASSWD, "passwd", 0);
    696  1.38       mrg 				_exit(1);
    697  1.38       mrg 			default:
    698  1.38       mrg 				if (wait(&status) == -1 ||
    699  1.38       mrg 				    WEXITSTATUS(status))
    700  1.38       mrg 					sleepexit(1);
    701  1.38       mrg 			}
    702  1.29   mycroft 		}
    703  1.24     lukem 	}
    704   1.1       cgd 
    705  1.44     aidan #ifdef KERBEROS5
    706  1.44     aidan 	k5_write_creds();
    707  1.44     aidan #endif
    708   1.1       cgd 	execlp(pwd->pw_shell, tbuf, 0);
    709  1.12       jtc 	err(1, "%s", pwd->pw_shell);
    710   1.1       cgd }
    711   1.1       cgd 
    712  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    713  1.16  sommerfe #define	NBUFSIZ		(MAXLOGNAME + 1 + 5)	/* .root suffix */
    714   1.1       cgd #else
    715  1.16  sommerfe #define	NBUFSIZ		(MAXLOGNAME + 1)
    716  1.10    brezak #endif
    717  1.10    brezak 
    718  1.10    brezak #if defined(KERBEROS) || defined(KERBEROS5)
    719  1.10    brezak /*
    720  1.10    brezak  * This routine handles cleanup stuff, and the like.
    721  1.10    brezak  * It exists only in the child process.
    722  1.10    brezak  */
    723  1.10    brezak #include <sys/wait.h>
    724  1.10    brezak void
    725  1.10    brezak dofork()
    726  1.10    brezak {
    727  1.38       mrg 	int child;
    728  1.38       mrg 
    729  1.38       mrg 	if (!(child = fork()))
    730  1.38       mrg 		return; /* Child process */
    731  1.38       mrg 
    732  1.38       mrg 	/* Setup stuff?  This would be things we could do in parallel with login */
    733  1.38       mrg 	(void) chdir("/");	/* Let's not keep the fs busy... */
    734  1.10    brezak 
    735  1.38       mrg 	/* If we're the parent, watch the child until it dies */
    736  1.38       mrg 	while (wait(0) != child)
    737  1.38       mrg 		;
    738  1.10    brezak 
    739  1.38       mrg 	/* Cleanup stuff */
    740  1.38       mrg 	/* Run kdestroy to destroy tickets */
    741  1.38       mrg 	kdestroy();
    742  1.10    brezak 
    743  1.38       mrg 	/* Leave */
    744  1.38       mrg 	exit(0);
    745  1.10    brezak }
    746   1.1       cgd #endif
    747   1.1       cgd 
    748   1.5       cgd void
    749   1.1       cgd getloginname()
    750   1.1       cgd {
    751  1.12       jtc 	int ch;
    752  1.12       jtc 	char *p;
    753   1.1       cgd 	static char nbuf[NBUFSIZ];
    754   1.1       cgd 
    755   1.1       cgd 	for (;;) {
    756   1.1       cgd 		(void)printf("login: ");
    757   1.1       cgd 		for (p = nbuf; (ch = getchar()) != '\n'; ) {
    758   1.1       cgd 			if (ch == EOF) {
    759   1.1       cgd 				badlogin(username);
    760   1.1       cgd 				exit(0);
    761   1.1       cgd 			}
    762   1.1       cgd 			if (p < nbuf + (NBUFSIZ - 1))
    763   1.1       cgd 				*p++ = ch;
    764   1.1       cgd 		}
    765  1.40      ross 		if (p > nbuf) {
    766   1.1       cgd 			if (nbuf[0] == '-')
    767   1.1       cgd 				(void)fprintf(stderr,
    768   1.1       cgd 				    "login names may not start with '-'.\n");
    769   1.1       cgd 			else {
    770   1.1       cgd 				*p = '\0';
    771   1.1       cgd 				username = nbuf;
    772   1.1       cgd 				break;
    773   1.1       cgd 			}
    774  1.40      ross 		}
    775   1.1       cgd 	}
    776   1.1       cgd }
    777   1.1       cgd 
    778   1.5       cgd int
    779   1.1       cgd rootterm(ttyn)
    780   1.1       cgd 	char *ttyn;
    781   1.1       cgd {
    782   1.1       cgd 	struct ttyent *t;
    783   1.1       cgd 
    784  1.12       jtc 	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
    785   1.1       cgd }
    786   1.1       cgd 
    787   1.1       cgd jmp_buf motdinterrupt;
    788   1.1       cgd 
    789   1.5       cgd void
    790  1.48       mjl motd(fname)
    791  1.48       mjl 	char *fname;
    792   1.1       cgd {
    793  1.12       jtc 	int fd, nchars;
    794   1.1       cgd 	sig_t oldint;
    795   1.1       cgd 	char tbuf[8192];
    796   1.1       cgd 
    797  1.48       mjl 	if ((fd = open(fname ? fname : _PATH_MOTDFILE, O_RDONLY, 0)) < 0)
    798   1.1       cgd 		return;
    799   1.1       cgd 	oldint = signal(SIGINT, sigint);
    800   1.1       cgd 	if (setjmp(motdinterrupt) == 0)
    801   1.1       cgd 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
    802   1.1       cgd 			(void)write(fileno(stdout), tbuf, nchars);
    803   1.1       cgd 	(void)signal(SIGINT, oldint);
    804   1.1       cgd 	(void)close(fd);
    805   1.1       cgd }
    806   1.1       cgd 
    807   1.5       cgd /* ARGSUSED */
    808   1.1       cgd void
    809   1.5       cgd sigint(signo)
    810   1.5       cgd 	int signo;
    811   1.1       cgd {
    812  1.38       mrg 
    813   1.1       cgd 	longjmp(motdinterrupt, 1);
    814   1.1       cgd }
    815   1.1       cgd 
    816   1.5       cgd /* ARGSUSED */
    817   1.5       cgd void
    818   1.5       cgd timedout(signo)
    819   1.5       cgd 	int signo;
    820   1.5       cgd {
    821  1.38       mrg 
    822   1.5       cgd 	(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
    823   1.5       cgd 	exit(0);
    824   1.5       cgd }
    825   1.5       cgd 
    826   1.5       cgd void
    827  1.48       mjl checknologin(fname)
    828  1.48       mjl 	char *fname;
    829   1.1       cgd {
    830  1.12       jtc 	int fd, nchars;
    831   1.1       cgd 	char tbuf[8192];
    832   1.1       cgd 
    833  1.48       mjl 	if ((fd = open(fname ? fname : _PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
    834   1.1       cgd 		while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
    835   1.1       cgd 			(void)write(fileno(stdout), tbuf, nchars);
    836   1.1       cgd 		sleepexit(0);
    837   1.1       cgd 	}
    838   1.1       cgd }
    839   1.1       cgd 
    840   1.5       cgd void
    841   1.1       cgd dolastlog(quiet)
    842   1.1       cgd 	int quiet;
    843   1.1       cgd {
    844   1.1       cgd 	struct lastlog ll;
    845   1.1       cgd 	int fd;
    846   1.1       cgd 
    847   1.1       cgd 	if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
    848  1.26    kleink 		(void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)), SEEK_SET);
    849   1.1       cgd 		if (!quiet) {
    850   1.1       cgd 			if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
    851   1.1       cgd 			    ll.ll_time != 0) {
    852   1.1       cgd 				(void)printf("Last login: %.*s ",
    853  1.42       kim 				    24, (char *)ctime(&ll.ll_time));
    854   1.1       cgd 				if (*ll.ll_host != '\0')
    855   1.1       cgd 					(void)printf("from %.*s\n",
    856   1.5       cgd 					    (int)sizeof(ll.ll_host),
    857   1.5       cgd 					    ll.ll_host);
    858   1.1       cgd 				else
    859   1.1       cgd 					(void)printf("on %.*s\n",
    860   1.5       cgd 					    (int)sizeof(ll.ll_line),
    861   1.5       cgd 					    ll.ll_line);
    862   1.1       cgd 			}
    863  1.26    kleink 			(void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)),
    864  1.26    kleink 			    SEEK_SET);
    865   1.1       cgd 		}
    866  1.12       jtc 		memset((void *)&ll, 0, sizeof(ll));
    867   1.1       cgd 		(void)time(&ll.ll_time);
    868   1.5       cgd 		(void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
    869   1.1       cgd 		if (hostname)
    870   1.5       cgd 			(void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
    871   1.1       cgd 		(void)write(fd, (char *)&ll, sizeof(ll));
    872   1.1       cgd 		(void)close(fd);
    873   1.1       cgd 	}
    874   1.1       cgd }
    875   1.1       cgd 
    876   1.5       cgd void
    877   1.1       cgd badlogin(name)
    878   1.1       cgd 	char *name;
    879   1.1       cgd {
    880   1.1       cgd 	if (failures == 0)
    881   1.1       cgd 		return;
    882   1.1       cgd 	if (hostname) {
    883   1.1       cgd 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
    884   1.1       cgd 		    failures, failures > 1 ? "S" : "", hostname);
    885   1.1       cgd 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
    886   1.1       cgd 		    "%d LOGIN FAILURE%s FROM %s, %s",
    887   1.1       cgd 		    failures, failures > 1 ? "S" : "", hostname, name);
    888   1.1       cgd 	} else {
    889   1.1       cgd 		syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
    890   1.1       cgd 		    failures, failures > 1 ? "S" : "", tty);
    891   1.1       cgd 		syslog(LOG_AUTHPRIV|LOG_NOTICE,
    892   1.1       cgd 		    "%d LOGIN FAILURE%s ON %s, %s",
    893   1.1       cgd 		    failures, failures > 1 ? "S" : "", tty, name);
    894   1.1       cgd 	}
    895   1.1       cgd }
    896   1.1       cgd 
    897  1.39   mycroft const char *
    898   1.1       cgd stypeof(ttyid)
    899  1.39   mycroft 	const char *ttyid;
    900   1.1       cgd {
    901   1.1       cgd 	struct ttyent *t;
    902   1.1       cgd 
    903  1.48       mjl 	return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : NULL);
    904   1.1       cgd }
    905   1.1       cgd 
    906   1.5       cgd void
    907   1.1       cgd sleepexit(eval)
    908   1.1       cgd 	int eval;
    909   1.1       cgd {
    910  1.38       mrg 
    911  1.12       jtc 	(void)sleep(5);
    912   1.1       cgd 	exit(eval);
    913   1.1       cgd }
    914