login.c revision 27605
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 3423246Swosch#if 0 351590Srgrimesstatic char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 3823246Swosch#endif 391590Srgrimes 401590Srgrimes#ifndef lint 4127605Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94"; 4327605Scharnier#endif 4427605Scharnierstatic const char rcsid[] = 4527605Scharnier "$Id$"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes/* 491590Srgrimes * login [ name ] 501590Srgrimes * login -h hostname (for telnetd, etc.) 511590Srgrimes * login -f name (for pre-authenticated login: datakit, xterm, etc.) 521590Srgrimes */ 531590Srgrimes 5423246Swosch#include <sys/copyright.h> 551590Srgrimes#include <sys/param.h> 561590Srgrimes#include <sys/stat.h> 571590Srgrimes#include <sys/time.h> 581590Srgrimes#include <sys/resource.h> 591590Srgrimes#include <sys/file.h> 6016423Sache#include <netinet/in.h> 6116423Sache#include <arpa/inet.h> 621590Srgrimes 631590Srgrimes#include <err.h> 641590Srgrimes#include <errno.h> 651590Srgrimes#include <grp.h> 6616423Sache#include <netdb.h> 671590Srgrimes#include <pwd.h> 681590Srgrimes#include <setjmp.h> 691590Srgrimes#include <signal.h> 701590Srgrimes#include <stdio.h> 711590Srgrimes#include <stdlib.h> 721590Srgrimes#include <string.h> 731590Srgrimes#include <syslog.h> 741590Srgrimes#include <ttyent.h> 751590Srgrimes#include <unistd.h> 761590Srgrimes#include <utmp.h> 771590Srgrimes 7821528Sdavidn#ifdef LOGIN_CAP 7921528Sdavidn#include <login_cap.h> 8021528Sdavidn#else /* Undef AUTH as well */ 8121528Sdavidn#undef LOGIN_CAP_AUTH 8221528Sdavidn#endif 8321528Sdavidn 8423985Sdavidn/* 8523985Sdavidn * If LOGIN_CAP_AUTH is activated: 8621528Sdavidn * kerberose & skey logins are runtime selected via login 8721528Sdavidn * login_getstyle() and authentication types for login classes 8821528Sdavidn * The actual login itself is handled via /usr/libexec/login_<style> 8921528Sdavidn * Valid styles are determined by the auth-type=style,style entries 9021528Sdavidn * in the login class. 9121528Sdavidn */ 9221528Sdavidn#ifdef LOGIN_CAP_AUTH 9321528Sdavidn#undef KERBEROS 9421528Sdavidn#undef SKEY 9523985Sdavidn#endif /* LOGIN_CAP_AUTH */ 9623985Sdavidn 973702Spst#ifdef SKEY 983702Spst#include <skey.h> 9921528Sdavidn#endif /* SKEY */ 1003702Spst 1011590Srgrimes#include "pathnames.h" 1021590Srgrimes 1031590Srgrimesvoid badlogin __P((char *)); 1041590Srgrimesvoid checknologin __P((void)); 1051590Srgrimesvoid dolastlog __P((int)); 1061590Srgrimesvoid getloginname __P((void)); 10721528Sdavidnvoid motd __P((char *)); 1081590Srgrimesint rootterm __P((char *)); 1091590Srgrimesvoid sigint __P((int)); 1101590Srgrimesvoid sleepexit __P((int)); 11123985Sdavidnvoid refused __P((char *,char *,int)); 1121590Srgrimeschar *stypeof __P((char *)); 1131590Srgrimesvoid timedout __P((int)); 1142224Sguidovoid login_fbtab __P((char *, uid_t, gid_t)); 1151590Srgrimes#ifdef KERBEROS 1161590Srgrimesint klogin __P((struct passwd *, char *, char *, char *)); 1171590Srgrimes#endif 1181590Srgrimes 1191590Srgrimesextern void login __P((struct utmp *)); 12027605Scharnierstatic void usage __P((void)); 1211590Srgrimes 1221590Srgrimes#define TTYGRPNAME "tty" /* name of group to own ttys */ 12323985Sdavidn#define DEFAULT_BACKOFF 3 12423985Sdavidn#define DEFAULT_RETRIES 10 1251590Srgrimes 1261590Srgrimes/* 1271590Srgrimes * This bounds the time given to login. Not a define so it can 1281590Srgrimes * be patched on machines where it's too small. 1291590Srgrimes */ 1301590Srgrimesu_int timeout = 300; 1311590Srgrimes 1321590Srgrimes#ifdef KERBEROS 1331590Srgrimesint notickets = 1; 1345627Swollmanint noticketsdontcomplain = 1; 1351590Srgrimeschar *instance; 1361590Srgrimeschar *krbtkfile_env; 1371590Srgrimesint authok; 1381590Srgrimes#endif 1391590Srgrimes 1401590Srgrimesstruct passwd *pwd; 1411590Srgrimesint failures; 14223985Sdavidnchar *term, *envinit[1], *hostname, *username, *tty; 14316423Sachechar full_hostname[MAXHOSTNAMELEN]; 1441590Srgrimes 1451590Srgrimesint 1461590Srgrimesmain(argc, argv) 1471590Srgrimes int argc; 1481590Srgrimes char *argv[]; 1491590Srgrimes{ 1501590Srgrimes extern char **environ; 1511590Srgrimes struct group *gr; 1521590Srgrimes struct stat st; 1531590Srgrimes struct timeval tp; 1541590Srgrimes struct utmp utmp; 15523985Sdavidn int rootok, retries, backoff; 1561590Srgrimes int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval; 1574878Sugen int changepass; 15823985Sdavidn time_t warntime; 1591590Srgrimes uid_t uid; 1603205Spst char *domain, *p, *ep, *salt, *ttyn; 1611590Srgrimes char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; 1621590Srgrimes char localhost[MAXHOSTNAMELEN]; 16323985Sdavidn char *shell = NULL; 16421528Sdavidn#ifdef LOGIN_CAP 16521528Sdavidn login_cap_t *lc = NULL; 16621528Sdavidn#ifdef LOGIN_CAP_AUTH 16721528Sdavidn char *style, *authtype; 16821528Sdavidn char *auth_method = NULL; 16921528Sdavidn char *instance = NULL; 17021528Sdavidn int authok; 17123985Sdavidn#endif /* LOGIN_CAP_AUTH */ 17223985Sdavidn#endif /* LOGIN_CAP */ 17321528Sdavidn#ifdef SKEY 1743205Spst int permit_passwd = 0; 17521528Sdavidn#endif /* SKEY */ 1761590Srgrimes 1771590Srgrimes (void)signal(SIGALRM, timedout); 1781590Srgrimes (void)alarm(timeout); 1791590Srgrimes (void)signal(SIGQUIT, SIG_IGN); 1801590Srgrimes (void)signal(SIGINT, SIG_IGN); 1811590Srgrimes (void)setpriority(PRIO_PROCESS, 0, 0); 1821590Srgrimes 1831590Srgrimes openlog("login", LOG_ODELAY, LOG_AUTH); 1841590Srgrimes 1851590Srgrimes /* 1861590Srgrimes * -p is used by getty to tell login not to destroy the environment 1871590Srgrimes * -f is used to skip a second login authentication 1881590Srgrimes * -h is used by other servers to pass the name of the remote 1891590Srgrimes * host to login so that it may be placed in utmp and wtmp 1901590Srgrimes */ 1913205Spst *full_hostname = '\0'; 1921590Srgrimes domain = NULL; 19323985Sdavidn term = NULL; 1941590Srgrimes if (gethostname(localhost, sizeof(localhost)) < 0) 1951590Srgrimes syslog(LOG_ERR, "couldn't get local hostname: %m"); 1961590Srgrimes else 1971590Srgrimes domain = strchr(localhost, '.'); 1981590Srgrimes 1991590Srgrimes fflag = hflag = pflag = 0; 2001590Srgrimes uid = getuid(); 20124360Simp while ((ch = getopt(argc, argv, "fh:p")) != -1) 2021590Srgrimes switch (ch) { 2031590Srgrimes case 'f': 2041590Srgrimes fflag = 1; 2051590Srgrimes break; 2061590Srgrimes case 'h': 2071590Srgrimes if (uid) 2081590Srgrimes errx(1, "-h option: %s", strerror(EPERM)); 2091590Srgrimes hflag = 1; 2103205Spst strncpy(full_hostname, optarg, sizeof(full_hostname)-1); 2111590Srgrimes if (domain && (p = strchr(optarg, '.')) && 2121590Srgrimes strcasecmp(p, domain) == 0) 2131590Srgrimes *p = 0; 21416423Sache if (strlen(optarg) > UT_HOSTSIZE) { 21516423Sache struct hostent *hp = gethostbyname(optarg); 21616423Sache 21716423Sache if (hp != NULL) { 21816423Sache struct in_addr in; 21916423Sache 22016423Sache memmove(&in, hp->h_addr, sizeof(in)); 22116423Sache optarg = strdup(inet_ntoa(in)); 22216423Sache } else 22316423Sache optarg = "invalid hostname"; 22416423Sache } 2251590Srgrimes hostname = optarg; 2261590Srgrimes break; 2271590Srgrimes case 'p': 2281590Srgrimes pflag = 1; 2291590Srgrimes break; 2301590Srgrimes case '?': 2311590Srgrimes default: 2321590Srgrimes if (!uid) 2331590Srgrimes syslog(LOG_ERR, "invalid flag %c", ch); 23427605Scharnier usage(); 2351590Srgrimes } 2361590Srgrimes argc -= optind; 2371590Srgrimes argv += optind; 2381590Srgrimes 2391590Srgrimes if (*argv) { 2401590Srgrimes username = *argv; 2411590Srgrimes ask = 0; 2421590Srgrimes } else 2431590Srgrimes ask = 1; 2441590Srgrimes 2451590Srgrimes for (cnt = getdtablesize(); cnt > 2; cnt--) 2461590Srgrimes (void)close(cnt); 2471590Srgrimes 2481590Srgrimes ttyn = ttyname(STDIN_FILENO); 2491590Srgrimes if (ttyn == NULL || *ttyn == '\0') { 2501590Srgrimes (void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY); 2511590Srgrimes ttyn = tname; 2521590Srgrimes } 25323985Sdavidn if ((tty = strrchr(ttyn, '/')) != NULL) 2541590Srgrimes ++tty; 2551590Srgrimes else 2561590Srgrimes tty = ttyn; 2571590Srgrimes 25821528Sdavidn#ifdef LOGIN_CAP_AUTH 25921528Sdavidn authtype = hostname ? "rlogin" : "login"; 26021528Sdavidn#endif 26123985Sdavidn#ifdef LOGIN_CAP 26223985Sdavidn /* 26323985Sdavidn * Get "login-retries" & "login-backoff" from default class 26423985Sdavidn */ 26523985Sdavidn lc = login_getclass(NULL); 26623985Sdavidn retries = login_getcapnum(lc, "login-retries", DEFAULT_RETRIES, DEFAULT_RETRIES); 26723985Sdavidn backoff = login_getcapnum(lc, "login-backoff", DEFAULT_BACKOFF, DEFAULT_BACKOFF); 26823985Sdavidn login_close(lc); 26923985Sdavidn lc = NULL; 27023985Sdavidn#else 27123985Sdavidn retries = DEFAULT_RETRIES; 27223985Sdavidn backoff = DEFAULT_BACKOFF; 27323985Sdavidn#endif 27421528Sdavidn 2751590Srgrimes for (cnt = 0;; ask = 1) { 2761590Srgrimes if (ask) { 2771590Srgrimes fflag = 0; 2781590Srgrimes getloginname(); 2791590Srgrimes } 2801590Srgrimes rootlogin = 0; 28121528Sdavidn rootok = rootterm(tty); /* Default (auth may change) */ 28221528Sdavidn#ifdef LOGIN_CAP_AUTH 28321528Sdavidn authok = 0; 28421528Sdavidn if (auth_method = strchr(username, ':')) { 28521528Sdavidn *auth_method = '\0'; 28621528Sdavidn auth_method++; 28721528Sdavidn if (*auth_method == '\0') 28821528Sdavidn auth_method = NULL; 28921528Sdavidn } 29021528Sdavidn /* 29121528Sdavidn * We need to do this regardless of whether 29221528Sdavidn * kerberos is available. 29321528Sdavidn */ 2941590Srgrimes if ((instance = strchr(username, '.')) != NULL) { 2951590Srgrimes if (strncmp(instance, ".root", 5) == 0) 2961590Srgrimes rootlogin = 1; 2971590Srgrimes *instance++ = '\0'; 2981590Srgrimes } else 2991590Srgrimes instance = ""; 30021528Sdavidn#else /* !LOGIN_CAP_AUTH */ 30121528Sdavidn#ifdef KERBEROS 30221528Sdavidn if ((instance = strchr(username, '.')) != NULL) { 30321528Sdavidn if (strncmp(instance, ".root", 5) == 0) 30421528Sdavidn rootlogin = 1; 30521528Sdavidn *instance++ = '\0'; 30621528Sdavidn } else 30721528Sdavidn instance = ""; 30821528Sdavidn#endif /* KERBEROS */ 30921528Sdavidn#endif /* LOGIN_CAP_AUTH */ 31021528Sdavidn 3111590Srgrimes if (strlen(username) > UT_NAMESIZE) 3121590Srgrimes username[UT_NAMESIZE] = '\0'; 3131590Srgrimes 3141590Srgrimes /* 3151590Srgrimes * Note if trying multiple user names; log failures for 3161590Srgrimes * previous user name, but don't bother logging one failure 3171590Srgrimes * for nonexistent name (mistyped username). 3181590Srgrimes */ 3191590Srgrimes if (failures && strcmp(tbuf, username)) { 3201590Srgrimes if (failures > (pwd ? 0 : 1)) 3211590Srgrimes badlogin(tbuf); 3221590Srgrimes failures = 0; 3231590Srgrimes } 32427605Scharnier (void)strncpy(tbuf, username, sizeof tbuf-1); 32527605Scharnier tbuf[sizeof tbuf-1] = '\0'; 3261590Srgrimes 32723985Sdavidn if ((pwd = getpwnam(username)) != NULL) 32823985Sdavidn salt = pwd->pw_passwd; 32923985Sdavidn else 33023985Sdavidn salt = "xx"; 33123985Sdavidn 33221528Sdavidn#ifdef LOGIN_CAP 33323985Sdavidn /* 33423985Sdavidn * Establish the class now, before we might goto 33521528Sdavidn * within the next block. pwd can be NULL since it 33621528Sdavidn * falls back to the "default" class if it is. 33721528Sdavidn */ 33825671Sdavidn lc = login_getpwclass(pwd); 33921528Sdavidn#endif /* LOGIN_CAP */ 3401590Srgrimes 3411590Srgrimes /* 3421590Srgrimes * if we have a valid account name, and it doesn't have a 3431590Srgrimes * password, or the -f option was specified and the caller 3441590Srgrimes * is root or the caller isn't changing their uid, don't 3451590Srgrimes * authenticate. 3461590Srgrimes */ 34723985Sdavidn rval = 1; 34821528Sdavidn if (pwd != NULL) { 3493205Spst if (pwd->pw_uid == 0) 3503205Spst rootlogin = 1; 3513205Spst 35223985Sdavidn if (fflag && (uid == (uid_t)0 || 35323985Sdavidn uid == (uid_t)pwd->pw_uid)) { 3543205Spst /* already authenticated */ 3553205Spst break; 3563205Spst } else if (pwd->pw_passwd[0] == '\0') { 35724321Sdavidn if (!rootlogin || rootok) { 35824251Sdavidn /* pretend password okay */ 35924251Sdavidn rval = 0; 36024251Sdavidn goto ttycheck; 36124251Sdavidn } 3623205Spst } 3633205Spst } 3643205Spst 3651590Srgrimes fflag = 0; 3661590Srgrimes 3671590Srgrimes (void)setpriority(PRIO_PROCESS, 0, -4); 3681590Srgrimes 36921528Sdavidn#ifdef LOGIN_CAP_AUTH 37021528Sdavidn /* 37123985Sdavidn * This hands off authorization to an authorization program, 37221528Sdavidn * depending on the styles available for the "auth-login", 37323985Sdavidn * auth-rlogin (or default) authorization styles. 37421528Sdavidn * We do this regardless of whether an account exists so that 37521528Sdavidn * the remote user cannot tell a "real" from an invented 37621528Sdavidn * account name. If we don't have an account we just fall 37721528Sdavidn * back to the first method for the "default" class. 37821528Sdavidn */ 37923985Sdavidn if (!(style = login_getstyle(lc, auth_method, authtype))) { 38023985Sdavidn 38123985Sdavidn /* 38223985Sdavidn * No available authorization method 38323985Sdavidn */ 38423985Sdavidn rval = 1; 38523985Sdavidn (void)printf("No auth method available for %s.\n", 38623985Sdavidn authtype); 38721528Sdavidn } else { 38823985Sdavidn 38923985Sdavidn /* 39023985Sdavidn * Put back the kerberos instance, if any was given. 39121528Sdavidn * Don't worry about the non-kerberos case here, since 39221528Sdavidn * if kerberos is not available or not selected and an 39321528Sdavidn * instance is given at the login prompt, su or rlogin -l, 39421528Sdavidn * then anything else should fail as well. 39521528Sdavidn */ 39621528Sdavidn if (*instance) 39721528Sdavidn *(instance - 1) = '.'; 39823985Sdavidn 39923985Sdavidn rval = authenticate(username, 40023985Sdavidn lc ? lc->lc_class : "default", 40123985Sdavidn style, authtype); 40221528Sdavidn /* Junk it again */ 40321528Sdavidn if (*instance) 40421528Sdavidn *(instance - 1) = '\0'; 40521528Sdavidn } 40621528Sdavidn 40721528Sdavidn if (!rval) { 40823985Sdavidn char * approvp; 40923985Sdavidn 41021528Sdavidn /* 41121528Sdavidn * If authentication succeeds, run any approval 41221528Sdavidn * program, if applicable for this class. 41321528Sdavidn */ 41423985Sdavidn approvep = login_getcapstr(lc, "approve", NULL, NULL); 41521528Sdavidn rval = 1; /* Assume bad login again */ 41623985Sdavidn 41723985Sdavidn if (approvep==NULL || 41823985Sdavidn auth_script(approvep, approvep, username, 41923985Sdavidn lc->lc_class, 0) == 0) { 42023985Sdavidn int r; 42123985Sdavidn 42223985Sdavidn r = auth_scan(AUTH_OKAY); 42323985Sdavidn /* 42423985Sdavidn * See what the authorize program says 42523985Sdavidn */ 42621528Sdavidn if (r != AUTH_NONE) { 42721528Sdavidn rval = 0; 42823985Sdavidn 42921528Sdavidn if (!rootok && (r & AUTH_ROOTOKAY)) 43021528Sdavidn rootok = 1; /* root approved */ 43123985Sdavidn else 43223985Sdavidn rootlogin = 0; 43323985Sdavidn 43421528Sdavidn if (!authok && (r & AUTH_SECURE)) 43521528Sdavidn authok = 1; /* secure */ 43621528Sdavidn } 43721528Sdavidn } 43821528Sdavidn } 43921528Sdavidn#else /* !LOGIN_CAP_AUTH */ 44021528Sdavidn#ifdef SKEY 44123985Sdavidn permit_passwd = skeyaccess(username, tty, 44223985Sdavidn hostname ? full_hostname : NULL, 44323985Sdavidn NULL); 4443205Spst p = skey_getpass("Password:", pwd, permit_passwd); 4453205Spst ep = skey_crypt(p, salt, pwd, permit_passwd); 44621528Sdavidn#else /* !SKEY */ 4471590Srgrimes p = getpass("Password:"); 4483205Spst ep = crypt(p, salt); 44921528Sdavidn#endif/* SKEY */ 45023985Sdavidn 45123985Sdavidn if (pwd) { 4521590Srgrimes#ifdef KERBEROS 4537800Swollman#ifdef SKEY 45423985Sdavidn /* 45523985Sdavidn * Do not allow user to type in kerberos password 4567800Swollman * over the net (actually, this is ok for encrypted 4577800Swollman * links, but we have no way of determining if the 4587800Swollman * link is encrypted. 4597800Swollman */ 4607893Srgrimes if (!permit_passwd) { 46123985Sdavidn rval = 1; /* failed */ 4627800Swollman } else 46321528Sdavidn#endif /* SKEY */ 4641590Srgrimes rval = klogin(pwd, instance, localhost, p); 4651590Srgrimes if (rval != 0 && rootlogin && pwd->pw_uid != 0) 4661590Srgrimes rootlogin = 0; 4671590Srgrimes if (rval == 0) 46821528Sdavidn authok = 1; /* kerberos authenticated ok */ 46921528Sdavidn else if (rval == 1) /* fallback to unix passwd */ 4703205Spst rval = strcmp(ep, pwd->pw_passwd); 47121528Sdavidn#else /* !KERBEROS */ 47223985Sdavidn rval = strcmp(ep, pwd->pw_passwd); 47321528Sdavidn#endif /* KERBEROS */ 47423985Sdavidn } 47523985Sdavidn 47621528Sdavidn /* clear entered password */ 4771590Srgrimes memset(p, 0, strlen(p)); 47821528Sdavidn#endif /* LOGIN_CAP_AUTH */ 4791590Srgrimes 4801590Srgrimes (void)setpriority(PRIO_PROCESS, 0, 0); 48123985Sdavidn 48225671Sdavidn#ifdef LOGIN_CAP_AUTH 48321528Sdavidn if (rval) 48421528Sdavidn auth_rmfiles(); 48521528Sdavidn#endif 4863205Spst ttycheck: 4871590Srgrimes /* 4881590Srgrimes * If trying to log in as root without Kerberos, 4891590Srgrimes * but with insecure terminal, refuse the login attempt. 4901590Srgrimes */ 49124222Sdavidn if (pwd && !rval) { 49221528Sdavidn#if defined(KERBEROS) || defined(LOGIN_CAP_AUTH) 49324222Sdavidn if (authok == 0 && rootlogin && !rootok) 49424222Sdavidn#else 49524222Sdavidn if (rootlogin && !rootok) 4961590Srgrimes#endif 49724222Sdavidn refused(NULL, "NOROOT", 0); 49824222Sdavidn else /* valid password & authenticated */ 49924222Sdavidn break; 5001590Srgrimes } 5011590Srgrimes 5021590Srgrimes (void)printf("Login incorrect\n"); 5031590Srgrimes failures++; 50423985Sdavidn 50523985Sdavidn /* 50623985Sdavidn * we allow up to 'retry' (10) tries, 50723985Sdavidn * but after 'backoff' (3) we start backing off 50823985Sdavidn */ 50923985Sdavidn if (++cnt > backoff) { 51023985Sdavidn if (cnt >= retries) { 5111590Srgrimes badlogin(username); 5121590Srgrimes sleepexit(1); 5131590Srgrimes } 5141590Srgrimes sleep((u_int)((cnt - 3) * 5)); 5151590Srgrimes } 5161590Srgrimes } 5171590Srgrimes 5181590Srgrimes /* committed to login -- turn off timeout */ 5191590Srgrimes (void)alarm((u_int)0); 5201590Srgrimes 5211590Srgrimes endpwent(); 5221590Srgrimes 5231590Srgrimes /* if user not super-user, check for disabled logins */ 52421528Sdavidn#ifdef LOGIN_CAP 5251590Srgrimes if (!rootlogin) 52621528Sdavidn auth_checknologin(lc); 52721528Sdavidn#else 52821528Sdavidn if (!rootlogin) 5291590Srgrimes checknologin(); 53021528Sdavidn#endif 5311590Srgrimes 53221528Sdavidn#ifdef LOGIN_CAP 53321528Sdavidn quietlog = login_getcapbool(lc, "hushlogin", 0); 53421528Sdavidn#else 53521528Sdavidn quietlog = 0; 53621528Sdavidn#endif 53721528Sdavidn if (!*pwd->pw_dir || chdir(pwd->pw_dir) < 0) { 53821528Sdavidn#ifdef LOGIN_CAP 53926021Spst if (login_getcapbool(lc, "requirehome", 0)) 54023985Sdavidn refused("Home directory not available", "HOMEDIR", 1); 54123985Sdavidn#endif 54224485Sdavidn if (chdir("/") < 0) 54323985Sdavidn refused("Cannot find root directory", "ROOTDIR", 1); 5441590Srgrimes pwd->pw_dir = "/"; 54523985Sdavidn if (!quietlog || *pwd->pw_dir) 54623985Sdavidn printf("No home directory.\nLogging in with home = \"/\".\n"); 5471590Srgrimes } 54821528Sdavidn if (!quietlog) 54921528Sdavidn quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 5501590Srgrimes 5511590Srgrimes if (pwd->pw_change || pwd->pw_expire) 5521590Srgrimes (void)gettimeofday(&tp, (struct timezone *)NULL); 5532532Sjkh 55421528Sdavidn#define DEFAULT_WARN (2L * 7L & 86400L) /* Two weeks */ 55521528Sdavidn 55623985Sdavidn#ifdef LOGIN_CAP 55723985Sdavidn warntime = login_getcaptime(lc, "warnpassword", 55823985Sdavidn DEFAULT_WARN, DEFAULT_WARN); 55923985Sdavidn#else 56023985Sdavidn warntime = DEFAULT_WARN; 56123985Sdavidn#endif 56223985Sdavidn 5634878Sugen changepass=0; 56421528Sdavidn if (pwd->pw_change) { 5651590Srgrimes if (tp.tv_sec >= pwd->pw_change) { 5661590Srgrimes (void)printf("Sorry -- your password has expired.\n"); 5674878Sugen changepass=1; 56823985Sdavidn syslog(LOG_INFO, 56923985Sdavidn "%s Password expired - forcing change", 57023985Sdavidn pwd->pw_name); 57123985Sdavidn } else if (pwd->pw_change - tp.tv_sec < warntime && !quietlog) 57223985Sdavidn (void)printf("Warning: your password expires on %s", 57323985Sdavidn ctime(&pwd->pw_change)); 57423985Sdavidn } 57523985Sdavidn 57621528Sdavidn#ifdef LOGIN_CAP 57723985Sdavidn warntime = login_getcaptime(lc, "warnexpire", 57823985Sdavidn DEFAULT_WARN, DEFAULT_WARN); 57921528Sdavidn#else 58023985Sdavidn warntime = DEFAULT_WARN; 58121528Sdavidn#endif 58223985Sdavidn 58321528Sdavidn if (pwd->pw_expire) { 5841590Srgrimes if (tp.tv_sec >= pwd->pw_expire) { 58523985Sdavidn refused("Sorry -- your account has expired", 58623985Sdavidn "EXPIRED", 1); 58723985Sdavidn } else if (pwd->pw_expire - tp.tv_sec < warntime && !quietlog) 58823985Sdavidn (void)printf("Warning: your account expires on %s", 58923985Sdavidn ctime(&pwd->pw_expire)); 59021528Sdavidn } 5911590Srgrimes 59221528Sdavidn#ifdef LOGIN_CAP 59321528Sdavidn if (lc != NULL) { 59421528Sdavidn if (hostname) { 59521528Sdavidn struct hostent *hp = gethostbyname(full_hostname); 59621528Sdavidn 59721528Sdavidn if (hp == NULL) 59821528Sdavidn optarg = NULL; 59921528Sdavidn else { 60021528Sdavidn struct in_addr in; 60121528Sdavidn memmove(&in, hp->h_addr, sizeof(in)); 60221528Sdavidn optarg = strdup(inet_ntoa(in)); 60321528Sdavidn } 60423985Sdavidn if (!auth_hostok(lc, full_hostname, optarg)) 60523985Sdavidn refused("Permission denied", "HOST", 1); 60621528Sdavidn } 60721528Sdavidn 60823985Sdavidn if (!auth_ttyok(lc, tty)) 60923985Sdavidn refused("Permission denied", "TTY", 1); 61021528Sdavidn 61123985Sdavidn if (!auth_timeok(lc, time(NULL))) 61223985Sdavidn refused("Logins not available right now", "TIME", 1); 61321528Sdavidn } 61423985Sdavidn shell=login_getcapstr(lc, "shell", pwd->pw_shell, pwd->pw_shell); 61521528Sdavidn#else /* !LOGIN_CAP */ 61623985Sdavidn shell=pwd->pw_shell; 61721528Sdavidn#endif /* LOGIN_CAP */ 61823985Sdavidn if (*pwd->pw_shell == '\0') 61923985Sdavidn pwd->pw_shell = _PATH_BSHELL; 62023985Sdavidn if (*shell == '\0') /* Not overridden */ 62123985Sdavidn shell = pwd->pw_shell; 62223985Sdavidn if ((shell = strdup(shell)) == NULL) { 62323985Sdavidn syslog(LOG_NOTICE, "memory allocation error"); 62423985Sdavidn sleepexit(1); 62523985Sdavidn } 62621528Sdavidn 62721528Sdavidn#ifdef LOGIN_ACCESS 62823985Sdavidn if (login_access(pwd->pw_name, hostname ? full_hostname : tty) == 0) 62923985Sdavidn refused("Permission denied", "ACCESS", 1); 63021528Sdavidn#endif /* LOGIN_ACCESS */ 63121528Sdavidn 6321590Srgrimes /* Nothing else left to fail -- really log in. */ 6331590Srgrimes memset((void *)&utmp, 0, sizeof(utmp)); 6341590Srgrimes (void)time(&utmp.ut_time); 6351590Srgrimes (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 6361590Srgrimes if (hostname) 6371590Srgrimes (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 6381590Srgrimes (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 6391590Srgrimes login(&utmp); 6401590Srgrimes 6411590Srgrimes dolastlog(quietlog); 6421590Srgrimes 6432224Sguido /* 6442224Sguido * Set device protections, depending on what terminal the 6452224Sguido * user is logged in. This feature is used on Suns to give 6462224Sguido * console users better privacy. 6472224Sguido */ 6482224Sguido login_fbtab(tty, pwd->pw_uid, pwd->pw_gid); 6492224Sguido 65023985Sdavidn (void)chown(ttyn, pwd->pw_uid, 65123985Sdavidn (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 6521590Srgrimes 65323985Sdavidn /* 65423985Sdavidn * Preserve TERM if it happens to be already set. 65523985Sdavidn */ 65624222Sdavidn if ((term = getenv("TERM")) != NULL) 65724222Sdavidn term = strdup(term); 6581590Srgrimes 65923985Sdavidn /* 66023985Sdavidn * Exclude cons/vt/ptys only, assume dialup otherwise 66123985Sdavidn * TODO: Make dialup tty determination a library call 66223985Sdavidn * for consistency (finger etc.) 66323985Sdavidn */ 66424894Sdavidn if (hostname==NULL && isdialuptty(tty)) 6651590Srgrimes syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 6661590Srgrimes 6671590Srgrimes#ifdef KERBEROS 6685627Swollman if (!quietlog && notickets == 1 && !noticketsdontcomplain) 6691590Srgrimes (void)printf("Warning: no Kerberos tickets issued.\n"); 6701590Srgrimes#endif 6711590Srgrimes 6723205Spst#ifdef LOGALL 6733205Spst /* 6743205Spst * Syslog each successful login, so we don't have to watch hundreds 6753205Spst * of wtmp or lastlogin files. 6763205Spst */ 67723985Sdavidn if (hostname) 67823985Sdavidn syslog(LOG_INFO, "login from %s on %s as %s", 67923985Sdavidn full_hostname, tty, pwd->pw_name); 68023985Sdavidn else 68123985Sdavidn syslog(LOG_INFO, "login on %s as %s", 68223985Sdavidn tty, pwd->pw_name); 68321528Sdavidn#endif 68421528Sdavidn 68523985Sdavidn /* 68623985Sdavidn * If fflag is on, assume caller/authenticator has logged root login. 68723985Sdavidn */ 68823985Sdavidn if (rootlogin && fflag == 0) 68923985Sdavidn { 69023985Sdavidn if (hostname) 69123985Sdavidn syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", 69223985Sdavidn username, tty, full_hostname); 69323985Sdavidn else 69423985Sdavidn syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", 69523985Sdavidn username, tty); 69623985Sdavidn } 69723985Sdavidn 69823985Sdavidn /* 69923985Sdavidn * Destroy environment unless user has requested its preservation. 70023985Sdavidn * We need to do this before setusercontext() because that may 70123985Sdavidn * set or reset some environment variables. 70223985Sdavidn */ 70321528Sdavidn if (!pflag) 70421528Sdavidn environ = envinit; 70521528Sdavidn 70623985Sdavidn /* 70723985Sdavidn * We don't need to be root anymore, so 70821528Sdavidn * set the user and session context 70921528Sdavidn */ 71021528Sdavidn#ifdef LOGIN_CAP 71121528Sdavidn if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETALL) != 0) { 71221528Sdavidn syslog(LOG_ERR, "setusercontext() failed - exiting"); 71321528Sdavidn exit(1); 7143205Spst } 71521528Sdavidn#else 71621528Sdavidn if (setlogin(pwd->pw_name) < 0) 71721528Sdavidn syslog(LOG_ERR, "setlogin() failure: %m"); 71821528Sdavidn 71921528Sdavidn (void)setgid(pwd->pw_gid); 72021528Sdavidn initgroups(username, pwd->pw_gid); 72121528Sdavidn (void)setuid(rootlogin ? 0 : pwd->pw_uid); 7223205Spst#endif 7233205Spst 72423148Sache (void)setenv("SHELL", pwd->pw_shell, 1); 72521528Sdavidn (void)setenv("HOME", pwd->pw_dir, 1); 72623985Sdavidn if (term != NULL && *term != '\0') 72721528Sdavidn (void)setenv("TERM", term, 1); /* Preset overrides */ 72821528Sdavidn else { 72923985Sdavidn (void)setenv("TERM", stypeof(tty), 0); /* Fallback doesn't */ 73021528Sdavidn } 73121528Sdavidn (void)setenv("LOGNAME", pwd->pw_name, 1); 73221528Sdavidn (void)setenv("USER", pwd->pw_name, 1); 73321528Sdavidn (void)setenv("PATH", rootlogin ? _PATH_STDPATH : _PATH_DEFPATH, 0); 73421528Sdavidn#ifdef KERBEROS 73521528Sdavidn if (krbtkfile_env) 73621528Sdavidn (void)setenv("KRBTKFILE", krbtkfile_env, 1); 73721528Sdavidn#endif 73823985Sdavidn#if LOGIN_CAP_AUTH 73923985Sdavidn auth_env(); 74021528Sdavidn#endif 74121528Sdavidn 74223985Sdavidn#ifdef LOGIN_CAP 7431590Srgrimes if (!quietlog) { 74423985Sdavidn char *cw; 74523985Sdavidn 74623985Sdavidn cw = login_getcapstr(lc, "copyright", NULL, NULL); 74721528Sdavidn if (cw != NULL && access(cw, F_OK) == 0) 74821528Sdavidn motd(cw); 74921528Sdavidn else 75023985Sdavidn (void)printf("%s\n\t%s %s\n", 75123985Sdavidn "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994", 75223985Sdavidn "The Regents of the University of California. ", 75323985Sdavidn "All rights reserved."); 75423985Sdavidn 75523985Sdavidn (void)printf("\n"); 75623985Sdavidn 75721528Sdavidn cw = login_getcapstr(lc, "welcome", NULL, NULL); 75821528Sdavidn if (cw == NULL || access(cw, F_OK) != 0) 75921528Sdavidn cw = _PATH_MOTDFILE; 76021528Sdavidn motd(cw); 76123985Sdavidn 76221528Sdavidn cw = getenv("MAIL"); /* $MAIL may have been set by class */ 76321528Sdavidn if (cw != NULL) { 76421528Sdavidn strncpy(tbuf, cw, sizeof(tbuf)); 76521528Sdavidn tbuf[sizeof(tbuf)-1] = '\0'; 76621528Sdavidn } else 76723985Sdavidn snprintf(tbuf, sizeof(tbuf), "%s/%s", 76823985Sdavidn _PATH_MAILDIR, pwd->pw_name); 76921528Sdavidn#else 77023985Sdavidn if (!quietlog) { 77123985Sdavidn (void)printf("%s\n\t%s %s\n", 77223985Sdavidn "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994", 77323985Sdavidn "The Regents of the University of California. ", 77423985Sdavidn "All rights reserved."); 77521528Sdavidn motd(_PATH_MOTDFILE); 77623985Sdavidn snprintf(tbuf, sizeof(tbuf), "%s/%s", 77723985Sdavidn _PATH_MAILDIR, pwd->pw_name); 77821528Sdavidn#endif 7791590Srgrimes if (stat(tbuf, &st) == 0 && st.st_size != 0) 78023985Sdavidn (void)printf("You have %smail.\n", 78123985Sdavidn (st.st_mtime > st.st_atime) ? "new " : ""); 7821590Srgrimes } 7831590Srgrimes 78421528Sdavidn#ifdef LOGIN_CAP 78521528Sdavidn login_close(lc); 7863205Spst#endif 7873205Spst 7881590Srgrimes (void)signal(SIGALRM, SIG_DFL); 7891590Srgrimes (void)signal(SIGQUIT, SIG_DFL); 7901590Srgrimes (void)signal(SIGINT, SIG_DFL); 7911590Srgrimes (void)signal(SIGTSTP, SIG_IGN); 7921590Srgrimes 7934878Sugen if (changepass) { 79421528Sdavidn if (system(_PATH_CHPASS) != 0) 7954878Sugen sleepexit(1); 7964878Sugen } 7974878Sugen 79823985Sdavidn /* 79923985Sdavidn * Login shells have a leading '-' in front of argv[0] 80023985Sdavidn */ 80123985Sdavidn tbuf[0] = '-'; 80223985Sdavidn (void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell); 80323985Sdavidn 80421528Sdavidn execlp(shell, tbuf, 0); 80521528Sdavidn err(1, "%s", shell); 8061590Srgrimes} 8071590Srgrimes 80827605Scharnierstatic void 80927605Scharnierusage() 81027605Scharnier{ 81127605Scharnier (void)fprintf(stderr, "usage: login [-fp] [-h hostname] [username]\n"); 81227605Scharnier exit(1); 81327605Scharnier} 8141590Srgrimes 81523985Sdavidn/* 81623985Sdavidn * Allow for authentication style and/or kerberos instance 81723985Sdavidn * */ 81821528Sdavidn 81921528Sdavidn#define NBUFSIZ UT_NAMESIZE + 64 82021528Sdavidn 8211590Srgrimesvoid 8221590Srgrimesgetloginname() 8231590Srgrimes{ 8241590Srgrimes int ch; 8251590Srgrimes char *p; 8261590Srgrimes static char nbuf[NBUFSIZ]; 8271590Srgrimes 8281590Srgrimes for (;;) { 8291590Srgrimes (void)printf("login: "); 8301590Srgrimes for (p = nbuf; (ch = getchar()) != '\n'; ) { 8311590Srgrimes if (ch == EOF) { 8321590Srgrimes badlogin(username); 8331590Srgrimes exit(0); 8341590Srgrimes } 8351590Srgrimes if (p < nbuf + (NBUFSIZ - 1)) 8361590Srgrimes *p++ = ch; 8371590Srgrimes } 8381590Srgrimes if (p > nbuf) 8391590Srgrimes if (nbuf[0] == '-') 8401590Srgrimes (void)fprintf(stderr, 8411590Srgrimes "login names may not start with '-'.\n"); 8421590Srgrimes else { 8431590Srgrimes *p = '\0'; 8441590Srgrimes username = nbuf; 8451590Srgrimes break; 8461590Srgrimes } 8471590Srgrimes } 8481590Srgrimes} 8491590Srgrimes 8501590Srgrimesint 8511590Srgrimesrootterm(ttyn) 8521590Srgrimes char *ttyn; 8531590Srgrimes{ 8541590Srgrimes struct ttyent *t; 85523985Sdavidn 8561590Srgrimes return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); 8571590Srgrimes} 8581590Srgrimes 85921528Sdavidnvolatile int motdinterrupt; 8601590Srgrimes 86121528Sdavidn/* ARGSUSED */ 8621590Srgrimesvoid 86321528Sdavidnsigint(signo) 86421528Sdavidn int signo; 8651590Srgrimes{ 86621528Sdavidn motdinterrupt = 1; 86721528Sdavidn} 86821528Sdavidn 86921528Sdavidnvoid 87021528Sdavidnmotd(motdfile) 87121528Sdavidn char *motdfile; 87221528Sdavidn{ 8731590Srgrimes int fd, nchars; 8741590Srgrimes sig_t oldint; 87521528Sdavidn char tbuf[256]; 8761590Srgrimes 87721528Sdavidn if ((fd = open(motdfile, O_RDONLY, 0)) < 0) 8781590Srgrimes return; 87921528Sdavidn motdinterrupt = 0; 8801590Srgrimes oldint = signal(SIGINT, sigint); 88121528Sdavidn while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0 && !motdinterrupt) 88221528Sdavidn (void)write(fileno(stdout), tbuf, nchars); 8831590Srgrimes (void)signal(SIGINT, oldint); 8841590Srgrimes (void)close(fd); 8851590Srgrimes} 8861590Srgrimes 8871590Srgrimes/* ARGSUSED */ 8881590Srgrimesvoid 8891590Srgrimestimedout(signo) 8901590Srgrimes int signo; 8911590Srgrimes{ 8921590Srgrimes (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 8931590Srgrimes exit(0); 8941590Srgrimes} 8951590Srgrimes 89621528Sdavidn#ifndef LOGIN_CAP 8971590Srgrimesvoid 8981590Srgrimeschecknologin() 8991590Srgrimes{ 9001590Srgrimes int fd, nchars; 9011590Srgrimes char tbuf[8192]; 9021590Srgrimes 9031590Srgrimes if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 9041590Srgrimes while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 9051590Srgrimes (void)write(fileno(stdout), tbuf, nchars); 9061590Srgrimes sleepexit(0); 9071590Srgrimes } 9081590Srgrimes} 90921528Sdavidn#endif 9101590Srgrimes 9111590Srgrimesvoid 9121590Srgrimesdolastlog(quiet) 9131590Srgrimes int quiet; 9141590Srgrimes{ 9151590Srgrimes struct lastlog ll; 9161590Srgrimes int fd; 9171590Srgrimes 9181590Srgrimes if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 9191590Srgrimes (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 9201590Srgrimes if (!quiet) { 9211590Srgrimes if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 9221590Srgrimes ll.ll_time != 0) { 9231590Srgrimes (void)printf("Last login: %.*s ", 9241590Srgrimes 24-5, (char *)ctime(&ll.ll_time)); 9251590Srgrimes if (*ll.ll_host != '\0') 9261590Srgrimes (void)printf("from %.*s\n", 9271590Srgrimes (int)sizeof(ll.ll_host), 9281590Srgrimes ll.ll_host); 9291590Srgrimes else 9301590Srgrimes (void)printf("on %.*s\n", 9311590Srgrimes (int)sizeof(ll.ll_line), 9321590Srgrimes ll.ll_line); 9331590Srgrimes } 9341590Srgrimes (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 9351590Srgrimes } 9361590Srgrimes memset((void *)&ll, 0, sizeof(ll)); 9371590Srgrimes (void)time(&ll.ll_time); 9381590Srgrimes (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 9391590Srgrimes if (hostname) 9401590Srgrimes (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 9411590Srgrimes (void)write(fd, (char *)&ll, sizeof(ll)); 9421590Srgrimes (void)close(fd); 9431590Srgrimes } 9441590Srgrimes} 9451590Srgrimes 9461590Srgrimesvoid 9471590Srgrimesbadlogin(name) 9481590Srgrimes char *name; 9491590Srgrimes{ 9501590Srgrimes 9511590Srgrimes if (failures == 0) 9521590Srgrimes return; 9531590Srgrimes if (hostname) { 9541590Srgrimes syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s", 95516423Sache failures, failures > 1 ? "S" : "", full_hostname); 9561590Srgrimes syslog(LOG_AUTHPRIV|LOG_NOTICE, 9571590Srgrimes "%d LOGIN FAILURE%s FROM %s, %s", 95816423Sache failures, failures > 1 ? "S" : "", full_hostname, name); 9591590Srgrimes } else { 9601590Srgrimes syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s", 9611590Srgrimes failures, failures > 1 ? "S" : "", tty); 9621590Srgrimes syslog(LOG_AUTHPRIV|LOG_NOTICE, 9631590Srgrimes "%d LOGIN FAILURE%s ON %s, %s", 9641590Srgrimes failures, failures > 1 ? "S" : "", tty, name); 9651590Srgrimes } 9661590Srgrimes} 9671590Srgrimes 9681590Srgrimes#undef UNKNOWN 9691590Srgrimes#define UNKNOWN "su" 9701590Srgrimes 9711590Srgrimeschar * 9721590Srgrimesstypeof(ttyid) 9731590Srgrimes char *ttyid; 9741590Srgrimes{ 97523985Sdavidn 9761590Srgrimes struct ttyent *t; 97723985Sdavidn 9781590Srgrimes return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 9791590Srgrimes} 9801590Srgrimes 9811590Srgrimesvoid 98223985Sdavidnrefused(msg, rtype, lout) 98323985Sdavidn char *msg; 98423985Sdavidn char *rtype; 98523985Sdavidn int lout; 98623985Sdavidn{ 98723985Sdavidn 98823985Sdavidn if (msg != NULL) 98923985Sdavidn printf("%s.\n", msg); 99023985Sdavidn if (hostname) 99123985Sdavidn syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) FROM %s ON TTY %s", 99223985Sdavidn pwd->pw_name, rtype, full_hostname, tty); 99323985Sdavidn else 99423985Sdavidn syslog(LOG_NOTICE, "LOGIN %s REFUSED (%s) ON TTY %s", 99523985Sdavidn pwd->pw_name, rtype, tty); 99623985Sdavidn if (lout) 99723985Sdavidn sleepexit(1); 99823985Sdavidn} 99923985Sdavidn 100023985Sdavidnvoid 10011590Srgrimessleepexit(eval) 10021590Srgrimes int eval; 10031590Srgrimes{ 100423985Sdavidn 10051590Srgrimes (void)sleep(5); 10061590Srgrimes exit(eval); 10071590Srgrimes} 1008