X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/f01752c580c2560960798fccb82fe0b9e0d90253..133ce0bc0996f2a55c50c673895d981e9c77691b:/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 b6164b4e71..d83752a117 100644 --- a/usr/src/usr.bin/login/login.c +++ b/usr/src/usr.bin/login/login.c @@ -1,11 +1,24 @@ +/* + * Copyright (c) 1980,1987 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + */ + #ifndef lint -static char *sccsid = "@(#)login.c 4.35 (Berkeley) 84/12/17"; -#endif +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif not lint + +#ifndef lint +static char sccsid[] = "@(#)login.c 5.23 (Berkeley) %G%"; +#endif not lint /* * login [ name ] - * login -r hostname (for rlogind) - * login -h hostname (for telnetd, etc.) + * login -r hostname (for rlogind) + * login -h hostname (for telnetd, etc.) + * login -f name (for pre-authenticated login: datakit, xterm, etc.) */ #include @@ -24,11 +37,16 @@ static char *sccsid = "@(#)login.c 4.35 (Berkeley) 84/12/17"; #include #include #include +#include + +#define TTYGRPNAME "tty" /* name of group to own ttys */ +#define TTYGID(gid) tty_gid(gid) /* gid that owns all ttys */ #define SCMPN(a, b) strncmp(a, b, sizeof(a)) #define SCPYN(a, b) strncpy(a, b, sizeof(a)) #define NMAX sizeof(utmp.ut_name) +#define HMAX sizeof(utmp.ut_host) #define FALSE 0 #define TRUE -1 @@ -41,19 +59,14 @@ struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; struct sgttyb ttyb; struct utmp utmp; char minusnam[16] = "-"; +char *envinit[1]; /* now set by setenv calls */ /* * This bounds the time given to login. We initialize it here * so it can be patched on machines where it's too small. */ -int timeout = 60; +int timeout = 300; -char homedir[64] = "HOME="; -char shell[64] = "SHELL="; -char term[64] = "TERM="; -char user[20] = "USER="; - -char *envinit[] = - { homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0 }; +char term[64]; struct passwd *pwd; char *strcat(), *rindex(), *index(); @@ -62,7 +75,6 @@ char *ttyname(); char *crypt(); char *getpass(); char *stypeof(); -extern char **environ; extern int errno; struct tchars tc = { @@ -72,21 +84,27 @@ struct ltchars ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; +struct winsize win = { 0, 0, 0, 0 }; + int rflag; +int usererr = -1; char rusername[NMAX+1], lusername[NMAX+1]; char rpassword[NMAX+1]; char name[NMAX+1]; +char me[MAXHOSTNAMELEN]; char *rhost; main(argc, argv) char *argv[]; { + extern char **environ; register char *namep; - int t, f, c; + int pflag = 0, hflag = 0, fflag = 0, t, f, c; int invalid, quietlog; FILE *nlfd; char *ttyn, *tty; int ldisc = 0, zero = 0; + char *p, *domain, *index(); signal(SIGALRM, timedout); alarm(timeout); @@ -95,20 +113,65 @@ main(argc, argv) setpriority(PRIO_PROCESS, 0, 0); quota(Q_SETUID, 0, 0, 0); /* + * -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 */ - if (argc > 1) { + (void) gethostname(me, sizeof(me)); + domain = index(me, '.'); + while (argc > 1) { if (strcmp(argv[1], "-r") == 0) { - rflag = doremotelogin(argv[2]); + if (rflag || hflag || fflag) { + printf("Other options not allowed with -r\n"); + exit(1); + } + if (argv[2] == 0) + exit(1); + rflag = 1; + usererr = doremotelogin(argv[2]); + if ((p = index(argv[2], '.')) && strcmp(p, domain) == 0) + *p = 0; SCPYN(utmp.ut_host, argv[2]); - argc = 0; + argc -= 2; + argv += 2; + continue; } - if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { - SCPYN(utmp.ut_host, argv[2]); - argc = 0; + if (strcmp(argv[1], "-h") == 0) { + if (getuid() == 0) { + if (rflag || hflag) { + printf("Only one of -r and -h allowed\n"); + exit(1); + } + hflag = 1; + if ((p = index(argv[2], '.')) && + strcmp(p, domain) == 0) + *p = 0; + SCPYN(utmp.ut_host, argv[2]); + } + argc -= 2; + argv += 2; + continue; + } + if (strcmp(argv[1], "-f") == 0 && argc > 2) { + if (rflag) { + printf("Only one of -r and -f allowed\n"); + exit(1); + } + fflag = 1; + SCPYN(utmp.ut_name, argv[2]); + argc -= 2; + argv += 2; + continue; } + if (strcmp(argv[1], "-p") == 0) { + argc--; + argv++; + pflag = 1; + continue; + } + break; } ioctl(0, TIOCLSET, &zero); ioctl(0, TIOCNXCL, 0); @@ -122,26 +185,29 @@ main(argc, argv) */ if (rflag) doremoteterm(term, &ttyb); + ttyb.sg_erase = CERASE; + ttyb.sg_kill = CKILL; ioctl(0, TIOCSLTC, <c); ioctl(0, TIOCSETC, &tc); ioctl(0, TIOCSETP, &ttyb); - for (t = getdtablesize(); t > 3; t--) + for (t = getdtablesize(); t > 2; t--) close(t); ttyn = ttyname(0); - if (ttyn == (char *)0) + if (ttyn == (char *)0 || *ttyn == '\0') ttyn = "/dev/tty??"; tty = rindex(ttyn, '/'); if (tty == NULL) tty = ttyn; else tty++; - openlog("login", 0, 0); + openlog("login", LOG_ODELAY, LOG_AUTH); t = 0; + invalid = FALSE; do { ldisc = 0; ioctl(0, TIOCSETD, &ldisc); - invalid = FALSE; - SCPYN(utmp.ut_name, ""); + if (fflag == 0) + SCPYN(utmp.ut_name, ""); /* * Name specified, take it. */ @@ -153,23 +219,38 @@ main(argc, argv) * If remote login take given name, * otherwise prompt user for something. */ - if (rflag) { + if (rflag && !invalid) SCPYN(utmp.ut_name, lusername); - /* autologin failed, prompt for passwd */ - if (rflag == -1) - rflag = 0; - } else + else { getloginname(&utmp); + if (utmp.ut_name[0] == '-') { + puts("login names may not start with '-'."); + invalid = TRUE; + continue; + } + } + invalid = FALSE; if (!strcmp(pwd->pw_shell, "/bin/csh")) { ldisc = NTTYDISC; ioctl(0, TIOCSETD, &ldisc); } + if (fflag) { + int uid = getuid(); + + if (uid != 0 && uid != pwd->pw_uid) + fflag = 0; + /* + * Disallow automatic login for root. + */ + if (pwd->pw_uid == 0) + fflag = 0; + } /* * If no remote login authentication and * a password exists for this user, prompt * for one and verify it. */ - if (!rflag && *pwd->pw_passwd != '\0') { + if (usererr == -1 && fflag == 0 && *pwd->pw_passwd != '\0') { char *pp; setpriority(PRIO_PROCESS, 0, -4); @@ -182,7 +263,7 @@ main(argc, argv) /* * If user not super-user, check for logins disabled. */ - if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { + if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r"))) { while ((c = getc(nlfd)) != EOF) putchar(c); fflush(stdout); @@ -194,19 +275,29 @@ main(argc, argv) * see if root logins on this terminal are permitted. */ if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { - syslog(LOG_INFO, "ROOT LOGIN REFUSED %s", tty); + if (utmp.ut_host[0]) + syslog(LOG_CRIT, + "ROOT LOGIN REFUSED ON %s FROM %.*s", + tty, HMAX, utmp.ut_host); + else + syslog(LOG_CRIT, + "ROOT LOGIN REFUSED ON %s", tty); invalid = TRUE; } if (invalid) { printf("Login incorrect\n"); if (++t >= 5) { - syslog(LOG_INFO, - "REPEATED LOGIN FAILURES %s, %s", - tty, utmp.ut_name); + if (utmp.ut_host[0]) + syslog(LOG_ERR, + "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s", + tty, HMAX, utmp.ut_host, + NMAX, utmp.ut_name); + else + syslog(LOG_ERR, + "REPEATED LOGIN FAILURES ON %s, %.*s", + tty, NMAX, utmp.ut_name); ioctl(0, TIOCHPCL, (struct sgttyb *) 0); - close(0); - close(1); - close(2); + close(0), close(1), close(2); sleep(10); exit(1); } @@ -227,13 +318,13 @@ main(argc, argv) * Remote login invalid must have been because * of a restriction of some sort, no extra chances. */ - if (rflag && invalid) + if (!usererr && invalid) exit(1); } while (invalid); /* committed to login turn off timeout */ alarm(0); - if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) { + if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { if (errno == EUSERS) printf("%s.\n%s.\n", "Too many users logged on already", @@ -241,22 +332,13 @@ main(argc, argv) else if (errno == EPROCLIM) printf("You have too many processes running.\n"); else - perror("setuid"); + perror("quota (Q_SETUID)"); sleep(5); exit(0); } time(&utmp.ut_time); - t = ttyslot(); - if (t > 0 && (f = open("/etc/utmp", O_WRONLY)) >= 0) { - lseek(f, (long)(t*sizeof(utmp)), 0); - SCPYN(utmp.ut_line, tty); - write(f, (char *)&utmp, sizeof(utmp)); - close(f); - } - if ((f = open("/usr/adm/wtmp", O_WRONLY|O_APPEND)) >= 0) { - write(f, (char *)&utmp, sizeof(utmp)); - close(f); - } + SCPYN(utmp.ut_line, tty); + login(&utmp); quietlog = access(qlog, F_OK) == 0; if ((f = open(lastlog, O_RDWR)) >= 0) { struct lastlog ll; @@ -280,36 +362,49 @@ main(argc, argv) write(f, (char *) &ll, sizeof ll); close(f); } - chown(ttyn, pwd->pw_uid, pwd->pw_gid); - chmod(ttyn, 0622); + chown(ttyn, pwd->pw_uid, TTYGID(pwd->pw_gid)); + if (!hflag && !rflag) /* XXX */ + ioctl(0, TIOCSWINSZ, &win); + chmod(ttyn, 0620); setgid(pwd->pw_gid); strncpy(name, utmp.ut_name, NMAX); name[NMAX] = '\0'; initgroups(name, pwd->pw_gid); quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); setuid(pwd->pw_uid); - environ = envinit; - strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); - strncat(shell, pwd->pw_shell, sizeof(shell)-7); - if (term[strlen("TERM=")] == 0) - strncat(term, stypeof(tty), sizeof(term)-6); - strncat(user, pwd->pw_name, sizeof(user)-6); + + /* destroy environment unless user has asked to preserve it */ + if (!pflag) + environ = envinit; + setenv("HOME", pwd->pw_dir, 1); + setenv("SHELL", pwd->pw_shell, 1); + if (term[0] == '\0') + strncpy(term, stypeof(tty), sizeof(term)); + setenv("TERM", term, 0); + setenv("USER", pwd->pw_name, 1); + setenv("PATH", ":/usr/ucb:/bin:/usr/bin", 0); + if ((namep = rindex(pwd->pw_shell, '/')) == NULL) namep = pwd->pw_shell; else namep++; strcat(minusnam, namep); if (tty[sizeof("tty")-1] == 'd') - syslog(LOG_INFO, "DIALUP %s %s", tty, pwd->pw_name); + syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); + if (pwd->pw_uid == 0) + if (utmp.ut_host[0]) + syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", + tty, HMAX, utmp.ut_host); + else + syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); if (!quietlog) { + struct stat st; + showmotd(); strcat(maildir, pwd->pw_name); - if (access(maildir, R_OK) == 0) { - struct stat statb; - stat(maildir, &statb); - if (statb.st_size) - printf("You have mail.\n"); - } + if (stat(maildir, &st) == 0 && st.st_size != 0) + printf("You have %smail.\n", + (st.st_mtime > st.st_atime) ? "new " : ""); } signal(SIGALRM, SIG_DFL); signal(SIGQUIT, SIG_DFL); @@ -403,65 +498,19 @@ stypeof(ttyid) doremotelogin(host) char *host; { - FILE *hostf; - int first = 1; - getstr(rusername, sizeof (rusername), "remuser"); getstr(lusername, sizeof (lusername), "locuser"); - getstr(term+5, sizeof(term)-5, "Terminal type"); + getstr(term, sizeof(term), "Terminal type"); if (getuid()) { pwd = &nouser; - goto bad; + return(-1); } pwd = getpwnam(lusername); if (pwd == NULL) { pwd = &nouser; - goto bad; + return(-1); } - hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0; -again: - if (hostf) { - char ahost[32]; - - while (fgets(ahost, sizeof (ahost), hostf)) { - char *user; - - if ((user = index(ahost, '\n')) != 0) - *user++ = '\0'; - if ((user = index(ahost, ' ')) != 0) - *user++ = '\0'; - if (!strcmp(host, ahost) && - !strcmp(rusername, user ? user : lusername)) { - fclose(hostf); - return (1); - } - } - fclose(hostf); - } - if (first == 1) { - char *rhosts = ".rhosts"; - struct stat sbuf; - - first = 0; - if (chdir(pwd->pw_dir) < 0) - goto again; - if (lstat(rhosts, &sbuf) < 0) - goto again; - if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { - printf("login: .rhosts is a soft link.\r\n"); - goto bad; - } - hostf = fopen(rhosts, "r"); - fstat(fileno(hostf), &sbuf); - if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { - printf("login: Bad .rhosts ownership.\r\n"); - fclose(hostf); - goto bad; - } - goto again; - } -bad: - return (-1); + return(ruserok(host, (pwd->pw_uid == 0), rusername, lusername)); } getstr(buf, cnt, err) @@ -491,16 +540,35 @@ doremoteterm(term, tp) char *term; struct sgttyb *tp; { - char *cp = index(term, '/'); - register int i; + register char *cp = index(term, '/'), **cpp; + char *speed; if (cp) { - *cp++ = 0; - for (i = 0; i < NSPEEDS; i++) - if (!strcmp(speeds[i], cp)) { - tp->sg_ispeed = tp->sg_ospeed = i; + *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; } + +tty_gid(default_gid) + int default_gid; +{ + struct group *getgrnam(), *gr; + int gid = default_gid; + + gr = getgrnam(TTYGRPNAME); + if (gr != (struct group *) 0) + gid = gr->gr_gid; + + endgrent(); + + return (gid); +}