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