|
|
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.11 (Berkeley) 5/23/86"; ! 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 errno; ! 48: int reapchild(); ! 49: struct passwd *getpwnam(); ! 50: char *malloc(); ! 51: ! 52: main(argc, argv) ! 53: int argc; ! 54: char **argv; ! 55: { ! 56: int on = 1, options = 0, fromlen; ! 57: struct sockaddr_in from; ! 58: ! 59: openlog("rlogind", LOG_PID | LOG_AUTH, LOG_AUTH); ! 60: fromlen = sizeof (from); ! 61: if (getpeername(0, &from, &fromlen) < 0) { ! 62: fprintf(stderr, "%s: ", argv[0]); ! 63: perror("getpeername"); ! 64: _exit(1); ! 65: } ! 66: if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { ! 67: syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); ! 68: } ! 69: doit(0, &from); ! 70: } ! 71: ! 72: int child; ! 73: int cleanup(); ! 74: int netf; ! 75: extern errno; ! 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: fatal(f, "Permission denied"); ! 109: write(f, "", 1); ! 110: for (c = 'p'; c <= 's'; c++) { ! 111: struct stat stb; ! 112: line = "/dev/ptyXX"; ! 113: line[strlen("/dev/pty")] = c; ! 114: line[strlen("/dev/ptyp")] = '0'; ! 115: if (stat(line, &stb) < 0) ! 116: break; ! 117: for (i = 0; i < 16; i++) { ! 118: line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; ! 119: p = open(line, 2); ! 120: if (p > 0) ! 121: goto gotpty; ! 122: } ! 123: } ! 124: fatal(f, "Out of ptys"); ! 125: /*NOTREACHED*/ ! 126: gotpty: ! 127: (void) ioctl(p, TIOCSWINSZ, &win); ! 128: netf = f; ! 129: line[strlen("/dev/")] = 't'; ! 130: #ifdef DEBUG ! 131: { int tt = open("/dev/tty", 2); ! 132: if (tt > 0) { ! 133: ioctl(tt, TIOCNOTTY, 0); ! 134: close(tt); ! 135: } ! 136: } ! 137: #endif ! 138: t = open(line, 2); ! 139: if (t < 0) ! 140: fatalperror(f, line, errno); ! 141: { struct sgttyb b; ! 142: gtty(t, &b); b.sg_flags = RAW|ANYP; stty(t, &b); ! 143: } ! 144: pid = fork(); ! 145: if (pid < 0) ! 146: fatalperror(f, "", errno); ! 147: if (pid == 0) { ! 148: close(f), close(p); ! 149: dup2(t, 0), dup2(t, 1), dup2(t, 2); ! 150: close(t); ! 151: execl("/bin/login", "login", "-r", hp->h_name, 0); ! 152: fatalperror(2, "/bin/login", errno); ! 153: /*NOTREACHED*/ ! 154: } ! 155: close(t); ! 156: ioctl(f, FIONBIO, &on); ! 157: ioctl(p, FIONBIO, &on); ! 158: ioctl(p, TIOCPKT, &on); ! 159: signal(SIGTSTP, SIG_IGN); ! 160: signal(SIGCHLD, cleanup); ! 161: setpgrp(0, 0); ! 162: protocol(f, p); ! 163: cleanup(); ! 164: } ! 165: ! 166: char magic[2] = { 0377, 0377 }; ! 167: char oobdata[] = {TIOCPKT_WINDOW}; ! 168: ! 169: /* ! 170: * Handle a "control" request (signaled by magic being present) ! 171: * in the data stream. For now, we are only willing to handle ! 172: * window size changes. ! 173: */ ! 174: control(pty, cp, n) ! 175: int pty; ! 176: char *cp; ! 177: int n; ! 178: { ! 179: struct winsize w; ! 180: ! 181: if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') ! 182: return (0); ! 183: oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ ! 184: bcopy(cp+4, (char *)&w, sizeof(w)); ! 185: w.ws_row = ntohs(w.ws_row); ! 186: w.ws_col = ntohs(w.ws_col); ! 187: w.ws_xpixel = ntohs(w.ws_xpixel); ! 188: w.ws_ypixel = ntohs(w.ws_ypixel); ! 189: (void)ioctl(pty, TIOCSWINSZ, &w); ! 190: return (4+sizeof (w)); ! 191: } ! 192: ! 193: /* ! 194: * rlogin "protocol" machine. ! 195: */ ! 196: protocol(f, p) ! 197: int f, p; ! 198: { ! 199: char pibuf[1024], fibuf[1024], *pbp, *fbp; ! 200: register pcc = 0, fcc = 0; ! 201: int cc; ! 202: char cntl; ! 203: ! 204: /* ! 205: * Must ignore SIGTTOU, otherwise we'll stop ! 206: * when we try and set slave pty's window shape ! 207: * (our controlling tty is the master pty). ! 208: */ ! 209: (void) signal(SIGTTOU, SIG_IGN); ! 210: send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ ! 211: for (;;) { ! 212: int ibits, obits, ebits; ! 213: ! 214: ibits = 0; ! 215: obits = 0; ! 216: if (fcc) ! 217: obits |= (1<<p); ! 218: else ! 219: ibits |= (1<<f); ! 220: if (pcc >= 0) ! 221: if (pcc) ! 222: obits |= (1<<f); ! 223: else ! 224: ibits |= (1<<p); ! 225: ebits = (1<<p); ! 226: if (select(16, &ibits, &obits, &ebits, 0) < 0) { ! 227: if (errno == EINTR) ! 228: continue; ! 229: fatalperror(f, "select", errno); ! 230: } ! 231: if (ibits == 0 && obits == 0 && ebits == 0) { ! 232: /* shouldn't happen... */ ! 233: sleep(5); ! 234: continue; ! 235: } ! 236: #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) ! 237: if (ebits & (1<<p)) { ! 238: cc = read(p, &cntl, 1); ! 239: if (cc == 1 && pkcontrol(cntl)) { ! 240: cntl |= oobdata[0]; ! 241: send(f, &cntl, 1, MSG_OOB); ! 242: if (cntl & TIOCPKT_FLUSHWRITE) { ! 243: pcc = 0; ! 244: ibits &= ~(1<<p); ! 245: } ! 246: } ! 247: } ! 248: if (ibits & (1<<f)) { ! 249: fcc = read(f, fibuf, sizeof (fibuf)); ! 250: if (fcc < 0 && errno == EWOULDBLOCK) ! 251: fcc = 0; ! 252: else { ! 253: register char *cp; ! 254: int left, n; ! 255: ! 256: if (fcc <= 0) ! 257: break; ! 258: fbp = fibuf; ! 259: ! 260: top: ! 261: for (cp = fibuf; cp < fibuf+fcc-1; cp++) ! 262: if (cp[0] == magic[0] && ! 263: cp[1] == magic[1]) { ! 264: left = fcc - (cp-fibuf); ! 265: n = control(p, cp, left); ! 266: if (n) { ! 267: left -= n; ! 268: if (left > 0) ! 269: bcopy(cp+n, cp, left); ! 270: fcc -= n; ! 271: goto top; /* n^2 */ ! 272: } ! 273: } ! 274: } ! 275: } ! 276: ! 277: if ((obits & (1<<p)) && fcc > 0) { ! 278: cc = write(p, fbp, fcc); ! 279: if (cc > 0) { ! 280: fcc -= cc; ! 281: fbp += cc; ! 282: } ! 283: } ! 284: ! 285: if (ibits & (1<<p)) { ! 286: pcc = read(p, pibuf, sizeof (pibuf)); ! 287: pbp = pibuf; ! 288: if (pcc < 0 && errno == EWOULDBLOCK) ! 289: pcc = 0; ! 290: else if (pcc <= 0) ! 291: break; ! 292: else if (pibuf[0] == 0) ! 293: pbp++, pcc--; ! 294: else { ! 295: if (pkcontrol(pibuf[0])) { ! 296: pibuf[0] |= oobdata[0]; ! 297: send(f, &pibuf[0], 1, MSG_OOB); ! 298: } ! 299: pcc = 0; ! 300: } ! 301: } ! 302: if ((obits & (1<<f)) && pcc > 0) { ! 303: cc = write(f, pbp, pcc); ! 304: if (cc < 0 && errno == EWOULDBLOCK) { ! 305: /* also shouldn't happen */ ! 306: sleep(5); ! 307: continue; ! 308: } ! 309: if (cc > 0) { ! 310: pcc -= cc; ! 311: pbp += cc; ! 312: } ! 313: } ! 314: } ! 315: } ! 316: ! 317: cleanup() ! 318: { ! 319: ! 320: rmut(); ! 321: vhangup(); /* XXX */ ! 322: shutdown(netf, 2); ! 323: exit(1); ! 324: } ! 325: ! 326: fatal(f, msg) ! 327: int f; ! 328: char *msg; ! 329: { ! 330: char buf[BUFSIZ]; ! 331: ! 332: buf[0] = '\01'; /* error indicator */ ! 333: (void) sprintf(buf + 1, "rlogind: %s.\r\n", msg); ! 334: (void) write(f, buf, strlen(buf)); ! 335: exit(1); ! 336: } ! 337: ! 338: fatalperror(f, msg, errno) ! 339: int f; ! 340: char *msg; ! 341: int errno; ! 342: { ! 343: char buf[BUFSIZ]; ! 344: extern int sys_nerr; ! 345: extern char *sys_errlist[]; ! 346: ! 347: if ((unsigned)errno < sys_nerr) ! 348: (void) sprintf(buf, "%s: %s", msg, sys_errlist[errno]); ! 349: else ! 350: (void) sprintf(buf, "%s: Error %d", msg, errno); ! 351: fatal(f, buf); ! 352: } ! 353: ! 354: #include <utmp.h> ! 355: ! 356: struct utmp wtmp; ! 357: char wtmpf[] = "/usr/adm/wtmp"; ! 358: char utmpf[] = "/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: struct utmp *u, *utmp; ! 367: int nutmp; ! 368: struct stat statbf; ! 369: ! 370: f = open(utmpf, O_RDWR); ! 371: if (f >= 0) { ! 372: fstat(f, &statbf); ! 373: utmp = (struct utmp *)malloc(statbf.st_size); ! 374: if (!utmp) ! 375: syslog(LOG_ERR, "utmp malloc failed"); ! 376: if (statbf.st_size && utmp) { ! 377: nutmp = read(f, utmp, statbf.st_size); ! 378: nutmp /= sizeof(struct utmp); ! 379: ! 380: for (u = utmp ; u < &utmp[nutmp] ; u++) { ! 381: if (SCMPN(u->ut_line, line+5) || ! 382: u->ut_name[0]==0) ! 383: continue; ! 384: lseek(f, ((long)u)-((long)utmp), L_SET); ! 385: SCPYN(u->ut_name, ""); ! 386: SCPYN(u->ut_host, ""); ! 387: time(&u->ut_time); ! 388: write(f, (char *)u, sizeof(wtmp)); ! 389: found++; ! 390: } ! 391: } ! 392: close(f); ! 393: } ! 394: if (found) { ! 395: f = open(wtmpf, O_WRONLY|O_APPEND); ! 396: if (f >= 0) { ! 397: SCPYN(wtmp.ut_line, line+5); ! 398: SCPYN(wtmp.ut_name, ""); ! 399: SCPYN(wtmp.ut_host, ""); ! 400: time(&wtmp.ut_time); ! 401: write(f, (char *)&wtmp, sizeof(wtmp)); ! 402: close(f); ! 403: } ! 404: } ! 405: chmod(line, 0666); ! 406: chown(line, 0, 0); ! 407: line[strlen("/dev/")] = 'p'; ! 408: chmod(line, 0666); ! 409: chown(line, 0, 0); ! 410: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.