119843Sdist /* 236515Sbostic * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. 336515Sbostic * All rights reserved. 436515Sbostic * 536515Sbostic * Redistribution and use in source and binary forms are permitted 636515Sbostic * provided that the above copyright notice and this paragraph are 736515Sbostic * duplicated in all such forms and that any documentation, 836515Sbostic * advertising materials, and other materials related to such 936515Sbostic * distribution and use acknowledge that the software was developed 1036515Sbostic * by the University of California, Berkeley. The name of the 1136515Sbostic * University may not be used to endorse or promote products derived 1236515Sbostic * from this software without specific prior written permission. 1336515Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436515Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536515Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1619843Sdist */ 1719843Sdist 1812678Ssam #ifndef lint 1919843Sdist char copyright[] = 2036515Sbostic "@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ 2119843Sdist All rights reserved.\n"; 2236515Sbostic #endif /* not lint */ 2312678Ssam 2419843Sdist #ifndef lint 25*37203Sbostic static char sccsid[] = "@(#)login.c 5.38 (Berkeley) 03/17/89"; 2636515Sbostic #endif /* not lint */ 2719843Sdist 281043Sbill /* 291043Sbill * login [ name ] 3031695Skarels * login -h hostname (for telnetd, etc.) 3131695Skarels * login -f name (for pre-authenticated login: datakit, xterm, etc.) 321043Sbill */ 331043Sbill 3412984Ssam #include <sys/param.h> 3512687Ssam #include <sys/quota.h> 3612687Ssam #include <sys/stat.h> 3712687Ssam #include <sys/time.h> 3812687Ssam #include <sys/resource.h> 3916453Sroot #include <sys/file.h> 4036460Sbostic #include <sys/ioctl.h> 4112687Ssam 421043Sbill #include <utmp.h> 431043Sbill #include <signal.h> 441043Sbill #include <lastlog.h> 4512678Ssam #include <errno.h> 4616453Sroot #include <ttyent.h> 4716453Sroot #include <syslog.h> 4826862Smckusick #include <grp.h> 4936460Sbostic #include <pwd.h> 5036515Sbostic #include <setjmp.h> 5136460Sbostic #include <stdio.h> 5236460Sbostic #include <strings.h> 53*37203Sbostic #include <tzfile.h> 54*37203Sbostic #include "pathnames.h" 551043Sbill 56*37203Sbostic #ifdef KERBEROS 57*37203Sbostic #include <kerberos/krb.h> 58*37203Sbostic #include <sys/termios.h> 59*37203Sbostic char realm[REALM_SZ]; 60*37203Sbostic int kerror = KSUCCESS, notickets = 1; 61*37203Sbostic #endif 62*37203Sbostic 6336460Sbostic #define TTYGRPNAME "tty" /* name of group to own ttys */ 6426862Smckusick 6512687Ssam /* 6636460Sbostic * This bounds the time given to login. Not a define so it can 6736460Sbostic * be patched on machines where it's too small. 6812687Ssam */ 6931509Sbostic int timeout = 300; 706005Swnj 7136647Skarels struct passwd *pwd; 7236647Skarels int failures; 7336647Skarels char term[64], *hostname, *username, *tty; 746005Swnj 7536647Skarels struct sgttyb sgttyb; 7636647Skarels struct tchars tc = { 7713074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 781365Sbill }; 7936647Skarels struct ltchars ltc = { 8013074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 8113074Ssam }; 821365Sbill 8336880Sbostic char *months[] = 8436880Sbostic { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", 8536880Sbostic "Sep", "Oct", "Nov", "Dec" }; 8636880Sbostic 871043Sbill main(argc, argv) 8836460Sbostic int argc; 8936460Sbostic char **argv; 901043Sbill { 9136460Sbostic extern int errno, optind; 9236460Sbostic extern char *optarg, **environ; 9336880Sbostic struct timeval tp; 9436880Sbostic struct tm *ttp; 9536460Sbostic struct group *gr; 9636460Sbostic register int ch; 9736647Skarels register char *p; 98*37203Sbostic int ask, fflag, hflag, pflag, cnt; 9936460Sbostic int quietlog, passwd_req, ioctlval, timedout(); 10036647Skarels char *domain, *salt, *envinit[1], *ttyn, *pp; 10136460Sbostic char tbuf[MAXPATHLEN + 2]; 10236880Sbostic char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); 10336460Sbostic time_t time(); 10436460Sbostic off_t lseek(); 1051043Sbill 10636460Sbostic (void)signal(SIGALRM, timedout); 10736460Sbostic (void)alarm((u_int)timeout); 10836460Sbostic (void)signal(SIGQUIT, SIG_IGN); 10936460Sbostic (void)signal(SIGINT, SIG_IGN); 11036460Sbostic (void)setpriority(PRIO_PROCESS, 0, 0); 11136460Sbostic (void)quota(Q_SETUID, 0, 0, 0); 11236460Sbostic 11312687Ssam /* 11418549Ssam * -p is used by getty to tell login not to destroy the environment 11531695Skarels * -f is used to skip a second login authentication 11636523Skarels * -h is used by other servers to pass the name of the remote 11736523Skarels * host to login so that it may be placed in utmp and wtmp 11812687Ssam */ 11936460Sbostic (void)gethostname(tbuf, sizeof(tbuf)); 12036460Sbostic domain = index(tbuf, '.'); 12136460Sbostic 122*37203Sbostic fflag = hflag = pflag = 0; 12336460Sbostic passwd_req = 1; 124*37203Sbostic while ((ch = getopt(argc, argv, "fh:p")) != EOF) 12536515Sbostic switch (ch) { 12636460Sbostic case 'f': 12736460Sbostic fflag = 1; 12836460Sbostic break; 12936460Sbostic case 'h': 13036460Sbostic if (getuid()) { 131*37203Sbostic (void)fprintf(stderr, 13236460Sbostic "login: -h for super-user only.\n"); 13332313Sbostic exit(1); 13431695Skarels } 13536460Sbostic hflag = 1; 13636460Sbostic if (domain && (p = index(optarg, '.')) && 13736553Sbostic strcasecmp(p, domain) == 0) 13836460Sbostic *p = 0; 13936460Sbostic hostname = optarg; 14036460Sbostic break; 14136460Sbostic case 'p': 14218549Ssam pflag = 1; 14336460Sbostic break; 14436460Sbostic case '?': 14536460Sbostic default: 146*37203Sbostic (void)fprintf(stderr, 147*37203Sbostic "usage: login [-fp] [username]\n"); 14836460Sbostic exit(1); 14918549Ssam } 15036460Sbostic argc -= optind; 15136460Sbostic argv += optind; 15236549Sbostic if (*argv) { 15336647Skarels username = *argv; 15436549Sbostic ask = 0; 15536647Skarels } else 15636549Sbostic ask = 1; 15736460Sbostic 15836460Sbostic ioctlval = 0; 15936460Sbostic (void)ioctl(0, TIOCLSET, &ioctlval); 16036460Sbostic (void)ioctl(0, TIOCNXCL, 0); 16136515Sbostic (void)fcntl(0, F_SETFL, ioctlval); 16236515Sbostic (void)ioctl(0, TIOCGETP, &sgttyb); 16336515Sbostic sgttyb.sg_erase = CERASE; 16436515Sbostic sgttyb.sg_kill = CKILL; 16536460Sbostic (void)ioctl(0, TIOCSLTC, <c); 16636460Sbostic (void)ioctl(0, TIOCSETC, &tc); 16736515Sbostic (void)ioctl(0, TIOCSETP, &sgttyb); 16836460Sbostic 16936460Sbostic for (cnt = getdtablesize(); cnt > 2; cnt--) 17036460Sbostic close(cnt); 17136460Sbostic 1721043Sbill ttyn = ttyname(0); 17336460Sbostic if (ttyn == NULL || *ttyn == '\0') 1741043Sbill ttyn = "/dev/tty??"; 17536460Sbostic if (tty = rindex(ttyn, '/')) 17636460Sbostic ++tty; 17736460Sbostic else 17816453Sroot tty = ttyn; 17936460Sbostic 18024852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 18136460Sbostic 18236549Sbostic for (cnt = 0;; ask = 1) { 18336460Sbostic ioctlval = 0; 18436460Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 18536460Sbostic 18636549Sbostic if (ask) { 18736515Sbostic fflag = 0; 18836460Sbostic getloginname(); 18936515Sbostic } 19036647Skarels /* 19136647Skarels * Note if trying multiple user names; 19236647Skarels * log failures for previous user name, 19336647Skarels * but don't bother logging one failure 19436647Skarels * for nonexistent name (mistyped username). 19536647Skarels */ 19636647Skarels if (failures && strcmp(tbuf, username)) { 19736647Skarels if (failures > (pwd ? 0 : 1)) 19836549Sbostic badlogin(tbuf); 19936647Skarels failures = 0; 20036549Sbostic } 20136647Skarels (void)strcpy(tbuf, username); 20236515Sbostic if (pwd = getpwnam(username)) 20336515Sbostic salt = pwd->pw_passwd; 20436515Sbostic else 20536515Sbostic salt = "xx"; 20636460Sbostic 20736460Sbostic /* if user not super-user, check for disabled logins */ 20836515Sbostic if (pwd == NULL || pwd->pw_uid) 20936460Sbostic checknologin(); 21036460Sbostic 21112687Ssam /* 21236515Sbostic * Disallow automatic login to root; if not invoked by 21336515Sbostic * root, disallow if the uid's differ. 21412687Ssam */ 21536515Sbostic if (fflag && pwd) { 21631695Skarels int uid = getuid(); 21731695Skarels 21836515Sbostic passwd_req = pwd->pw_uid == 0 || 21936515Sbostic (uid && uid != pwd->pw_uid); 22031695Skarels } 22136460Sbostic 22212687Ssam /* 22336523Skarels * If no pre-authentication and a password exists 22436460Sbostic * for this user, prompt for one and verify it. 22512687Ssam */ 22636608Skfall if (!passwd_req || (pwd && !*pwd->pw_passwd)) 22736460Sbostic break; 22812687Ssam 22936460Sbostic setpriority(PRIO_PROCESS, 0, -4); 23036608Skfall pp = getpass("Password:"); 23136608Skfall p = crypt(pp, salt); 23236460Sbostic setpriority(PRIO_PROCESS, 0, 0); 23336608Skfall 234*37203Sbostic #ifdef KERBEROS 235*37203Sbostic 236*37203Sbostic /* 237*37203Sbostic * If not present in pw file, act as we normally would. 238*37203Sbostic * If we aren't Kerberos-authenticated, try the normal 239*37203Sbostic * pw file for a password. If that's ok, log the user 240*37203Sbostic * in without issueing any tickets. 241*37203Sbostic */ 242*37203Sbostic 243*37203Sbostic if (pwd && !krb_get_lrealm(realm,1)) { 244*37203Sbostic /* 245*37203Sbostic * get TGT for local realm; be careful about uid's 246*37203Sbostic * here for ticket file ownership 247*37203Sbostic */ 248*37203Sbostic (void)setreuid(geteuid(),pwd->pw_uid); 249*37203Sbostic kerror = krb_get_pw_in_tkt(pwd->pw_name, "", realm, 250*37203Sbostic "krbtgt", realm, DEFAULT_TKT_LIFE, pp); 251*37203Sbostic (void)setuid(0); 252*37203Sbostic if (kerror == INTK_OK) { 253*37203Sbostic bzero(pp, strlen(pp)); 254*37203Sbostic notickets = 0; /* user got ticket */ 255*37203Sbostic break; 256*37203Sbostic } 257*37203Sbostic } 258*37203Sbostic #endif 25936608Skfall (void) bzero(pp, strlen(pp)); 26036515Sbostic if (pwd && !strcmp(p, pwd->pw_passwd)) 26136460Sbostic break; 26236460Sbostic 263*37203Sbostic (void)printf("Login incorrect\n"); 26436647Skarels failures++; 26536549Sbostic /* we allow 10 tries, but after 3 we start backing off */ 26636549Sbostic if (++cnt > 3) { 26736549Sbostic if (cnt >= 10) { 26836549Sbostic badlogin(username); 26936549Sbostic (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); 27036549Sbostic sleepexit(1); 27136549Sbostic } 27236549Sbostic sleep((u_int)((cnt - 3) * 5)); 2732822Swnj } 27436460Sbostic } 2751043Sbill 27636460Sbostic /* committed to login -- turn off timeout */ 27736460Sbostic (void)alarm((u_int)0); 27836460Sbostic 27936460Sbostic /* 28036460Sbostic * If valid so far and root is logging in, see if root logins on 28136460Sbostic * this terminal are permitted. 28236460Sbostic */ 28336647Skarels if (pwd->pw_uid == 0 && !rootterm(tty)) { 28436460Sbostic if (hostname) 28536647Skarels syslog(LOG_NOTICE, "ROOT LOGIN REFUSED FROM %s", 28636647Skarels hostname); 28712678Ssam else 28836647Skarels syslog(LOG_NOTICE, "ROOT LOGIN REFUSED ON %s", tty); 289*37203Sbostic (void)printf("Login incorrect\n"); 29036460Sbostic sleepexit(1); 29112678Ssam } 2922822Swnj 29336460Sbostic if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 29436460Sbostic switch(errno) { 29536460Sbostic case EUSERS: 296*37203Sbostic (void)fprintf(stderr, 29736460Sbostic "Too many users logged on already.\nTry again later.\n"); 29836460Sbostic break; 29936460Sbostic case EPROCLIM: 300*37203Sbostic (void)fprintf(stderr, 30136460Sbostic "You have too many processes running.\n"); 30236460Sbostic break; 30336460Sbostic default: 30436460Sbostic perror("quota (Q_SETUID)"); 3052822Swnj } 30636460Sbostic sleepexit(0); 3072822Swnj } 30836460Sbostic 30936515Sbostic if (chdir(pwd->pw_dir) < 0) { 310*37203Sbostic (void)printf("No directory %s!\n", pwd->pw_dir); 31136515Sbostic if (chdir("/")) 31236515Sbostic exit(0); 31336515Sbostic pwd->pw_dir = "/"; 314*37203Sbostic (void)printf("Logging in with home = \"/\".\n"); 31536515Sbostic } 31636515Sbostic 317*37203Sbostic quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 318*37203Sbostic 319*37203Sbostic #ifdef KERBEROS 320*37203Sbostic if (notickets && !quietlog) 321*37203Sbostic (void)printf("Warning: no Kerberos tickets issued\n"); 322*37203Sbostic #endif 323*37203Sbostic 32436880Sbostic #define TWOWEEKS (14*24*60*60) 32536880Sbostic if (pwd->pw_change || pwd->pw_expire) 32636880Sbostic (void)gettimeofday(&tp, (struct timezone *)NULL); 32736880Sbostic if (pwd->pw_change) 32836880Sbostic if (tp.tv_sec >= pwd->pw_change) { 329*37203Sbostic (void)printf("Sorry -- your password has expired.\n"); 33036880Sbostic sleepexit(1); 33136880Sbostic } 332*37203Sbostic else if (tp.tv_sec - pwd->pw_change < TWOWEEKS && !quietlog) { 33336880Sbostic ttp = localtime(&pwd->pw_change); 334*37203Sbostic (void)printf("Warning: your password expires on %s %d, %d\n", 335*37203Sbostic months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); 33636880Sbostic } 33736880Sbostic if (pwd->pw_expire) 33836880Sbostic if (tp.tv_sec >= pwd->pw_expire) { 339*37203Sbostic (void)printf("Sorry -- your account has expired.\n"); 34036880Sbostic sleepexit(1); 34136880Sbostic } 342*37203Sbostic else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS && !quietlog) { 34336880Sbostic ttp = localtime(&pwd->pw_expire); 344*37203Sbostic (void)printf("Warning: your account expires on %s %d, %d\n", 345*37203Sbostic months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); 34636880Sbostic } 34736880Sbostic 34836515Sbostic /* nothing else left to fail -- really log in */ 34936460Sbostic { 35036460Sbostic struct utmp utmp; 35136460Sbostic 35236647Skarels bzero((char *)&utmp, sizeof(utmp)); 35336460Sbostic (void)time(&utmp.ut_time); 35436460Sbostic strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 35536591Sbostic if (hostname) 35636591Sbostic strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 35736460Sbostic strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 35836460Sbostic login(&utmp); 35936460Sbostic } 36036460Sbostic 36136549Sbostic dolastlog(quietlog); 36236460Sbostic 363*37203Sbostic if (!hflag) { /* XXX */ 36436460Sbostic static struct winsize win = { 0, 0, 0, 0 }; 36536460Sbostic 36636460Sbostic (void)ioctl(0, TIOCSWINSZ, &win); 36736460Sbostic } 36836460Sbostic 36936460Sbostic (void)chown(ttyn, pwd->pw_uid, 37036460Sbostic (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 37136460Sbostic (void)chmod(ttyn, 0620); 37236460Sbostic (void)setgid(pwd->pw_gid); 37336460Sbostic 37436460Sbostic initgroups(username, pwd->pw_gid); 37536460Sbostic 37612678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 37730606Sbostic 37836515Sbostic if (*pwd->pw_shell == '\0') 379*37203Sbostic pwd->pw_shell = _PATH_BSHELL; 38036515Sbostic /* turn on new line discipline for the csh */ 381*37203Sbostic else if (!strcmp(pwd->pw_shell, _PATH_CSHELL)) { 38236515Sbostic ioctlval = NTTYDISC; 38336515Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 38436515Sbostic } 38536515Sbostic 38636460Sbostic /* destroy environment unless user has requested preservation */ 38718549Ssam if (!pflag) 38818549Ssam environ = envinit; 38936515Sbostic (void)setenv("HOME", pwd->pw_dir, 1); 39036515Sbostic (void)setenv("SHELL", pwd->pw_shell, 1); 39118549Ssam if (term[0] == '\0') 39236647Skarels strncpy(term, stypeof(tty), sizeof(term)); 39336515Sbostic (void)setenv("TERM", term, 0); 39436515Sbostic (void)setenv("USER", pwd->pw_name, 1); 39536515Sbostic (void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0); 39618549Ssam 39716453Sroot if (tty[sizeof("tty")-1] == 'd') 39818549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 39918549Ssam if (pwd->pw_uid == 0) 40036460Sbostic if (hostname) 40136647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", 40236549Sbostic tty, hostname); 40325230Smckusick else 40436647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); 40536460Sbostic 4066329Swnj if (!quietlog) { 40717664Sserge struct stat st; 40818549Ssam 40936460Sbostic motd(); 410*37203Sbostic (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 41136460Sbostic if (stat(tbuf, &st) == 0 && st.st_size != 0) 412*37203Sbostic (void)printf("You have %smail.\n", 41336460Sbostic (st.st_mtime > st.st_atime) ? "new " : ""); 4142822Swnj } 41536460Sbostic 41636460Sbostic (void)signal(SIGALRM, SIG_DFL); 41736460Sbostic (void)signal(SIGQUIT, SIG_DFL); 41836460Sbostic (void)signal(SIGINT, SIG_DFL); 41936460Sbostic (void)signal(SIGTSTP, SIG_IGN); 42036460Sbostic 42136460Sbostic tbuf[0] = '-'; 42236460Sbostic strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? 42336460Sbostic p + 1 : pwd->pw_shell); 424*37203Sbostic 425*37203Sbostic /* discard permissions last so can't get killed and drop core */ 426*37203Sbostic (void)setuid(pwd->pw_uid); 427*37203Sbostic 42836460Sbostic execlp(pwd->pw_shell, tbuf, 0); 429*37203Sbostic (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); 4301043Sbill exit(0); 4311043Sbill } 4321043Sbill 43336460Sbostic getloginname() 43412687Ssam { 43536460Sbostic register int ch; 43636460Sbostic register char *p; 43736460Sbostic static char nbuf[UT_NAMESIZE + 1]; 43812687Ssam 43936460Sbostic for (;;) { 440*37203Sbostic (void)printf("login: "); 44136515Sbostic for (p = nbuf; (ch = getchar()) != '\n'; ) { 44236549Sbostic if (ch == EOF) { 44336549Sbostic badlogin(username); 44412687Ssam exit(0); 44536549Sbostic } 44636515Sbostic if (p < nbuf + UT_NAMESIZE) 44736460Sbostic *p++ = ch; 44812687Ssam } 44936460Sbostic if (p > nbuf) 45036460Sbostic if (nbuf[0] == '-') 451*37203Sbostic (void)fprintf(stderr, 45236460Sbostic "login names may not start with '-'.\n"); 45336460Sbostic else { 45436460Sbostic *p = '\0'; 45536460Sbostic username = nbuf; 45636515Sbostic break; 45736460Sbostic } 45812687Ssam } 45912687Ssam } 46012687Ssam 46112687Ssam timedout() 46212687Ssam { 463*37203Sbostic (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 46412687Ssam exit(0); 46512687Ssam } 46612687Ssam 46736647Skarels rootterm(ttyn) 46836647Skarels char *ttyn; 4691043Sbill { 47036460Sbostic struct ttyent *t; 4716466Swnj 47236647Skarels return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); 4731043Sbill } 4741043Sbill 47536515Sbostic jmp_buf motdinterrupt; 47636515Sbostic 47736460Sbostic motd() 4782822Swnj { 47936515Sbostic register int fd, nchars; 48036460Sbostic int (*oldint)(), sigint(); 48136515Sbostic char tbuf[8192]; 4822822Swnj 483*37203Sbostic if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) 48436460Sbostic return; 48536460Sbostic oldint = signal(SIGINT, sigint); 48636515Sbostic if (setjmp(motdinterrupt) == 0) 48736515Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 48836515Sbostic (void)write(fileno(stdout), tbuf, nchars); 48936460Sbostic (void)signal(SIGINT, oldint); 49036515Sbostic (void)close(fd); 49136460Sbostic } 49236460Sbostic 49336460Sbostic sigint() 49436460Sbostic { 49536515Sbostic longjmp(motdinterrupt, 1); 49636460Sbostic } 49736460Sbostic 49836460Sbostic checknologin() 49936460Sbostic { 50036460Sbostic register int fd, nchars; 50136515Sbostic char tbuf[8192]; 50236460Sbostic 503*37203Sbostic if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 50436460Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 50536460Sbostic (void)write(fileno(stdout), tbuf, nchars); 50636460Sbostic sleepexit(0); 5072822Swnj } 5082822Swnj } 5092822Swnj 51036549Sbostic dolastlog(quiet) 51136460Sbostic int quiet; 5121043Sbill { 51336460Sbostic struct lastlog ll; 51436460Sbostic int fd; 51536880Sbostic char *ctime(); 5161043Sbill 517*37203Sbostic if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 51836515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 51936460Sbostic if (!quiet) { 52036460Sbostic if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 52136460Sbostic ll.ll_time != 0) { 522*37203Sbostic (void)printf("Last login: %.*s ", 52336460Sbostic 24-5, (char *)ctime(&ll.ll_time)); 52436460Sbostic if (*ll.ll_host != '\0') 525*37203Sbostic (void)printf("from %.*s\n", 52636460Sbostic sizeof(ll.ll_host), ll.ll_host); 52736460Sbostic else 528*37203Sbostic (void)printf("on %.*s\n", 52936460Sbostic sizeof(ll.ll_line), ll.ll_line); 53036460Sbostic } 53136515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 53236460Sbostic } 53336647Skarels bzero((char *)&ll, sizeof(ll)); 53436460Sbostic (void)time(&ll.ll_time); 53536460Sbostic strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 53636591Sbostic if (hostname) 53736591Sbostic strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 53836460Sbostic (void)write(fd, (char *)&ll, sizeof(ll)); 53936460Sbostic (void)close(fd); 5401043Sbill } 5411043Sbill } 5421043Sbill 54336549Sbostic badlogin(name) 54436549Sbostic char *name; 54536549Sbostic { 54636647Skarels if (failures == 0) 54736549Sbostic return; 54836549Sbostic if (hostname) 54936647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", 55036647Skarels failures, failures > 1 ? "S" : "", hostname, name); 55136549Sbostic else 55236647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", 55336647Skarels failures, failures > 1 ? "S" : "", tty, name); 55436549Sbostic } 55536549Sbostic 5562822Swnj #undef UNKNOWN 55736460Sbostic #define UNKNOWN "su" 5581043Sbill 5591043Sbill char * 56036647Skarels stypeof(ttyid) 56136647Skarels char *ttyid; 5621043Sbill { 56336460Sbostic struct ttyent *t; 5641043Sbill 56536647Skarels return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 5661043Sbill } 5676005Swnj 5686005Swnj getstr(buf, cnt, err) 56936460Sbostic char *buf, *err; 5706005Swnj int cnt; 5716005Swnj { 57236460Sbostic char ch; 5736005Swnj 5746005Swnj do { 57536460Sbostic if (read(0, &ch, sizeof(ch)) != sizeof(ch)) 5766005Swnj exit(1); 5776005Swnj if (--cnt < 0) { 578*37203Sbostic (void)fprintf(stderr, "%s too long\r\n", err); 57936460Sbostic sleepexit(1); 5806005Swnj } 58136460Sbostic *buf++ = ch; 58236460Sbostic } while (ch); 5836005Swnj } 5846329Swnj 58536460Sbostic sleepexit(eval) 58636460Sbostic int eval; 58726862Smckusick { 58836460Sbostic sleep((u_int)5); 58936460Sbostic exit(eval); 59026862Smckusick } 591