|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: char copyright[] = ! 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)rlogind.c 5.15 (Berkeley) 5/23/88"; ! 15: #endif not lint ! 16: ! 17: /* ! 18: * remote login server: ! 19: * remuser\0 ! 20: * locuser\0 ! 21: * terminal info\0 ! 22: * data ! 23: */ ! 24: ! 25: #include <stdio.h> ! 26: #include <sys/types.h> ! 27: #include <sys/stat.h> ! 28: #include <sys/socket.h> ! 29: #include <sys/wait.h> ! 30: #include <sys/file.h> ! 31: ! 32: #include <netinet/in.h> ! 33: ! 34: #include <errno.h> ! 35: #include <pwd.h> ! 36: #include <signal.h> ! 37: #include <sgtty.h> ! 38: #include <stdio.h> ! 39: #include <netdb.h> ! 40: #include <syslog.h> ! 41: #include <strings.h> ! 42: ! 43: # ifndef TIOCPKT_WINDOW ! 44: # define TIOCPKT_WINDOW 0x80 ! 45: # endif TIOCPKT_WINDOW ! 46: ! 47: extern int errno; ! 48: int reapchild(); ! 49: struct passwd *getpwnam(); ! 50: char *malloc(); ! 51: ! 52: /*ARGSUSED*/ ! 53: main(argc, argv) ! 54: int argc; ! 55: char **argv; ! 56: { ! 57: int on = 1, fromlen; ! 58: struct sockaddr_in from; ! 59: ! 60: openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH); ! 61: fromlen = sizeof (from); ! 62: if (getpeername(0, &from, &fromlen) < 0) { ! 63: fprintf(stderr, "%s: ", argv[0]); ! 64: perror("getpeername"); ! 65: _exit(1); ! 66: } ! 67: if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { ! 68: syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); ! 69: } ! 70: doit(0, &from); ! 71: } ! 72: ! 73: int child; ! 74: int cleanup(); ! 75: int netf; ! 76: char *line; ! 77: extern char *inet_ntoa(); ! 78: ! 79: struct winsize win = { 0, 0, 0, 0 }; ! 80: ! 81: ! 82: doit(f, fromp) ! 83: int f; ! 84: struct sockaddr_in *fromp; ! 85: { ! 86: int i, p, t, pid, on = 1; ! 87: register struct hostent *hp; ! 88: struct hostent hostent; ! 89: char c; ! 90: ! 91: alarm(60); ! 92: read(f, &c, 1); ! 93: if (c != 0) ! 94: exit(1); ! 95: alarm(0); ! 96: fromp->sin_port = ntohs((u_short)fromp->sin_port); ! 97: hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), ! 98: fromp->sin_family); ! 99: if (hp == 0) { ! 100: /* ! 101: * Only the name is used below. ! 102: */ ! 103: hp = &hostent; ! 104: hp->h_name = inet_ntoa(fromp->sin_addr); ! 105: } ! 106: if (fromp->sin_family != AF_INET || ! 107: fromp->sin_port >= IPPORT_RESERVED || ! 108: fromp->sin_port < IPPORT_RESERVED/2) ! 109: fatal(f, "Permission denied"); ! 110: write(f, "", 1); ! 111: for (c = 'p'; c <= 's'; c++) { ! 112: struct stat stb; ! 113: line = "/dev/ptyXX"; ! 114: line[strlen("/dev/pty")] = c; ! 115: line[strlen("/dev/ptyp")] = '0'; ! 116: if (stat(line, &stb) < 0) ! 117: break; ! 118: for (i = 0; i < 16; i++) { ! 119: line[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i]; ! 120: p = open(line, O_RDWR); ! 121: if (p > 0) ! 122: goto gotpty; ! 123: } ! 124: } ! 125: fatal(f, "Out of ptys"); ! 126: /*NOTREACHED*/ ! 127: gotpty: ! 128: (void) ioctl(p, TIOCSWINSZ, &win); ! 129: netf = f; ! 130: line[strlen("/dev/")] = 't'; ! 131: t = open(line, O_RDWR); ! 132: if (t < 0) ! 133: fatalperror(f, line); ! 134: if (fchmod(t, 0)) ! 135: fatalperror(f, line); ! 136: (void)signal(SIGHUP, SIG_IGN); ! 137: vhangup(); ! 138: (void)signal(SIGHUP, SIG_DFL); ! 139: t = open(line, O_RDWR); ! 140: if (t < 0) ! 141: fatalperror(f, line); ! 142: { ! 143: struct sgttyb b; ! 144: ! 145: (void)ioctl(t, TIOCGETP, &b); ! 146: b.sg_flags = RAW|ANYP; ! 147: (void)ioctl(t, TIOCSETP, &b); ! 148: } ! 149: #ifdef DEBUG ! 150: { ! 151: int tt = open("/dev/tty", O_RDWR); ! 152: if (tt > 0) { ! 153: (void)ioctl(tt, TIOCNOTTY, 0); ! 154: (void)close(tt); ! 155: } ! 156: } ! 157: #endif ! 158: pid = fork(); ! 159: if (pid < 0) ! 160: fatalperror(f, ""); ! 161: if (pid == 0) { ! 162: close(f), close(p); ! 163: dup2(t, 0), dup2(t, 1), dup2(t, 2); ! 164: close(t); ! 165: execl("/bin/login", "login", "-r", hp->h_name, 0); ! 166: fatalperror(2, "/bin/login"); ! 167: /*NOTREACHED*/ ! 168: } ! 169: close(t); ! 170: ioctl(f, FIONBIO, &on); ! 171: ioctl(p, FIONBIO, &on); ! 172: ioctl(p, TIOCPKT, &on); ! 173: signal(SIGTSTP, SIG_IGN); ! 174: signal(SIGCHLD, cleanup); ! 175: setpgrp(0, 0); ! 176: protocol(f, p); ! 177: signal(SIGCHLD, SIG_IGN); ! 178: cleanup(); ! 179: } ! 180: ! 181: char magic[2] = { 0377, 0377 }; ! 182: char oobdata[] = {TIOCPKT_WINDOW}; ! 183: ! 184: /* ! 185: * Handle a "control" request (signaled by magic being present) ! 186: * in the data stream. For now, we are only willing to handle ! 187: * window size changes. ! 188: */ ! 189: control(pty, cp, n) ! 190: int pty; ! 191: char *cp; ! 192: int n; ! 193: { ! 194: struct winsize w; ! 195: ! 196: if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') ! 197: return (0); ! 198: oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ ! 199: bcopy(cp+4, (char *)&w, sizeof(w)); ! 200: w.ws_row = ntohs(w.ws_row); ! 201: w.ws_col = ntohs(w.ws_col); ! 202: w.ws_xpixel = ntohs(w.ws_xpixel); ! 203: w.ws_ypixel = ntohs(w.ws_ypixel); ! 204: (void)ioctl(pty, TIOCSWINSZ, &w); ! 205: return (4+sizeof (w)); ! 206: } ! 207: ! 208: /* ! 209: * rlogin "protocol" machine. ! 210: */ ! 211: protocol(f, p) ! 212: int f, p; ! 213: { ! 214: char pibuf[1024], fibuf[1024], *pbp, *fbp; ! 215: register pcc = 0, fcc = 0; ! 216: int cc; ! 217: char cntl; ! 218: ! 219: /* ! 220: * Must ignore SIGTTOU, otherwise we'll stop ! 221: * when we try and set slave pty's window shape ! 222: * (our controlling tty is the master pty). ! 223: */ ! 224: (void) signal(SIGTTOU, SIG_IGN); ! 225: send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ ! 226: for (;;) { ! 227: int ibits, obits, ebits; ! 228: ! 229: ibits = 0; ! 230: obits = 0; ! 231: if (fcc) ! 232: obits |= (1<<p); ! 233: else ! 234: ibits |= (1<<f); ! 235: if (pcc >= 0) ! 236: if (pcc) ! 237: obits |= (1<<f); ! 238: else ! 239: ibits |= (1<<p); ! 240: ebits = (1<<p); ! 241: if (select(16, &ibits, &obits, &ebits, 0) < 0) { ! 242: if (errno == EINTR) ! 243: continue; ! 244: fatalperror(f, "select"); ! 245: } ! 246: if (ibits == 0 && obits == 0 && ebits == 0) { ! 247: /* shouldn't happen... */ ! 248: sleep(5); ! 249: continue; ! 250: } ! 251: #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) ! 252: if (ebits & (1<<p)) { ! 253: cc = read(p, &cntl, 1); ! 254: if (cc == 1 && pkcontrol(cntl)) { ! 255: cntl |= oobdata[0]; ! 256: send(f, &cntl, 1, MSG_OOB); ! 257: if (cntl & TIOCPKT_FLUSHWRITE) { ! 258: pcc = 0; ! 259: ibits &= ~(1<<p); ! 260: } ! 261: } ! 262: } ! 263: if (ibits & (1<<f)) { ! 264: fcc = read(f, fibuf, sizeof (fibuf)); ! 265: if (fcc < 0 && errno == EWOULDBLOCK) ! 266: fcc = 0; ! 267: else { ! 268: register char *cp; ! 269: int left, n; ! 270: ! 271: if (fcc <= 0) ! 272: break; ! 273: fbp = fibuf; ! 274: ! 275: top: ! 276: for (cp = fibuf; cp < fibuf+fcc-1; cp++) ! 277: if (cp[0] == magic[0] && ! 278: cp[1] == magic[1]) { ! 279: left = fcc - (cp-fibuf); ! 280: n = control(p, cp, left); ! 281: if (n) { ! 282: left -= n; ! 283: if (left > 0) ! 284: bcopy(cp+n, cp, left); ! 285: fcc -= n; ! 286: goto top; /* n^2 */ ! 287: } ! 288: } ! 289: } ! 290: } ! 291: ! 292: if ((obits & (1<<p)) && fcc > 0) { ! 293: cc = write(p, fbp, fcc); ! 294: if (cc > 0) { ! 295: fcc -= cc; ! 296: fbp += cc; ! 297: } ! 298: } ! 299: ! 300: if (ibits & (1<<p)) { ! 301: pcc = read(p, pibuf, sizeof (pibuf)); ! 302: pbp = pibuf; ! 303: if (pcc < 0 && errno == EWOULDBLOCK) ! 304: pcc = 0; ! 305: else if (pcc <= 0) ! 306: break; ! 307: else if (pibuf[0] == 0) ! 308: pbp++, pcc--; ! 309: else { ! 310: if (pkcontrol(pibuf[0])) { ! 311: pibuf[0] |= oobdata[0]; ! 312: send(f, &pibuf[0], 1, MSG_OOB); ! 313: } ! 314: pcc = 0; ! 315: } ! 316: } ! 317: if ((obits & (1<<f)) && pcc > 0) { ! 318: cc = write(f, pbp, pcc); ! 319: if (cc < 0 && errno == EWOULDBLOCK) { ! 320: /* also shouldn't happen */ ! 321: sleep(5); ! 322: continue; ! 323: } ! 324: if (cc > 0) { ! 325: pcc -= cc; ! 326: pbp += cc; ! 327: } ! 328: } ! 329: } ! 330: } ! 331: ! 332: cleanup() ! 333: { ! 334: rmut(); ! 335: shutdown(netf, 2); ! 336: exit(1); ! 337: } ! 338: ! 339: fatal(f, msg) ! 340: int f; ! 341: char *msg; ! 342: { ! 343: char buf[BUFSIZ]; ! 344: ! 345: buf[0] = '\01'; /* error indicator */ ! 346: (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); ! 347: (void) write(f, buf, strlen(buf)); ! 348: exit(1); ! 349: } ! 350: ! 351: fatalperror(f, msg) ! 352: int f; ! 353: char *msg; ! 354: { ! 355: char buf[BUFSIZ]; ! 356: extern int sys_nerr; ! 357: extern char *sys_errlist[]; ! 358: ! 359: if ((unsigned)errno < sys_nerr) ! 360: (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); ! 361: else ! 362: (void) sprintf(buf, "%s: Error %d", msg, errno); ! 363: fatal(f, buf); ! 364: } ! 365: ! 366: #include <utmp.h> ! 367: ! 368: struct utmp wtmp; ! 369: char wtmpf[] = "/usr/adm/wtmp"; ! 370: char utmpf[] = "/etc/utmp"; ! 371: #define SCPYN(a, b) strncpy(a, b, sizeof(a)) ! 372: #define SCMPN(a, b) strncmp(a, b, sizeof(a)) ! 373: ! 374: rmut() ! 375: { ! 376: register f; ! 377: int found = 0; ! 378: struct utmp *u, *utmp; ! 379: int nutmp; ! 380: struct stat statbf; ! 381: ! 382: f = open(utmpf, O_RDWR); ! 383: if (f >= 0) { ! 384: fstat(f, &statbf); ! 385: utmp = (struct utmp *)malloc(statbf.st_size); ! 386: if (!utmp) ! 387: syslog(LOG_ERR, "utmp malloc failed"); ! 388: if (statbf.st_size && utmp) { ! 389: nutmp = read(f, utmp, statbf.st_size); ! 390: nutmp /= sizeof(struct utmp); ! 391: ! 392: for (u = utmp ; u < &utmp[nutmp] ; u++) { ! 393: if (SCMPN(u->ut_line, line+5) || ! 394: u->ut_name[0]==0) ! 395: continue; ! 396: lseek(f, ((long)u)-((long)utmp), L_SET); ! 397: SCPYN(u->ut_name, ""); ! 398: SCPYN(u->ut_host, ""); ! 399: time(&u->ut_time); ! 400: write(f, (char *)u, sizeof(wtmp)); ! 401: found++; ! 402: } ! 403: } ! 404: close(f); ! 405: } ! 406: if (found) { ! 407: f = open(wtmpf, O_WRONLY|O_APPEND); ! 408: if (f >= 0) { ! 409: SCPYN(wtmp.ut_line, line+5); ! 410: SCPYN(wtmp.ut_name, ""); ! 411: SCPYN(wtmp.ut_host, ""); ! 412: time(&wtmp.ut_time); ! 413: write(f, (char *)&wtmp, sizeof(wtmp)); ! 414: close(f); ! 415: } ! 416: } ! 417: chmod(line, 0666); ! 418: chown(line, 0, 0); ! 419: line[strlen("/dev/")] = 'p'; ! 420: chmod(line, 0666); ! 421: chown(line, 0, 0); ! 422: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.