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