|
|
1.1 ! root 1: /* ! 2: * login [ -f name ] [ -p passwdline ] [ command ] ! 3: * -f: if su, log in with no password ! 4: * -p: if su, use entire password line. ! 5: * command: if given, just execute command ! 6: */ ! 7: ! 8: #include <sys/param.h> ! 9: #include <sys/ttyio.h> ! 10: #include <utmp.h> ! 11: #include <signal.h> ! 12: #include <pwd.h> ! 13: #include <libc.h> ! 14: #include <stdio.h> ! 15: #include <sys/stat.h> ! 16: #include <sys/vlimit.h> ! 17: ! 18: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) ! 19: ! 20: #define ISIZE 32 ! 21: #define POSTMKSIZ sizeof "From Sun Jan 00 00:00:00 1979" ! 22: char maildir[30] = "/usr/spool/mail/"; ! 23: struct passwd nouser = {"", "nope"}; ! 24: struct utmp utmp, xtmp; ! 25: char minusnam[16] = "-"; ! 26: char homedir[64] = "HOME="; ! 27: char path[] = "PATH=:/bin:/usr/bin"; ! 28: char **env; ! 29: int nenv = 0; ! 30: char nolog[] = "/etc/nologin"; ! 31: char motd[] = "/etc/motd"; ! 32: struct passwd *pwd; ! 33: struct passwd *pwdecode(); ! 34: char *cmd; ! 35: ! 36: extern char **environ; ! 37: ! 38: main(argc, argv) ! 39: char **argv; ! 40: { ! 41: register char *namep; ! 42: register int i, f; ! 43: char input[ISIZE]; ! 44: char *ttyn; ! 45: int neednopass = 0; ! 46: int hangitup = 0; ! 47: int ntries = 0; ! 48: struct ttydevb tb; ! 49: ! 50: alarm(60); ! 51: signal(SIGQUIT, SIG_IGN); ! 52: signal(SIGINT, SIG_IGN); ! 53: signal(SIGHUP, SIG_IGN); ! 54: nice(-100); ! 55: nice(20); ! 56: for (i=NSYSFILE; i<NOFILE; i++) ! 57: close(i); ! 58: ttyn = ttyname(0); ! 59: if (ttyn==0) ! 60: SCPYN(utmp.ut_line, "tty??"); ! 61: else if (strncmp(ttyn, "/dev/", 5) == 0) ! 62: SCPYN(utmp.ut_line, ttyn+5); ! 63: else ! 64: SCPYN(utmp.ut_line, ttyn); /* shouldn't happen */ ! 65: SCPYN(input, ""); ! 66: switch(argc) { ! 67: case 0: ! 68: case 1: ! 69: break; ! 70: ! 71: case 2: ! 72: SCPYN(input, argv[1]); ! 73: break; ! 74: ! 75: default: ! 76: if (strcmp(argv[1], "-f")==0 || strcmp(argv[1], "-p")==0) { ! 77: if (getuid()!=0) { ! 78: printf("login: not super-user\n"); ! 79: exit(1); ! 80: } ! 81: neednopass++; ! 82: if (strcmp(argv[1], "-f")==0) ! 83: SCPYN(input, argv[2]); ! 84: else { ! 85: pwd = pwdecode(argv[2]); ! 86: SCPYN(input, pwd->pw_name); ! 87: } ! 88: if (argc>3) ! 89: cmd = argv[3]; ! 90: } else ! 91: exit(1); ! 92: } ! 93: loop: ! 94: if (ntries) { ! 95: if (ntries > 5 || hangitup) { ! 96: ioctl(0, TIOCGDEV, &tb); ! 97: tb.ispeed = tb.ospeed = 0; ! 98: ioctl(0, TIOCSDEV, &tb); ! 99: sleep(5); ! 100: exit(1); ! 101: } ! 102: neednopass = 0; ! 103: pwd = NULL; ! 104: SCPYN(input, ""); ! 105: } ! 106: ntries++; ! 107: while (input[0] == '\0') { ! 108: namep = input; ! 109: printf("login: "); ! 110: while ((i = getchar()) != '\n') { ! 111: if(i == ' ') ! 112: i = '_'; ! 113: if (i == EOF) ! 114: exit(0); ! 115: if (namep < input + ISIZE - 1) ! 116: *namep++ = i; ! 117: } ! 118: *namep = NULL; ! 119: } ! 120: SCPYN(utmp.ut_name, input); ! 121: utmp.ut_time = 0; ! 122: if (pwd == NULL) { ! 123: setpwent(); ! 124: if ((pwd = getpwnam(input)) == NULL) ! 125: pwd = &nouser; ! 126: endpwent(); ! 127: } ! 128: if (namep = strchr(utmp.ut_name, '\001')) ! 129: if (namep[1]=='L' && namep[2]=='\002') /* loopback? */ ! 130: hangitup++; ! 131: time(&utmp.ut_time); ! 132: if (*pwd->pw_passwd != '\0' && !neednopass) { ! 133: namep = crypt(getpass("Password:"), pwd->pw_passwd); ! 134: if (strcmp(namep, pwd->pw_passwd)) { ! 135: /* magic string detects loopbacks */ ! 136: printf("\001L\002ogin incorrect\n"); ! 137: f = open("/usr/adm/xtmp", 1); ! 138: if (f > 0) { ! 139: lseek(f, 0L, 2); ! 140: write(f, (char *)&utmp, sizeof(utmp)); ! 141: close(f); ! 142: } ! 143: goto loop; ! 144: } ! 145: } ! 146: if(pwd->pw_uid != 0 && access(nolog, 0) == 0){ ! 147: showmotd(nolog); ! 148: exit(0); ! 149: } ! 150: if(chdir(pwd->pw_dir) < 0) { ! 151: printf("No directory\n"); ! 152: if(pwd->pw_uid != 0 || (access(nolog, 0) < 0)) ! 153: goto loop; ! 154: } ! 155: setlogname(utmp.ut_name); ! 156: if(setupshares(pwd->pw_uid, printf)) ! 157: goto loop; ! 158: if (cmd) { /* remote exec */ ! 159: i = strlen(utmp.ut_name); ! 160: if (i < sizeof(utmp.ut_name)) ! 161: utmp.ut_name[i] = '*'; ! 162: } ! 163: if (ttyn && cmd == 0) ! 164: setut(&utmp); ! 165: if ((f = open("/usr/adm/wtmp", 1)) >= 0) { ! 166: lseek(f, 0L, 2); ! 167: write(f, (char *)&utmp, sizeof(utmp)); ! 168: close(f); ! 169: } ! 170: if (ttyn) { ! 171: chown(ttyn, pwd->pw_uid, pwd->pw_gid); ! 172: chmod(ttyn, 0622); ! 173: } ! 174: setgid(pwd->pw_gid); ! 175: setuid(pwd->pw_uid); ! 176: if (*pwd->pw_shell == '\0') ! 177: pwd->pw_shell = "/bin/sh"; ! 178: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); ! 179: nenv = 0; ! 180: for(i = 0; environ[i]; i++) ! 181: ; ! 182: env = (char **) malloc(sizeof(char *) * (i + 10)); ! 183: if (env == NULL) { ! 184: printf("No memory for environment.\n"); ! 185: exit(1); ! 186: } ! 187: for (i = 0; environ[i]; i++) { ! 188: if (strncmp(environ[i], "HOME=", 5) == 0) ! 189: continue; ! 190: if (strncmp(environ[i], "PATH=", 5) == 0) ! 191: continue; ! 192: env[nenv++] = environ[i]; ! 193: } ! 194: if(homedir[0]) ! 195: env[nenv++] = homedir; ! 196: if(path[0]) ! 197: env[nenv++] = path; ! 198: env[nenv] = NULL; ! 199: if ((namep = strrchr(pwd->pw_shell, '/')) == NULL) ! 200: namep = pwd->pw_shell; ! 201: else ! 202: namep++; ! 203: strcat(minusnam, namep); ! 204: alarm(0); ! 205: umask(02); ! 206: vlimit(LIM_CORE, 1024*1024); ! 207: if (cmd==NULL) { ! 208: showmotd(motd); ! 209: strcat(maildir, pwd->pw_name); ! 210: if(access(maildir,4)==0) { ! 211: struct stat statb; ! 212: stat(maildir, &statb); ! 213: if (statb.st_size > POSTMKSIZ) ! 214: printf("You have mail.\n"); ! 215: } ! 216: } ! 217: signal(SIGQUIT, SIG_DFL); ! 218: signal(SIGINT, SIG_DFL); ! 219: signal(SIGHUP, SIG_DFL); ! 220: environ = env; ! 221: fflush(stdout); ! 222: if (cmd==NULL) ! 223: execlp(pwd->pw_shell, minusnam, 0); ! 224: else { ! 225: env[nenv++] = "REXEC=1"; ! 226: ioctl(0, TIOCEXCL, (void *)NULL); ! 227: env[nenv] = 0; ! 228: execlp(pwd->pw_shell, minusnam, "-c", cmd, (char *)0); ! 229: } ! 230: printf("No shell\n"); ! 231: exit(0); ! 232: } ! 233: ! 234: setut(u) ! 235: register struct utmp *u; ! 236: { ! 237: register struct utmp *v, *ev; ! 238: struct utmp xtmp[200]; ! 239: register int slot; ! 240: register int n, i; ! 241: int fd; ! 242: ! 243: if ((fd = open("/etc/utmp", 2)) < 0) ! 244: return; ! 245: slot = -1; ! 246: i = 0; ! 247: while ((n = read(fd, (char *)xtmp, sizeof(xtmp))) > 0) { ! 248: ev = &xtmp[n/sizeof(struct utmp)]; ! 249: for (v = xtmp; v < ev; i++, v++) { ! 250: if (slot < 0 && v->ut_line[0] == 0) { ! 251: slot = i; ! 252: continue; ! 253: } ! 254: if (strncmp(u->ut_line, v->ut_line, sizeof(v->ut_line))==0) { ! 255: slot = i; ! 256: goto found; ! 257: } ! 258: } ! 259: } ! 260: if (slot < 0) /* no empties found */ ! 261: slot = i; ! 262: found: ! 263: lseek(fd, (off_t)slot*sizeof(struct utmp), 0); ! 264: write(fd, (char *)u, sizeof(*u)); ! 265: close(fd); ! 266: } ! 267: ! 268: int stopmotd; ! 269: catch() ! 270: { ! 271: signal(SIGINT, SIG_IGN); ! 272: stopmotd++; ! 273: } ! 274: ! 275: showmotd(f) ! 276: char *f; ! 277: { ! 278: register FILE *mf; ! 279: register c; ! 280: ! 281: signal(SIGINT, catch); ! 282: if((mf = fopen(f, "r")) != NULL) { ! 283: while((c = getc(mf)) != EOF && stopmotd == 0) ! 284: putchar(c); ! 285: fclose(mf); ! 286: fflush(stdout); ! 287: } ! 288: signal(SIGINT, SIG_IGN); ! 289: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.