X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/83cc725310bcf8fd99e531f375690e9638fa4101..b32e4ad7898d7bb743d7344a9d418096f80075d7:/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 8d699fcea7..625a3aa8f2 100644 --- a/usr/src/usr.bin/login/login.c +++ b/usr/src/usr.bin/login/login.c @@ -22,17 +22,18 @@ char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)login.c 5.32.1.2 (Berkeley) %G%"; +static char sccsid[] = "@(#)login.c 5.44 (Berkeley) %G%"; #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.) */ #include -#include +#include #include #include #include @@ -41,7 +42,6 @@ static char sccsid[] = "@(#)login.c 5.32.1.2 (Berkeley) %G%"; #include #include -#include #include #include #include @@ -50,16 +50,11 @@ static char sccsid[] = "@(#)login.c 5.32.1.2 (Berkeley) %G%"; #include #include #include +#include +#include "pathnames.h" #define TTYGRPNAME "tty" /* name of group to own ttys */ -#define MOTDFILE "/etc/motd" -#define MAILDIR "/usr/spool/mail" -#define NOLOGIN "/etc/nologin" -#define HUSHLOGIN ".hushlogin" -#define LASTLOG "/usr/adm/lastlog" -#define BSHELL "/bin/sh" - /* * This bounds the time given to login. Not a define so it can * be patched on machines where it's too small. @@ -99,10 +94,11 @@ main(argc, argv) struct group *gr; register int ch; register char *p; - int ask, fflag, hflag, pflag, cnt; + int ask, fflag, hflag, pflag, rflag, cnt; int quietlog, passwd_req, ioctlval, timedout(); char *domain, *salt, *envinit[1], *ttyn, *pp; - char tbuf[MAXPATHLEN + 2]; + char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; + char localhost[MAXHOSTNAMELEN]; char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); time_t time(); off_t lseek(); @@ -116,26 +112,40 @@ 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 */ - (void)gethostname(tbuf, sizeof(tbuf)); - domain = index(tbuf, '.'); + domain = NULL; + if (gethostname(localhost, sizeof(localhost)) < 0) + syslog(LOG_ERR, "couldn't get local hostname: %m"); + else + domain = index(localhost, '.'); - fflag = hflag = pflag = 0; + fflag = hflag = pflag = rflag = 0; passwd_req = 1; - while ((ch = getopt(argc, argv, "fh:p")) != EOF) + while ((ch = getopt(argc, argv, "fh:pr:")) != 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 (getuid()) { - fprintf(stderr, + (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"); + exit(1); + } hflag = 1; if (domain && (p = index(optarg, '.')) && strcasecmp(p, domain) == 0) @@ -145,9 +155,34 @@ 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: - fprintf(stderr, "usage: login [-fp] [username]\n"); + syslog(LOG_ERR, "invalid flag"); + (void)fprintf(stderr, + "usage: login [-fp] [username]\n"); exit(1); } argc -= optind; @@ -157,12 +192,21 @@ main(argc, argv) 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); @@ -173,8 +217,10 @@ main(argc, argv) close(cnt); ttyn = ttyname(0); - if (ttyn == NULL || *ttyn == '\0') - ttyn = "/dev/tty??"; + if (ttyn == NULL || *ttyn == '\0') { + (void)sprintf(tname, "%s??", _PATH_TTY); + ttyn = tname; + } if (tty = rindex(ttyn, '/')) ++tty; else @@ -183,7 +229,7 @@ main(argc, argv) openlog("login", LOG_ODELAY, LOG_AUTH); for (cnt = 0;; ask = 1) { - ioctlval = 0; + ioctlval = TTYDISC; (void)ioctl(0, TIOCSETD, &ioctlval); if (ask) { @@ -218,7 +264,10 @@ main(argc, argv) if (fflag && pwd) { int uid = getuid(); - passwd_req = pwd->pw_uid == 0 || + passwd_req = +#ifndef KERBEROS + pwd->pw_uid == 0 || +#endif (uid && uid != pwd->pw_uid); } @@ -238,7 +287,7 @@ main(argc, argv) if (pwd && !strcmp(p, pwd->pw_passwd)) break; - printf("Login incorrect\n"); + (void)printf("Login incorrect\n"); failures++; /* we allow 10 tries, but after 3 we start backing off */ if (++cnt > 3) { @@ -254,6 +303,9 @@ main(argc, argv) /* committed to login -- turn off timeout */ (void)alarm((u_int)0); + /* paranoia... */ + endpwent(); + /* * If valid so far and root is logging in, see if root logins on * this terminal are permitted. @@ -264,18 +316,18 @@ main(argc, argv) hostname); else syslog(LOG_NOTICE, "ROOT LOGIN REFUSED ON %s", tty); - printf("Login incorrect\n"); + (void)printf("Login incorrect\n"); sleepexit(1); } if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { switch(errno) { case EUSERS: - fprintf(stderr, + (void)fprintf(stderr, "Too many users logged on already.\nTry again later.\n"); break; case EPROCLIM: - fprintf(stderr, + (void)fprintf(stderr, "You have too many processes running.\n"); break; default: @@ -285,13 +337,14 @@ main(argc, argv) } if (chdir(pwd->pw_dir) < 0) { - printf("No directory %s!\n", pwd->pw_dir); + (void)printf("No directory %s!\n", pwd->pw_dir); if (chdir("/")) exit(0); pwd->pw_dir = "/"; - printf("Logging in with home = \"/\".\n"); + (void)printf("Logging in with home = \"/\".\n"); } +#if BSD > 43 #define TWOWEEKS (14*24*60*60) if (pwd->pw_change || pwd->pw_expire) (void)gettimeofday(&tp, (struct timezone *)NULL); @@ -316,29 +369,33 @@ main(argc, argv) months[ttp->tm_mon], ttp->tm_mday, ttp->tm_year); } -#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"); + (void)printf("Sorry -- your password has expired.\n"); sleepexit(1); } - else if (tp.tv_sec - pwd->pw_change < TWOWEEKS) { + else if (pwd->pw_change - tp.tv_sec < + 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) { 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); + (void)printf("Warning: your password expires on %s %d, %d\n", + months[ttp->tm_mon], ttp->tm_mday, + TM_YEAR_BASE + ttp->tm_year); } if (pwd->pw_expire) if (tp.tv_sec >= pwd->pw_expire) { - printf("Sorry -- your account has expired.\n"); + (void)printf("Sorry -- your account has expired.\n"); sleepexit(1); } - else if (tp.tv_sec - pwd->pw_expire < TWOWEEKS) { + else if (pwd->pw_expire - tp.tv_sec < + 2 * DAYSPERWEEK * SECSPERDAY && !quietlog) { 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); + (void)printf("Warning: your account expires on %s %d, %d\n", + months[ttp->tm_mon], ttp->tm_mday, + TM_YEAR_BASE + ttp->tm_year); } +#endif /* nothing else left to fail -- really log in */ { @@ -353,10 +410,9 @@ main(argc, argv) login(&utmp); } - quietlog = access(HUSHLOGIN, F_OK) == 0; dolastlog(quietlog); - if (!hflag) { /* XXX */ + if (!hflag && !rflag) { /* XXX */ static struct winsize win = { 0, 0, 0, 0 }; (void)ioctl(0, TIOCSWINSZ, &win); @@ -370,15 +426,9 @@ main(argc, argv) initgroups(username, pwd->pw_gid); quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); - (void)setuid(pwd->pw_uid); if (*pwd->pw_shell == '\0') - pwd->pw_shell = BSHELL; - /* turn on new line discipline for the csh */ - else if (!strcmp(pwd->pw_shell, "/bin/csh")) { - ioctlval = NTTYDISC; - (void)ioctl(0, TIOCSETD, &ioctlval); - } + pwd->pw_shell = _PATH_BSHELL; /* destroy environment unless user has requested preservation */ if (!pflag) @@ -389,7 +439,7 @@ main(argc, argv) strncpy(term, stypeof(tty), sizeof(term)); (void)setenv("TERM", term, 0); (void)setenv("USER", pwd->pw_name, 1); - (void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0); + (void)setenv("PATH", _PATH_DEFPATH, 0); if (tty[sizeof("tty")-1] == 'd') syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); @@ -404,9 +454,9 @@ main(argc, argv) struct stat st; motd(); - (void)sprintf(tbuf, "%s/%s", MAILDIR, pwd->pw_name); + (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) - printf("You have %smail.\n", + (void)printf("You have %smail.\n", (st.st_mtime > st.st_atime) ? "new " : ""); } @@ -418,9 +468,17 @@ main(argc, argv) tbuf[0] = '-'; strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell); + +#if BSD > 43 + if (setlogname(pwd->pw_name, strlen(pwd->pw_name)) < 0) + syslog(LOG_ERR, "setlogname() failure: %m"); +#endif + + /* discard permissions last so can't get killed and drop core */ + (void)setuid(pwd->pw_uid); + execlp(pwd->pw_shell, tbuf, 0); - fprintf(stderr, "login: no shell: "); - perror(pwd->pw_shell); + (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); exit(0); } @@ -431,7 +489,7 @@ getloginname() static char nbuf[UT_NAMESIZE + 1]; for (;;) { - printf("login: "); + (void)printf("login: "); for (p = nbuf; (ch = getchar()) != '\n'; ) { if (ch == EOF) { badlogin(username); @@ -442,7 +500,7 @@ getloginname() } if (p > nbuf) if (nbuf[0] == '-') - fprintf(stderr, + (void)fprintf(stderr, "login names may not start with '-'.\n"); else { *p = '\0'; @@ -454,7 +512,7 @@ getloginname() timedout() { - fprintf(stderr, "Login timed out after %d seconds\n", timeout); + (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); exit(0); } @@ -471,10 +529,11 @@ jmp_buf motdinterrupt; motd() { register int fd, nchars; - int (*oldint)(), sigint(); + sig_t oldint; + int sigint(); char tbuf[8192]; - if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0) + if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) return; oldint = signal(SIGINT, sigint); if (setjmp(motdinterrupt) == 0) @@ -494,7 +553,7 @@ checknologin() register int fd, nchars; char tbuf[8192]; - if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) { + if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) (void)write(fileno(stdout), tbuf, nchars); sleepexit(0); @@ -509,18 +568,18 @@ dolastlog(quiet) char *ctime(); char *ctime(); - if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) { + if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); if (!quiet) { if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) { - printf("Last login: %.*s ", + (void)printf("Last login: %.*s ", 24-5, (char *)ctime(&ll.ll_time)); if (*ll.ll_host != '\0') - printf("from %.*s\n", + (void)printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host); else - printf("on %.*s\n", + (void)printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line); } (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); @@ -570,7 +629,7 @@ getstr(buf, cnt, err) if (read(0, &ch, sizeof(ch)) != sizeof(ch)) exit(1); if (--cnt < 0) { - fprintf(stderr, "%s too long\r\n", err); + (void)fprintf(stderr, "%s too long\r\n", err); sleepexit(1); } *buf++ = ch; @@ -583,3 +642,46 @@ 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; +}