login.c revision 72445
1/*
2 * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "login_locl.h"
35#ifdef HAVE_CAPABILITY_H
36#include <capability.h>
37#endif
38#ifdef HAVE_SYS_CAPABILITY_H
39#include <sys/capability.h>
40#endif
41
42RCSID("$Id: login.c,v 1.46 2001/01/29 02:18:03 assar Exp $");
43
44static int login_timeout = 60;
45
46static int
47start_login_process(void)
48{
49    char *prog, *argv0;
50    prog = login_conf_get_string("login_program");
51    if(prog == NULL)
52	return 0;
53    argv0 = strrchr(prog, '/');
54
55    if(argv0)
56	argv0++;
57    else
58	argv0 = prog;
59
60    return simple_execle(prog, argv0, NULL, env);
61}
62
63static int
64start_logout_process(void)
65{
66    char *prog, *argv0;
67    pid_t pid;
68
69    prog = login_conf_get_string("logout_program");
70    if(prog == NULL)
71	return 0;
72    argv0 = strrchr(prog, '/');
73
74    if(argv0)
75	argv0++;
76    else
77	argv0 = prog;
78
79    pid = fork();
80    if(pid == 0) {
81	/* avoid getting signals sent to the shell */
82	setpgid(0, getpid());
83	return 0;
84    }
85    if(pid == -1)
86	err(1, "fork");
87    /* wait for the real login process to exit */
88#ifdef HAVE_SETPROCTITLE
89    setproctitle("waitpid %d", pid);
90#endif
91    while(1) {
92	int status;
93	int ret;
94	ret = waitpid(pid, &status, 0);
95	if(ret > 0) {
96	    if(WIFEXITED(status) || WIFSIGNALED(status)) {
97		execle(prog, argv0, NULL, env);
98		err(1, "exec %s", prog);
99	    }
100	} else if(ret < 0)
101	    err(1, "waitpid");
102    }
103}
104
105static void
106exec_shell(const char *shell, int fallback)
107{
108    char *sh;
109    const char *p;
110
111    extend_env(NULL);
112    if(start_login_process() < 0)
113	warn("login process");
114    start_logout_process();
115
116    p = strrchr(shell, '/');
117    if(p)
118	p++;
119    else
120	p = shell;
121    asprintf(&sh, "-%s", p);
122    execle(shell, sh, NULL, env);
123    if(fallback){
124	warnx("Can't exec %s, trying %s",
125	      shell, _PATH_BSHELL);
126	execle(_PATH_BSHELL, "-sh", NULL, env);
127	err(1, "%s", _PATH_BSHELL);
128    }
129    err(1, "%s", shell);
130}
131
132static enum { NONE = 0, AUTH_KRB4 = 1, AUTH_KRB5 = 2, AUTH_OTP = 3 } auth;
133
134#ifdef OTP
135static OtpContext otp_ctx;
136
137static int
138otp_verify(struct passwd *pwd, const char *password)
139{
140   return (otp_verify_user (&otp_ctx, password));
141}
142#endif /* OTP */
143
144
145#ifdef KRB5
146static krb5_context context;
147static krb5_ccache  id, id2;
148
149static int
150krb5_verify(struct passwd *pwd, const char *password)
151{
152    krb5_error_code ret;
153    krb5_principal princ;
154
155    ret = krb5_parse_name(context, pwd->pw_name, &princ);
156    if(ret)
157	return 1;
158    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
159    if(ret) {
160	krb5_free_principal(context, princ);
161	return 1;
162    }
163    ret = krb5_verify_user_lrealm(context,
164				  princ,
165				  id,
166				  password,
167				  1,
168				  NULL);
169    krb5_free_principal(context, princ);
170    return ret;
171}
172
173#ifdef KRB4
174static krb5_error_code
175krb5_to4 (krb5_ccache id)
176{
177    if (krb5_config_get_bool(context, NULL,
178			     "libdefaults",
179			     "krb4_get_tickets",
180			     NULL)) {
181        CREDENTIALS c;
182        krb5_creds mcred, cred;
183        char krb4tkfile[MAXPATHLEN];
184	krb5_error_code ret;
185	krb5_principal princ;
186
187	ret = krb5_cc_get_principal (context, id, &princ);
188	if (ret)
189	    return ret;
190
191	ret = krb5_make_principal(context, &mcred.server,
192				  princ->realm,
193				  "krbtgt",
194				  princ->realm,
195				  NULL);
196	krb5_free_principal (context, princ);
197	if (ret)
198	    return ret;
199
200	ret = krb5_cc_retrieve_cred(context, id, 0, &mcred, &cred);
201	if(ret == 0) {
202	    ret = krb524_convert_creds_kdc(context, id, &cred, &c);
203	    if(ret == 0) {
204		snprintf(krb4tkfile,sizeof(krb4tkfile),"%s%d",TKT_ROOT,
205			 getuid());
206		krb_set_tkt_string(krb4tkfile);
207		tf_setup(&c, c.pname, c.pinst);
208	    }
209	    memset(&c, 0, sizeof(c));
210	    krb5_free_creds_contents(context, &cred);
211	}
212	krb5_free_principal(context, mcred.server);
213    }
214    return 0;
215}
216#endif /* KRB4 */
217
218static int
219krb5_start_session (const struct passwd *pwd)
220{
221    krb5_error_code ret;
222    char residual[64];
223
224    /* copy credentials to file cache */
225    snprintf(residual, sizeof(residual), "FILE:/tmp/krb5cc_%u",
226	     (unsigned)pwd->pw_uid);
227    krb5_cc_resolve(context, residual, &id2);
228    ret = krb5_cc_copy_cache(context, id, id2);
229    if (ret == 0)
230	add_env("KRB5CCNAME", residual);
231    else {
232	krb5_cc_destroy (context, id2);
233	return ret;
234    }
235#ifdef KRB4
236    krb5_to4 (id2);
237#endif
238    krb5_cc_close(context, id2);
239    krb5_cc_destroy(context, id);
240    return 0;
241}
242
243static void
244krb5_finish (void)
245{
246    krb5_free_context(context);
247}
248
249#ifdef KRB4
250
251static int pag_set = 0;
252
253static void
254krb5_get_afs_tokens (const struct passwd *pwd)
255{
256    char cell[64];
257    char *pw_dir;
258    krb5_error_code ret;
259
260    if (!k_hasafs ())
261	return;
262
263    ret = krb5_cc_default(context, &id2);
264
265    if (ret == 0) {
266	pw_dir = pwd->pw_dir;
267
268	if (!pag_set) {
269	    k_setpag();
270	    pag_set = 1;
271	}
272
273	if(k_afs_cell_of_file(pw_dir, cell, sizeof(cell)) == 0)
274	    krb5_afslog_uid_home (context, id2,
275				  cell, NULL, pwd->pw_uid, pwd->pw_dir);
276	krb5_afslog_uid_home (context, id2, NULL, NULL,
277			      pwd->pw_uid, pwd->pw_dir);
278	krb5_cc_close (context, id2);
279    }
280}
281
282#endif /* KRB4 */
283
284#endif /* KRB5 */
285
286#ifdef KRB4
287
288static int
289krb4_verify(struct passwd *pwd, const char *password)
290{
291    char lrealm[REALM_SZ];
292    int ret;
293    char ticket_file[MaxPathLen];
294
295    ret = krb_get_lrealm (lrealm, 1);
296    if (ret)
297	return 1;
298
299    snprintf (ticket_file, sizeof(ticket_file),
300	      "%s%u_%u",
301	      TKT_ROOT, (unsigned)pwd->pw_uid, (unsigned)getpid());
302
303    krb_set_tkt_string (ticket_file);
304
305    ret = krb_verify_user (pwd->pw_name, "", lrealm, (char *)password,
306			   KRB_VERIFY_SECURE_FAIL, NULL);
307    if (ret)
308	return 1;
309
310    if (chown (ticket_file, pwd->pw_uid, pwd->pw_gid) < 0) {
311	dest_tkt();
312	return 1;
313    }
314
315    add_env ("KRBTKFILE", ticket_file);
316    return 0;
317}
318
319static void
320krb4_get_afs_tokens (const struct passwd *pwd)
321{
322    char cell[64];
323    char *pw_dir;
324
325    if (!k_hasafs ())
326	return;
327
328    pw_dir = pwd->pw_dir;
329
330    if (!pag_set) {
331	k_setpag();
332	pag_set = 1;
333    }
334
335    if(k_afs_cell_of_file(pw_dir, cell, sizeof(cell)) == 0)
336	krb_afslog_uid_home (cell, NULL, pwd->pw_uid, pwd->pw_dir);
337
338    krb_afslog_uid_home (NULL, NULL, pwd->pw_uid, pwd->pw_dir);
339}
340
341#endif /* KRB4 */
342
343static int f_flag;
344static int p_flag;
345#if 0
346static int r_flag;
347#endif
348static int version_flag;
349static int help_flag;
350static char *remote_host;
351static char *auth_level = NULL;
352
353struct getargs args[] = {
354    { NULL, 'a', arg_string,    &auth_level,    "authentication mode" },
355#if 0
356    { NULL, 'd' },
357#endif
358    { NULL, 'f', arg_flag,	&f_flag,	"pre-authenticated" },
359    { NULL, 'h', arg_string,	&remote_host,	"remote host", "hostname" },
360    { NULL, 'p', arg_flag,	&p_flag,	"don't purge environment" },
361#if 0
362    { NULL, 'r', arg_flag,	&r_flag,	"rlogin protocol" },
363#endif
364    { "version", 0,  arg_flag,	&version_flag },
365    { "help",	 0,  arg_flag,&help_flag, }
366};
367
368int nargs = sizeof(args) / sizeof(args[0]);
369
370static void
371update_utmp(const char *username, const char *hostname,
372	    char *tty, char *ttyn)
373{
374    /*
375     * Update the utmp files, both BSD and SYSV style.
376     */
377    if (utmpx_login(tty, username, hostname) != 0 && !f_flag) {
378	printf("No utmpx entry.  You must exec \"login\" from the "
379	       "lowest level shell.\n");
380	exit(1);
381    }
382    utmp_login(ttyn, username, hostname);
383}
384
385static void
386checknologin(void)
387{
388    FILE *f;
389    char buf[1024];
390
391    f = fopen(_PATH_NOLOGIN, "r");
392    if(f == NULL)
393	return;
394    while(fgets(buf, sizeof(buf), f))
395	fputs(buf, stdout);
396    fclose(f);
397    exit(0);
398}
399
400/*
401 * Actually log in the user.  `pwd' contains all the relevant
402 * information about the user.  `ttyn' is the complete name of the tty
403 * and `tty' the short name.
404 */
405
406static void
407do_login(const struct passwd *pwd, char *tty, char *ttyn)
408{
409#ifdef HAVE_GETSPNAM
410    struct spwd *sp;
411#endif
412    int rootlogin = (pwd->pw_uid == 0);
413    gid_t tty_gid;
414    struct group *gr;
415    const char *home_dir;
416
417    if(!rootlogin)
418	checknologin();
419
420#ifdef HAVE_GETSPNAM
421    sp = getspnam(pwd->pw_name);
422#endif
423
424    update_utmp(pwd->pw_name, remote_host ? remote_host : "",
425		tty, ttyn);
426
427    gr = getgrnam ("tty");
428    if (gr != NULL)
429	tty_gid = gr->gr_gid;
430    else
431	tty_gid = pwd->pw_gid;
432
433    if (chown (ttyn, pwd->pw_uid, tty_gid) < 0) {
434	warn("chown %s", ttyn);
435	if (rootlogin == 0)
436	    exit (1);
437    }
438
439    if (chmod (ttyn, S_IRUSR | S_IWUSR | S_IWGRP) < 0) {
440	warn("chmod %s", ttyn);
441	if (rootlogin == 0)
442	    exit (1);
443    }
444
445#ifdef HAVE_SETLOGIN
446    if(setlogin(pwd->pw_name)){
447	warn("setlogin(%s)", pwd->pw_name);
448	if(rootlogin == 0)
449	    exit(1);
450    }
451#endif
452#ifdef HAVE_INITGROUPS
453    if(initgroups(pwd->pw_name, pwd->pw_gid)){
454	warn("initgroups(%s, %u)", pwd->pw_name, (unsigned)pwd->pw_gid);
455	if(rootlogin == 0)
456	    exit(1);
457    }
458#endif
459    if(setgid(pwd->pw_gid)){
460	warn("setgid(%u)", (unsigned)pwd->pw_gid);
461	if(rootlogin == 0)
462	    exit(1);
463    }
464    if(setuid(pwd->pw_uid) || (pwd->pw_uid != 0 && setuid(0) == 0)) {
465	warn("setuid(%u)", (unsigned)pwd->pw_uid);
466	if(rootlogin == 0)
467	    exit(1);
468    }
469    /* all kinds of different magic */
470
471#ifdef HAVE_GETSPNAM
472    check_shadow(pwd, sp);
473#endif
474
475    if(do_osfc2_magic(pwd->pw_uid))
476	exit(1);
477#if defined(HAVE_GETUDBNAM) && defined(HAVE_SETLIM)
478    {
479	struct udb *udb;
480	long t;
481	const long maxcpu = 46116860184; /* some random constant */
482	udb = getudbnam(pwd->pw_name);
483	if(udb == UDB_NULL)
484	    errx(1, "Failed to get UDB entry.");
485	t = udb->ue_pcpulim[UDBRC_INTER];
486	if(t == 0 || t > maxcpu)
487	    t = CPUUNLIM;
488	else
489	    t *= 100 * CLOCKS_PER_SEC;
490
491	if(limit(C_PROC, 0, L_CPU, t) < 0)
492	    warn("limit C_PROC");
493
494	t = udb->ue_jcpulim[UDBRC_INTER];
495	if(t == 0 || t > maxcpu)
496	    t = CPUUNLIM;
497	else
498	    t *= 100 * CLOCKS_PER_SEC;
499
500	if(limit(C_JOBPROCS, 0, L_CPU, t) < 0)
501	    warn("limit C_JOBPROCS");
502
503	nice(udb->ue_nice[UDBRC_INTER]);
504    }
505#endif
506#if defined(HAVE_SGI_GETCAPABILITYBYNAME) && defined(HAVE_CAP_SET_PROC)
507	/* XXX SGI capability hack IRIX 6.x (x >= 0?) has something
508	   called capabilities, that allow you to give away
509	   permissions (such as chown) to specific processes. From 6.5
510	   this is default on, and the default capability set seems to
511	   not always be the empty set. The problem is that the
512	   runtime linker refuses to do just about anything if the
513	   process has *any* capabilities set, so we have to remove
514	   them here (unless otherwise instructed by /etc/capability).
515	   In IRIX < 6.5, these functions was called sgi_cap_setproc,
516	   etc, but we ignore this fact (it works anyway). */
517	{
518	    struct user_cap *ucap = sgi_getcapabilitybyname(pwd->pw_name);
519	    cap_t cap;
520	    if(ucap == NULL)
521		cap = cap_from_text("all=");
522	    else
523		cap = cap_from_text(ucap->ca_default);
524	    if(cap == NULL)
525		err(1, "cap_from_text");
526	    if(cap_set_proc(cap) < 0)
527		err(1, "cap_set_proc");
528	    cap_free(cap);
529	    free(ucap);
530	}
531#endif
532    home_dir = pwd->pw_dir;
533    if (chdir(home_dir) < 0) {
534	fprintf(stderr, "No home directory \"%s\"!\n", pwd->pw_dir);
535	if (chdir("/"))
536	    exit(0);
537	home_dir = "/";
538	fprintf(stderr, "Logging in with home = \"/\".\n");
539    }
540#ifdef KRB5
541    if (auth == AUTH_KRB5) {
542	krb5_start_session (pwd);
543    }
544#ifdef KRB4
545    else if (auth == 0) {
546	krb5_error_code ret;
547	krb5_ccache id;
548
549	ret = krb5_cc_default (context, &id);
550	if (ret == 0) {
551	    krb5_to4 (id);
552	    krb5_cc_close (context, id);
553	}
554    }
555
556    krb5_get_afs_tokens (pwd);
557#endif /* KRB4 */
558    krb5_finish ();
559#endif /* KRB5 */
560
561#ifdef KRB4
562    krb4_get_afs_tokens (pwd);
563#endif /* KRB4 */
564
565    add_env("PATH", _PATH_DEFPATH);
566
567    {
568	const char *str = login_conf_get_string("environment");
569	char buf[MAXPATHLEN];
570
571	if(str == NULL) {
572	    login_read_env(_PATH_ETC_ENVIRONMENT);
573	} else {
574	    while(strsep_copy(&str, ",", buf, sizeof(buf)) != -1) {
575		if(buf[0] == '\0')
576		    continue;
577		login_read_env(buf);
578	    }
579	}
580    }
581    add_env("HOME", home_dir);
582    add_env("USER", pwd->pw_name);
583    add_env("LOGNAME", pwd->pw_name);
584    add_env("SHELL", pwd->pw_shell);
585    exec_shell(pwd->pw_shell, rootlogin);
586}
587
588static int
589check_password(struct passwd *pwd, const char *password)
590{
591    if(pwd->pw_passwd == NULL)
592	return 1;
593    if(pwd->pw_passwd[0] == '\0'){
594#ifdef ALLOW_NULL_PASSWORD
595	return password[0] != '\0';
596#else
597	return 1;
598#endif
599    }
600    if(strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) == 0)
601	return 0;
602#ifdef KRB5
603    if(krb5_verify(pwd, password) == 0) {
604	auth = AUTH_KRB5;
605	return 0;
606    }
607#endif
608#ifdef KRB4
609    if (krb4_verify (pwd, password) == 0) {
610	auth = AUTH_KRB4;
611	return 0;
612    }
613#endif
614#ifdef OTP
615    if (otp_verify (pwd, password) == 0) {
616       auth = AUTH_OTP;
617       return 0;
618    }
619#endif
620    return 1;
621}
622
623static void
624usage(int status)
625{
626    arg_printusage(args, nargs, NULL, "[username]");
627    exit(status);
628}
629
630static RETSIGTYPE
631sig_handler(int sig)
632{
633    if (sig == SIGALRM)
634         fprintf(stderr, "Login timed out after %d seconds\n",
635                login_timeout);
636      else
637         fprintf(stderr, "Login received signal, exiting\n");
638    exit(0);
639}
640
641int
642main(int argc, char **argv)
643{
644    int max_tries = 5;
645    int try;
646
647    char username[32];
648    int optind = 0;
649
650    int ask = 1;
651    struct sigaction sa;
652
653    set_progname(argv[0]);
654
655#ifdef KRB5
656    {
657	krb5_error_code ret;
658
659	ret = krb5_init_context(&context);
660	if (ret)
661	    errx (1, "krb5_init_context failed: %d", ret);
662    }
663#endif
664
665    openlog("login", LOG_ODELAY, LOG_AUTH);
666
667    if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
668		&optind))
669	usage (1);
670    argc -= optind;
671    argv += optind;
672
673    if(help_flag)
674	usage(0);
675    if (version_flag) {
676	print_version (NULL);
677	return 0;
678    }
679
680    if (geteuid() != 0)
681	errx(1, "only root may use login, use su");
682
683    /* Default tty settings. */
684    stty_default();
685
686    if(p_flag)
687	copy_env();
688    else {
689	/* this set of variables is always preserved by BSD login */
690	if(getenv("TERM"))
691	    add_env("TERM", getenv("TERM"));
692	if(getenv("TZ"))
693	    add_env("TZ", getenv("TZ"));
694    }
695
696    if(*argv){
697	if(strchr(*argv, '=') == NULL && strcmp(*argv, "-") != 0){
698	    strlcpy (username, *argv, sizeof(username));
699	    ask = 0;
700	}
701    }
702
703#if defined(DCE) && defined(AIX)
704    esetenv("AUTHSTATE", "DCE", 1);
705#endif
706
707    /* XXX should we care about environment on the command line? */
708
709    memset(&sa, 0, sizeof(sa));
710    sa.sa_handler = sig_handler;
711    sigemptyset(&sa.sa_mask);
712    sa.sa_flags = 0;
713    sigaction(SIGALRM, &sa, NULL);
714    alarm(login_timeout);
715
716    for(try = 0; try < max_tries; try++){
717	struct passwd *pwd;
718	char password[128];
719	int ret;
720	char ttname[32];
721	char *tty, *ttyn;
722        char prompt[128];
723#ifdef OTP
724        char otp_str[256];
725#endif
726
727	if(ask){
728	    f_flag = 0;
729#if 0
730	    r_flag = 0;
731#endif
732	    ret = read_string("login: ", username, sizeof(username), 1);
733	    if(ret == -3)
734		exit(0);
735	    if(ret == -2)
736		sig_handler(0); /* exit */
737	}
738        pwd = k_getpwnam(username);
739#ifdef ALLOW_NULL_PASSWORD
740        if (pwd != NULL && (pwd->pw_passwd[0] == '\0')) {
741            strcpy(password,"");
742        }
743        else
744#endif
745
746        {
747#ifdef OTP
748           if(auth_level && strcmp(auth_level, "otp") == 0 &&
749                 otp_challenge(&otp_ctx, username,
750                            otp_str, sizeof(otp_str)) == 0)
751                 snprintf (prompt, sizeof(prompt), "%s's %s Password: ",
752                            username, otp_str);
753            else
754#endif
755                 strncpy(prompt, "Password: ", sizeof(prompt));
756
757	    if (f_flag == 0) {
758	       ret = read_string(prompt, password, sizeof(password), 0);
759               if (ret == -3) {
760                  ask = 1;
761                  continue;
762               }
763               if (ret == -2)
764                  sig_handler(0);
765            }
766         }
767
768	if(pwd == NULL){
769	    fprintf(stderr, "Login incorrect.\n");
770	    ask = 1;
771	    continue;
772	}
773
774	if(f_flag == 0 && check_password(pwd, password)){
775	    fprintf(stderr, "Login incorrect.\n");
776            ask = 1;
777	    continue;
778	}
779	ttyn = ttyname(STDIN_FILENO);
780	if(ttyn == NULL){
781	    snprintf(ttname, sizeof(ttname), "%s??", _PATH_TTY);
782	    ttyn = ttname;
783	}
784	if (strncmp (ttyn, _PATH_DEV, strlen(_PATH_DEV)) == 0)
785	    tty = ttyn + strlen(_PATH_DEV);
786	else
787	    tty = ttyn;
788
789	if (login_access (pwd, remote_host ? remote_host : tty) == 0) {
790	    fprintf(stderr, "Permission denied\n");
791	    if (remote_host)
792		syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s",
793		       pwd->pw_name, remote_host);
794	    else
795		syslog(LOG_NOTICE, "%s LOGIN REFUSED ON %s",
796		       pwd->pw_name, tty);
797	    exit (1);
798	}
799        alarm(0);
800	do_login(pwd, tty, ttyn);
801    }
802    exit(1);
803}
804