login.c revision 2532
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 341590Srgrimes#ifndef lint 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"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 411590Srgrimesstatic char sccsid[] = "@(#)login.c 8.4 (Berkeley) 4/2/94"; 421590Srgrimes#endif /* not lint */ 431590Srgrimes 441590Srgrimes/* 451590Srgrimes * login [ name ] 461590Srgrimes * login -h hostname (for telnetd, etc.) 471590Srgrimes * login -f name (for pre-authenticated login: datakit, xterm, etc.) 481590Srgrimes */ 491590Srgrimes 501590Srgrimes#include <sys/param.h> 511590Srgrimes#include <sys/stat.h> 521590Srgrimes#include <sys/time.h> 531590Srgrimes#include <sys/resource.h> 541590Srgrimes#include <sys/file.h> 551590Srgrimes 561590Srgrimes#include <err.h> 571590Srgrimes#include <errno.h> 581590Srgrimes#include <grp.h> 591590Srgrimes#include <pwd.h> 601590Srgrimes#include <setjmp.h> 611590Srgrimes#include <signal.h> 621590Srgrimes#include <stdio.h> 631590Srgrimes#include <stdlib.h> 641590Srgrimes#include <string.h> 651590Srgrimes#include <syslog.h> 661590Srgrimes#include <ttyent.h> 671590Srgrimes#include <tzfile.h> 681590Srgrimes#include <unistd.h> 691590Srgrimes#include <utmp.h> 701590Srgrimes 711590Srgrimes#include "pathnames.h" 721590Srgrimes 731590Srgrimesvoid badlogin __P((char *)); 741590Srgrimesvoid checknologin __P((void)); 751590Srgrimesvoid dolastlog __P((int)); 761590Srgrimesvoid getloginname __P((void)); 771590Srgrimesvoid motd __P((void)); 782532Sjkhvoid change_passwd __P((void)); 791590Srgrimesint rootterm __P((char *)); 801590Srgrimesvoid sigint __P((int)); 811590Srgrimesvoid sleepexit __P((int)); 821590Srgrimeschar *stypeof __P((char *)); 831590Srgrimesvoid timedout __P((int)); 842224Sguidovoid login_fbtab __P((char *, uid_t, gid_t)); 851590Srgrimes#ifdef KERBEROS 861590Srgrimesint klogin __P((struct passwd *, char *, char *, char *)); 871590Srgrimes#endif 881590Srgrimes 891590Srgrimesextern void login __P((struct utmp *)); 901590Srgrimes 911590Srgrimes#define TTYGRPNAME "tty" /* name of group to own ttys */ 921590Srgrimes 931590Srgrimes/* 941590Srgrimes * This bounds the time given to login. Not a define so it can 951590Srgrimes * be patched on machines where it's too small. 961590Srgrimes */ 971590Srgrimesu_int timeout = 300; 981590Srgrimes 991590Srgrimes#ifdef KERBEROS 1001590Srgrimesint notickets = 1; 1011590Srgrimeschar *instance; 1021590Srgrimeschar *krbtkfile_env; 1031590Srgrimesint authok; 1041590Srgrimes#endif 1051590Srgrimes 1061590Srgrimesstruct passwd *pwd; 1071590Srgrimesint failures; 1081590Srgrimeschar term[64], *envinit[1], *hostname, *username, *tty; 1091590Srgrimes 1101590Srgrimesint 1111590Srgrimesmain(argc, argv) 1121590Srgrimes int argc; 1131590Srgrimes char *argv[]; 1141590Srgrimes{ 1151590Srgrimes extern char **environ; 1161590Srgrimes struct group *gr; 1171590Srgrimes struct stat st; 1181590Srgrimes struct timeval tp; 1191590Srgrimes struct utmp utmp; 1201590Srgrimes int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval; 1211590Srgrimes uid_t uid; 1221590Srgrimes char *domain, *p, *salt, *ttyn; 1231590Srgrimes char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; 1241590Srgrimes char localhost[MAXHOSTNAMELEN]; 1251590Srgrimes 1261590Srgrimes (void)signal(SIGALRM, timedout); 1271590Srgrimes (void)alarm(timeout); 1281590Srgrimes (void)signal(SIGQUIT, SIG_IGN); 1291590Srgrimes (void)signal(SIGINT, SIG_IGN); 1301590Srgrimes (void)setpriority(PRIO_PROCESS, 0, 0); 1311590Srgrimes 1321590Srgrimes openlog("login", LOG_ODELAY, LOG_AUTH); 1331590Srgrimes 1341590Srgrimes /* 1351590Srgrimes * -p is used by getty to tell login not to destroy the environment 1361590Srgrimes * -f is used to skip a second login authentication 1371590Srgrimes * -h is used by other servers to pass the name of the remote 1381590Srgrimes * host to login so that it may be placed in utmp and wtmp 1391590Srgrimes */ 1401590Srgrimes domain = NULL; 1411590Srgrimes if (gethostname(localhost, sizeof(localhost)) < 0) 1421590Srgrimes syslog(LOG_ERR, "couldn't get local hostname: %m"); 1431590Srgrimes else 1441590Srgrimes domain = strchr(localhost, '.'); 1451590Srgrimes 1461590Srgrimes fflag = hflag = pflag = 0; 1471590Srgrimes uid = getuid(); 1481590Srgrimes while ((ch = getopt(argc, argv, "fh:p")) != EOF) 1491590Srgrimes switch (ch) { 1501590Srgrimes case 'f': 1511590Srgrimes fflag = 1; 1521590Srgrimes break; 1531590Srgrimes case 'h': 1541590Srgrimes if (uid) 1551590Srgrimes errx(1, "-h option: %s", strerror(EPERM)); 1561590Srgrimes hflag = 1; 1571590Srgrimes if (domain && (p = strchr(optarg, '.')) && 1581590Srgrimes strcasecmp(p, domain) == 0) 1591590Srgrimes *p = 0; 1601590Srgrimes hostname = optarg; 1611590Srgrimes break; 1621590Srgrimes case 'p': 1631590Srgrimes pflag = 1; 1641590Srgrimes break; 1651590Srgrimes case '?': 1661590Srgrimes default: 1671590Srgrimes if (!uid) 1681590Srgrimes syslog(LOG_ERR, "invalid flag %c", ch); 1691590Srgrimes (void)fprintf(stderr, 1701590Srgrimes "usage: login [-fp] [-h hostname] [username]\n"); 1711590Srgrimes exit(1); 1721590Srgrimes } 1731590Srgrimes argc -= optind; 1741590Srgrimes argv += optind; 1751590Srgrimes 1761590Srgrimes if (*argv) { 1771590Srgrimes username = *argv; 1781590Srgrimes ask = 0; 1791590Srgrimes } else 1801590Srgrimes ask = 1; 1811590Srgrimes 1821590Srgrimes for (cnt = getdtablesize(); cnt > 2; cnt--) 1831590Srgrimes (void)close(cnt); 1841590Srgrimes 1851590Srgrimes ttyn = ttyname(STDIN_FILENO); 1861590Srgrimes if (ttyn == NULL || *ttyn == '\0') { 1871590Srgrimes (void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY); 1881590Srgrimes ttyn = tname; 1891590Srgrimes } 1901590Srgrimes if (tty = strrchr(ttyn, '/')) 1911590Srgrimes ++tty; 1921590Srgrimes else 1931590Srgrimes tty = ttyn; 1941590Srgrimes 1951590Srgrimes for (cnt = 0;; ask = 1) { 1961590Srgrimes if (ask) { 1971590Srgrimes fflag = 0; 1981590Srgrimes getloginname(); 1991590Srgrimes } 2001590Srgrimes rootlogin = 0; 2011590Srgrimes#ifdef KERBEROS 2021590Srgrimes if ((instance = strchr(username, '.')) != NULL) { 2031590Srgrimes if (strncmp(instance, ".root", 5) == 0) 2041590Srgrimes rootlogin = 1; 2051590Srgrimes *instance++ = '\0'; 2061590Srgrimes } else 2071590Srgrimes instance = ""; 2081590Srgrimes#endif 2091590Srgrimes if (strlen(username) > UT_NAMESIZE) 2101590Srgrimes username[UT_NAMESIZE] = '\0'; 2111590Srgrimes 2121590Srgrimes /* 2131590Srgrimes * Note if trying multiple user names; log failures for 2141590Srgrimes * previous user name, but don't bother logging one failure 2151590Srgrimes * for nonexistent name (mistyped username). 2161590Srgrimes */ 2171590Srgrimes if (failures && strcmp(tbuf, username)) { 2181590Srgrimes if (failures > (pwd ? 0 : 1)) 2191590Srgrimes badlogin(tbuf); 2201590Srgrimes failures = 0; 2211590Srgrimes } 2221590Srgrimes (void)strcpy(tbuf, username); 2231590Srgrimes 2241590Srgrimes if (pwd = getpwnam(username)) 2251590Srgrimes salt = pwd->pw_passwd; 2261590Srgrimes else 2271590Srgrimes salt = "xx"; 2281590Srgrimes 2291590Srgrimes /* 2301590Srgrimes * if we have a valid account name, and it doesn't have a 2311590Srgrimes * password, or the -f option was specified and the caller 2321590Srgrimes * is root or the caller isn't changing their uid, don't 2331590Srgrimes * authenticate. 2341590Srgrimes */ 2351590Srgrimes if (pwd && (*pwd->pw_passwd == '\0' || 2361590Srgrimes fflag && (uid == 0 || uid == pwd->pw_uid))) 2371590Srgrimes break; 2381590Srgrimes fflag = 0; 2391590Srgrimes if (pwd && pwd->pw_uid == 0) 2401590Srgrimes rootlogin = 1; 2411590Srgrimes 2421590Srgrimes (void)setpriority(PRIO_PROCESS, 0, -4); 2431590Srgrimes 2441590Srgrimes p = getpass("Password:"); 2451590Srgrimes 2461590Srgrimes if (pwd) { 2471590Srgrimes#ifdef KERBEROS 2481590Srgrimes rval = klogin(pwd, instance, localhost, p); 2491590Srgrimes if (rval != 0 && rootlogin && pwd->pw_uid != 0) 2501590Srgrimes rootlogin = 0; 2511590Srgrimes if (rval == 0) 2521590Srgrimes authok = 1; 2531590Srgrimes else if (rval == 1) 2541590Srgrimes rval = strcmp(crypt(p, salt), pwd->pw_passwd); 2551590Srgrimes#else 2561590Srgrimes rval = strcmp(crypt(p, salt), pwd->pw_passwd); 2571590Srgrimes#endif 2581590Srgrimes } 2591590Srgrimes memset(p, 0, strlen(p)); 2601590Srgrimes 2611590Srgrimes (void)setpriority(PRIO_PROCESS, 0, 0); 2621590Srgrimes 2631590Srgrimes /* 2641590Srgrimes * If trying to log in as root without Kerberos, 2651590Srgrimes * but with insecure terminal, refuse the login attempt. 2661590Srgrimes */ 2671590Srgrimes#ifdef KERBEROS 2681590Srgrimes if (authok == 0) 2691590Srgrimes#endif 2701590Srgrimes if (pwd && rootlogin && !rootterm(tty)) { 2711590Srgrimes (void)fprintf(stderr, 2721590Srgrimes "%s login refused on this terminal.\n", 2731590Srgrimes pwd->pw_name); 2741590Srgrimes if (hostname) 2751590Srgrimes syslog(LOG_NOTICE, 2761590Srgrimes "LOGIN %s REFUSED FROM %s ON TTY %s", 2771590Srgrimes pwd->pw_name, hostname, tty); 2781590Srgrimes else 2791590Srgrimes syslog(LOG_NOTICE, 2801590Srgrimes "LOGIN %s REFUSED ON TTY %s", 2811590Srgrimes pwd->pw_name, tty); 2821590Srgrimes continue; 2831590Srgrimes } 2841590Srgrimes 2851590Srgrimes if (pwd && !rval) 2861590Srgrimes break; 2871590Srgrimes 2881590Srgrimes (void)printf("Login incorrect\n"); 2891590Srgrimes failures++; 2901590Srgrimes /* we allow 10 tries, but after 3 we start backing off */ 2911590Srgrimes if (++cnt > 3) { 2921590Srgrimes if (cnt >= 10) { 2931590Srgrimes badlogin(username); 2941590Srgrimes sleepexit(1); 2951590Srgrimes } 2961590Srgrimes sleep((u_int)((cnt - 3) * 5)); 2971590Srgrimes } 2981590Srgrimes } 2991590Srgrimes 3001590Srgrimes /* committed to login -- turn off timeout */ 3011590Srgrimes (void)alarm((u_int)0); 3021590Srgrimes 3031590Srgrimes endpwent(); 3041590Srgrimes 3051590Srgrimes /* if user not super-user, check for disabled logins */ 3061590Srgrimes if (!rootlogin) 3071590Srgrimes checknologin(); 3081590Srgrimes 3091590Srgrimes if (chdir(pwd->pw_dir) < 0) { 3101590Srgrimes (void)printf("No home directory %s!\n", pwd->pw_dir); 3111590Srgrimes if (chdir("/")) 3121590Srgrimes exit(0); 3131590Srgrimes pwd->pw_dir = "/"; 3141590Srgrimes (void)printf("Logging in with home = \"/\".\n"); 3151590Srgrimes } 3161590Srgrimes 3171590Srgrimes quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; 3181590Srgrimes 3191590Srgrimes if (pwd->pw_change || pwd->pw_expire) 3201590Srgrimes (void)gettimeofday(&tp, (struct timezone *)NULL); 3212532Sjkh 3221590Srgrimes if (pwd->pw_change) 3231590Srgrimes if (tp.tv_sec >= pwd->pw_change) { 3241590Srgrimes (void)printf("Sorry -- your password has expired.\n"); 3252532Sjkh change_passwd(); 3261590Srgrimes } else if (pwd->pw_change - tp.tv_sec < 3271590Srgrimes 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) 3281590Srgrimes (void)printf("Warning: your password expires on %s", 3291590Srgrimes ctime(&pwd->pw_change)); 3301590Srgrimes if (pwd->pw_expire) 3311590Srgrimes if (tp.tv_sec >= pwd->pw_expire) { 3321590Srgrimes (void)printf("Sorry -- your account has expired.\n"); 3331590Srgrimes sleepexit(1); 3341590Srgrimes } else if (pwd->pw_expire - tp.tv_sec < 3351590Srgrimes 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) 3361590Srgrimes (void)printf("Warning: your account expires on %s", 3371590Srgrimes ctime(&pwd->pw_expire)); 3381590Srgrimes 3391590Srgrimes /* Nothing else left to fail -- really log in. */ 3401590Srgrimes memset((void *)&utmp, 0, sizeof(utmp)); 3411590Srgrimes (void)time(&utmp.ut_time); 3421590Srgrimes (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); 3431590Srgrimes if (hostname) 3441590Srgrimes (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); 3451590Srgrimes (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); 3461590Srgrimes login(&utmp); 3471590Srgrimes 3481590Srgrimes dolastlog(quietlog); 3491590Srgrimes 3502224Sguido /* 3512224Sguido * Set device protections, depending on what terminal the 3522224Sguido * user is logged in. This feature is used on Suns to give 3532224Sguido * console users better privacy. 3542224Sguido */ 3552224Sguido login_fbtab(tty, pwd->pw_uid, pwd->pw_gid); 3562224Sguido 3571590Srgrimes (void)chown(ttyn, pwd->pw_uid, 3581590Srgrimes (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); 3591590Srgrimes (void)setgid(pwd->pw_gid); 3601590Srgrimes 3611590Srgrimes initgroups(username, pwd->pw_gid); 3621590Srgrimes 3631590Srgrimes if (*pwd->pw_shell == '\0') 3641590Srgrimes pwd->pw_shell = _PATH_BSHELL; 3651590Srgrimes 3661590Srgrimes /* Destroy environment unless user has requested its preservation. */ 3671590Srgrimes if (!pflag) 3681590Srgrimes environ = envinit; 3691590Srgrimes (void)setenv("HOME", pwd->pw_dir, 1); 3701590Srgrimes (void)setenv("SHELL", pwd->pw_shell, 1); 3711590Srgrimes if (term[0] == '\0') 3721590Srgrimes (void)strncpy(term, stypeof(tty), sizeof(term)); 3731590Srgrimes (void)setenv("TERM", term, 0); 3741590Srgrimes (void)setenv("LOGNAME", pwd->pw_name, 1); 3751590Srgrimes (void)setenv("USER", pwd->pw_name, 1); 3761590Srgrimes (void)setenv("PATH", _PATH_DEFPATH, 0); 3771590Srgrimes#ifdef KERBEROS 3781590Srgrimes if (krbtkfile_env) 3791590Srgrimes (void)setenv("KRBTKFILE", krbtkfile_env, 1); 3801590Srgrimes#endif 3811590Srgrimes 3821590Srgrimes if (tty[sizeof("tty")-1] == 'd') 3831590Srgrimes syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); 3841590Srgrimes 3851590Srgrimes /* If fflag is on, assume caller/authenticator has logged root login. */ 3861590Srgrimes if (rootlogin && fflag == 0) 3871590Srgrimes if (hostname) 3881590Srgrimes syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", 3891590Srgrimes username, tty, hostname); 3901590Srgrimes else 3911590Srgrimes syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); 3921590Srgrimes 3931590Srgrimes#ifdef KERBEROS 3941590Srgrimes if (!quietlog && notickets == 1) 3951590Srgrimes (void)printf("Warning: no Kerberos tickets issued.\n"); 3961590Srgrimes#endif 3971590Srgrimes 3981590Srgrimes if (!quietlog) { 3991590Srgrimes (void)printf("%s\n\t%s %s\n\n", 4001590Srgrimes "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994", 4011590Srgrimes "The Regents of the University of California. ", 4021590Srgrimes "All rights reserved."); 4031590Srgrimes motd(); 4041590Srgrimes (void)snprintf(tbuf, 4051590Srgrimes sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name); 4061590Srgrimes if (stat(tbuf, &st) == 0 && st.st_size != 0) 4071590Srgrimes (void)printf("You have %smail.\n", 4081590Srgrimes (st.st_mtime > st.st_atime) ? "new " : ""); 4091590Srgrimes } 4101590Srgrimes 4111590Srgrimes (void)signal(SIGALRM, SIG_DFL); 4121590Srgrimes (void)signal(SIGQUIT, SIG_DFL); 4131590Srgrimes (void)signal(SIGINT, SIG_DFL); 4141590Srgrimes (void)signal(SIGTSTP, SIG_IGN); 4151590Srgrimes 4161590Srgrimes tbuf[0] = '-'; 4171590Srgrimes (void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ? 4181590Srgrimes p + 1 : pwd->pw_shell); 4191590Srgrimes 4201590Srgrimes if (setlogin(pwd->pw_name) < 0) 4211590Srgrimes syslog(LOG_ERR, "setlogin() failure: %m"); 4221590Srgrimes 4231590Srgrimes /* Discard permissions last so can't get killed and drop core. */ 4241590Srgrimes if (rootlogin) 4251590Srgrimes (void) setuid(0); 4261590Srgrimes else 4271590Srgrimes (void) setuid(pwd->pw_uid); 4281590Srgrimes 4291590Srgrimes execlp(pwd->pw_shell, tbuf, 0); 4301590Srgrimes err(1, "%s", pwd->pw_shell); 4311590Srgrimes} 4321590Srgrimes 4331590Srgrimes#ifdef KERBEROS 4341590Srgrimes#define NBUFSIZ (UT_NAMESIZE + 1 + 5) /* .root suffix */ 4351590Srgrimes#else 4361590Srgrimes#define NBUFSIZ (UT_NAMESIZE + 1) 4371590Srgrimes#endif 4381590Srgrimes 4391590Srgrimesvoid 4401590Srgrimesgetloginname() 4411590Srgrimes{ 4421590Srgrimes int ch; 4431590Srgrimes char *p; 4441590Srgrimes static char nbuf[NBUFSIZ]; 4451590Srgrimes 4461590Srgrimes for (;;) { 4471590Srgrimes (void)printf("login: "); 4481590Srgrimes for (p = nbuf; (ch = getchar()) != '\n'; ) { 4491590Srgrimes if (ch == EOF) { 4501590Srgrimes badlogin(username); 4511590Srgrimes exit(0); 4521590Srgrimes } 4531590Srgrimes if (p < nbuf + (NBUFSIZ - 1)) 4541590Srgrimes *p++ = ch; 4551590Srgrimes } 4561590Srgrimes if (p > nbuf) 4571590Srgrimes if (nbuf[0] == '-') 4581590Srgrimes (void)fprintf(stderr, 4591590Srgrimes "login names may not start with '-'.\n"); 4601590Srgrimes else { 4611590Srgrimes *p = '\0'; 4621590Srgrimes username = nbuf; 4631590Srgrimes break; 4641590Srgrimes } 4651590Srgrimes } 4661590Srgrimes} 4671590Srgrimes 4681590Srgrimesint 4691590Srgrimesrootterm(ttyn) 4701590Srgrimes char *ttyn; 4711590Srgrimes{ 4721590Srgrimes struct ttyent *t; 4731590Srgrimes 4741590Srgrimes return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); 4751590Srgrimes} 4761590Srgrimes 4771590Srgrimesjmp_buf motdinterrupt; 4781590Srgrimes 4791590Srgrimesvoid 4801590Srgrimesmotd() 4811590Srgrimes{ 4821590Srgrimes int fd, nchars; 4831590Srgrimes sig_t oldint; 4841590Srgrimes char tbuf[8192]; 4851590Srgrimes 4861590Srgrimes if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) 4871590Srgrimes return; 4881590Srgrimes oldint = signal(SIGINT, sigint); 4891590Srgrimes if (setjmp(motdinterrupt) == 0) 4901590Srgrimes while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 4911590Srgrimes (void)write(fileno(stdout), tbuf, nchars); 4921590Srgrimes (void)signal(SIGINT, oldint); 4931590Srgrimes (void)close(fd); 4941590Srgrimes} 4951590Srgrimes 4961590Srgrimes/* ARGSUSED */ 4971590Srgrimesvoid 4981590Srgrimessigint(signo) 4991590Srgrimes int signo; 5001590Srgrimes{ 5011590Srgrimes 5021590Srgrimes longjmp(motdinterrupt, 1); 5031590Srgrimes} 5041590Srgrimes 5051590Srgrimes/* ARGSUSED */ 5061590Srgrimesvoid 5071590Srgrimestimedout(signo) 5081590Srgrimes int signo; 5091590Srgrimes{ 5101590Srgrimes 5111590Srgrimes (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); 5121590Srgrimes exit(0); 5131590Srgrimes} 5141590Srgrimes 5151590Srgrimesvoid 5161590Srgrimeschecknologin() 5171590Srgrimes{ 5181590Srgrimes int fd, nchars; 5191590Srgrimes char tbuf[8192]; 5201590Srgrimes 5211590Srgrimes if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { 5221590Srgrimes while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) 5231590Srgrimes (void)write(fileno(stdout), tbuf, nchars); 5241590Srgrimes sleepexit(0); 5251590Srgrimes } 5261590Srgrimes} 5271590Srgrimes 5281590Srgrimesvoid 5291590Srgrimesdolastlog(quiet) 5301590Srgrimes int quiet; 5311590Srgrimes{ 5321590Srgrimes struct lastlog ll; 5331590Srgrimes int fd; 5341590Srgrimes 5351590Srgrimes if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { 5361590Srgrimes (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 5371590Srgrimes if (!quiet) { 5381590Srgrimes if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && 5391590Srgrimes ll.ll_time != 0) { 5401590Srgrimes (void)printf("Last login: %.*s ", 5411590Srgrimes 24-5, (char *)ctime(&ll.ll_time)); 5421590Srgrimes if (*ll.ll_host != '\0') 5431590Srgrimes (void)printf("from %.*s\n", 5441590Srgrimes (int)sizeof(ll.ll_host), 5451590Srgrimes ll.ll_host); 5461590Srgrimes else 5471590Srgrimes (void)printf("on %.*s\n", 5481590Srgrimes (int)sizeof(ll.ll_line), 5491590Srgrimes ll.ll_line); 5501590Srgrimes } 5511590Srgrimes (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); 5521590Srgrimes } 5531590Srgrimes memset((void *)&ll, 0, sizeof(ll)); 5541590Srgrimes (void)time(&ll.ll_time); 5551590Srgrimes (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); 5561590Srgrimes if (hostname) 5571590Srgrimes (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); 5581590Srgrimes (void)write(fd, (char *)&ll, sizeof(ll)); 5591590Srgrimes (void)close(fd); 5601590Srgrimes } 5611590Srgrimes} 5621590Srgrimes 5631590Srgrimesvoid 5641590Srgrimesbadlogin(name) 5651590Srgrimes char *name; 5661590Srgrimes{ 5671590Srgrimes 5681590Srgrimes if (failures == 0) 5691590Srgrimes return; 5701590Srgrimes if (hostname) { 5711590Srgrimes syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s", 5721590Srgrimes failures, failures > 1 ? "S" : "", hostname); 5731590Srgrimes syslog(LOG_AUTHPRIV|LOG_NOTICE, 5741590Srgrimes "%d LOGIN FAILURE%s FROM %s, %s", 5751590Srgrimes failures, failures > 1 ? "S" : "", hostname, name); 5761590Srgrimes } else { 5771590Srgrimes syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s", 5781590Srgrimes failures, failures > 1 ? "S" : "", tty); 5791590Srgrimes syslog(LOG_AUTHPRIV|LOG_NOTICE, 5801590Srgrimes "%d LOGIN FAILURE%s ON %s, %s", 5811590Srgrimes failures, failures > 1 ? "S" : "", tty, name); 5821590Srgrimes } 5831590Srgrimes} 5841590Srgrimes 5851590Srgrimes#undef UNKNOWN 5861590Srgrimes#define UNKNOWN "su" 5871590Srgrimes 5881590Srgrimeschar * 5891590Srgrimesstypeof(ttyid) 5901590Srgrimes char *ttyid; 5911590Srgrimes{ 5921590Srgrimes struct ttyent *t; 5931590Srgrimes 5941590Srgrimes return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); 5951590Srgrimes} 5961590Srgrimes 5971590Srgrimesvoid 5981590Srgrimessleepexit(eval) 5991590Srgrimes int eval; 6001590Srgrimes{ 6011590Srgrimes 6021590Srgrimes (void)sleep(5); 6031590Srgrimes exit(eval); 6041590Srgrimes} 6052532Sjkh 6062532Sjkhvoid 6072532Sjkhchange_passwd() 6082532Sjkh{ 6092532Sjkh int pid, status, w; 6102532Sjkh register void (*istat)(), (*qstat)(); 6112532Sjkh 6122532Sjkh if (( pid=fork() ) == 0) 6132532Sjkh { 6142532Sjkh execl( "/usr/bin/passwd", "passwd", NULL ); 6152532Sjkh fprintf( stderr, "ERROR: Can't execute passwd!\n" ); 6162532Sjkh sleepexit( 1 ); 6172532Sjkh } 6182532Sjkh 6192532Sjkh istat = signal( SIGINT, SIG_IGN ); 6202532Sjkh qstat = signal( SIGQUIT, SIG_IGN ); 6212532Sjkh 6222532Sjkh while ((w = wait( &status )) != pid && w != -1) 6232532Sjkh ; 6242532Sjkh 6252532Sjkh signal( SIGINT, istat ); 6262532Sjkh signal( SIGQUIT, qstat ); 6272532Sjkh} 6282532Sjkh 629