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