16442Swnj #ifndef lint 2*9200Ssam static char sccsid[] = "@(#)rexecd.c 4.2 82/11/14"; 36442Swnj #endif 46442Swnj 56442Swnj #include <sys/ioctl.h> 66442Swnj #include <sys/param.h> 76442Swnj #include <sys/socket.h> 8*9200Ssam 9*9200Ssam #include <netinet/in.h> 10*9200Ssam 11*9200Ssam #include <stdio.h> 126442Swnj #include <errno.h> 136442Swnj #include <pwd.h> 146442Swnj #include <wait.h> 156442Swnj #include <signal.h> 16*9200Ssam #include <netdb.h> 176442Swnj 186442Swnj extern errno; 19*9200Ssam struct sockaddr_in sin = { AF_INET }; 206442Swnj struct passwd *getpwnam(); 216442Swnj char *crypt(), *rindex(), *sprintf(); 226442Swnj /* VARARGS 1 */ 236442Swnj int error(); 246442Swnj /* 256442Swnj * remote execute server: 266442Swnj * username\0 276442Swnj * password\0 286442Swnj * command\0 296442Swnj * data 306442Swnj */ 316442Swnj main(argc, argv) 326442Swnj int argc; 336442Swnj char **argv; 346442Swnj { 356442Swnj union wait status; 366442Swnj int f; 376442Swnj struct sockaddr_in from; 38*9200Ssam struct servent *sp; 396442Swnj 40*9200Ssam sp = getservbyname("exec", "tcp"); 41*9200Ssam if (sp == 0) { 42*9200Ssam fprintf(stderr, "tcp/exec: unknown service\n"); 43*9200Ssam exit(1); 44*9200Ssam } 45*9200Ssam sin.sin_port = htons((u_short)sp->s_port); 466442Swnj #ifndef DEBUG 476442Swnj if (fork()) 486442Swnj exit(0); 496442Swnj for (f = 0; f < 10; f++) 506442Swnj (void) close(f); 516442Swnj (void) open("/", 0); 526442Swnj (void) dup2(0, 1); 536442Swnj (void) dup2(0, 2); 546442Swnj { int t = open("/dev/tty", 2); 556442Swnj if (t >= 0) { 566442Swnj ioctl(t, TIOCNOTTY, (char *)0); 576442Swnj (void) close(t); 586442Swnj } 596442Swnj } 606442Swnj #endif 616442Swnj argc--, argv++; 62*9200Ssam f = socket(0, SOCK_STREAM, 0, 0); 63*9200Ssam if (f < 0) { 64*9200Ssam perror("rexecd: socket"); 65*9200Ssam exit(1); 66*9200Ssam } 67*9200Ssam if (bind(f, &sin, sizeof (sin), 0) < 0) { 68*9200Ssam perror("rexecd: bind:"); 69*9200Ssam exit(1); 70*9200Ssam } 71*9200Ssam listen(f, 10); 726442Swnj for (;;) { 73*9200Ssam int s, len = sizeof (from); 74*9200Ssam 75*9200Ssam s = accept(f, &from, &len, 0); 76*9200Ssam if (s < 0) { 77*9200Ssam perror("rexecd: accept"); 786442Swnj sleep(1); 796442Swnj continue; 806442Swnj } 816442Swnj if (fork() == 0) 82*9200Ssam doit(s, &from); 83*9200Ssam (void) close(s); 84*9200Ssam while (wait3(status, WNOHANG, 0) > 0) 856442Swnj continue; 866442Swnj } 876442Swnj } 886442Swnj 896442Swnj char username[20] = "USER="; 906442Swnj char homedir[64] = "HOME="; 916442Swnj char shell[64] = "SHELL="; 926442Swnj char *envinit[] = 936442Swnj {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0}; 946442Swnj char **environ; 956442Swnj 966442Swnj struct sockaddr_in asin = { AF_INET }; 976442Swnj 986442Swnj doit(f, fromp) 996442Swnj int f; 1006442Swnj struct sockaddr_in *fromp; 1016442Swnj { 1026442Swnj char cmdbuf[NCARGS+1], *cp, *namep; 1036442Swnj char user[16], pass[16]; 1046442Swnj struct passwd *pwd; 1056442Swnj int s; 1066442Swnj short port; 1076442Swnj int pv[2], pid, ready, readfrom, cc; 1086442Swnj char buf[BUFSIZ], sig; 1096442Swnj int one = 1; 1106442Swnj 1116442Swnj (void) signal(SIGINT, SIG_DFL); 1126442Swnj (void) signal(SIGQUIT, SIG_DFL); 1136442Swnj (void) signal(SIGTERM, SIG_DFL); 1146442Swnj #ifdef DEBUG 1156442Swnj { int t = open("/dev/tty", 2); 1166442Swnj if (t >= 0) { 1176442Swnj ioctl(t, TIOCNOTTY, (char *)0); 1186442Swnj (void) close(t); 1196442Swnj } 1206442Swnj } 1216442Swnj #endif 1226442Swnj dup2(f, 0); 1236442Swnj dup2(f, 1); 1246442Swnj dup2(f, 2); 1256442Swnj #if vax 1266442Swnj fromp->sin_port = ntohs((u_short)fromp->sin_port); 1276442Swnj #endif 1286442Swnj (void) alarm(60); 1296442Swnj port = 0; 1306442Swnj for (;;) { 1316442Swnj char c; 1326442Swnj if (read(f, &c, 1) != 1) 1336442Swnj exit(1); 1346442Swnj if (c == 0) 1356442Swnj break; 1366442Swnj port = port * 10 + c - '0'; 1376442Swnj } 1386442Swnj (void) alarm(0); 1396442Swnj if (port != 0) { 1406442Swnj s = socket(SOCK_STREAM, 0, &asin, 0); 1416442Swnj if (s < 0) 1426442Swnj exit(1); 1436442Swnj (void) alarm(60); 144*9200Ssam fromp->sin_port = ntohs((u_short)fromp->sin_port); 145*9200Ssam if (connect(s, fromp, sizeof (*fromp), 0) < 0) 1466442Swnj exit(1); 1476442Swnj (void) alarm(0); 1486442Swnj } 1496442Swnj getstr(user, sizeof(user), "username"); 1506442Swnj getstr(pass, sizeof(pass), "password"); 1516442Swnj getstr(cmdbuf, sizeof(cmdbuf), "command"); 1526442Swnj setpwent(); 1536442Swnj pwd = getpwnam(user); 1546442Swnj if (pwd == NULL) { 1556442Swnj error("Login incorrect.\n"); 1566442Swnj exit(1); 1576442Swnj } 1586442Swnj endpwent(); 1596442Swnj if (*pwd->pw_passwd != '\0') { 1606442Swnj namep = crypt(pass, pwd->pw_passwd); 1616442Swnj if (strcmp(namep, pwd->pw_passwd)) { 1626442Swnj error("Password incorrect.\n"); 1636442Swnj exit(1); 1646442Swnj } 1656442Swnj } 1666442Swnj if (chdir(pwd->pw_dir) < 0) { 1676442Swnj error("No remote directory.\n"); 1686442Swnj exit(1); 1696442Swnj } 1706442Swnj (void) write(2, "\0", 1); 1716442Swnj if (port) { 1726442Swnj (void) pipe(pv); 1736442Swnj pid = fork(); 1746442Swnj if (pid == -1) { 1756442Swnj error("Try again.\n"); 1766442Swnj exit(1); 1776442Swnj } 1786442Swnj if (pid) { 1796442Swnj (void) close(0); (void) close(1); (void) close(2); 1806442Swnj (void) close(f); (void) close(pv[1]); 1816442Swnj readfrom = (1<<s) | (1<<pv[0]); 1826442Swnj ioctl(pv[1], FIONBIO, (char *)&one); 1836442Swnj /* should set s nbio! */ 1846442Swnj do { 1856442Swnj ready = readfrom; 186*9200Ssam (void) select(16, &ready, 0, 0, 0); 1876442Swnj if (ready & (1<<s)) { 1886442Swnj if (read(s, &sig, 1) <= 0) 1896442Swnj readfrom &= ~(1<<s); 1906442Swnj else 1916442Swnj killpg(pid, sig); 1926442Swnj } 1936442Swnj if (ready & (1<<pv[0])) { 1946442Swnj cc = read(pv[0], buf, sizeof (buf)); 1956442Swnj if (cc <= 0) { 1966442Swnj int done = 1+1; 1976442Swnj ioctl(s, SIOCDONE, (char *)&done); 1986442Swnj readfrom &= ~(1<<pv[0]); 1996442Swnj } else 2006442Swnj (void) write(s, buf, cc); 2016442Swnj } 2026442Swnj } while (readfrom); 2036442Swnj exit(0); 2046442Swnj } 2056442Swnj setpgrp(0, getpid()); 2066442Swnj (void) close(s); (void)close(pv[0]); 2076442Swnj dup2(pv[1], 2); 2086442Swnj } 2096442Swnj if (*pwd->pw_shell == '\0') 2106442Swnj pwd->pw_shell = "/bin/sh"; 2116442Swnj (void) close(f); 212*9200Ssam initgroups(pwd->pw_name, pwd->pw_gid); 2136442Swnj (void) setuid(pwd->pw_uid); 2146442Swnj (void) setgid(pwd->pw_gid); 2156442Swnj environ = envinit; 2166442Swnj strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 2176442Swnj strncat(shell, pwd->pw_shell, sizeof(shell)-7); 2186442Swnj strncat(username, pwd->pw_name, sizeof(username)-6); 2196442Swnj cp = rindex(pwd->pw_shell, '/'); 2206442Swnj if (cp) 2216442Swnj cp++; 2226442Swnj else 2236442Swnj cp = pwd->pw_shell; 2246442Swnj execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); 2256442Swnj perror(pwd->pw_shell); 2266442Swnj exit(1); 2276442Swnj } 2286442Swnj 2296442Swnj /* VARARGS 1 */ 2306442Swnj error(fmt, a1, a2, a3) 2316442Swnj char *fmt; 2326442Swnj int a1, a2, a3; 2336442Swnj { 2346442Swnj char buf[BUFSIZ]; 2356442Swnj 2366442Swnj buf[0] = 1; 2376442Swnj (void) sprintf(buf+1, fmt, a1, a2, a3); 2386442Swnj (void) write(2, buf, strlen(buf)); 2396442Swnj } 2406442Swnj 2416442Swnj getstr(buf, cnt, err) 2426442Swnj char *buf; 2436442Swnj int cnt; 2446442Swnj char *err; 2456442Swnj { 2466442Swnj char c; 2476442Swnj 2486442Swnj do { 2496442Swnj if (read(0, &c, 1) != 1) 2506442Swnj exit(1); 2516442Swnj *buf++ = c; 2526442Swnj if (--cnt == 0) { 2536442Swnj error("%s too long\n", err); 2546442Swnj exit(1); 2556442Swnj } 2566442Swnj } while (c != 0); 2576442Swnj } 258