|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)rshd.c 4.17 (Berkeley) 83/07/02"; ! 3: #endif ! 4: ! 5: #include <sys/ioctl.h> ! 6: #include <sys/param.h> ! 7: #include <sys/socket.h> ! 8: #include <sys/wait.h> ! 9: ! 10: #include <netinet/in.h> ! 11: ! 12: #include <stdio.h> ! 13: #include <errno.h> ! 14: #include <pwd.h> ! 15: #include <signal.h> ! 16: #include <netdb.h> ! 17: ! 18: int errno; ! 19: int reapchild(); ! 20: struct sockaddr_in sin = { AF_INET }; ! 21: struct passwd *getpwnam(); ! 22: char *index(), *rindex(), *sprintf(); ! 23: int options; ! 24: /* VARARGS 1 */ ! 25: int error(); ! 26: /* ! 27: * remote shell server: ! 28: * remuser\0 ! 29: * locuser\0 ! 30: * command\0 ! 31: * data ! 32: */ ! 33: main(argc, argv) ! 34: int argc; ! 35: char **argv; ! 36: { ! 37: int errcnt = 0; ! 38: int f, linger; ! 39: struct sockaddr_in from; ! 40: struct servent *sp; ! 41: ! 42: sp = getservbyname("shell", "tcp"); ! 43: if (sp == 0) { ! 44: fprintf(stderr, "rshd: tcp/shell: unknown service\n"); ! 45: exit(1); ! 46: } ! 47: #ifndef DEBUG ! 48: if (fork()) ! 49: exit(0); ! 50: close(0); ! 51: if ( open("/dev/console", 2) <0) { ! 52: fprintf(stderr,"rshd: cannot open /dev/console\n"); ! 53: exit(1); ! 54: } ! 55: (void) dup2(0, 1); ! 56: (void) dup2(0, 2); ! 57: for (f = 3; f < 10; f++) ! 58: (void) close(f); ! 59: { int t = open("/dev/tty", 2); ! 60: if (t >= 0) { ! 61: ioctl(t, TIOCNOTTY, (char *)0); ! 62: (void) close(t); ! 63: } ! 64: } ! 65: #endif ! 66: sin.sin_port = sp->s_port; ! 67: argc--, argv++; ! 68: if (argc > 0 && !strcmp(argv[0], "-d")) { ! 69: options |= SO_DEBUG; ! 70: argc--, argv++; ! 71: } ! 72: if (argc > 0) { ! 73: int port = atoi(argv[0]); ! 74: ! 75: if (port < 0) { ! 76: fprintf(stderr, "%s: bad port #\n", argv[0]); ! 77: exit(1); ! 78: } ! 79: sin.sin_port = htons((u_short)port); ! 80: argc--, argv++; ! 81: } ! 82: f = socket(AF_INET, SOCK_STREAM, 0, 0); ! 83: if (f < 0) { ! 84: perror("rshd: socket"); ! 85: exit(1); ! 86: } ! 87: if (options & SO_DEBUG && setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) ! 88: perror("rshd: setsockopt (SO_DEBUG)"); ! 89: if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0) ! 90: perror("rshd: setsockopt (SO_KEEPALIVE)"); ! 91: linger = 60; /* XXX */ ! 92: if (setsockopt(f, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) < 0) ! 93: perror("rshd: setsockopt (SO_LINGER)"); ! 94: if (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) { ! 95: perror("rshd: bind"); ! 96: exit(1); ! 97: } ! 98: signal(SIGCHLD, reapchild); ! 99: listen(f, 10); ! 100: for (;errcnt < 20;) { ! 101: int child; ! 102: int g, len = sizeof (from); ! 103: ! 104: g = accept(f, &from, &len, 0); ! 105: if (g < 0) { ! 106: if (errno == EINTR) ! 107: continue; ! 108: perror("rshd: accept"); ! 109: errcnt++; ! 110: sleep(5); ! 111: continue; ! 112: } ! 113: child = fork(); ! 114: if (child < 0) { ! 115: perror("rshd: cannot fork"); ! 116: sleep(5); ! 117: continue; ! 118: } ! 119: if (child == 0) { ! 120: signal(SIGCHLD, SIG_IGN); ! 121: close(f); ! 122: errcnt = 0; ! 123: doit(g, &from); ! 124: } ! 125: /* when we get here, all is okay */ ! 126: errcnt = 0; ! 127: close(g); ! 128: } ! 129: fprintf(stderr,"rshd: terminated due to too many errors\n"); ! 130: } ! 131: ! 132: reapchild() ! 133: { ! 134: union wait status; ! 135: ! 136: while (wait3(&status, WNOHANG, 0) > 0) ! 137: ; ! 138: } ! 139: ! 140: char username[20] = "USER="; ! 141: char homedir[64] = "HOME="; ! 142: char shell[64] = "SHELL="; ! 143: char *envinit[] = ! 144: {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0}; ! 145: char **environ; ! 146: ! 147: doit(f, fromp) ! 148: int f; ! 149: struct sockaddr_in *fromp; ! 150: { ! 151: char cmdbuf[NCARGS+1], *cp; ! 152: char locuser[16], remuser[16]; ! 153: struct passwd *pwd; ! 154: int s, backoff; ! 155: struct hostent *hp; ! 156: short port; ! 157: int pv[2], pid, ready, readfrom, cc; ! 158: char buf[BUFSIZ], sig; ! 159: int one = 1; ! 160: ! 161: (void) signal(SIGINT, SIG_DFL); ! 162: (void) signal(SIGQUIT, SIG_DFL); ! 163: (void) signal(SIGTERM, SIG_DFL); ! 164: #ifdef DEBUG ! 165: { int t = open("/dev/tty", 2); ! 166: if (t >= 0) { ! 167: ioctl(t, TIOCNOTTY, (char *)0); ! 168: (void) close(t); ! 169: } ! 170: } ! 171: #endif ! 172: fromp->sin_port = ntohs((u_short)fromp->sin_port); ! 173: if (fromp->sin_family != AF_INET || ! 174: fromp->sin_port >= IPPORT_RESERVED) { ! 175: fprintf(stderr, "rshd: malformed from address\n"); ! 176: exit(1); ! 177: } ! 178: (void) alarm(60); ! 179: port = 0; ! 180: for (;;) { ! 181: char c; ! 182: if (read(f, &c, 1) != 1) { ! 183: perror("rshd: read"); ! 184: shutdown(f, 1+1); ! 185: exit(1); ! 186: } ! 187: if (c == 0) ! 188: break; ! 189: port = port * 10 + c - '0'; ! 190: } ! 191: (void) alarm(0); ! 192: if (port != 0) { ! 193: int lport = IPPORT_RESERVED - 1, retryshift; ! 194: s = rresvport(&lport); ! 195: if (s < 0) { ! 196: perror("rshd: can't get stderr port"); ! 197: exit(1); ! 198: } ! 199: if (port >= IPPORT_RESERVED) { ! 200: fprintf(stderr, "rshd: 2nd port not reserved\n"); ! 201: exit(1); ! 202: } ! 203: fromp->sin_port = htons((u_short)port); ! 204: if (connect(s, fromp, sizeof (*fromp), 0) < 0) { ! 205: perror("rshd: connect"); ! 206: exit(1); ! 207: } ! 208: } ! 209: dup2(f, 0); ! 210: dup2(f, 1); ! 211: dup2(f, 2); ! 212: hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr), ! 213: fromp->sin_family); ! 214: if (hp == 0) { ! 215: error("Host name for your address unknown\n"); ! 216: exit(1); ! 217: } ! 218: getstr(remuser, sizeof(remuser), "remuser"); ! 219: getstr(locuser, sizeof(locuser), "locuser"); ! 220: getstr(cmdbuf, sizeof(cmdbuf), "command"); ! 221: setpwent(); ! 222: pwd = getpwnam(locuser); ! 223: if (pwd == NULL) { ! 224: error("Login incorrect.\n"); ! 225: exit(1); ! 226: } ! 227: endpwent(); ! 228: if (chdir(pwd->pw_dir) < 0) { ! 229: error("No remote directory.\n"); ! 230: exit(1); ! 231: } ! 232: if (ruserok(hp->h_name, pwd->pw_uid == 0, remuser, locuser) < 0) { ! 233: error("Permission denied.\n"); ! 234: exit(1); ! 235: } ! 236: (void) write(2, "\0", 1); ! 237: if (port) { ! 238: if (pipe(pv) < 0) { ! 239: error("Can't make pipe.\n"); ! 240: exit(1); ! 241: } ! 242: pid = fork(); ! 243: if (pid == -1) { ! 244: error("Try again.\n"); ! 245: exit(1); ! 246: } ! 247: if (pid) { ! 248: (void) close(0); (void) close(1); (void) close(2); ! 249: (void) close(f); (void) close(pv[1]); ! 250: readfrom = (1<<s) | (1<<pv[0]); ! 251: ioctl(pv[1], FIONBIO, (char *)&one); ! 252: /* should set s nbio! */ ! 253: do { ! 254: ready = readfrom; ! 255: if (select(16, &ready, 0, 0, 0) < 0) ! 256: break; ! 257: if (ready & (1<<s)) { ! 258: if (read(s, &sig, 1) <= 0) ! 259: readfrom &= ~(1<<s); ! 260: else ! 261: killpg(pid, sig); ! 262: } ! 263: if (ready & (1<<pv[0])) { ! 264: errno = 0; ! 265: cc = read(pv[0], buf, sizeof (buf)); ! 266: if (cc <= 0) { ! 267: shutdown(s, 1+1); ! 268: readfrom &= ~(1<<pv[0]); ! 269: } else ! 270: (void) write(s, buf, cc); ! 271: } ! 272: } while (readfrom); ! 273: exit(0); ! 274: } ! 275: setpgrp(0, getpid()); ! 276: (void) close(s); (void) close(pv[0]); ! 277: dup2(pv[1], 2); ! 278: } ! 279: if (*pwd->pw_shell == '\0') ! 280: pwd->pw_shell = "/bin/sh"; ! 281: (void) close(f); ! 282: initgroups(pwd->pw_name, pwd->pw_gid); ! 283: (void) setgid(pwd->pw_gid); ! 284: (void) setuid(pwd->pw_uid); ! 285: environ = envinit; ! 286: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); ! 287: strncat(shell, pwd->pw_shell, sizeof(shell)-7); ! 288: strncat(username, pwd->pw_name, sizeof(username)-6); ! 289: cp = rindex(pwd->pw_shell, '/'); ! 290: if (cp) ! 291: cp++; ! 292: else ! 293: cp = pwd->pw_shell; ! 294: execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); ! 295: perror(pwd->pw_shell); ! 296: exit(1); ! 297: protofail: ! 298: error("rsh: protocol failure detected by remote\n"); ! 299: exit(1); ! 300: } ! 301: ! 302: /* VARARGS 1 */ ! 303: error(fmt) ! 304: char *fmt; ! 305: { ! 306: char buf[BUFSIZ]; ! 307: ! 308: buf[0] = 1; ! 309: (void) sprintf(buf+1, fmt); ! 310: (void) write(2, buf, strlen(buf)); ! 311: } ! 312: ! 313: getstr(buf, cnt, err) ! 314: char *buf; ! 315: int cnt; ! 316: char *err; ! 317: { ! 318: char c; ! 319: ! 320: do { ! 321: if (read(0, &c, 1) != 1) ! 322: exit(1); ! 323: *buf++ = c; ! 324: if (--cnt == 0) { ! 325: error("%s too long\n", err); ! 326: exit(1); ! 327: } ! 328: } while (c != 0); ! 329: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.