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