|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <pwd.h> ! 3: #include <signal.h> ! 4: #include <sys/types.h> ! 5: #include <sys/ioctl.h> ! 6: #include <errno.h> ! 7: #include <utmp.h> ! 8: ! 9: #include <sys/wait.h> ! 10: #include <netdb.h> ! 11: #include <sys/inet/in.h> ! 12: #include <sys/socket.h> ! 13: ! 14: extern errno; ! 15: extern char **environ; ! 16: ! 17: #define PATH "PATH=/usr/fbin:/bin:/usr/bin:/usr/usgbin" ! 18: char home[128], mail[128], user[32], shell[128]; ! 19: ! 20: char *envinit[] = { ! 21: home, PATH, mail, user, shell, ! 22: NULL}; ! 23: ! 24: int debug; ! 25: int nfd; ! 26: char *cmdname; ! 27: struct sockaddr_in sin = { AF_INET }, from; ! 28: ! 29: ! 30: main(argc, argv) ! 31: int argc; ! 32: char *argv[]; ! 33: { ! 34: struct servent *sp; ! 35: register int c, i; ! 36: int f; ! 37: short lport = -1; ! 38: char *p, *rindex(); ! 39: int reapchild(); ! 40: ! 41: cmdname = argv[0]; ! 42: p = rindex(cmdname, '/'); ! 43: if (p != NULL) cmdname = p+1; ! 44: ! 45: for(i = 1; i < argc; i++) { ! 46: if(argv[i][0] == '-') switch(argv[i][1]) { ! 47: case 'd': ! 48: debug++; ! 49: continue; ! 50: default: ! 51: fprintf(stderr, "Usage: %s [-d] [port]\n", cmdname); ! 52: exit(1); ! 53: } else ! 54: lport = atoi(argv[i]); ! 55: } ! 56: ! 57: if (lport > 0) sin.sin_port = htons(lport); ! 58: else { ! 59: sp = getservbyname("uucp", "tcp"); ! 60: if (sp == 0) { ! 61: fprintf(stderr, "uucpsrv: tcp/rlogin: unknown service\n"); ! 62: exit(1); ! 63: } ! 64: sin.sin_port = sp->s_port; ! 65: } ! 66: ! 67: if (!debug) { ! 68: ! 69: if (fork()) ! 70: exit(0); ! 71: for (f = 0; f < 10; f++) ! 72: (void) close(f); ! 73: (void) open("/", 0); ! 74: (void) dup2(0, 1); ! 75: (void) dup2(0, 2); ! 76: { int tt = open("/dev/tty", 2); ! 77: if (tt > 0) { ! 78: ioctl(tt, TIOCNOTTY, 0); ! 79: close(tt); ! 80: } ! 81: } ! 82: } ! 83: if (debug < 2) { ! 84: f = socket(AF_INET, SOCK_STREAM, 0, 0); ! 85: if (f < 0) { ! 86: perror("rlogind: socket"); ! 87: exit(1); ! 88: } ! 89: if (bind(f, &sin, sizeof (sin), 0) < 0) { ! 90: perror("rlogind: bind"); ! 91: exit(1); ! 92: } ! 93: signal(SIGCHLD, reapchild); ! 94: listen(f, 10); ! 95: for (;;) { ! 96: int len = sizeof (from); ! 97: ! 98: nfd = accept(f, &from, &len, 0); ! 99: if (nfd < 0) { ! 100: if (errno == EINTR) ! 101: continue; ! 102: perror("rlogind: accept"); ! 103: continue; ! 104: } ! 105: if (fork() == 0) { ! 106: signal(SIGCHLD, SIG_IGN); ! 107: signal(SIGPIPE, SIG_IGN); ! 108: setbuf(stdin, NULL); ! 109: if (nfd != 0) close(0); ! 110: if (nfd != 1) close(1); ! 111: if (!debug) { ! 112: if (nfd != 2) close(2); ! 113: } ! 114: dup(nfd); dup(nfd); dup(nfd); ! 115: for (i=3; i<25; i++) close(i); ! 116: break; ! 117: } ! 118: close(nfd); ! 119: } ! 120: } ! 121: else { ! 122: fprintf(stderr, "pseudo-connect port %d\n", lport); ! 123: nfd = 2; ! 124: } ! 125: login(); ! 126: if (debug < 2) { ! 127: fprintf(stderr, "%s: no shell!\n", cmdname); ! 128: exit(1); ! 129: } ! 130: else exit(0); ! 131: } ! 132: ! 133: reapchild() ! 134: { ! 135: union wait status; ! 136: ! 137: while (wait3(&status, WNOHANG, 0) > 0) ! 138: ; ! 139: } ! 140: ! 141: #define NMAX (sizeof utmp.ut_name + 1) ! 142: #define PWMAX 20 ! 143: char *nolog = "/etc/nologin"; ! 144: struct utmp utmp; ! 145: ! 146: login() ! 147: { ! 148: int c; ! 149: char lname[NMAX]; ! 150: char pwt[PWMAX]; ! 151: struct passwd *pwd, *getpwnam(); ! 152: static struct passwd nouser = {"none", "nope"}; ! 153: FILE *nlfd; ! 154: char *crypt(); ! 155: ! 156: do { ! 157: instr("login:", lname, NMAX); ! 158: } while (lname[0] == '\0'); ! 159: ! 160: if ((pwd = getpwnam(lname)) == NULL) { ! 161: pwd = &nouser; ! 162: } ! 163: if (*pwd->pw_passwd != '\0') { ! 164: instr("Password:", pwt, PWMAX); ! 165: if (strcmp(crypt(pwt, pwd->pw_passwd), pwd->pw_passwd)) { ! 166: fprintf(stderr, "Login incorrect\n"); ! 167: exit(1); ! 168: } ! 169: } ! 170: if ((nlfd = fopen(nolog, "r")) > 0) { ! 171: /* logins are disabled */ ! 172: while ((c = getc(nlfd)) != EOF) { ! 173: putc(c, stderr); ! 174: } ! 175: exit(0); ! 176: } ! 177: if (*pwd->pw_shell == '\0') ! 178: pwd->pw_shell = "/bin/sh"; ! 179: if (chdir(pwd->pw_dir) < 0) { ! 180: if (chdir("/") < 0) { ! 181: fprintf(stderr, "No directory!\n"); ! 182: exit(1); ! 183: } else { ! 184: fprintf(stderr, "No directory! Logging in with home=/\n"); ! 185: pwd->pw_dir = "/"; ! 186: } ! 187: } ! 188: strncpy(utmp.ut_name, lname, sizeof utmp.ut_name); ! 189: logit(); ! 190: setgid(pwd->pw_gid); ! 191: setuid(pwd->pw_uid); ! 192: signal(SIGHUP, SIG_IGN); ! 193: signal(SIGINT, SIG_IGN); ! 194: signal(SIGQUIT, SIG_IGN); ! 195: envset(pwd); ! 196: dosh(pwd->pw_shell); ! 197: } ! 198: ! 199: instr(prompt, buf, len) char *buf; int len; ! 200: { ! 201: register char *p, c; ! 202: ! 203: p = buf; ! 204: fputs(prompt, stdout); ! 205: fflush(stdout); ! 206: while ((c = getchar()) != '\n') { ! 207: if (c == '\r') break; ! 208: if (c == ' ') ! 209: c = '_'; ! 210: if (c == EOF) ! 211: exit(0); ! 212: if (p < buf+len-1) ! 213: *p++ = c; ! 214: } ! 215: *p = '\0'; ! 216: } ! 217: ! 218: envset(pwd) struct passwd *pwd; ! 219: { ! 220: ! 221: sprintf(home, "HOME=%s", pwd->pw_dir); ! 222: sprintf(shell, "SHELL=%s", pwd->pw_shell); ! 223: sprintf(mail, "MAIL=/usr/spool/mail/%s", pwd->pw_name); ! 224: sprintf(user, "USER=%s", pwd->pw_name); ! 225: environ = envinit; ! 226: } ! 227: ! 228: dosh(shellp) char *shellp; ! 229: { ! 230: char shn[300], *p, *rindex(); ! 231: ! 232: p = rindex(shellp, '/'); ! 233: sprintf(shn, "-%s", (p == NULL ? shellp : p+1)); ! 234: if (debug > 1) ! 235: fprintf(stderr, "exec %s %s\n", shellp, shn); ! 236: else execl(shellp, shn, 0); ! 237: } ! 238: ! 239: logit() ! 240: { ! 241: setpgrp(); ! 242: #if 0==1 ! 243: /* What we do here is create a utmp entry, then fork and wait */ ! 244: /* for the child to terminate so we can record the new entry. */ ! 245: /* The main process never returns from this subroutine, only */ ! 246: /* the child. */ ! 247: struct stat statb; ! 248: int pid, status; ! 249: char tmp[100]; ! 250: ! 251: if ((pid = fork()) <= 0) { /* If fork fails -- no entry made */ ! 252: setpgrp(); ! 253: return; ! 254: } ! 255: ! 256: if (fstat(0, &statb) == 0) ! 257: sprintf(tmp, "%*.*d", sizeof utmp.ut_id, ! 258: sizeof utmp.ut_id, statb.st_dev & 0xff); ! 259: else strcpy(tmp, "unet"); ! 260: strncpy(utmp.ut_id, tmp, sizeof utmp.ut_id); ! 261: ! 262: ut.ut_pid = pid; ! 263: ut.ut_type = USER_PROCESS; ! 264: utmp.ut_exit.e_termination = 0; ! 265: utmp.ut_exit.e_exit = 0; ! 266: time(&utmp.ut_time); ! 267: pututline(&utmp); ! 268: endutent(); ! 269: ! 270: while ((i = wait(&status)) != pid) ! 271: if (i == ENOCHILD) break; ! 272: ! 273: ut.ut_type = DEAD_PROCESS; ! 274: ut.ut_exit.e_termination = status & 0xff; ! 275: ut.ut_exit.e_exit = (status >> 8) & 0xff; ! 276: #endif ! 277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.