|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)rlogind.c 4.18 83/07/01"; ! 3: #endif ! 4: ! 5: #include <stdio.h> ! 6: #include <sys/types.h> ! 7: #include <sys/stat.h> ! 8: #include <sys/socket.h> ! 9: #include <sys/wait.h> ! 10: ! 11: #include <netinet/in.h> ! 12: ! 13: #include <errno.h> ! 14: #include <pwd.h> ! 15: #include <signal.h> ! 16: #include <sgtty.h> ! 17: #include <stdio.h> ! 18: #include <netdb.h> ! 19: ! 20: extern errno; ! 21: int reapchild(); ! 22: struct passwd *getpwnam(); ! 23: char *crypt(), *rindex(), *index(), *malloc(), *ntoa(); ! 24: struct sockaddr_in sin = { AF_INET }; ! 25: /* ! 26: * remote login server: ! 27: * remuser\0 ! 28: * locuser\0 ! 29: * terminal type\0 ! 30: * data ! 31: */ ! 32: main(argc, argv) ! 33: int argc; ! 34: char **argv; ! 35: { ! 36: int f, options = 0; ! 37: struct sockaddr_in from; ! 38: struct servent *sp; ! 39: ! 40: sp = getservbyname("login", "tcp"); ! 41: if (sp == 0) { ! 42: fprintf(stderr, "rlogind: tcp/rlogin: unknown service\n"); ! 43: exit(1); ! 44: } ! 45: #ifndef DEBUG ! 46: if (fork()) ! 47: exit(0); ! 48: for (f = 0; f < 10; f++) ! 49: (void) close(f); ! 50: (void) open("/", 0); ! 51: (void) dup2(0, 1); ! 52: (void) dup2(0, 2); ! 53: { int tt = open("/dev/tty", 2); ! 54: if (tt > 0) { ! 55: ioctl(tt, TIOCNOTTY, 0); ! 56: close(tt); ! 57: } ! 58: } ! 59: #endif ! 60: sin.sin_port = sp->s_port; ! 61: argc--, argv++; ! 62: if (argc > 0 && !strcmp(argv[0], "-d")) { ! 63: options |= SO_DEBUG; ! 64: argc--, argv++; ! 65: } ! 66: if (argc > 0) { ! 67: int port = atoi(argv[0]); ! 68: ! 69: if (port < 0) { ! 70: fprintf(stderr, "%s: bad port #\n", argv[0]); ! 71: exit(1); ! 72: } ! 73: sin.sin_port = htons((u_short)port); ! 74: argv++, argc--; ! 75: } ! 76: f = socket(AF_INET, SOCK_STREAM, 0, 0); ! 77: if (f < 0) { ! 78: perror("rlogind: socket"); ! 79: exit(1); ! 80: } ! 81: if (options & SO_DEBUG) ! 82: if (setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) ! 83: perror("rlogind: setsockopt (SO_DEBUG)"); ! 84: if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0) ! 85: perror("rlogind: setsockopt (SO_KEEPALIVE)"); ! 86: if (bind(f, &sin, sizeof (sin), 0) < 0) { ! 87: perror("rlogind: bind"); ! 88: exit(1); ! 89: } ! 90: signal(SIGCHLD, reapchild); ! 91: listen(f, 10); ! 92: for (;;) { ! 93: int s, len = sizeof (from); ! 94: ! 95: s = accept(f, &from, &len, 0); ! 96: if (s < 0) { ! 97: if (errno == EINTR) ! 98: continue; ! 99: perror("rlogind: accept"); ! 100: continue; ! 101: } ! 102: if (fork() == 0) { ! 103: signal(SIGCHLD, SIG_IGN); ! 104: close(f); ! 105: doit(s, &from); ! 106: } ! 107: close(s); ! 108: } ! 109: } ! 110: ! 111: reapchild() ! 112: { ! 113: union wait status; ! 114: ! 115: while (wait3(&status, WNOHANG, 0) > 0) ! 116: ; ! 117: } ! 118: ! 119: char locuser[32], remuser[32]; ! 120: char buf[BUFSIZ]; ! 121: int child; ! 122: int cleanup(); ! 123: int netf; ! 124: extern errno; ! 125: char *line; ! 126: ! 127: doit(f, fromp) ! 128: int f; ! 129: struct sockaddr_in *fromp; ! 130: { ! 131: char c; ! 132: int i, p, cc, t, pid; ! 133: int stop = TIOCPKT_DOSTOP; ! 134: register struct hostent *hp; ! 135: ! 136: alarm(60); ! 137: read(f, &c, 1); ! 138: if (c != 0) ! 139: exit(1); ! 140: alarm(0); ! 141: fromp->sin_port = htons((u_short)fromp->sin_port); ! 142: hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), ! 143: fromp->sin_family); ! 144: if (hp == 0) { ! 145: char buf[BUFSIZ], *cp = (char *)&fromp->sin_addr; ! 146: ! 147: fatal(f, sprintf(buf, "Host name for your address (%s) unknown", ! 148: ntoa(fromp->sin_addr))); ! 149: } ! 150: if (fromp->sin_family != AF_INET || ! 151: fromp->sin_port >= IPPORT_RESERVED || ! 152: hp == 0) ! 153: fatal(f, "Permission denied"); ! 154: write(f, "", 1); ! 155: for (c = 'p'; c <= 's'; c++) { ! 156: struct stat stb; ! 157: line = "/dev/ptyXX"; ! 158: line[strlen("/dev/pty")] = c; ! 159: line[strlen("/dev/ptyp")] = '0'; ! 160: if (stat(line, &stb) < 0) ! 161: break; ! 162: for (i = 0; i < 16; i++) { ! 163: line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; ! 164: p = open(line, 2); ! 165: if (p > 0) ! 166: goto gotpty; ! 167: } ! 168: } ! 169: fatal(f, "All network ports in use"); ! 170: /*NOTREACHED*/ ! 171: gotpty: ! 172: dup2(f, 0); ! 173: line[strlen("/dev/")] = 't'; ! 174: #ifdef DEBUG ! 175: { int tt = open("/dev/tty", 2); ! 176: if (tt > 0) { ! 177: ioctl(tt, TIOCNOTTY, 0); ! 178: close(tt); ! 179: } ! 180: } ! 181: #endif ! 182: t = open(line, 2); ! 183: if (t < 0) ! 184: fatalperror(f, line, errno); ! 185: { struct sgttyb b; ! 186: gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); ! 187: } ! 188: pid = fork(); ! 189: if (pid < 0) ! 190: fatalperror(f, "", errno); ! 191: if (pid) { ! 192: char pibuf[1024], fibuf[1024], *pbp, *fbp; ! 193: int pcc = 0, fcc = 0, on = 1; ! 194: /* FILE *console = fopen("/dev/console", "w"); */ ! 195: /* setbuf(console, 0); */ ! 196: ! 197: /* fprintf(console, "f %d p %d\r\n", f, p); */ ! 198: ioctl(f, FIONBIO, &on); ! 199: ioctl(p, FIONBIO, &on); ! 200: ioctl(p, TIOCPKT, &on); ! 201: signal(SIGTSTP, SIG_IGN); ! 202: signal(SIGCHLD, cleanup); ! 203: for (;;) { ! 204: int ibits = 0, obits = 0; ! 205: ! 206: if (fcc) ! 207: obits |= (1<<p); ! 208: else ! 209: ibits |= (1<<f); ! 210: if (pcc >= 0) ! 211: if (pcc) ! 212: obits |= (1<<f); ! 213: else ! 214: ibits |= (1<<p); ! 215: if (fcc < 0 && pcc < 0) ! 216: break; ! 217: /* fprintf(console, "ibits from %d obits from %d\r\n", ibits, obits); */ ! 218: select(16, &ibits, &obits, 0, 0, 0); ! 219: /* fprintf(console, "ibits %d obits %d\r\n", ibits, obits); */ ! 220: if (ibits == 0 && obits == 0) { ! 221: sleep(5); ! 222: continue; ! 223: } ! 224: if (ibits & (1<<f)) { ! 225: fcc = read(f, fibuf, sizeof (fibuf)); ! 226: /* fprintf(console, "%d from f\r\n", fcc); */ ! 227: if (fcc < 0 && errno == EWOULDBLOCK) ! 228: fcc = 0; ! 229: else { ! 230: if (fcc <= 0) ! 231: break; ! 232: fbp = fibuf; ! 233: } ! 234: } ! 235: if (ibits & (1<<p)) { ! 236: pcc = read(p, pibuf, sizeof (pibuf)); ! 237: /* fprintf(console, "%d from p, buf[0] %x, errno %d\r\n", pcc, buf[0], errno); */ ! 238: pbp = pibuf; ! 239: if (pcc < 0 && errno == EWOULDBLOCK) ! 240: pcc = 0; ! 241: else if (pcc <= 0) ! 242: pcc = -1; ! 243: else if (pibuf[0] == 0) ! 244: pbp++, pcc--; ! 245: else { ! 246: if (pibuf[0]&(TIOCPKT_FLUSHWRITE| ! 247: TIOCPKT_NOSTOP| ! 248: TIOCPKT_DOSTOP)) { ! 249: int nstop = pibuf[0] & ! 250: (TIOCPKT_NOSTOP| ! 251: TIOCPKT_DOSTOP); ! 252: if (nstop) ! 253: stop = nstop; ! 254: pibuf[0] |= nstop; ! 255: send(f,&pibuf[0],1,MSG_OOB); ! 256: } ! 257: pcc = 0; ! 258: } ! 259: } ! 260: if ((obits & (1<<f)) && pcc > 0) { ! 261: cc = write(f, pbp, pcc); ! 262: /* fprintf(console, "%d of %d to f\r\n", cc, pcc); */ ! 263: if (cc > 0) { ! 264: pcc -= cc; ! 265: pbp += cc; ! 266: } ! 267: } ! 268: if ((obits & (1<<p)) && fcc > 0) { ! 269: cc = write(p, fbp, fcc); ! 270: /* fprintf(console, "%d of %d to p\r\n", cc, fcc); */ ! 271: if (cc > 0) { ! 272: fcc -= cc; ! 273: fbp += cc; ! 274: } ! 275: } ! 276: } ! 277: cleanup(); ! 278: } ! 279: close(f); ! 280: close(p); ! 281: dup2(t, 0); ! 282: dup2(t, 1); ! 283: dup2(t, 2); ! 284: close(t); ! 285: execl("/bin/login", "login", "-r", hp->h_name, 0); ! 286: fatalperror(2, "/bin/login", errno); ! 287: /*NOTREACHED*/ ! 288: } ! 289: ! 290: cleanup() ! 291: { ! 292: ! 293: rmut(); ! 294: vhangup(); /* XXX */ ! 295: shutdown(netf, 2); ! 296: kill(0, SIGKILL); ! 297: exit(1); ! 298: } ! 299: ! 300: fatal(f, msg) ! 301: int f; ! 302: char *msg; ! 303: { ! 304: char buf[BUFSIZ]; ! 305: ! 306: buf[0] = '\01'; /* error indicator */ ! 307: (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); ! 308: (void) write(f, buf, strlen(buf)); ! 309: exit(1); ! 310: } ! 311: ! 312: fatalperror(f, msg, errno) ! 313: int f; ! 314: char *msg; ! 315: int errno; ! 316: { ! 317: char buf[BUFSIZ]; ! 318: extern char *sys_errlist[]; ! 319: ! 320: (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); ! 321: fatal(f, buf); ! 322: } ! 323: ! 324: #include <utmp.h> ! 325: ! 326: struct utmp wtmp; ! 327: char wtmpf[] = "/usr/adm/wtmp"; ! 328: char utmp[] = "/etc/utmp"; ! 329: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) ! 330: #define SCMPN(a, b) strncmp(a, b, sizeof(a)) ! 331: ! 332: rmut() ! 333: { ! 334: register f; ! 335: int found = 0; ! 336: ! 337: f = open(utmp, 2); ! 338: if (f >= 0) { ! 339: while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) { ! 340: if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) ! 341: continue; ! 342: lseek(f, -(long)sizeof(wtmp), 1); ! 343: SCPYN(wtmp.ut_name, ""); ! 344: SCPYN(wtmp.ut_host, ""); ! 345: time(&wtmp.ut_time); ! 346: write(f, (char *)&wtmp, sizeof(wtmp)); ! 347: found++; ! 348: } ! 349: close(f); ! 350: } ! 351: if (found) { ! 352: f = open(wtmpf, 1); ! 353: if (f >= 0) { ! 354: SCPYN(wtmp.ut_line, line+5); ! 355: SCPYN(wtmp.ut_name, ""); ! 356: SCPYN(wtmp.ut_host, ""); ! 357: time(&wtmp.ut_time); ! 358: lseek(f, (long)0, 2); ! 359: write(f, (char *)&wtmp, sizeof(wtmp)); ! 360: close(f); ! 361: } ! 362: } ! 363: chmod(line, 0666); ! 364: chown(line, 0, 0); ! 365: line[strlen("/dev/")] = 'p'; ! 366: chmod(line, 0666); ! 367: chown(line, 0, 0); ! 368: } ! 369: ! 370: /* ! 371: * Convert network-format internet address ! 372: * to base 256 d.d.d.d representation. ! 373: */ ! 374: char * ! 375: ntoa(in) ! 376: struct in_addr in; ! 377: { ! 378: static char b[18]; ! 379: register char *p; ! 380: ! 381: p = (char *)∈ ! 382: #define UC(b) (((int)b)&0xff) ! 383: sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); ! 384: return (b); ! 385: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.