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