16442Swnj #ifndef lint 2*9257Ssam static char sccsid[] = "@(#)rexecd.c 4.4 82/11/15"; 36442Swnj #endif 46442Swnj 56442Swnj #include <sys/ioctl.h> 66442Swnj #include <sys/param.h> 76442Swnj #include <sys/socket.h> 89200Ssam 99200Ssam #include <netinet/in.h> 109200Ssam 119200Ssam #include <stdio.h> 126442Swnj #include <errno.h> 136442Swnj #include <pwd.h> 146442Swnj #include <wait.h> 156442Swnj #include <signal.h> 169200Ssam #include <netdb.h> 176442Swnj 186442Swnj extern errno; 199200Ssam 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; 389200Ssam struct servent *sp; 396442Swnj 409200Ssam sp = getservbyname("exec", "tcp"); 419200Ssam if (sp == 0) { 429200Ssam fprintf(stderr, "tcp/exec: unknown service\n"); 439200Ssam exit(1); 449200Ssam } 459200Ssam 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*9257Ssam f = socket(AF_INET, SOCK_STREAM, 0, 0); 639200Ssam if (f < 0) { 649200Ssam perror("rexecd: socket"); 659200Ssam exit(1); 669200Ssam } 679200Ssam if (bind(f, &sin, sizeof (sin), 0) < 0) { 689200Ssam perror("rexecd: bind:"); 699200Ssam exit(1); 709200Ssam } 719200Ssam listen(f, 10); 726442Swnj for (;;) { 739200Ssam int s, len = sizeof (from); 749200Ssam 759200Ssam s = accept(f, &from, &len, 0); 769200Ssam if (s < 0) { 779200Ssam perror("rexecd: accept"); 786442Swnj sleep(1); 796442Swnj continue; 806442Swnj } 816442Swnj if (fork() == 0) 829200Ssam doit(s, &from); 839200Ssam (void) close(s); 849200Ssam 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 (void) alarm(60); 1266442Swnj port = 0; 1276442Swnj for (;;) { 1286442Swnj char c; 1296442Swnj if (read(f, &c, 1) != 1) 1306442Swnj exit(1); 1316442Swnj if (c == 0) 1326442Swnj break; 1336442Swnj port = port * 10 + c - '0'; 1346442Swnj } 1356442Swnj (void) alarm(0); 1366442Swnj if (port != 0) { 137*9257Ssam s = socket(AF_INET, SOCK_STREAM, 0, 0); 1386442Swnj if (s < 0) 1396442Swnj exit(1); 140*9257Ssam if (bind(s, &asin, sizeof (asin), 0) < 0) 141*9257Ssam exit(1); 1426442Swnj (void) alarm(60); 143*9257Ssam fromp->sin_port = htons((u_short)port); 1449200Ssam if (connect(s, fromp, sizeof (*fromp), 0) < 0) 1456442Swnj exit(1); 1466442Swnj (void) alarm(0); 1476442Swnj } 1486442Swnj getstr(user, sizeof(user), "username"); 1496442Swnj getstr(pass, sizeof(pass), "password"); 1506442Swnj getstr(cmdbuf, sizeof(cmdbuf), "command"); 1516442Swnj setpwent(); 1526442Swnj pwd = getpwnam(user); 1536442Swnj if (pwd == NULL) { 1546442Swnj error("Login incorrect.\n"); 1556442Swnj exit(1); 1566442Swnj } 1576442Swnj endpwent(); 1586442Swnj if (*pwd->pw_passwd != '\0') { 1596442Swnj namep = crypt(pass, pwd->pw_passwd); 1606442Swnj if (strcmp(namep, pwd->pw_passwd)) { 1616442Swnj error("Password incorrect.\n"); 1626442Swnj exit(1); 1636442Swnj } 1646442Swnj } 1656442Swnj if (chdir(pwd->pw_dir) < 0) { 1666442Swnj error("No remote directory.\n"); 1676442Swnj exit(1); 1686442Swnj } 1696442Swnj (void) write(2, "\0", 1); 1706442Swnj if (port) { 1716442Swnj (void) pipe(pv); 1726442Swnj pid = fork(); 1736442Swnj if (pid == -1) { 1746442Swnj error("Try again.\n"); 1756442Swnj exit(1); 1766442Swnj } 1776442Swnj if (pid) { 1786442Swnj (void) close(0); (void) close(1); (void) close(2); 1796442Swnj (void) close(f); (void) close(pv[1]); 1806442Swnj readfrom = (1<<s) | (1<<pv[0]); 1816442Swnj ioctl(pv[1], FIONBIO, (char *)&one); 1826442Swnj /* should set s nbio! */ 1836442Swnj do { 1846442Swnj ready = readfrom; 1859200Ssam (void) select(16, &ready, 0, 0, 0); 1866442Swnj if (ready & (1<<s)) { 1876442Swnj if (read(s, &sig, 1) <= 0) 1886442Swnj readfrom &= ~(1<<s); 1896442Swnj else 1906442Swnj killpg(pid, sig); 1916442Swnj } 1926442Swnj if (ready & (1<<pv[0])) { 1936442Swnj cc = read(pv[0], buf, sizeof (buf)); 1946442Swnj if (cc <= 0) { 1956442Swnj int done = 1+1; 1966442Swnj ioctl(s, SIOCDONE, (char *)&done); 1976442Swnj readfrom &= ~(1<<pv[0]); 1986442Swnj } else 1996442Swnj (void) write(s, buf, cc); 2006442Swnj } 2016442Swnj } while (readfrom); 2026442Swnj exit(0); 2036442Swnj } 2046442Swnj setpgrp(0, getpid()); 2056442Swnj (void) close(s); (void)close(pv[0]); 2066442Swnj dup2(pv[1], 2); 2076442Swnj } 2086442Swnj if (*pwd->pw_shell == '\0') 2096442Swnj pwd->pw_shell = "/bin/sh"; 2106442Swnj (void) close(f); 2119200Ssam initgroups(pwd->pw_name, pwd->pw_gid); 2126442Swnj (void) setuid(pwd->pw_uid); 2136442Swnj (void) setgid(pwd->pw_gid); 2146442Swnj environ = envinit; 2156442Swnj strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 2166442Swnj strncat(shell, pwd->pw_shell, sizeof(shell)-7); 2176442Swnj strncat(username, pwd->pw_name, sizeof(username)-6); 2186442Swnj cp = rindex(pwd->pw_shell, '/'); 2196442Swnj if (cp) 2206442Swnj cp++; 2216442Swnj else 2226442Swnj cp = pwd->pw_shell; 2236442Swnj execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); 2246442Swnj perror(pwd->pw_shell); 2256442Swnj exit(1); 2266442Swnj } 2276442Swnj 2286442Swnj /* VARARGS 1 */ 2296442Swnj error(fmt, a1, a2, a3) 2306442Swnj char *fmt; 2316442Swnj int a1, a2, a3; 2326442Swnj { 2336442Swnj char buf[BUFSIZ]; 2346442Swnj 2356442Swnj buf[0] = 1; 2366442Swnj (void) sprintf(buf+1, fmt, a1, a2, a3); 2376442Swnj (void) write(2, buf, strlen(buf)); 2386442Swnj } 2396442Swnj 2406442Swnj getstr(buf, cnt, err) 2416442Swnj char *buf; 2426442Swnj int cnt; 2436442Swnj char *err; 2446442Swnj { 2456442Swnj char c; 2466442Swnj 2476442Swnj do { 2486442Swnj if (read(0, &c, 1) != 1) 2496442Swnj exit(1); 2506442Swnj *buf++ = c; 2516442Swnj if (--cnt == 0) { 2526442Swnj error("%s too long\n", err); 2536442Swnj exit(1); 2546442Swnj } 2556442Swnj } while (c != 0); 2566442Swnj } 257