X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/e804469b5b0975de34bae1e66c3e6371249d3ee7..0f4556f12c8f75078501c9d1338ae7648a97f975:/usr/src/bin/login.c?ds=inline diff --git a/usr/src/bin/login.c b/usr/src/bin/login.c index 7bb1c6e435..22066abde8 100644 --- a/usr/src/bin/login.c +++ b/usr/src/bin/login.c @@ -1,22 +1,30 @@ -static char *sccsid = "@(#)login.c 4.20 82/12/21"; +#ifndef lint +static char *sccsid = "@(#)login.c 4.33 (Berkeley) 83/09/02"; +#endif + /* * login [ name ] - * login -r + * login -r hostname (for rlogind) + * login -h hostname (for telnetd, etc.) */ -#include +#include +#include +#include +#include +#include + #include #include #include #include #include -#include #include +#include #define SCPYN(a, b) strncpy(a, b, sizeof(a)) #define NMAX sizeof(utmp.ut_name) -#define LMAX sizeof(utmp.ut_line) #define FALSE 0 #define TRUE -1 @@ -30,34 +38,37 @@ struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; struct sgttyb ttyb; struct utmp utmp; char minusnam[16] = "-"; +/* + * 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; char homedir[64] = "HOME="; char shell[64] = "SHELL="; char term[64] = "TERM="; char user[20] = "USER="; -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])) char *envinit[] = - {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0}; + { homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0 }; struct passwd *pwd; struct passwd *getpwnam(); char *strcat(), *rindex(), *index(); int setpwent(); +int timedout(); char *ttyname(); char *crypt(); char *getpass(); -char *rindex(); char *stypeof(); extern char **environ; +extern int errno; -struct ttychars tc = { - CERASE, CKILL, CINTR, CQUIT, CSTART, - CSTOP, CEOF, CBRK, CSUSP, CDSUSP, - CRPRNT, CFLUSH, CWERASE,CLNEXT +struct tchars tc = { + CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK +}; +struct ltchars ltc = { + CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; int rflag; @@ -67,93 +78,53 @@ char name[NMAX+1]; char *rhost; main(argc, argv) -char **argv; + char *argv[]; { register char *namep; - int t, f, c; - int invalid; - int quietlog; - int i; + int t, f, c, i; + int invalid, quietlog; FILE *nlfd; char *ttyn; int ldisc = 0, zero = 0; - FILE *hostf; int first = 1; - alarm(60); + signal(SIGALRM, timedout); + alarm(timeout); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); - nice(-100); - nice(20); - nice(0); - if (argc > 1 && !strcmp(argv[1], "-r")) { - rflag++; - rhost = argv[2]; - argc = 1; - getstr(rusername, sizeof (rusername), "remuser"); - getstr(lusername, sizeof (lusername), "locuser"); - getstr(term+5, sizeof(term)-5, "Terminal type"); - if (getuid()) - goto abnormal; - setpwent(); - pwd = getpwnam(lusername); - endpwent(); - if (pwd == NULL) { - if (strcmp(rusername, lusername)) - printf("%s: No such user\r\n", lusername); - goto abnormal; - } - 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 (index(ahost, '\n')) - *index(ahost, '\n') = 0; - user = index(ahost, ' '); - if (user) - *user++ = 0; - if (!strcmp(rhost, ahost) && - !strcmp(rusername, user ? user : lusername)) { - fclose(hostf); - goto normal; - } - } - fclose(hostf); + setpriority(PRIO_PROCESS, 0, 0); + quota(Q_SETUID, 0, 0, 0); + /* + * -r is used by rlogind to cause the autologin protocol; + * -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) { + if (strcmp(argv[1], "-r") == 0) { + rflag = doremotelogin(argv[2]); + SCPYN(utmp.ut_host, argv[2]); + argc = 0; } - if (first == 1) { - first = 0; - if (chdir(pwd->pw_dir) < 0) - goto again; - hostf = fopen(".rhosts", "r"); - goto again; + if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { + SCPYN(utmp.ut_host, argv[2]); + argc = 0; } -abnormal: - rhost = 0; - rflag = -1; } -normal: - ioctl(0, TIOCLSET, &zero); /* XXX */ + ioctl(0, TIOCLSET, &zero); ioctl(0, TIOCNXCL, 0); ioctl(0, FIONBIO, &zero); ioctl(0, FIOASYNC, &zero); - ioctl(0, TIOCGETP, &ttyb); /* XXX */ - if (rflag) { - char *cp = index(term, '/'); - if (cp) { - int i; - *cp++ = 0; - for (i = 0; i < NSPEEDS; i++) - if (!strcmp(speeds[i], cp)) { - ttyb.sg_ispeed = ttyb.sg_ospeed = i; - break; - } - } - ttyb.sg_flags = ECHO|CRMOD|ANYP|XTABS; - } - ioctl(0, TIOCSETP, &ttyb); /* XXX */ - ioctl(0, TIOCCSET, &tc); - for (t=3; t<20; t++) + ioctl(0, TIOCGETP, &ttyb); + /* + * If talking to an rlogin process, + * propagate the terminal type and + * baud rate across the network. + */ + if (rflag) + doremoteterm(term, &ttyb); + ioctl(0, TIOCSLTC, <c); + ioctl(0, TIOCSETC, &tc); + ioctl(0, TIOCSETP, &ttyb); + for (t = getdtablesize(); t > 3; t--) close(t); ttyn = ttyname(0); if (ttyn==(char *)0) @@ -163,61 +134,57 @@ normal: ioctl(0, TIOCSETD, &ldisc); invalid = FALSE; SCPYN(utmp.ut_name, ""); - if (argc>1) { + /* + * Name specified, take it. + */ + if (argc > 1) { SCPYN(utmp.ut_name, argv[1]); argc = 0; } + /* + * If remote login take given name, + * otherwise prompt user for something. + */ if (rflag) { SCPYN(utmp.ut_name, lusername); + /* autologin failed, prompt for passwd */ if (rflag == -1) rflag = 0; } else - while (utmp.ut_name[0] == '\0') { - namep = utmp.ut_name; - { char hostname[32]; - gethostname(hostname, sizeof (hostname)); - printf("%s login: ", hostname); } - while ((c = getchar()) != '\n') { - if (c == ' ') - c = '_'; - if (c == EOF) - exit(0); - if (namep < utmp.ut_name+NMAX) - *namep++ = c; - } - } - if (rhost == 0) { - setpwent(); - if ((pwd = getpwnam(utmp.ut_name)) == NULL) - pwd = &nouser; - endpwent(); - } + getloginname(&utmp); if (!strcmp(pwd->pw_shell, "/bin/csh")) { ldisc = NTTYDISC; ioctl(0, TIOCSETD, &ldisc); } - if (rhost == 0) { - if (*pwd->pw_passwd != '\0') { - char *pp; - nice(-4); - if (rflag == 0) - pp = getpass("Password:"); - else - pp = rpassword; - namep = crypt(pp,pwd->pw_passwd); - nice(4); - if (strcmp(namep, pwd->pw_passwd)) - invalid = TRUE; - } + /* + * If no remote login authentication and + * a password exists for this user, prompt + * for one and verify it. + */ + if (!rflag && *pwd->pw_passwd != '\0') { + char *pp; + + setpriority(PRIO_PROCESS, 0, -4); + pp = getpass("Password:"); + namep = crypt(pp, pwd->pw_passwd); + setpriority(PRIO_PROCESS, 0, 0); + if (strcmp(namep, pwd->pw_passwd)) + invalid = TRUE; } + /* + * If user not super-user, check for logins disabled. + */ if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { - /* logins are disabled except for root */ while ((c = getc(nlfd)) != EOF) putchar(c); fflush(stdout); sleep(5); exit(0); } + /* + * If valid so far and root is logging in, + * see if root logins on this terminal are permitted. + */ if (!invalid && pwd->pw_uid == 0 && !rootterm(ttyn+sizeof("/dev/")-1)) { logerr("ROOT LOGIN REFUSED %s", @@ -227,7 +194,7 @@ normal: if (invalid) { printf("Login incorrect\n"); if (ttyn[sizeof("/dev/tty")-1] == 'd') - logerr("BADDIALUP %s %s\n", + logerr("BADDIALUP %s %s", ttyn+sizeof("/dev/")-1, utmp.ut_name); } if (*pwd->pw_shell == '\0') @@ -238,48 +205,66 @@ normal: printf("No directory!\n"); invalid = TRUE; } else { - printf("No directory! Logging in with home=/\n"); + printf("No directory! %s\n", + "Logging in with home=/"); pwd->pw_dir = "/"; } } + /* + * Remote login invalid must have been because + * of a restriction of some sort, no extra chances. + */ if (rflag && invalid) exit(1); } while (invalid); +/* committed to login turn off timeout */ + alarm(0); - + if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) { + if (errno == EUSERS) + printf("%s.\n%s.\n", + "Too many users logged on already", + "Try again later"); + else if (errno == EPROCLIM) + printf("You have too many processes running.\n"); + else + perror("setuid"); + sleep(5); + exit(0); + } time(&utmp.ut_time); t = ttyslot(); - if (t>0 && (f = open("/etc/utmp", 1)) >= 0) { + if (t > 0 && (f = open("/etc/utmp", 1)) >= 0) { lseek(f, (long)(t*sizeof(utmp)), 0); SCPYN(utmp.ut_line, rindex(ttyn, '/')+1); write(f, (char *)&utmp, sizeof(utmp)); close(f); } - if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { + if (t > 0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { lseek(f, 0L, 2); write(f, (char *)&utmp, sizeof(utmp)); close(f); } - quietlog = 0; - if (access(qlog, 0) == 0) - quietlog = 1; + quietlog = access(qlog, 0) == 0; if ((f = open(lastlog, 2)) >= 0) { struct lastlog ll; lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); if (read(f, (char *) &ll, sizeof ll) == sizeof ll && - ll.ll_time != 0) { - if (quietlog == 0) - printf("Last login: %.*s on %.*s\n" - , 24-5 - , (char *) ctime(&ll.ll_time) - , sizeof(ll.ll_line) - , ll.ll_line - ); + ll.ll_time != 0 && !quietlog) { + printf("Last login: %.*s ", + 24-5, (char *)ctime(&ll.ll_time)); + if (*ll.ll_host != '\0') + printf("from %.*s\n", + sizeof (ll.ll_host), ll.ll_host); + else + printf("on %.*s\n", + sizeof (ll.ll_line), ll.ll_line); } lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); time(&ll.ll_time); SCPYN(ll.ll_line, rindex(ttyn, '/')+1); + SCPYN(ll.ll_host, utmp.ut_host); write(f, (char *) &ll, sizeof ll); close(f); } @@ -289,6 +274,7 @@ normal: 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); @@ -301,10 +287,10 @@ normal: else namep++; strcat(minusnam, namep); - alarm(0); umask(022); if (ttyn[sizeof("/dev/tty")-1] == 'd') - logerr("DIALUP %s %s\n", ttyn+sizeof("/dev/")-1, pwd->pw_name); + logerr("DIALUP %s %s", + ttyn+sizeof("/dev/")-1, pwd->pw_name); if (!quietlog) { showmotd(); strcat(maildir, pwd->pw_name); @@ -315,7 +301,7 @@ normal: printf("You have mail.\n"); } } - + signal(SIGALRM, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGTSTP, SIG_IGN); @@ -325,6 +311,39 @@ normal: exit(0); } +getloginname(up) + register struct utmp *up; +{ + register char *namep; + char c; + + while (up->ut_name[0] == '\0') { + namep = up->ut_name; + printf("login: "); + while ((c = getchar()) != '\n') { + if (c == ' ') + c = '_'; + if (c == EOF) + exit(0); + if (namep < up->ut_name+NMAX) + *namep++ = c; + } + } + strncpy(lusername, up->ut_name, NMAX); + lusername[NMAX] = 0; + setpwent(); + if ((pwd = getpwnam(lusername)) == NULL) + pwd = &nouser; + endpwent(); +} + +timedout() +{ + + printf("Login timed out after %d seconds\n", timeout); + exit(0); +} + int stopmotd; catch() { @@ -339,8 +358,6 @@ rootterm(tty) register FILE *fd; char buf[100]; - if (rflag) - return(1); if ((fd = fopen(securetty, "r")) == NULL) return(1); while (fgets(buf, sizeof buf, fd) != NULL) { @@ -373,12 +390,12 @@ showmotd() char * stypeof(ttyid) -char *ttyid; + char *ttyid; { - static char typebuf[16]; - char buf[50]; - register FILE *f; - register char *p, *t, *q; + static char typebuf[16]; + char buf[50]; + register FILE *f; + register char *p, *t, *q; if (ttyid == NULL) return (UNKNOWN); @@ -391,17 +408,16 @@ char *ttyid; q = p + 1; /* scan the file */ - while (fgets(buf, sizeof buf, f) != NULL) - { - for (t=buf; *t!=' ' && *t != '\t'; t++) + while (fgets(buf, sizeof buf, f) != NULL) { + for (t = buf; *t != ' ' && *t != '\t'; t++) ; *t++ = 0; while (*t == ' ' || *t == '\t') t++; - for (p=t; *p>' '; p++) + for (p = t; *p > ' '; p++) ; *p = 0; - if (strcmp(q,t)==0) { + if (strcmp(q,t) == 0) { strcpy(typebuf, buf); fclose(f); return (typebuf); @@ -411,6 +427,72 @@ char *ttyid; return (UNKNOWN); } +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"); + if (getuid()) { + pwd = &nouser; + goto bad; + } + setpwent(); + pwd = getpwnam(lusername); + endpwent(); + if (pwd == NULL) { + pwd = &nouser; + goto bad; + } + 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); +} + getstr(buf, cnt, err) char *buf; int cnt; @@ -429,8 +511,39 @@ getstr(buf, cnt, err) } while (c != 0); } +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(term, tp) + char *term; + struct sgttyb *tp; +{ + char *cp = index(term, '/'); + register int i; + + if (cp) { + *cp++ = 0; + for (i = 0; i < NSPEEDS; i++) + if (!strcmp(speeds[i], cp)) { + tp->sg_ispeed = tp->sg_ospeed = i; + break; + } + } + tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; +} + logerr(fmt, a1, a2, a3) char *fmt, *a1, *a2, *a3; { +#ifdef LOGERR + FILE *cons = fopen("/dev/console", "w"); + if (cons != NULL) { + fprintf(cons, fmt, a1, a2, a3); + fprintf(cons, "\n\r"); + fclose(cons); + } +#endif }