X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/9bcf1061c5624c6a24b1aa85829b79e1e7de35f5..f5576df6fd6c54ac0836b6cc9634f63a156f325a:/usr/src/usr.bin/login/login.c diff --git a/usr/src/usr.bin/login/login.c b/usr/src/usr.bin/login/login.c index c6f3343194..e0955381ec 100644 --- a/usr/src/usr.bin/login/login.c +++ b/usr/src/usr.bin/login/login.c @@ -1,23 +1,48 @@ /*- - * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1980, 1987, 1988, 1991 The Regents of the University + * of California. All rights reserved. * - * %sccs.include.redist.c% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef lint char copyright[] = -"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ +"@(#) Copyright (c) 1980, 1987, 1988, 1991 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)login.c 5.56 (Berkeley) %G%"; +static char sccsid[] = "@(#)login.c 5.73 (Berkeley) 6/29/91"; #endif /* not lint */ /* * login [ name ] - * login -r hostname (for rlogind) * login -h hostname (for telnetd, etc.) * login -f name (for pre-authenticated login: datakit, xterm, etc.) */ @@ -27,7 +52,6 @@ static char sccsid[] = "@(#)login.c 5.56 (Berkeley) %G%"; #include #include #include -#include #include #include @@ -49,30 +73,18 @@ static char sccsid[] = "@(#)login.c 5.56 (Berkeley) %G%"; * be patched on machines where it's too small. */ int timeout = 300; +int rootlogin; #ifdef KERBEROS int notickets = 1; +char *instance; +char *krbtkfile_env; +int authok; #endif struct passwd *pwd; int failures; char term[64], *envinit[1], *hostname, *username, *tty; -struct sgttyb sgttyb; -struct tchars tc = { - CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK -}; -struct ltchars ltc = { - CSUSP, CDSUSP, CRPRNT, CDISCARD, CWERASE, CLNEXT -}; - -char *months[] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" }; - -char *months[] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" }; - main(argc, argv) int argc; char **argv; @@ -80,14 +92,11 @@ main(argc, argv) extern int optind; extern char *optarg, **environ; struct timeval tp; - struct tm *ttp; - struct timeval tp; - struct tm *ttp; struct group *gr; register int ch; register char *p; - int ask, fflag, hflag, pflag, rflag, cnt; - int quietlog, passwd_req, ioctlval, rval; + int ask, fflag, hflag, pflag, cnt, uid; + int quietlog, rval; char *domain, *salt, *ttyn; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; char localhost[MAXHOSTNAMELEN]; @@ -106,7 +115,6 @@ main(argc, argv) /* * -p is used by getty to tell login not to destroy the environment - * -r is used by rlogind to cause the autologin protocol; * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the remote * host to login so that it may be placed in utmp and wtmp @@ -117,28 +125,17 @@ main(argc, argv) else domain = index(localhost, '.'); - fflag = hflag = pflag = rflag = 0; - passwd_req = 1; + fflag = hflag = pflag = 0; uid = getuid(); - while ((ch = getopt(argc, argv, "fh:pr:")) != EOF) + while ((ch = getopt(argc, argv, "fh:p")) != EOF) switch (ch) { case 'f': - if (rflag) { - fprintf(stderr, - "login: only one of -r and -f allowed.\n"); - exit(1); - } fflag = 1; break; case 'h': if (uid) { (void)fprintf(stderr, - "login: -h for super-user only.\n"); - exit(1); - } - if (rflag) { - fprintf(stderr, - "login: only one of -r and -h allowed.\n"); + "login: -h option: %s\n", strerror(EPERM)); exit(1); } hflag = 1; @@ -150,66 +147,21 @@ main(argc, argv) case 'p': pflag = 1; break; - case 'r': - if (hflag || fflag) { - fprintf(stderr, - "login: -f and -h not allowed with -r.\n"); - exit(1); - } - if (getuid()) { - fprintf(stderr, - "login: -r for super-user only.\n"); - exit(1); - } - /* "-r hostname" must be last args */ - if (optind != argc) { - fprintf(stderr, "Syntax error.\n"); - exit(1); - } - rflag = 1; - passwd_req = (doremotelogin(optarg) == -1); - if (domain && (p = index(optarg, '.')) && - !strcmp(p, domain)) - *p = '\0'; - hostname = optarg; - break; case '?': default: if (!uid) syslog(LOG_ERR, "invalid flag %c", ch); (void)fprintf(stderr, - "usage: login [-fp] [username]\n"); + "usage: login [-fp] [-h hostname] [username]\n"); exit(1); } argc -= optind; argv += optind; if (*argv) { username = *argv; - if (strlen(username) > UT_NAMESIZE) - username[UT_NAMESIZE] = '\0'; ask = 0; } else ask = 1; - if (rflag) - ask = 0; - - ioctlval = 0; - (void)ioctl(0, TIOCLSET, &ioctlval); - (void)ioctl(0, TIOCNXCL, 0); - (void)fcntl(0, F_SETFL, ioctlval); - (void)ioctl(0, TIOCGETP, &sgttyb); - - /* - * If talking to an rlogin process, propagate the terminal type and - * baud rate across the network. - */ - if (rflag) - doremoteterm(&sgttyb); - sgttyb.sg_erase = CERASE; - sgttyb.sg_kill = CKILL; - (void)ioctl(0, TIOCSLTC, <c); - (void)ioctl(0, TIOCSETC, &tc); - (void)ioctl(0, TIOCSETP, &sgttyb); for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); @@ -225,13 +177,25 @@ main(argc, argv) tty = ttyn; for (cnt = 0;; ask = 1) { - ioctlval = TTYDISC; - (void)ioctl(0, TIOCSETD, &ioctlval); - if (ask) { fflag = 0; getloginname(); } +#ifdef KERBEROS + if ((instance = index(username, '.')) != NULL) { + if (strncmp(instance, ".root", 5) == 0) + rootlogin++; + *instance++ = '\0'; + } else { + rootlogin = 0; + instance = ""; + } +#else + rootlogin = 0; +#endif + if (strlen(username) > UT_NAMESIZE) + username[UT_NAMESIZE] = '\0'; + /* * Note if trying multiple user names; log failures for * previous user name, but don't bother logging one failure @@ -243,42 +207,61 @@ main(argc, argv) failures = 0; } (void)strcpy(tbuf, username); + if (pwd = getpwnam(username)) salt = pwd->pw_passwd; - else { - /* take up the right amount of time */ - (void)crypt(getpass("Password:"), "xx"); - goto faked; - } - - /* if user not super-user, check for disabled logins */ - if (pwd->pw_uid) - checknologin(); + else + salt = "xx"; /* - * Disallow automatic login to root; if not invoked by - * root, disallow if the uid's differ. + * if we have a valid account name, and it doesn't have a + * password, or the -f option was specified and the caller + * is root or the caller isn't changing their uid, don't + * authenticate. */ - if (fflag) { - passwd_req = -#ifndef KERBEROS - pwd->pw_uid == 0 || + if (pwd && (*pwd->pw_passwd == '\0' || + fflag && (uid == 0 || uid == pwd->pw_uid))) + break; + fflag = 0; + if (pwd && pwd->pw_uid == 0) + rootlogin = 1; + + (void)setpriority(PRIO_PROCESS, 0, -4); + + p = getpass("Password:"); + + if (pwd) { +#ifdef KERBEROS + rval = klogin(pwd, instance, localhost, p); + if (rval == 0) + authok = 1; + else if (rval == 1) { + if (pwd->pw_uid != 0) + rootlogin = 0; + rval = strcmp(crypt(p, salt), pwd->pw_passwd); + } +#else + if (pwd->pw_uid != 0) + rootlogin = 0; +#ifdef DES + rval = strcmp(crypt(p, salt), pwd->pw_passwd); +#else + rval = strcmp(p, pwd->pw_passwd); +#endif #endif - (uid && uid != pwd->pw_uid); } + bzero(p, strlen(p)); - /* - * If no pre-authentication and a password exists - * for this user, prompt for one and verify it. - */ - if (!passwd_req || !*pwd->pw_passwd) - break; + (void)setpriority(PRIO_PROCESS, 0, 0); /* - * If trying to log in as root, but with insecure terminal, - * refuse the login attempt. + * If trying to log in as root without Kerberos, + * but with insecure terminal, refuse the login attempt. */ - if (pwd->pw_uid == 0 && !rootterm(tty)) { +#ifdef KERBEROS + if (authok == 0) +#endif + if (pwd && rootlogin && !rootterm(tty)) { (void)fprintf(stderr, "%s login refused on this terminal.\n", pwd->pw_name); @@ -293,20 +276,15 @@ main(argc, argv) continue; } - (void)setpriority(PRIO_PROCESS, 0, -4); - p = getpass("Password:"); - - bzero(p, strlen(p)); - if (!rval) + if (pwd && !rval) break; -faked: (void)printf("Login incorrect\n"); + (void)printf("Login incorrect\n"); failures++; /* we allow 10 tries, but after 3 we start backing off */ if (++cnt > 3) { if (cnt >= 10) { badlogin(username); - (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); sleepexit(1); } sleep((u_int)((cnt - 3) * 5)); @@ -316,42 +294,21 @@ faked: (void)printf("Login incorrect\n"); /* committed to login -- turn off timeout */ (void)alarm((u_int)0); - /* reset priority */ - (void)setpriority(PRIO_PROCESS, 0, 0); - - /* paranoia... */ endpwent(); + /* if user not super-user, check for disabled logins */ + if (!rootlogin) + checknologin(); + if (chdir(pwd->pw_dir) < 0) { - (void)printf("No directory %s!\n", pwd->pw_dir); + (void)printf("No home directory %s!\n", pwd->pw_dir); if (chdir("/")) exit(0); pwd->pw_dir = "/"; (void)printf("Logging in with home = \"/\".\n"); } -#define TWOWEEKS (14*24*60*60) - if (pwd->pw_change || pwd->pw_expire) - (void)gettimeofday(&tp, (struct timezone *)NULL); - if (pwd->pw_change) - if (tp.tv_sec >= pwd->pw_change) { - printf("Sorry -- your password has expired.\n"); - sleepexit(1); - } - else if (tp.tv_sec - pwd->pw_change < TWOWEEKS) { - ttp = localtime(&pwd->pw_change); - printf("Warning: your password expires on %s %d, 19%d\n", - months[ttp->tm_mon], ttp->tm_mday, ttp->tm_year); - } - if (pwd->pw_expire) - if (tp.tv_sec >= pwd->pw_expire) { - printf("Sorry -- your account has expired.\n"); - sleepexit(1); - } - else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS) { - ttp = localtime(&pwd->pw_expire); - printf("Warning: your account expires on %s %d, 19%d\n", - months[ttp->tm_mon], ttp->tm_mday, ttp->tm_year); - } + + quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; if (pwd->pw_change || pwd->pw_expire) (void)gettimeofday(&tp, (struct timezone *)NULL); @@ -359,26 +316,18 @@ faked: (void)printf("Login incorrect\n"); if (tp.tv_sec >= pwd->pw_change) { (void)printf("Sorry -- your password has expired.\n"); sleepexit(1); - } - else if (pwd->pw_change - tp.tv_sec < - 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) { - ttp = localtime(&pwd->pw_change); - (void)printf("Warning: your password expires on %s %d, %d\n", - months[ttp->tm_mon], ttp->tm_mday, - TM_YEAR_BASE + ttp->tm_year); - } + } else if (pwd->pw_change - tp.tv_sec < + 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) + (void)printf("Warning: your password expires on %s", + ctime(&pwd->pw_expire)); if (pwd->pw_expire) if (tp.tv_sec >= pwd->pw_expire) { (void)printf("Sorry -- your account has expired.\n"); sleepexit(1); - } - else if (pwd->pw_expire - tp.tv_sec < - 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) { - ttp = localtime(&pwd->pw_expire); - (void)printf("Warning: your account expires on %s %d, %d\n", - months[ttp->tm_mon], ttp->tm_mday, - TM_YEAR_BASE + ttp->tm_year); - } + } else if (pwd->pw_expire - tp.tv_sec < + 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) + (void)printf("Warning: your account expires on %s", + ctime(&pwd->pw_expire)); /* nothing else left to fail -- really log in */ { @@ -395,15 +344,8 @@ faked: (void)printf("Login incorrect\n"); dolastlog(quietlog); - if (!hflag && !rflag) { /* XXX */ - static struct winsize win = { 0, 0, 0, 0 }; - - (void)ioctl(0, TIOCSWINSZ, &win); - } - (void)chown(ttyn, pwd->pw_uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); - (void)chmod(ttyn, 0620); (void)setgid(pwd->pw_gid); initgroups(username, pwd->pw_gid); @@ -419,17 +361,23 @@ faked: (void)printf("Login incorrect\n"); if (term[0] == '\0') strncpy(term, stypeof(tty), sizeof(term)); (void)setenv("TERM", term, 0); + (void)setenv("LOGNAME", pwd->pw_name, 1); (void)setenv("USER", pwd->pw_name, 1); (void)setenv("PATH", _PATH_DEFPATH, 0); +#ifdef KERBEROS + if (krbtkfile_env) + (void)setenv("KRBTKFILE", krbtkfile_env, 1); +#endif if (tty[sizeof("tty")-1] == 'd') syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); - if (pwd->pw_uid == 0) + /* if fflag is on, assume caller/authenticator has logged root login */ + if (rootlogin && fflag == 0) if (hostname) - syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", - tty, hostname); + syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s", + username, tty, hostname); else - syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); + syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty); #ifdef KERBEROS if (!quietlog && notickets == 1) @@ -439,6 +387,12 @@ faked: (void)printf("Login incorrect\n"); if (!quietlog) { struct stat st; + printf("%s%s", + "386BSD Release 0.1 by William and Lynne Jolitz.\n", +"Copyright (c) 1989,1990,1991,1992 William F. Jolitz. All rights reserved.\n\ +Based in part on work by the 386BSD User Community and the\n\ +BSD Networking Software, Release 2 by UCB EECS Department.\n"); + motd(); (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) @@ -459,18 +413,27 @@ faked: (void)printf("Login incorrect\n"); syslog(LOG_ERR, "setlogin() failure: %m"); /* discard permissions last so can't get killed and drop core */ - (void)setuid(pwd->pw_uid); + if (rootlogin) + (void) setuid(0); + else + (void) setuid(pwd->pw_uid); execlp(pwd->pw_shell, tbuf, 0); - (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); - exit(0); + (void)fprintf(stderr, "%s: %s\n", pwd->pw_shell, strerror(errno)); + exit(1); } +#ifdef KERBEROS +#define NBUFSIZ (UT_NAMESIZE + 1 + 5) /* .root suffix */ +#else +#define NBUFSIZ (UT_NAMESIZE + 1) +#endif + getloginname() { register int ch; register char *p; - static char nbuf[UT_NAMESIZE + 1]; + static char nbuf[NBUFSIZ]; for (;;) { (void)printf("login: "); @@ -479,7 +442,7 @@ getloginname() badlogin(username); exit(0); } - if (p < nbuf + UT_NAMESIZE) + if (p < nbuf + (NBUFSIZ - 1)) *p++ = ch; } if (p > nbuf) @@ -515,7 +478,7 @@ motd() { register int fd, nchars; sig_t oldint; - int sigint(); + void sigint(); char tbuf[8192]; if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) @@ -528,6 +491,7 @@ motd() (void)close(fd); } +void sigint() { longjmp(motdinterrupt, 1); @@ -551,7 +515,6 @@ dolastlog(quiet) struct lastlog ll; int fd; char *ctime(); - char *ctime(); if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); @@ -584,12 +547,19 @@ badlogin(name) { if (failures == 0) return; - if (hostname) - syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", + if (hostname) { + syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s", + failures, failures > 1 ? "S" : "", hostname); + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "%d LOGIN FAILURE%s FROM %s, %s", failures, failures > 1 ? "S" : "", hostname, name); - else - syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", + } else { + syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s", + failures, failures > 1 ? "S" : "", tty); + syslog(LOG_AUTHPRIV|LOG_NOTICE, + "%d LOGIN FAILURE%s ON %s, %s", failures, failures > 1 ? "S" : "", tty, name); + } } #undef UNKNOWN @@ -610,46 +580,3 @@ sleepexit(eval) sleep((u_int)5); exit(eval); } - -doremotelogin(host) - char *host; -{ - static char lusername[UT_NAMESIZE+1]; - char rusername[UT_NAMESIZE+1]; - - getstr(rusername, sizeof(rusername), "remuser"); - getstr(lusername, sizeof(lusername), "locuser"); - getstr(term, sizeof(term), "Terminal type"); - username = lusername; - pwd = getpwnam(username); - if (pwd == NULL) - return(-1); - return(ruserok(host, (pwd->pw_uid == 0), rusername, username)); -} - -char *speeds[] = { - "0", "50", "75", "110", "134", "150", "200", "300", "600", - "1200", "1800", "2400", "4800", "9600", "19200", "38400", -}; -#define NSPEEDS (sizeof(speeds) / sizeof(speeds[0])) - -doremoteterm(tp) - struct sgttyb *tp; -{ - register char *cp = index(term, '/'), **cpp; - char *speed; - - if (cp) { - *cp++ = '\0'; - speed = cp; - cp = index(speed, '/'); - if (cp) - *cp++ = '\0'; - for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) - if (strcmp(*cpp, speed) == 0) { - tp->sg_ispeed = tp->sg_ospeed = cpp-speeds; - break; - } - } - tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; -}