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