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*37692Sbostic static char sccsid[] = "@(#)login.c 5.40 (Berkeley) 05/09/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> 35*37692Sbostic #include <ufs/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> 4412678Ssam #include <errno.h> 4516453Sroot #include <ttyent.h> 4616453Sroot #include <syslog.h> 4726862Smckusick #include <grp.h> 4836460Sbostic #include <pwd.h> 4936515Sbostic #include <setjmp.h> 5036460Sbostic #include <stdio.h> 5136460Sbostic #include <strings.h> 5237203Sbostic #include <tzfile.h> 5337203Sbostic #include "pathnames.h" 541043Sbill 5537203Sbostic #ifdef KERBEROS 5637203Sbostic #include <kerberos/krb.h> 5737203Sbostic #include <sys/termios.h> 5837203Sbostic char realm[REALM_SZ]; 5937203Sbostic int kerror = KSUCCESS, notickets = 1; 6037203Sbostic #endif 6137203Sbostic 6236460Sbostic #define TTYGRPNAME "tty" /* name of group to own ttys */ 6326862Smckusick 6412687Ssam /* 6536460Sbostic * This bounds the time given to login. Not a define so it can 6636460Sbostic * be patched on machines where it's too small. 6712687Ssam */ 6831509Sbostic int timeout = 300; 696005Swnj 7036647Skarels struct passwd *pwd; 7136647Skarels int failures; 7236647Skarels char term[64], *hostname, *username, *tty; 736005Swnj 7436647Skarels struct sgttyb sgttyb; 7536647Skarels struct tchars tc = { 7613074Ssam CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK 771365Sbill }; 7836647Skarels struct ltchars ltc = { 7913074Ssam CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT 8013074Ssam }; 811365Sbill 8236880Sbostic char *months[] = 8336880Sbostic { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", 8436880Sbostic "Sep", "Oct", "Nov", "Dec" }; 8536880Sbostic 861043Sbill main(argc, argv) 8736460Sbostic int argc; 8836460Sbostic char **argv; 891043Sbill { 9036460Sbostic extern int errno, optind; 9136460Sbostic extern char *optarg, **environ; 9236880Sbostic struct timeval tp; 9336880Sbostic struct tm *ttp; 9436460Sbostic struct group *gr; 9536460Sbostic register int ch; 9636647Skarels register char *p; 9737203Sbostic int ask, fflag, hflag, pflag, cnt; 9836460Sbostic int quietlog, passwd_req, ioctlval, timedout(); 9936647Skarels char *domain, *salt, *envinit[1], *ttyn, *pp; 100*37692Sbostic char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; 10136880Sbostic char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); 10236460Sbostic time_t time(); 10336460Sbostic off_t lseek(); 1041043Sbill 10536460Sbostic (void)signal(SIGALRM, timedout); 10636460Sbostic (void)alarm((u_int)timeout); 10736460Sbostic (void)signal(SIGQUIT, SIG_IGN); 10836460Sbostic (void)signal(SIGINT, SIG_IGN); 10936460Sbostic (void)setpriority(PRIO_PROCESS, 0, 0); 11036460Sbostic (void)quota(Q_SETUID, 0, 0, 0); 11136460Sbostic 11212687Ssam /* 11318549Ssam * -p is used by getty to tell login not to destroy the environment 11431695Skarels * -f is used to skip a second login authentication 11536523Skarels * -h is used by other servers to pass the name of the remote 11636523Skarels * host to login so that it may be placed in utmp and wtmp 11712687Ssam */ 11836460Sbostic (void)gethostname(tbuf, sizeof(tbuf)); 11936460Sbostic domain = index(tbuf, '.'); 12036460Sbostic 12137203Sbostic fflag = hflag = pflag = 0; 12236460Sbostic passwd_req = 1; 12337203Sbostic while ((ch = getopt(argc, argv, "fh:p")) != EOF) 12436515Sbostic switch (ch) { 12536460Sbostic case 'f': 12636460Sbostic fflag = 1; 12736460Sbostic break; 12836460Sbostic case 'h': 12936460Sbostic if (getuid()) { 13037203Sbostic (void)fprintf(stderr, 13136460Sbostic "login: -h for super-user only.\n"); 13232313Sbostic exit(1); 13331695Skarels } 13436460Sbostic hflag = 1; 13536460Sbostic if (domain && (p = index(optarg, '.')) && 13636553Sbostic strcasecmp(p, domain) == 0) 13736460Sbostic *p = 0; 13836460Sbostic hostname = optarg; 13936460Sbostic break; 14036460Sbostic case 'p': 14118549Ssam pflag = 1; 14236460Sbostic break; 14336460Sbostic case '?': 14436460Sbostic default: 14537203Sbostic (void)fprintf(stderr, 14637203Sbostic "usage: login [-fp] [username]\n"); 14736460Sbostic exit(1); 14818549Ssam } 14936460Sbostic argc -= optind; 15036460Sbostic argv += optind; 15136549Sbostic if (*argv) { 15236647Skarels username = *argv; 15336549Sbostic ask = 0; 15436647Skarels } else 15536549Sbostic ask = 1; 15636460Sbostic 15736460Sbostic ioctlval = 0; 15836460Sbostic (void)ioctl(0, TIOCLSET, &ioctlval); 15936460Sbostic (void)ioctl(0, TIOCNXCL, 0); 16036515Sbostic (void)fcntl(0, F_SETFL, ioctlval); 16136515Sbostic (void)ioctl(0, TIOCGETP, &sgttyb); 16236515Sbostic sgttyb.sg_erase = CERASE; 16336515Sbostic sgttyb.sg_kill = CKILL; 16436460Sbostic (void)ioctl(0, TIOCSLTC, <c); 16536460Sbostic (void)ioctl(0, TIOCSETC, &tc); 16636515Sbostic (void)ioctl(0, TIOCSETP, &sgttyb); 16736460Sbostic 16836460Sbostic for (cnt = getdtablesize(); cnt > 2; cnt--) 16936460Sbostic close(cnt); 17036460Sbostic 1711043Sbill ttyn = ttyname(0); 172*37692Sbostic if (ttyn == NULL || *ttyn == '\0') { 173*37692Sbostic (void)sprintf(tname, "%s??", _PATH_TTY); 174*37692Sbostic ttyn = tname; 175*37692Sbostic } 17636460Sbostic if (tty = rindex(ttyn, '/')) 17736460Sbostic ++tty; 17836460Sbostic else 17916453Sroot tty = ttyn; 18036460Sbostic 18124852Seric openlog("login", LOG_ODELAY, LOG_AUTH); 18236460Sbostic 18336549Sbostic for (cnt = 0;; ask = 1) { 18436460Sbostic ioctlval = 0; 18536460Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 18636460Sbostic 18736549Sbostic if (ask) { 18836515Sbostic fflag = 0; 18936460Sbostic getloginname(); 19036515Sbostic } 19136647Skarels /* 19236647Skarels * Note if trying multiple user names; 19336647Skarels * log failures for previous user name, 19436647Skarels * but don't bother logging one failure 19536647Skarels * for nonexistent name (mistyped username). 19636647Skarels */ 19736647Skarels if (failures && strcmp(tbuf, username)) { 19836647Skarels if (failures > (pwd ? 0 : 1)) 19936549Sbostic badlogin(tbuf); 20036647Skarels failures = 0; 20136549Sbostic } 20236647Skarels (void)strcpy(tbuf, username); 20336515Sbostic if (pwd = getpwnam(username)) 20436515Sbostic salt = pwd->pw_passwd; 20536515Sbostic else 20636515Sbostic salt = "xx"; 20736460Sbostic 20836460Sbostic /* if user not super-user, check for disabled logins */ 20936515Sbostic if (pwd == NULL || pwd->pw_uid) 21036460Sbostic checknologin(); 21136460Sbostic 21212687Ssam /* 21336515Sbostic * Disallow automatic login to root; if not invoked by 21436515Sbostic * root, disallow if the uid's differ. 21512687Ssam */ 21636515Sbostic if (fflag && pwd) { 21731695Skarels int uid = getuid(); 21831695Skarels 21936515Sbostic passwd_req = pwd->pw_uid == 0 || 22036515Sbostic (uid && uid != pwd->pw_uid); 22131695Skarels } 22236460Sbostic 22312687Ssam /* 22436523Skarels * If no pre-authentication and a password exists 22536460Sbostic * for this user, prompt for one and verify it. 22612687Ssam */ 22736608Skfall if (!passwd_req || (pwd && !*pwd->pw_passwd)) 22836460Sbostic break; 22912687Ssam 23036460Sbostic setpriority(PRIO_PROCESS, 0, -4); 23136608Skfall pp = getpass("Password:"); 23236608Skfall p = crypt(pp, salt); 23336460Sbostic setpriority(PRIO_PROCESS, 0, 0); 23436608Skfall 23537203Sbostic #ifdef KERBEROS 23637203Sbostic 23737203Sbostic /* 23837203Sbostic * If not present in pw file, act as we normally would. 23937203Sbostic * If we aren't Kerberos-authenticated, try the normal 24037203Sbostic * pw file for a password. If that's ok, log the user 24137203Sbostic * in without issueing any tickets. 24237203Sbostic */ 24337203Sbostic 24437203Sbostic if (pwd && !krb_get_lrealm(realm,1)) { 24537203Sbostic /* 24637203Sbostic * get TGT for local realm; be careful about uid's 24737203Sbostic * here for ticket file ownership 24837203Sbostic */ 24937203Sbostic (void)setreuid(geteuid(),pwd->pw_uid); 25037203Sbostic kerror = krb_get_pw_in_tkt(pwd->pw_name, "", realm, 25137203Sbostic "krbtgt", realm, DEFAULT_TKT_LIFE, pp); 25237203Sbostic (void)setuid(0); 25337203Sbostic if (kerror == INTK_OK) { 25437203Sbostic bzero(pp, strlen(pp)); 25537203Sbostic notickets = 0; /* user got ticket */ 25637203Sbostic break; 25737203Sbostic } 25837203Sbostic } 25937203Sbostic #endif 26036608Skfall (void) bzero(pp, strlen(pp)); 26136515Sbostic if (pwd && !strcmp(p, pwd->pw_passwd)) 26236460Sbostic break; 26336460Sbostic 26437203Sbostic (void)printf("Login incorrect\n"); 26536647Skarels failures++; 26636549Sbostic /* we allow 10 tries, but after 3 we start backing off */ 26736549Sbostic if (++cnt > 3) { 26836549Sbostic if (cnt >= 10) { 26936549Sbostic badlogin(username); 27036549Sbostic (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); 27136549Sbostic sleepexit(1); 27236549Sbostic } 27336549Sbostic sleep((u_int)((cnt - 3) * 5)); 2742822Swnj } 27536460Sbostic } 2761043Sbill 27736460Sbostic /* committed to login -- turn off timeout */ 27836460Sbostic (void)alarm((u_int)0); 27936460Sbostic 280*37692Sbostic /* paranoia... */ 281*37692Sbostic endpwent(); 282*37692Sbostic 28336460Sbostic /* 28436460Sbostic * If valid so far and root is logging in, see if root logins on 28536460Sbostic * this terminal are permitted. 28636460Sbostic */ 28736647Skarels if (pwd->pw_uid == 0 && !rootterm(tty)) { 28836460Sbostic if (hostname) 28936647Skarels syslog(LOG_NOTICE, "ROOT LOGIN REFUSED FROM %s", 29036647Skarels hostname); 29112678Ssam else 29236647Skarels syslog(LOG_NOTICE, "ROOT LOGIN REFUSED ON %s", tty); 29337203Sbostic (void)printf("Login incorrect\n"); 29436460Sbostic sleepexit(1); 29512678Ssam } 2962822Swnj 29736460Sbostic if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { 29836460Sbostic switch(errno) { 29936460Sbostic case EUSERS: 30037203Sbostic (void)fprintf(stderr, 30136460Sbostic "Too many users logged on already.\nTry again later.\n"); 30236460Sbostic break; 30336460Sbostic case EPROCLIM: 30437203Sbostic (void)fprintf(stderr, 30536460Sbostic "You have too many processes running.\n"); 30636460Sbostic break; 30736460Sbostic default: 30836460Sbostic perror("quota (Q_SETUID)"); 3092822Swnj } 31036460Sbostic sleepexit(0); 3112822Swnj } 31236460Sbostic 31336515Sbostic if (chdir(pwd->pw_dir) < 0) { 31437203Sbostic (void)printf("No directory %s!\n", pwd->pw_dir); 31536515Sbostic if (chdir("/")) 31636515Sbostic exit(0); 31736515Sbostic pwd->pw_dir = "/"; 31837203Sbostic (void)printf("Logging in with home = \"/\".\n"); 31936515Sbostic } 32036515Sbostic 32137203Sbostic quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 32237203Sbostic 32337203Sbostic #ifdef KERBEROS 32437203Sbostic if (notickets && !quietlog) 32537203Sbostic (void)printf("Warning: no Kerberos tickets issued\n"); 32637203Sbostic #endif 32737203Sbostic 32836880Sbostic #define TWOWEEKS (14*24*60*60) 32936880Sbostic if (pwd->pw_change || pwd->pw_expire) 33036880Sbostic (void)gettimeofday(&tp, (struct timezone *)NULL); 33136880Sbostic if (pwd->pw_change) 33236880Sbostic if (tp.tv_sec >= pwd->pw_change) { 33337203Sbostic (void)printf("Sorry -- your password has expired.\n"); 33436880Sbostic sleepexit(1); 33536880Sbostic } 33637203Sbostic else if (tp.tv_sec - pwd->pw_change < TWOWEEKS && !quietlog) { 33736880Sbostic ttp = localtime(&pwd->pw_change); 33837203Sbostic (void)printf("Warning: your password expires on %s %d, %d\n", 33937203Sbostic months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); 34036880Sbostic } 34136880Sbostic if (pwd->pw_expire) 34236880Sbostic if (tp.tv_sec >= pwd->pw_expire) { 34337203Sbostic (void)printf("Sorry -- your account has expired.\n"); 34436880Sbostic sleepexit(1); 34536880Sbostic } 34637203Sbostic else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS && !quietlog) { 34736880Sbostic ttp = localtime(&pwd->pw_expire); 34837203Sbostic (void)printf("Warning: your account expires on %s %d, %d\n", 34937203Sbostic months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); 35036880Sbostic } 35136880Sbostic 35236515Sbostic /* nothing else left to fail -- really log in */ 35336460Sbostic { 35436460Sbostic struct utmp utmp; 35536460Sbostic 35636647Skarels bzero((char *)&utmp, sizeof(utmp)); 35736460Sbostic (void)time(&utmp.ut_time); 35836460Sbostic strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 35936591Sbostic if (hostname) 36036591Sbostic strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 36136460Sbostic strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 36236460Sbostic login(&utmp); 36336460Sbostic } 36436460Sbostic 36536549Sbostic dolastlog(quietlog); 36636460Sbostic 36737203Sbostic if (!hflag) { /* XXX */ 36836460Sbostic static struct winsize win = { 0, 0, 0, 0 }; 36936460Sbostic 37036460Sbostic (void)ioctl(0, TIOCSWINSZ, &win); 37136460Sbostic } 37236460Sbostic 37336460Sbostic (void)chown(ttyn, pwd->pw_uid, 37436460Sbostic (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 37536460Sbostic (void)chmod(ttyn, 0620); 37636460Sbostic (void)setgid(pwd->pw_gid); 37736460Sbostic 37836460Sbostic initgroups(username, pwd->pw_gid); 37936460Sbostic 38012678Ssam quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); 38130606Sbostic 38236515Sbostic if (*pwd->pw_shell == '\0') 38337203Sbostic pwd->pw_shell = _PATH_BSHELL; 38436515Sbostic /* turn on new line discipline for the csh */ 38537203Sbostic else if (!strcmp(pwd->pw_shell, _PATH_CSHELL)) { 38636515Sbostic ioctlval = NTTYDISC; 38736515Sbostic (void)ioctl(0, TIOCSETD, &ioctlval); 38836515Sbostic } 38936515Sbostic 39036460Sbostic /* destroy environment unless user has requested preservation */ 39118549Ssam if (!pflag) 39218549Ssam environ = envinit; 39336515Sbostic (void)setenv("HOME", pwd->pw_dir, 1); 39436515Sbostic (void)setenv("SHELL", pwd->pw_shell, 1); 39518549Ssam if (term[0] == '\0') 39636647Skarels strncpy(term, stypeof(tty), sizeof(term)); 39736515Sbostic (void)setenv("TERM", term, 0); 39836515Sbostic (void)setenv("USER", pwd->pw_name, 1); 39937252Sbostic (void)setenv("PATH", _PATH_DEFPATH, 0); 40018549Ssam 40116453Sroot if (tty[sizeof("tty")-1] == 'd') 40218549Ssam syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 40318549Ssam if (pwd->pw_uid == 0) 40436460Sbostic if (hostname) 40536647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", 40636549Sbostic tty, hostname); 40725230Smckusick else 40836647Skarels syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); 40936460Sbostic 4106329Swnj if (!quietlog) { 41117664Sserge struct stat st; 41218549Ssam 41336460Sbostic motd(); 41437203Sbostic (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); 41536460Sbostic if (stat(tbuf, &st) == 0 && st.st_size != 0) 41637203Sbostic (void)printf("You have %smail.\n", 41736460Sbostic (st.st_mtime > st.st_atime) ? "new " : ""); 4182822Swnj } 41936460Sbostic 42036460Sbostic (void)signal(SIGALRM, SIG_DFL); 42136460Sbostic (void)signal(SIGQUIT, SIG_DFL); 42236460Sbostic (void)signal(SIGINT, SIG_DFL); 42336460Sbostic (void)signal(SIGTSTP, SIG_IGN); 42436460Sbostic 42536460Sbostic tbuf[0] = '-'; 42636460Sbostic strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? 42736460Sbostic p + 1 : pwd->pw_shell); 42837203Sbostic 429*37692Sbostic if (setlogname(pwd->pw_name, strlen(pwd->pw_name)) < 0) 430*37692Sbostic syslog(LOG_ERR, "setlogname() failure: %m"); 431*37692Sbostic 43237203Sbostic /* discard permissions last so can't get killed and drop core */ 43337203Sbostic (void)setuid(pwd->pw_uid); 43437203Sbostic 43536460Sbostic execlp(pwd->pw_shell, tbuf, 0); 43637203Sbostic (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); 4371043Sbill exit(0); 4381043Sbill } 4391043Sbill 44036460Sbostic getloginname() 44112687Ssam { 44236460Sbostic register int ch; 44336460Sbostic register char *p; 44436460Sbostic static char nbuf[UT_NAMESIZE + 1]; 44512687Ssam 44636460Sbostic for (;;) { 44737203Sbostic (void)printf("login: "); 44836515Sbostic for (p = nbuf; (ch = getchar()) != '\n'; ) { 44936549Sbostic if (ch == EOF) { 45036549Sbostic badlogin(username); 45112687Ssam exit(0); 45236549Sbostic } 45336515Sbostic if (p < nbuf + UT_NAMESIZE) 45436460Sbostic *p++ = ch; 45512687Ssam } 45636460Sbostic if (p > nbuf) 45736460Sbostic if (nbuf[0] == '-') 45837203Sbostic (void)fprintf(stderr, 45936460Sbostic "login names may not start with '-'.\n"); 46036460Sbostic else { 46136460Sbostic *p = '\0'; 46236460Sbostic username = nbuf; 46336515Sbostic break; 46436460Sbostic } 46512687Ssam } 46612687Ssam } 46712687Ssam 46812687Ssam timedout() 46912687Ssam { 47037203Sbostic (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 47112687Ssam exit(0); 47212687Ssam } 47312687Ssam 47436647Skarels rootterm(ttyn) 47536647Skarels char *ttyn; 4761043Sbill { 47736460Sbostic struct ttyent *t; 4786466Swnj 47936647Skarels return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); 4801043Sbill } 4811043Sbill 48236515Sbostic jmp_buf motdinterrupt; 48336515Sbostic 48436460Sbostic motd() 4852822Swnj { 48636515Sbostic register int fd, nchars; 48736460Sbostic int (*oldint)(), sigint(); 48836515Sbostic char tbuf[8192]; 4892822Swnj 49037203Sbostic if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) 49136460Sbostic return; 49236460Sbostic oldint = signal(SIGINT, sigint); 49336515Sbostic if (setjmp(motdinterrupt) == 0) 49436515Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 49536515Sbostic (void)write(fileno(stdout), tbuf, nchars); 49636460Sbostic (void)signal(SIGINT, oldint); 49736515Sbostic (void)close(fd); 49836460Sbostic } 49936460Sbostic 50036460Sbostic sigint() 50136460Sbostic { 50236515Sbostic longjmp(motdinterrupt, 1); 50336460Sbostic } 50436460Sbostic 50536460Sbostic checknologin() 50636460Sbostic { 50736460Sbostic register int fd, nchars; 50836515Sbostic char tbuf[8192]; 50936460Sbostic 51037203Sbostic if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 51136460Sbostic while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 51236460Sbostic (void)write(fileno(stdout), tbuf, nchars); 51336460Sbostic sleepexit(0); 5142822Swnj } 5152822Swnj } 5162822Swnj 51736549Sbostic dolastlog(quiet) 51836460Sbostic int quiet; 5191043Sbill { 52036460Sbostic struct lastlog ll; 52136460Sbostic int fd; 52236880Sbostic char *ctime(); 5231043Sbill 52437203Sbostic if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 52536515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 52636460Sbostic if (!quiet) { 52736460Sbostic if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 52836460Sbostic ll.ll_time != 0) { 52937203Sbostic (void)printf("Last login: %.*s ", 53036460Sbostic 24-5, (char *)ctime(&ll.ll_time)); 53136460Sbostic if (*ll.ll_host != '\0') 53237203Sbostic (void)printf("from %.*s\n", 53336460Sbostic sizeof(ll.ll_host), ll.ll_host); 53436460Sbostic else 53537203Sbostic (void)printf("on %.*s\n", 53636460Sbostic sizeof(ll.ll_line), ll.ll_line); 53736460Sbostic } 53836515Sbostic (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 53936460Sbostic } 54036647Skarels bzero((char *)&ll, sizeof(ll)); 54136460Sbostic (void)time(&ll.ll_time); 54236460Sbostic strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 54336591Sbostic if (hostname) 54436591Sbostic strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 54536460Sbostic (void)write(fd, (char *)&ll, sizeof(ll)); 54636460Sbostic (void)close(fd); 5471043Sbill } 5481043Sbill } 5491043Sbill 55036549Sbostic badlogin(name) 55136549Sbostic char *name; 55236549Sbostic { 55336647Skarels if (failures == 0) 55436549Sbostic return; 55536549Sbostic if (hostname) 55636647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", 55736647Skarels failures, failures > 1 ? "S" : "", hostname, name); 55836549Sbostic else 55936647Skarels syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", 56036647Skarels failures, failures > 1 ? "S" : "", tty, name); 56136549Sbostic } 56236549Sbostic 5632822Swnj #undef UNKNOWN 56436460Sbostic #define UNKNOWN "su" 5651043Sbill 5661043Sbill char * 56736647Skarels stypeof(ttyid) 56836647Skarels char *ttyid; 5691043Sbill { 57036460Sbostic struct ttyent *t; 5711043Sbill 57236647Skarels return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 5731043Sbill } 5746005Swnj 5756005Swnj getstr(buf, cnt, err) 57636460Sbostic char *buf, *err; 5776005Swnj int cnt; 5786005Swnj { 57936460Sbostic char ch; 5806005Swnj 5816005Swnj do { 58236460Sbostic if (read(0, &ch, sizeof(ch)) != sizeof(ch)) 5836005Swnj exit(1); 5846005Swnj if (--cnt < 0) { 58537203Sbostic (void)fprintf(stderr, "%s too long\r\n", err); 58636460Sbostic sleepexit(1); 5876005Swnj } 58836460Sbostic *buf++ = ch; 58936460Sbostic } while (ch); 5906005Swnj } 5916329Swnj 59236460Sbostic sleepexit(eval) 59336460Sbostic int eval; 59426862Smckusick { 59536460Sbostic sleep((u_int)5); 59636460Sbostic exit(eval); 59726862Smckusick } 598