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