|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)login.c 4.33 (Berkeley) 83/09/02"; ! 3: #endif ! 4: ! 5: /* ! 6: * login [ name ] ! 7: * login -r hostname (for rlogind) ! 8: * login -h hostname (for telnetd, etc.) ! 9: */ ! 10: ! 11: #include <sys/param.h> ! 12: #include <sys/quota.h> ! 13: #include <sys/stat.h> ! 14: #include <sys/time.h> ! 15: #include <sys/resource.h> ! 16: ! 17: #include <sgtty.h> ! 18: #include <utmp.h> ! 19: #include <signal.h> ! 20: #include <pwd.h> ! 21: #include <stdio.h> ! 22: #include <lastlog.h> ! 23: #include <errno.h> ! 24: ! 25: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) ! 26: ! 27: #define NMAX sizeof(utmp.ut_name) ! 28: ! 29: #define FALSE 0 ! 30: #define TRUE -1 ! 31: ! 32: char nolog[] = "/etc/nologin"; ! 33: char qlog[] = ".hushlogin"; ! 34: char securetty[] = "/etc/securetty"; ! 35: char maildir[30] = "/usr/spool/mail/"; ! 36: char lastlog[] = "/usr/adm/lastlog"; ! 37: struct passwd nouser = {"", "nope", -1, -1, -1, "", "", "", "" }; ! 38: struct sgttyb ttyb; ! 39: struct utmp utmp; ! 40: char minusnam[16] = "-"; ! 41: /* ! 42: * This bounds the time given to login. We initialize it here ! 43: * so it can be patched on machines where it's too small. ! 44: */ ! 45: int timeout = 60; ! 46: ! 47: char homedir[64] = "HOME="; ! 48: char shell[64] = "SHELL="; ! 49: char term[64] = "TERM="; ! 50: char user[20] = "USER="; ! 51: ! 52: char *envinit[] = ! 53: { homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", term, user, 0 }; ! 54: ! 55: struct passwd *pwd; ! 56: struct passwd *getpwnam(); ! 57: char *strcat(), *rindex(), *index(); ! 58: int setpwent(); ! 59: int timedout(); ! 60: char *ttyname(); ! 61: char *crypt(); ! 62: char *getpass(); ! 63: char *stypeof(); ! 64: extern char **environ; ! 65: extern int errno; ! 66: ! 67: struct tchars tc = { ! 68: CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK ! 69: }; ! 70: struct ltchars ltc = { ! 71: CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT ! 72: }; ! 73: ! 74: int rflag; ! 75: char rusername[NMAX+1], lusername[NMAX+1]; ! 76: char rpassword[NMAX+1]; ! 77: char name[NMAX+1]; ! 78: char *rhost; ! 79: ! 80: main(argc, argv) ! 81: char *argv[]; ! 82: { ! 83: register char *namep; ! 84: int t, f, c, i; ! 85: int invalid, quietlog; ! 86: FILE *nlfd; ! 87: char *ttyn; ! 88: int ldisc = 0, zero = 0; ! 89: ! 90: signal(SIGALRM, timedout); ! 91: alarm(timeout); ! 92: signal(SIGQUIT, SIG_IGN); ! 93: signal(SIGINT, SIG_IGN); ! 94: setpriority(PRIO_PROCESS, 0, 0); ! 95: quota(Q_SETUID, 0, 0, 0); ! 96: /* ! 97: * -r is used by rlogind to cause the autologin protocol; ! 98: * -h is used by other servers to pass the name of the ! 99: * remote host to login so that it may be placed in utmp and wtmp ! 100: */ ! 101: if (argc > 1) { ! 102: if (strcmp(argv[1], "-r") == 0) { ! 103: rflag = doremotelogin(argv[2]); ! 104: SCPYN(utmp.ut_host, argv[2]); ! 105: argc = 0; ! 106: } ! 107: if (strcmp(argv[1], "-h") == 0 && getuid() == 0) { ! 108: SCPYN(utmp.ut_host, argv[2]); ! 109: argc = 0; ! 110: } ! 111: } ! 112: ioctl(0, TIOCLSET, &zero); ! 113: ioctl(0, TIOCNXCL, 0); ! 114: ioctl(0, FIONBIO, &zero); ! 115: ioctl(0, FIOASYNC, &zero); ! 116: ioctl(0, TIOCGETP, &ttyb); ! 117: /* ! 118: * If talking to an rlogin process, ! 119: * propagate the terminal type and ! 120: * baud rate across the network. ! 121: */ ! 122: if (rflag) ! 123: doremoteterm(term, &ttyb); ! 124: ioctl(0, TIOCSLTC, <c); ! 125: ioctl(0, TIOCSETC, &tc); ! 126: ioctl(0, TIOCSETP, &ttyb); ! 127: for (t = getdtablesize(); t > 3; t--) ! 128: close(t); ! 129: ttyn = ttyname(0); ! 130: if (ttyn==(char *)0) ! 131: ttyn = "/dev/tty??"; ! 132: do { ! 133: ldisc = 0; ! 134: ioctl(0, TIOCSETD, &ldisc); ! 135: invalid = FALSE; ! 136: SCPYN(utmp.ut_name, ""); ! 137: /* ! 138: * Name specified, take it. ! 139: */ ! 140: if (argc > 1) { ! 141: SCPYN(utmp.ut_name, argv[1]); ! 142: argc = 0; ! 143: } ! 144: /* ! 145: * If remote login take given name, ! 146: * otherwise prompt user for something. ! 147: */ ! 148: if (rflag) { ! 149: SCPYN(utmp.ut_name, lusername); ! 150: /* autologin failed, prompt for passwd */ ! 151: if (rflag == -1) ! 152: rflag = 0; ! 153: } else ! 154: getloginname(&utmp); ! 155: if (!strcmp(pwd->pw_shell, "/bin/csh")) { ! 156: ldisc = NTTYDISC; ! 157: ioctl(0, TIOCSETD, &ldisc); ! 158: } ! 159: /* ! 160: * If no remote login authentication and ! 161: * a password exists for this user, prompt ! 162: * for one and verify it. ! 163: */ ! 164: if (!rflag && *pwd->pw_passwd != '\0') { ! 165: char *pp; ! 166: ! 167: setpriority(PRIO_PROCESS, 0, -4); ! 168: pp = getpass("Password:"); ! 169: namep = crypt(pp, pwd->pw_passwd); ! 170: setpriority(PRIO_PROCESS, 0, 0); ! 171: if (strcmp(namep, pwd->pw_passwd)) ! 172: invalid = TRUE; ! 173: } ! 174: /* ! 175: * If user not super-user, check for logins disabled. ! 176: */ ! 177: if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { ! 178: while ((c = getc(nlfd)) != EOF) ! 179: putchar(c); ! 180: fflush(stdout); ! 181: sleep(5); ! 182: exit(0); ! 183: } ! 184: /* ! 185: * If valid so far and root is logging in, ! 186: * see if root logins on this terminal are permitted. ! 187: */ ! 188: if (!invalid && pwd->pw_uid == 0 && ! 189: !rootterm(ttyn+sizeof("/dev/")-1)) { ! 190: logerr("ROOT LOGIN REFUSED %s", ! 191: ttyn+sizeof("/dev/")-1); ! 192: invalid = TRUE; ! 193: } ! 194: if (invalid) { ! 195: printf("Login incorrect\n"); ! 196: if (ttyn[sizeof("/dev/tty")-1] == 'd') ! 197: logerr("BADDIALUP %s %s", ! 198: ttyn+sizeof("/dev/")-1, utmp.ut_name); ! 199: } ! 200: if (*pwd->pw_shell == '\0') ! 201: pwd->pw_shell = "/bin/sh"; ! 202: i = strlen(pwd->pw_shell); ! 203: if (chdir(pwd->pw_dir) < 0 && !invalid ) { ! 204: if (chdir("/") < 0) { ! 205: printf("No directory!\n"); ! 206: invalid = TRUE; ! 207: } else { ! 208: printf("No directory! %s\n", ! 209: "Logging in with home=/"); ! 210: pwd->pw_dir = "/"; ! 211: } ! 212: } ! 213: /* ! 214: * Remote login invalid must have been because ! 215: * of a restriction of some sort, no extra chances. ! 216: */ ! 217: if (rflag && invalid) ! 218: exit(1); ! 219: } while (invalid); ! 220: /* committed to login turn off timeout */ ! 221: alarm(0); ! 222: ! 223: if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0) { ! 224: if (errno == EUSERS) ! 225: printf("%s.\n%s.\n", ! 226: "Too many users logged on already", ! 227: "Try again later"); ! 228: else if (errno == EPROCLIM) ! 229: printf("You have too many processes running.\n"); ! 230: else ! 231: perror("setuid"); ! 232: sleep(5); ! 233: exit(0); ! 234: } ! 235: time(&utmp.ut_time); ! 236: t = ttyslot(); ! 237: if (t > 0 && (f = open("/etc/utmp", 1)) >= 0) { ! 238: lseek(f, (long)(t*sizeof(utmp)), 0); ! 239: SCPYN(utmp.ut_line, rindex(ttyn, '/')+1); ! 240: write(f, (char *)&utmp, sizeof(utmp)); ! 241: close(f); ! 242: } ! 243: if (t > 0 && (f = open("/usr/adm/wtmp", 1)) >= 0) { ! 244: lseek(f, 0L, 2); ! 245: write(f, (char *)&utmp, sizeof(utmp)); ! 246: close(f); ! 247: } ! 248: quietlog = access(qlog, 0) == 0; ! 249: if ((f = open(lastlog, 2)) >= 0) { ! 250: struct lastlog ll; ! 251: ! 252: lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); ! 253: if (read(f, (char *) &ll, sizeof ll) == sizeof ll && ! 254: ll.ll_time != 0 && !quietlog) { ! 255: printf("Last login: %.*s ", ! 256: 24-5, (char *)ctime(&ll.ll_time)); ! 257: if (*ll.ll_host != '\0') ! 258: printf("from %.*s\n", ! 259: sizeof (ll.ll_host), ll.ll_host); ! 260: else ! 261: printf("on %.*s\n", ! 262: sizeof (ll.ll_line), ll.ll_line); ! 263: } ! 264: lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0); ! 265: time(&ll.ll_time); ! 266: SCPYN(ll.ll_line, rindex(ttyn, '/')+1); ! 267: SCPYN(ll.ll_host, utmp.ut_host); ! 268: write(f, (char *) &ll, sizeof ll); ! 269: close(f); ! 270: } ! 271: chown(ttyn, pwd->pw_uid, pwd->pw_gid); ! 272: chmod(ttyn, 0622); ! 273: setgid(pwd->pw_gid); ! 274: strncpy(name, utmp.ut_name, NMAX); ! 275: name[NMAX] = '\0'; ! 276: initgroups(name, pwd->pw_gid); ! 277: quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); ! 278: setuid(pwd->pw_uid); ! 279: environ = envinit; ! 280: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); ! 281: strncat(shell, pwd->pw_shell, sizeof(shell)-7); ! 282: if (term[strlen("TERM=")] == 0) ! 283: strncat(term, stypeof(ttyn), sizeof(term)-6); ! 284: strncat(user, pwd->pw_name, sizeof(user)-6); ! 285: if ((namep = rindex(pwd->pw_shell, '/')) == NULL) ! 286: namep = pwd->pw_shell; ! 287: else ! 288: namep++; ! 289: strcat(minusnam, namep); ! 290: umask(022); ! 291: if (ttyn[sizeof("/dev/tty")-1] == 'd') ! 292: logerr("DIALUP %s %s", ! 293: ttyn+sizeof("/dev/")-1, pwd->pw_name); ! 294: if (!quietlog) { ! 295: showmotd(); ! 296: strcat(maildir, pwd->pw_name); ! 297: if (access(maildir,4)==0) { ! 298: struct stat statb; ! 299: stat(maildir, &statb); ! 300: if (statb.st_size) ! 301: printf("You have mail.\n"); ! 302: } ! 303: } ! 304: signal(SIGALRM, SIG_DFL); ! 305: signal(SIGQUIT, SIG_DFL); ! 306: signal(SIGINT, SIG_DFL); ! 307: signal(SIGTSTP, SIG_IGN); ! 308: execlp(pwd->pw_shell, minusnam, 0); ! 309: perror(pwd->pw_shell); ! 310: printf("No shell\n"); ! 311: exit(0); ! 312: } ! 313: ! 314: getloginname(up) ! 315: register struct utmp *up; ! 316: { ! 317: register char *namep; ! 318: char c; ! 319: ! 320: while (up->ut_name[0] == '\0') { ! 321: namep = up->ut_name; ! 322: printf("login: "); ! 323: while ((c = getchar()) != '\n') { ! 324: if (c == ' ') ! 325: c = '_'; ! 326: if (c == EOF) ! 327: exit(0); ! 328: if (namep < up->ut_name+NMAX) ! 329: *namep++ = c; ! 330: } ! 331: } ! 332: strncpy(lusername, up->ut_name, NMAX); ! 333: lusername[NMAX] = 0; ! 334: setpwent(); ! 335: if ((pwd = getpwnam(lusername)) == NULL) ! 336: pwd = &nouser; ! 337: endpwent(); ! 338: } ! 339: ! 340: timedout() ! 341: { ! 342: ! 343: printf("Login timed out after %d seconds\n", timeout); ! 344: exit(0); ! 345: } ! 346: ! 347: int stopmotd; ! 348: catch() ! 349: { ! 350: ! 351: signal(SIGINT, SIG_IGN); ! 352: stopmotd++; ! 353: } ! 354: ! 355: rootterm(tty) ! 356: char *tty; ! 357: { ! 358: register FILE *fd; ! 359: char buf[100]; ! 360: ! 361: if ((fd = fopen(securetty, "r")) == NULL) ! 362: return(1); ! 363: while (fgets(buf, sizeof buf, fd) != NULL) { ! 364: buf[strlen(buf)-1] = '\0'; ! 365: if (strcmp(tty, buf) == 0) { ! 366: fclose(fd); ! 367: return(1); ! 368: } ! 369: } ! 370: fclose(fd); ! 371: return(0); ! 372: } ! 373: ! 374: showmotd() ! 375: { ! 376: FILE *mf; ! 377: register c; ! 378: ! 379: signal(SIGINT, catch); ! 380: if ((mf = fopen("/etc/motd","r")) != NULL) { ! 381: while ((c = getc(mf)) != EOF && stopmotd == 0) ! 382: putchar(c); ! 383: fclose(mf); ! 384: } ! 385: signal(SIGINT, SIG_IGN); ! 386: } ! 387: ! 388: #undef UNKNOWN ! 389: #define UNKNOWN "su" ! 390: ! 391: char * ! 392: stypeof(ttyid) ! 393: char *ttyid; ! 394: { ! 395: static char typebuf[16]; ! 396: char buf[50]; ! 397: register FILE *f; ! 398: register char *p, *t, *q; ! 399: ! 400: if (ttyid == NULL) ! 401: return (UNKNOWN); ! 402: f = fopen("/etc/ttytype", "r"); ! 403: if (f == NULL) ! 404: return (UNKNOWN); ! 405: /* split off end of name */ ! 406: for (p = q = ttyid; *p != 0; p++) ! 407: if (*p == '/') ! 408: q = p + 1; ! 409: ! 410: /* scan the file */ ! 411: while (fgets(buf, sizeof buf, f) != NULL) { ! 412: for (t = buf; *t != ' ' && *t != '\t'; t++) ! 413: ; ! 414: *t++ = 0; ! 415: while (*t == ' ' || *t == '\t') ! 416: t++; ! 417: for (p = t; *p > ' '; p++) ! 418: ; ! 419: *p = 0; ! 420: if (strcmp(q,t) == 0) { ! 421: strcpy(typebuf, buf); ! 422: fclose(f); ! 423: return (typebuf); ! 424: } ! 425: } ! 426: fclose (f); ! 427: return (UNKNOWN); ! 428: } ! 429: ! 430: doremotelogin(host) ! 431: char *host; ! 432: { ! 433: FILE *hostf; ! 434: int first = 1; ! 435: ! 436: getstr(rusername, sizeof (rusername), "remuser"); ! 437: getstr(lusername, sizeof (lusername), "locuser"); ! 438: getstr(term+5, sizeof(term)-5, "Terminal type"); ! 439: if (getuid()) { ! 440: pwd = &nouser; ! 441: goto bad; ! 442: } ! 443: setpwent(); ! 444: pwd = getpwnam(lusername); ! 445: endpwent(); ! 446: if (pwd == NULL) { ! 447: pwd = &nouser; ! 448: goto bad; ! 449: } ! 450: hostf = pwd->pw_uid ? fopen("/etc/hosts.equiv", "r") : 0; ! 451: again: ! 452: if (hostf) { ! 453: char ahost[32]; ! 454: ! 455: while (fgets(ahost, sizeof (ahost), hostf)) { ! 456: char *user; ! 457: ! 458: if ((user = index(ahost, '\n')) != 0) ! 459: *user++ = '\0'; ! 460: if ((user = index(ahost, ' ')) != 0) ! 461: *user++ = '\0'; ! 462: if (!strcmp(host, ahost) && ! 463: !strcmp(rusername, user ? user : lusername)) { ! 464: fclose(hostf); ! 465: return (1); ! 466: } ! 467: } ! 468: fclose(hostf); ! 469: } ! 470: if (first == 1) { ! 471: char *rhosts = ".rhosts"; ! 472: struct stat sbuf; ! 473: ! 474: first = 0; ! 475: if (chdir(pwd->pw_dir) < 0) ! 476: goto again; ! 477: if (lstat(rhosts, &sbuf) < 0) ! 478: goto again; ! 479: if ((sbuf.st_mode & S_IFMT) == S_IFLNK) { ! 480: printf("login: .rhosts is a soft link.\r\n"); ! 481: goto bad; ! 482: } ! 483: hostf = fopen(rhosts, "r"); ! 484: fstat(fileno(hostf), &sbuf); ! 485: if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid) { ! 486: printf("login: Bad .rhosts ownership.\r\n"); ! 487: fclose(hostf); ! 488: goto bad; ! 489: } ! 490: goto again; ! 491: } ! 492: bad: ! 493: return (-1); ! 494: } ! 495: ! 496: getstr(buf, cnt, err) ! 497: char *buf; ! 498: int cnt; ! 499: char *err; ! 500: { ! 501: char c; ! 502: ! 503: do { ! 504: if (read(0, &c, 1) != 1) ! 505: exit(1); ! 506: if (--cnt < 0) { ! 507: printf("%s too long\r\n", err); ! 508: exit(1); ! 509: } ! 510: *buf++ = c; ! 511: } while (c != 0); ! 512: } ! 513: ! 514: char *speeds[] = ! 515: { "0", "50", "75", "110", "134", "150", "200", "300", ! 516: "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; ! 517: #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) ! 518: ! 519: doremoteterm(term, tp) ! 520: char *term; ! 521: struct sgttyb *tp; ! 522: { ! 523: char *cp = index(term, '/'); ! 524: register int i; ! 525: ! 526: if (cp) { ! 527: *cp++ = 0; ! 528: for (i = 0; i < NSPEEDS; i++) ! 529: if (!strcmp(speeds[i], cp)) { ! 530: tp->sg_ispeed = tp->sg_ospeed = i; ! 531: break; ! 532: } ! 533: } ! 534: tp->sg_flags = ECHO|CRMOD|ANYP|XTABS; ! 535: } ! 536: ! 537: logerr(fmt, a1, a2, a3) ! 538: char *fmt, *a1, *a2, *a3; ! 539: { ! 540: #ifdef LOGERR ! 541: FILE *cons = fopen("/dev/console", "w"); ! 542: ! 543: if (cons != NULL) { ! 544: fprintf(cons, fmt, a1, a2, a3); ! 545: fprintf(cons, "\n\r"); ! 546: fclose(cons); ! 547: } ! 548: #endif ! 549: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.