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