|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)rexecd.c 4.10 (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: extern errno; ! 19: struct sockaddr_in sin = { AF_INET }; ! 20: struct passwd *getpwnam(); ! 21: char *crypt(), *rindex(), *sprintf(); ! 22: /* VARARGS 1 */ ! 23: int error(); ! 24: int reapchild(); ! 25: /* ! 26: * remote execute server: ! 27: * username\0 ! 28: * password\0 ! 29: * command\0 ! 30: * data ! 31: */ ! 32: main(argc, argv) ! 33: int argc; ! 34: char **argv; ! 35: { ! 36: int errcnt = 0; ! 37: int f; ! 38: struct sockaddr_in from; ! 39: struct servent *sp; ! 40: ! 41: sp = getservbyname("exec", "tcp"); ! 42: if (sp == 0) { ! 43: fprintf(stderr, "tcp/exec: unknown service\n"); ! 44: exit(1); ! 45: } ! 46: sin.sin_port = sp->s_port; ! 47: #ifndef DEBUG ! 48: if (fork()) ! 49: exit(0); ! 50: close(0); ! 51: if ( open("/dev/console", 2) < 0) { ! 52: fprintf(stderr,"rexecd: 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: argc--, argv++; ! 67: f = socket(AF_INET, SOCK_STREAM, 0, 0); ! 68: if (f < 0) { ! 69: perror("rexecd: socket"); ! 70: exit(1); ! 71: } ! 72: if (bind(f, &sin, sizeof (sin), 0) < 0) { ! 73: perror("rexecd: bind:"); ! 74: exit(1); ! 75: } ! 76: signal(SIGCHLD, reapchild); ! 77: listen(f, 10); ! 78: for (;errcnt < 20;) { ! 79: int child; ! 80: int s, len = sizeof (from); ! 81: ! 82: s = accept(f, &from, &len, 0); ! 83: if (s < 0) { ! 84: if (errno == EINTR) ! 85: continue; ! 86: perror("rexecd: accept"); ! 87: ++errcnt; ! 88: sleep(1); ! 89: continue; ! 90: } ! 91: child = fork(); ! 92: if (child < 0) { ! 93: perror("rexecd: out of processes"); ! 94: sleep(1); ! 95: continue; ! 96: } ! 97: if (child == 0) { ! 98: errcnt = 0; ! 99: signal(SIGCHLD, SIG_IGN); ! 100: doit(s, &from); ! 101: } ! 102: errcnt = 0; ! 103: (void) close(s); ! 104: } ! 105: fprintf(stderr,"rexecd terminates due to too many errors\n"); ! 106: } ! 107: ! 108: reapchild() ! 109: { ! 110: union wait status; ! 111: ! 112: while (wait3(&status, WNOHANG, 0) > 0) ! 113: ; ! 114: } ! 115: ! 116: char username[20] = "USER="; ! 117: char homedir[64] = "HOME="; ! 118: char shell[64] = "SHELL="; ! 119: char *envinit[] = ! 120: {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0}; ! 121: char **environ; ! 122: ! 123: struct sockaddr_in asin = { AF_INET }; ! 124: ! 125: doit(f, fromp) ! 126: int f; ! 127: struct sockaddr_in *fromp; ! 128: { ! 129: char cmdbuf[NCARGS+1], *cp, *namep; ! 130: char user[16], pass[16]; ! 131: struct passwd *pwd; ! 132: int s; ! 133: short port; ! 134: int pv[2], pid, ready, readfrom, cc; ! 135: char buf[BUFSIZ], sig; ! 136: int one = 1; ! 137: ! 138: (void) signal(SIGINT, SIG_DFL); ! 139: (void) signal(SIGQUIT, SIG_DFL); ! 140: (void) signal(SIGTERM, SIG_DFL); ! 141: #ifdef DEBUG ! 142: { int t = open("/dev/tty", 2); ! 143: if (t >= 0) { ! 144: ioctl(t, TIOCNOTTY, (char *)0); ! 145: (void) close(t); ! 146: } ! 147: } ! 148: #endif ! 149: dup2(f, 0); ! 150: dup2(f, 1); ! 151: dup2(f, 2); ! 152: (void) alarm(60); ! 153: port = 0; ! 154: for (;;) { ! 155: char c; ! 156: if (read(f, &c, 1) != 1) ! 157: exit(1); ! 158: if (c == 0) ! 159: break; ! 160: port = port * 10 + c - '0'; ! 161: } ! 162: (void) alarm(0); ! 163: if (port != 0) { ! 164: s = socket(AF_INET, SOCK_STREAM, 0, 0); ! 165: if (s < 0) ! 166: exit(1); ! 167: if (bind(s, &asin, sizeof (asin), 0) < 0) ! 168: exit(1); ! 169: (void) alarm(60); ! 170: fromp->sin_port = htons((u_short)port); ! 171: if (connect(s, fromp, sizeof (*fromp), 0) < 0) ! 172: exit(1); ! 173: (void) alarm(0); ! 174: } ! 175: getstr(user, sizeof(user), "username"); ! 176: getstr(pass, sizeof(pass), "password"); ! 177: getstr(cmdbuf, sizeof(cmdbuf), "command"); ! 178: setpwent(); ! 179: pwd = getpwnam(user); ! 180: if (pwd == NULL) { ! 181: error("Login incorrect.\n"); ! 182: exit(1); ! 183: } ! 184: endpwent(); ! 185: if (*pwd->pw_passwd != '\0') { ! 186: namep = crypt(pass, pwd->pw_passwd); ! 187: if (strcmp(namep, pwd->pw_passwd)) { ! 188: error("Password incorrect.\n"); ! 189: exit(1); ! 190: } ! 191: } ! 192: if (chdir(pwd->pw_dir) < 0) { ! 193: error("No remote directory.\n"); ! 194: exit(1); ! 195: } ! 196: (void) write(2, "\0", 1); ! 197: if (port) { ! 198: (void) pipe(pv); ! 199: pid = fork(); ! 200: if (pid == -1) { ! 201: error("Try again.\n"); ! 202: exit(1); ! 203: } ! 204: if (pid) { ! 205: (void) close(0); (void) close(1); (void) close(2); ! 206: (void) close(f); (void) close(pv[1]); ! 207: readfrom = (1<<s) | (1<<pv[0]); ! 208: ioctl(pv[1], FIONBIO, (char *)&one); ! 209: /* should set s nbio! */ ! 210: do { ! 211: ready = readfrom; ! 212: (void) select(16, &ready, 0, 0, 0); ! 213: if (ready & (1<<s)) { ! 214: if (read(s, &sig, 1) <= 0) ! 215: readfrom &= ~(1<<s); ! 216: else ! 217: killpg(pid, sig); ! 218: } ! 219: if (ready & (1<<pv[0])) { ! 220: cc = read(pv[0], buf, sizeof (buf)); ! 221: if (cc <= 0) { ! 222: shutdown(s, 1+1); ! 223: readfrom &= ~(1<<pv[0]); ! 224: } else ! 225: (void) write(s, buf, cc); ! 226: } ! 227: } while (readfrom); ! 228: exit(0); ! 229: } ! 230: setpgrp(0, getpid()); ! 231: (void) close(s); (void)close(pv[0]); ! 232: dup2(pv[1], 2); ! 233: } ! 234: if (*pwd->pw_shell == '\0') ! 235: pwd->pw_shell = "/bin/sh"; ! 236: (void) close(f); ! 237: initgroups(pwd->pw_name, pwd->pw_gid); ! 238: (void) setuid(pwd->pw_uid); ! 239: (void) setgid(pwd->pw_gid); ! 240: environ = envinit; ! 241: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); ! 242: strncat(shell, pwd->pw_shell, sizeof(shell)-7); ! 243: strncat(username, pwd->pw_name, sizeof(username)-6); ! 244: cp = rindex(pwd->pw_shell, '/'); ! 245: if (cp) ! 246: cp++; ! 247: else ! 248: cp = pwd->pw_shell; ! 249: execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); ! 250: perror(pwd->pw_shell); ! 251: exit(1); ! 252: } ! 253: ! 254: /* VARARGS 1 */ ! 255: error(fmt, a1, a2, a3) ! 256: char *fmt; ! 257: int a1, a2, a3; ! 258: { ! 259: char buf[BUFSIZ]; ! 260: ! 261: buf[0] = 1; ! 262: (void) sprintf(buf+1, fmt, a1, a2, a3); ! 263: (void) write(2, buf, strlen(buf)); ! 264: } ! 265: ! 266: getstr(buf, cnt, err) ! 267: char *buf; ! 268: int cnt; ! 269: char *err; ! 270: { ! 271: char c; ! 272: ! 273: do { ! 274: if (read(0, &c, 1) != 1) ! 275: exit(1); ! 276: *buf++ = c; ! 277: if (--cnt == 0) { ! 278: error("%s too long\n", err); ! 279: exit(1); ! 280: } ! 281: } while (c != 0); ! 282: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.