X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/80f91e3f5a3bb9e578fa691d5938a1df6e5c7895..abc4056e93f8780d7cafe28754a1f7f211f948d6:/usr/src/usr.bin/login/login.c.1 diff --git a/usr/src/usr.bin/login/login.c.1 b/usr/src/usr.bin/login/login.c.1 index ae2a46bdb2..fd3188766f 100644 --- a/usr/src/usr.bin/login/login.c.1 +++ b/usr/src/usr.bin/login/login.c.1 @@ -1,22 +1,32 @@ /* - * 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. + * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = -"@(#) Copyright (c) 1980 Regents of the University of California.\n\ +"@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ All rights reserved.\n"; -#endif not lint +#endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)login.c.1 5.24 (Berkeley) %G%"; -#endif not lint +static char sccsid[] = "@(#)login.c.1 5.28 (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.) */ @@ -27,7 +37,6 @@ static char sccsid[] = "@(#)login.c.1 5.24 (Berkeley) %G%"; #include #include #include -#include #include #include @@ -38,6 +47,7 @@ static char sccsid[] = "@(#)login.c.1 5.24 (Berkeley) %G%"; #include #include #include +#include #include #include @@ -56,11 +66,11 @@ static char sccsid[] = "@(#)login.c.1 5.24 (Berkeley) %G%"; */ int timeout = 300; -struct passwd nouser = {"", "NOLOGIN", -1, -1, -1, "", "", "", "" }; -struct sgttyb ttyb; struct passwd *pwd; -char term[64], *hostname, *username; +int repeatcnt; +char term[64], *hostname, *username, *tty; +struct sgttyb sgttyb; struct tchars tc = { CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK }; @@ -77,9 +87,9 @@ main(argc, argv) struct group *gr; register int ch; register char *p; - int fflag, hflag, pflag, rflag, cnt; + int ask, fflag, hflag, pflag, cnt; int quietlog, passwd_req, ioctlval, timedout(); - char *domain, *envinit[1], *ttyn, *tty; + char *domain, *salt, *envinit[1], *ttyn; char tbuf[MAXPATHLEN + 2]; char *ttyname(), *stypeof(), *crypt(), *getpass(); time_t time(); @@ -94,26 +104,19 @@ 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 + * -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, '.'); - fflag = hflag = pflag = rflag = 0; + fflag = hflag = pflag = 0; passwd_req = 1; - while ((ch = getopt(argc, argv, "f:h:pr:")) != EOF) - switch(ch) { + 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; - username = optarg; break; case 'h': if (getuid()) { @@ -121,61 +124,39 @@ main(argc, argv) "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, '.')) && - strcmp(p, domain) == 0) + strcasecmp(p, domain) == 0) *p = 0; hostname = optarg; break; case 'p': pflag = 1; break; - case 'r': - if (hflag || fflag) { - fprintf(stderr, - "login: -f and -h not allowed with -r.\n"); - exit(1); - } - rflag = 1; - passwd_req = doremotelogin(optarg); - if (domain && (p = index(optarg, '.')) && - !strcmp(p, domain)) - *p = '\0'; - hostname = optarg; - break; case '?': default: - fprintf(stderr, "usage: login [-p] [username]\n"); + fprintf(stderr, "usage: login [-fp] [username]\n"); exit(1); } argc -= optind; argv += optind; - if (*argv) + if (*argv) { + ask = 0; username = *argv; + } + else + ask = 1; ioctlval = 0; (void)ioctl(0, TIOCLSET, &ioctlval); (void)ioctl(0, TIOCNXCL, 0); - (void)ioctl(0, FIONBIO, &ioctlval); - (void)ioctl(0, FIOASYNC, &ioctlval); - (void)ioctl(0, TIOCGETP, &ttyb); - - /* - * If talking to an rlogin process, propagate the terminal type and - * baud rate across the network. - */ - if (rflag) - doremoteterm(&ttyb); - ttyb.sg_erase = CERASE; - ttyb.sg_kill = CKILL; + (void)fcntl(0, F_SETFL, ioctlval); + (void)ioctl(0, TIOCGETP, &sgttyb); + sgttyb.sg_erase = CERASE; + sgttyb.sg_kill = CKILL; (void)ioctl(0, TIOCSLTC, <c); (void)ioctl(0, TIOCSETC, &tc); - (void)ioctl(0, TIOCSETP, &ttyb); + (void)ioctl(0, TIOCSETP, &sgttyb); for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); @@ -190,92 +171,94 @@ main(argc, argv) openlog("login", LOG_ODELAY, LOG_AUTH); - for (cnt = 0;; username = NULL) { + for (cnt = 0;; ask = 1) { ioctlval = 0; (void)ioctl(0, TIOCSETD, &ioctlval); - if (!username) + if (ask) { + fflag = 0; getloginname(); - if ((pwd = getpwnam(username)) == NULL) - pwd = &nouser; + } + /* note if trying multiple login's */ + if (repeatcnt) { + if (strcmp(tbuf, username)) { + badlogin(tbuf); + repeatcnt = 1; + (void)strcpy(tbuf, username); + } + else + ++repeatcnt; + } + else { + repeatcnt = 1; + (void)strcpy(tbuf, username); + } + if (pwd = getpwnam(username)) + salt = pwd->pw_passwd; + else + salt = "xx"; /* if user not super-user, check for disabled logins */ - if (pwd->pw_uid) + if (pwd == NULL || pwd->pw_uid) checknologin(); - if (!strcmp(pwd->pw_shell, "/bin/csh")) { - ioctlval = NTTYDISC; - (void)ioctl(0, TIOCSETD, &ioctlval); - } - /* - * disallow automatic login to root, or if not root - * and the uid's differ + * Disallow automatic login to root; if not invoked by + * root, disallow if the uid's differ. */ - if (fflag) { + if (fflag && pwd) { int uid = getuid(); - passwd_req = !pwd->pw_uid || uid && uid != pwd->pw_uid; + passwd_req = pwd->pw_uid == 0 || + (uid && uid != pwd->pw_uid); } /* - * If no remote login authentication and a password exists + * If no pre-authentication and a password exists * for this user, prompt for one and verify it. */ - if (!passwd_req || !*pwd->pw_passwd) + if (!passwd_req || pwd && !*pwd->pw_passwd) break; setpriority(PRIO_PROCESS, 0, -4); - p = getpass("Password:"); - p = crypt(p, pwd->pw_passwd); + p = crypt(getpass("Password:"), salt); setpriority(PRIO_PROCESS, 0, 0); - if (!strcmp(p, pwd->pw_passwd)) + if (pwd && !strcmp(p, pwd->pw_passwd)) break; printf("Login incorrect\n"); - if (++cnt >= 5) { - if (hostname) - syslog(LOG_ERR, - "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s", - tty, UT_HOSTSIZE, hostname, UT_NAMESIZE, - username); - else - syslog(LOG_ERR, - "REPEATED LOGIN FAILURES ON %s, %.*s", - tty, UT_NAMESIZE, username); - (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); - sleepexit(1); + /* 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)); } } /* committed to login -- turn off timeout */ (void)alarm((u_int)0); + /* log any mistakes -- don't count last one */ + --repeatcnt; + badlogin(username); + /* * If valid so far and root is logging in, see if root logins on * this terminal are permitted. */ - if (!pwd->pw_uid && !rootterm(tty)) { + if (pwd->pw_uid == 0 && !rootterm()) { if (hostname) - syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s FROM %.*s", - tty, UT_HOSTSIZE, hostname); + syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s FROM %s", + tty, hostname); else - syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s", tty); + syslog(LOG_ERR, "ROOT LOGIN REFUSED ON %s", tty); printf("Login incorrect\n"); sleepexit(1); } - if (*pwd->pw_shell == '\0') - pwd->pw_shell = BSHELL; - - if (chdir(pwd->pw_dir) < 0) { - printf("No directory %s!\n", pwd->pw_dir); - if (chdir("/")) - exit(0); - pwd->pw_dir = "/"; - printf("Logging in with home = \"/\".\n"); - } - if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { switch(errno) { case EUSERS: @@ -292,6 +275,15 @@ main(argc, argv) sleepexit(0); } + if (chdir(pwd->pw_dir) < 0) { + printf("No directory %s!\n", pwd->pw_dir); + if (chdir("/")) + exit(0); + pwd->pw_dir = "/"; + printf("Logging in with home = \"/\".\n"); + } + + /* nothing else left to fail -- really log in */ { struct utmp utmp; @@ -303,9 +295,9 @@ main(argc, argv) } quietlog = access(HUSHLOGIN, F_OK) == 0; - dolastlog(quietlog, tty); + dolastlog(quietlog); - if (!hflag && !rflag) { /* XXX */ + if (!hflag) { /* XXX */ static struct winsize win = { 0, 0, 0, 0 }; (void)ioctl(0, TIOCSWINSZ, &win); @@ -321,23 +313,31 @@ main(argc, argv) 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); + } + /* destroy environment unless user has requested preservation */ if (!pflag) environ = envinit; - setenv("HOME", pwd->pw_dir, 1); - setenv("SHELL", pwd->pw_shell, 1); + (void)setenv("HOME", pwd->pw_dir, 1); + (void)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); + strncpy(term, stypeof(), sizeof(term)); + (void)setenv("TERM", term, 0); + (void)setenv("USER", pwd->pw_name, 1); + (void)setenv("PATH", "/usr/ucb:/bin:/usr/bin:", 0); if (tty[sizeof("tty")-1] == 'd') syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); if (pwd->pw_uid == 0) if (hostname) - syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", - tty, UT_HOSTSIZE, hostname); + syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %s", + tty, hostname); else syslog(LOG_NOTICE, "ROOT LOGIN %s", tty); @@ -360,8 +360,8 @@ main(argc, argv) strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell); execlp(pwd->pw_shell, tbuf, 0); + fprintf(stderr, "login: no shell: "); perror(pwd->pw_shell); - fprintf(stderr, "login: no shell\n"); exit(0); } @@ -372,14 +372,13 @@ getloginname() static char nbuf[UT_NAMESIZE + 1]; for (;;) { - p = nbuf; printf("login: "); - while ((ch = getchar()) != '\n') { - if (ch == ' ') - ch = '_'; - if (ch == EOF) + for (p = nbuf; (ch = getchar()) != '\n'; ) { + if (ch == EOF) { + badlogin(username); exit(0); - if (p < nbuf+UT_NAMESIZE) + } + if (p < nbuf + UT_NAMESIZE) *p++ = ch; } if (p > nbuf) @@ -389,10 +388,9 @@ getloginname() else { *p = '\0'; username = nbuf; - return; + break; } } - /* NOTREACHED */ } timedout() @@ -401,41 +399,40 @@ timedout() exit(0); } -rootterm(tty) - char *tty; +rootterm() { struct ttyent *t; return((t = getttynam(tty)) && t->ty_status&TTY_SECURE); } -int motdinterrupt; +jmp_buf motdinterrupt; + motd() { - register int ch; - FILE *fp; + register int fd, nchars; int (*oldint)(), sigint(); + char tbuf[8192]; - if ((fp = fopen(MOTDFILE, "r")) == NULL) + if ((fd = open(MOTDFILE, O_RDONLY, 0)) < 0) return; oldint = signal(SIGINT, sigint); - while ((ch = getc(fp)) != EOF && !motdinterrupt) - (void)putchar(ch); + if (setjmp(motdinterrupt) == 0) + while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) + (void)write(fileno(stdout), tbuf, nchars); (void)signal(SIGINT, oldint); - if (motdinterrupt) - fpurge(fp); - (void)fclose(fp); + (void)close(fd); } sigint() { - motdinterrupt = 1; + longjmp(motdinterrupt, 1); } checknologin() { register int fd, nchars; - char tbuf[1024]; + char tbuf[8192]; if ((fd = open(NOLOGIN, O_RDONLY, 0)) >= 0) { while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) @@ -444,15 +441,14 @@ checknologin() } } -dolastlog(quiet, tty) +dolastlog(quiet) int quiet; - char *tty; { struct lastlog ll; int fd; if ((fd = open(LASTLOG, O_RDWR, 0)) >= 0) { - (void)lseek(fd, (long)pwd->pw_uid * sizeof(ll), L_SET); + (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) { @@ -465,7 +461,7 @@ dolastlog(quiet, tty) printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line); } - (void)lseek(fd, (long)pwd->pw_uid * sizeof(ll), L_SET); + (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); } (void)time(&ll.ll_time); strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); @@ -475,38 +471,28 @@ dolastlog(quiet, tty) } } +badlogin(name) + char *name; +{ + if (!repeatcnt) + return; + if (hostname) + syslog(LOG_ERR, "%d LOGIN FAILURE%s ON %s FROM %s, %s", + repeatcnt, repeatcnt > 1 ? "S" : "", tty, hostname, name); + else + syslog(LOG_ERR, "%d LOGIN FAILURE%s ON %s, %s", + repeatcnt, repeatcnt > 1 ? "S" : "", tty, name); +} + #undef UNKNOWN #define UNKNOWN "su" char * -stypeof(ttyid) - char *ttyid; +stypeof() { struct ttyent *t; - return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); -} - -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; - if (getuid()) { - pwd = &nouser; - return(-1); - } - pwd = getpwnam(username); - if (pwd == NULL) { - pwd = &nouser; - return(-1); - } - return(ruserok(host, (pwd->pw_uid == 0), rusername, username)); + return(tty && (t = getttynam(tty)) ? t->ty_type : UNKNOWN); } getstr(buf, cnt, err) @@ -526,33 +512,6 @@ getstr(buf, cnt, err) } while (ch); } -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; -} - sleepexit(eval) int eval; {