login.c revision 1.39 1 /* $NetBSD: login.c,v 1.39 1998/07/26 22:04:37 mycroft 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.39 1998/07/26 22:04:37 mycroft 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
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 if (pwd->pw_change)
441 if (pwd->pw_change == _PASSWORD_CHGNOW)
442 need_chpass = 1;
443 else if (tp.tv_sec >= pwd->pw_change) {
444 (void)printf("Sorry -- your password has expired.\n");
445 sleepexit(1);
446 } else if (pwd->pw_change - tp.tv_sec <
447 _PASSWORD_WARNDAYS * SECSPERDAY && !quietlog)
448 (void)printf("Warning: your password expires on %s",
449 ctime(&pwd->pw_change));
450
451 /* Nothing else left to fail -- really log in. */
452 memset((void *)&utmp, 0, sizeof(utmp));
453 (void)time(&utmp.ut_time);
454 (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
455 if (hostname)
456 (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
457 (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
458 login(&utmp);
459
460 dolastlog(quietlog);
461
462 (void)chown(ttyn, pwd->pw_uid,
463 (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
464
465 if (ttyaction(ttyn, "login", pwd->pw_name))
466 (void)printf("Warning: ttyaction failed.\n");
467
468 #if defined(KERBEROS) || defined(KERBEROS5)
469 /* Fork so that we can call kdestroy */
470 if (krbtkfile_env)
471 dofork();
472 #endif
473 (void)setgid(pwd->pw_gid);
474
475 initgroups(username, pwd->pw_gid);
476
477 if (*pwd->pw_shell == '\0')
478 pwd->pw_shell = _PATH_BSHELL;
479
480 /* Destroy environment unless user has requested its preservation. */
481 if (!pflag)
482 environ = envinit;
483 (void)setenv("HOME", pwd->pw_dir, 1);
484 (void)setenv("SHELL", pwd->pw_shell, 1);
485 if (term[0] == '\0')
486 (void)strncpy(term, stypeof(tty), sizeof(term));
487 (void)setenv("TERM", term, 0);
488 (void)setenv("LOGNAME", pwd->pw_name, 1);
489 (void)setenv("USER", pwd->pw_name, 1);
490 (void)setenv("PATH", _PATH_DEFPATH, 0);
491 #ifdef KERBEROS
492 if (krbtkfile_env)
493 (void)setenv("KRBTKFILE", krbtkfile_env, 1);
494 #endif
495 #ifdef KERBEROS5
496 if (krbtkfile_env)
497 (void)setenv("KRB5CCNAME", krbtkfile_env, 1);
498 #endif
499
500 if (tty[sizeof("tty")-1] == 'd')
501 syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
502
503 /* If fflag is on, assume caller/authenticator has logged root login. */
504 if (rootlogin && fflag == 0)
505 if (hostname)
506 syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
507 username, tty, hostname);
508 else
509 syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
510
511 #if defined(KERBEROS) || defined(KERBEROS5)
512 if (!quietlog && notickets == 1)
513 (void)printf("Warning: no Kerberos tickets issued.\n");
514 #endif
515
516 if (!quietlog) {
517 (void)printf(copyrightstr);
518 motd();
519 (void)snprintf(tbuf,
520 sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
521 if (stat(tbuf, &st) == 0 && st.st_size != 0)
522 (void)printf("You have %smail.\n",
523 (st.st_mtime > st.st_atime) ? "new " : "");
524 }
525
526 (void)signal(SIGALRM, SIG_DFL);
527 (void)signal(SIGQUIT, SIG_DFL);
528 (void)signal(SIGINT, SIG_DFL);
529 (void)signal(SIGTSTP, SIG_IGN);
530
531 tbuf[0] = '-';
532 (void)strncpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
533 p + 1 : pwd->pw_shell, sizeof(tbuf) - 2);
534
535 if (setlogin(pwd->pw_name) < 0)
536 syslog(LOG_ERR, "setlogin() failure: %m");
537
538 /* Discard permissions last so can't get killed and drop core. */
539 if (rootlogin)
540 (void)setuid(0);
541 else
542 (void)setuid(pwd->pw_uid);
543
544 /* Wait to change password until we're unprivileged */
545 if (need_chpass) {
546 if (!require_chpass)
547 (void)printf(
548 "Warning: your password has expired. Please change it as soon as possible.\n");
549 else {
550 int status;
551
552 (void)printf(
553 "Your password has expired. Please choose a new one.\n");
554 switch (fork()) {
555 case -1:
556 warn("fork");
557 sleepexit(1);
558 case 0:
559 execl(_PATH_BINPASSWD, "passwd", 0);
560 _exit(1);
561 default:
562 if (wait(&status) == -1 ||
563 WEXITSTATUS(status))
564 sleepexit(1);
565 }
566 }
567 }
568
569 execlp(pwd->pw_shell, tbuf, 0);
570 err(1, "%s", pwd->pw_shell);
571 }
572
573 #if defined(KERBEROS) || defined(KERBEROS5)
574 #define NBUFSIZ (MAXLOGNAME + 1 + 5) /* .root suffix */
575 #else
576 #define NBUFSIZ (MAXLOGNAME + 1)
577 #endif
578
579 #if defined(KERBEROS) || defined(KERBEROS5)
580 /*
581 * This routine handles cleanup stuff, and the like.
582 * It exists only in the child process.
583 */
584 #include <sys/wait.h>
585 void
586 dofork()
587 {
588 int child;
589
590 if (!(child = fork()))
591 return; /* Child process */
592
593 /* Setup stuff? This would be things we could do in parallel with login */
594 (void) chdir("/"); /* Let's not keep the fs busy... */
595
596 /* If we're the parent, watch the child until it dies */
597 while (wait(0) != child)
598 ;
599
600 /* Cleanup stuff */
601 /* Run kdestroy to destroy tickets */
602 kdestroy();
603
604 /* Leave */
605 exit(0);
606 }
607 #endif
608
609 void
610 getloginname()
611 {
612 int ch;
613 char *p;
614 static char nbuf[NBUFSIZ];
615
616 for (;;) {
617 (void)printf("login: ");
618 for (p = nbuf; (ch = getchar()) != '\n'; ) {
619 if (ch == EOF) {
620 badlogin(username);
621 exit(0);
622 }
623 if (p < nbuf + (NBUFSIZ - 1))
624 *p++ = ch;
625 }
626 if (p > nbuf)
627 if (nbuf[0] == '-')
628 (void)fprintf(stderr,
629 "login names may not start with '-'.\n");
630 else {
631 *p = '\0';
632 username = nbuf;
633 break;
634 }
635 }
636 }
637
638 int
639 rootterm(ttyn)
640 char *ttyn;
641 {
642 struct ttyent *t;
643
644 return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
645 }
646
647 jmp_buf motdinterrupt;
648
649 void
650 motd()
651 {
652 int fd, nchars;
653 sig_t oldint;
654 char tbuf[8192];
655
656 if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
657 return;
658 oldint = signal(SIGINT, sigint);
659 if (setjmp(motdinterrupt) == 0)
660 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
661 (void)write(fileno(stdout), tbuf, nchars);
662 (void)signal(SIGINT, oldint);
663 (void)close(fd);
664 }
665
666 /* ARGSUSED */
667 void
668 sigint(signo)
669 int signo;
670 {
671
672 longjmp(motdinterrupt, 1);
673 }
674
675 /* ARGSUSED */
676 void
677 timedout(signo)
678 int signo;
679 {
680
681 (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
682 exit(0);
683 }
684
685 void
686 checknologin()
687 {
688 int fd, nchars;
689 char tbuf[8192];
690
691 if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
692 while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
693 (void)write(fileno(stdout), tbuf, nchars);
694 sleepexit(0);
695 }
696 }
697
698 void
699 dolastlog(quiet)
700 int quiet;
701 {
702 struct lastlog ll;
703 int fd;
704
705 if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
706 (void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)), SEEK_SET);
707 if (!quiet) {
708 if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
709 ll.ll_time != 0) {
710 (void)printf("Last login: %.*s ",
711 24-5, (char *)ctime(&ll.ll_time));
712 if (*ll.ll_host != '\0')
713 (void)printf("from %.*s\n",
714 (int)sizeof(ll.ll_host),
715 ll.ll_host);
716 else
717 (void)printf("on %.*s\n",
718 (int)sizeof(ll.ll_line),
719 ll.ll_line);
720 }
721 (void)lseek(fd, (off_t)(pwd->pw_uid * sizeof(ll)),
722 SEEK_SET);
723 }
724 memset((void *)&ll, 0, sizeof(ll));
725 (void)time(&ll.ll_time);
726 (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
727 if (hostname)
728 (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
729 (void)write(fd, (char *)&ll, sizeof(ll));
730 (void)close(fd);
731 }
732 }
733
734 void
735 badlogin(name)
736 char *name;
737 {
738 if (failures == 0)
739 return;
740 if (hostname) {
741 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
742 failures, failures > 1 ? "S" : "", hostname);
743 syslog(LOG_AUTHPRIV|LOG_NOTICE,
744 "%d LOGIN FAILURE%s FROM %s, %s",
745 failures, failures > 1 ? "S" : "", hostname, name);
746 } else {
747 syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
748 failures, failures > 1 ? "S" : "", tty);
749 syslog(LOG_AUTHPRIV|LOG_NOTICE,
750 "%d LOGIN FAILURE%s ON %s, %s",
751 failures, failures > 1 ? "S" : "", tty, name);
752 }
753 }
754
755 #undef UNKNOWN
756 #define UNKNOWN "su"
757
758 const char *
759 stypeof(ttyid)
760 const char *ttyid;
761 {
762 struct ttyent *t;
763
764 return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
765 }
766
767 void
768 sleepexit(eval)
769 int eval;
770 {
771
772 (void)sleep(5);
773 exit(eval);
774 }
775