1*6442Swnj #ifndef lint 2*6442Swnj static char sccsid[] = "@(#)rexecd.c 4.1 82/04/02"; 3*6442Swnj #endif 4*6442Swnj 5*6442Swnj #include <stdio.h> 6*6442Swnj #include <sys/ioctl.h> 7*6442Swnj #include <sys/param.h> 8*6442Swnj #include <sys/socket.h> 9*6442Swnj #include <net/in.h> 10*6442Swnj #include <errno.h> 11*6442Swnj #include <pwd.h> 12*6442Swnj #include <wait.h> 13*6442Swnj #include <signal.h> 14*6442Swnj 15*6442Swnj extern errno; 16*6442Swnj struct sockaddr_in sin = { AF_INET, IPPORT_EXECSERVER }; 17*6442Swnj struct passwd *getpwnam(); 18*6442Swnj char *crypt(), *rindex(), *sprintf(); 19*6442Swnj int options = SO_ACCEPTCONN|SO_KEEPALIVE; 20*6442Swnj /* VARARGS 1 */ 21*6442Swnj int error(); 22*6442Swnj /* 23*6442Swnj * remote execute server: 24*6442Swnj * username\0 25*6442Swnj * password\0 26*6442Swnj * command\0 27*6442Swnj * data 28*6442Swnj */ 29*6442Swnj main(argc, argv) 30*6442Swnj int argc; 31*6442Swnj char **argv; 32*6442Swnj { 33*6442Swnj union wait status; 34*6442Swnj int f; 35*6442Swnj struct sockaddr_in from; 36*6442Swnj 37*6442Swnj #ifndef DEBUG 38*6442Swnj if (fork()) 39*6442Swnj exit(0); 40*6442Swnj for (f = 0; f < 10; f++) 41*6442Swnj (void) close(f); 42*6442Swnj (void) open("/", 0); 43*6442Swnj (void) dup2(0, 1); 44*6442Swnj (void) dup2(0, 2); 45*6442Swnj { int t = open("/dev/tty", 2); 46*6442Swnj if (t >= 0) { 47*6442Swnj ioctl(t, TIOCNOTTY, (char *)0); 48*6442Swnj (void) close(t); 49*6442Swnj } 50*6442Swnj } 51*6442Swnj #endif 52*6442Swnj #if vax 53*6442Swnj sin.sin_port = htons(sin.sin_port); 54*6442Swnj #endif 55*6442Swnj argc--, argv++; 56*6442Swnj if (argc > 0 && !strcmp(argv[0], "-d")) 57*6442Swnj options |= SO_DEBUG; 58*6442Swnj for (;;) { 59*6442Swnj errno = 0; 60*6442Swnj f = socket(SOCK_STREAM, 0, &sin, options); 61*6442Swnj if (f < 0) { 62*6442Swnj perror("socket"); 63*6442Swnj sleep(5); 64*6442Swnj continue; 65*6442Swnj } 66*6442Swnj if (accept(f, &from) < 0) { 67*6442Swnj perror("accept"); 68*6442Swnj (void) close(f); 69*6442Swnj sleep(1); 70*6442Swnj continue; 71*6442Swnj } 72*6442Swnj if (fork() == 0) 73*6442Swnj doit(f, &from); 74*6442Swnj (void) close(f); 75*6442Swnj while(wait3(status, WNOHANG, 0) > 0) 76*6442Swnj continue; 77*6442Swnj } 78*6442Swnj } 79*6442Swnj 80*6442Swnj char username[20] = "USER="; 81*6442Swnj char homedir[64] = "HOME="; 82*6442Swnj char shell[64] = "SHELL="; 83*6442Swnj char *envinit[] = 84*6442Swnj {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0}; 85*6442Swnj char **environ; 86*6442Swnj 87*6442Swnj struct sockaddr_in asin = { AF_INET }; 88*6442Swnj 89*6442Swnj doit(f, fromp) 90*6442Swnj int f; 91*6442Swnj struct sockaddr_in *fromp; 92*6442Swnj { 93*6442Swnj char cmdbuf[NCARGS+1], *cp, *namep; 94*6442Swnj char user[16], pass[16]; 95*6442Swnj struct passwd *pwd; 96*6442Swnj int s; 97*6442Swnj short port; 98*6442Swnj int pv[2], pid, ready, readfrom, cc; 99*6442Swnj char buf[BUFSIZ], sig; 100*6442Swnj int one = 1; 101*6442Swnj 102*6442Swnj (void) signal(SIGINT, SIG_DFL); 103*6442Swnj (void) signal(SIGQUIT, SIG_DFL); 104*6442Swnj (void) signal(SIGTERM, SIG_DFL); 105*6442Swnj #ifdef DEBUG 106*6442Swnj { int t = open("/dev/tty", 2); 107*6442Swnj if (t >= 0) { 108*6442Swnj ioctl(t, TIOCNOTTY, (char *)0); 109*6442Swnj (void) close(t); 110*6442Swnj } 111*6442Swnj } 112*6442Swnj #endif 113*6442Swnj dup2(f, 0); 114*6442Swnj dup2(f, 1); 115*6442Swnj dup2(f, 2); 116*6442Swnj #if vax 117*6442Swnj fromp->sin_port = ntohs((u_short)fromp->sin_port); 118*6442Swnj #endif 119*6442Swnj (void) alarm(60); 120*6442Swnj port = 0; 121*6442Swnj for (;;) { 122*6442Swnj char c; 123*6442Swnj if (read(f, &c, 1) != 1) 124*6442Swnj exit(1); 125*6442Swnj if (c == 0) 126*6442Swnj break; 127*6442Swnj port = port * 10 + c - '0'; 128*6442Swnj } 129*6442Swnj (void) alarm(0); 130*6442Swnj if (port != 0) { 131*6442Swnj s = socket(SOCK_STREAM, 0, &asin, 0); 132*6442Swnj if (s < 0) 133*6442Swnj exit(1); 134*6442Swnj (void) alarm(60); 135*6442Swnj fromp->sin_port = port; 136*6442Swnj #if vax 137*6442Swnj fromp->sin_port = ntohs(fromp->sin_port); 138*6442Swnj #endif 139*6442Swnj if (connect(s, fromp) < 0) 140*6442Swnj exit(1); 141*6442Swnj (void) alarm(0); 142*6442Swnj } 143*6442Swnj getstr(user, sizeof(user), "username"); 144*6442Swnj getstr(pass, sizeof(pass), "password"); 145*6442Swnj getstr(cmdbuf, sizeof(cmdbuf), "command"); 146*6442Swnj setpwent(); 147*6442Swnj pwd = getpwnam(user); 148*6442Swnj if (pwd == NULL) { 149*6442Swnj error("Login incorrect.\n"); 150*6442Swnj exit(1); 151*6442Swnj } 152*6442Swnj endpwent(); 153*6442Swnj if (*pwd->pw_passwd != '\0') { 154*6442Swnj namep = crypt(pass, pwd->pw_passwd); 155*6442Swnj if (strcmp(namep, pwd->pw_passwd)) { 156*6442Swnj error("Password incorrect.\n"); 157*6442Swnj exit(1); 158*6442Swnj } 159*6442Swnj } 160*6442Swnj if (chdir(pwd->pw_dir) < 0) { 161*6442Swnj error("No remote directory.\n"); 162*6442Swnj exit(1); 163*6442Swnj } 164*6442Swnj (void) write(2, "\0", 1); 165*6442Swnj if (port) { 166*6442Swnj (void) pipe(pv); 167*6442Swnj pid = fork(); 168*6442Swnj if (pid == -1) { 169*6442Swnj error("Try again.\n"); 170*6442Swnj exit(1); 171*6442Swnj } 172*6442Swnj if (pid) { 173*6442Swnj (void) close(0); (void) close(1); (void) close(2); 174*6442Swnj (void) close(f); (void) close(pv[1]); 175*6442Swnj readfrom = (1<<s) | (1<<pv[0]); 176*6442Swnj ioctl(pv[1], FIONBIO, (char *)&one); 177*6442Swnj /* should set s nbio! */ 178*6442Swnj do { 179*6442Swnj ready = readfrom; 180*6442Swnj (void) select(32, &ready, 0, 1000000); 181*6442Swnj if (ready & (1<<s)) { 182*6442Swnj if (read(s, &sig, 1) <= 0) 183*6442Swnj readfrom &= ~(1<<s); 184*6442Swnj else 185*6442Swnj killpg(pid, sig); 186*6442Swnj } 187*6442Swnj if (ready & (1<<pv[0])) { 188*6442Swnj cc = read(pv[0], buf, sizeof (buf)); 189*6442Swnj if (cc <= 0) { 190*6442Swnj int done = 1+1; 191*6442Swnj ioctl(s, SIOCDONE, (char *)&done); 192*6442Swnj readfrom &= ~(1<<pv[0]); 193*6442Swnj } else 194*6442Swnj (void) write(s, buf, cc); 195*6442Swnj } 196*6442Swnj } while (readfrom); 197*6442Swnj exit(0); 198*6442Swnj } 199*6442Swnj setpgrp(0, getpid()); 200*6442Swnj (void) close(s); (void)close(pv[0]); 201*6442Swnj dup2(pv[1], 2); 202*6442Swnj } 203*6442Swnj if (*pwd->pw_shell == '\0') 204*6442Swnj pwd->pw_shell = "/bin/sh"; 205*6442Swnj (void) close(f); 206*6442Swnj inigrp(pwd->pw_name, pwd->pw_gid); 207*6442Swnj (void) setuid(pwd->pw_uid); 208*6442Swnj (void) setgid(pwd->pw_gid); 209*6442Swnj environ = envinit; 210*6442Swnj strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); 211*6442Swnj strncat(shell, pwd->pw_shell, sizeof(shell)-7); 212*6442Swnj strncat(username, pwd->pw_name, sizeof(username)-6); 213*6442Swnj cp = rindex(pwd->pw_shell, '/'); 214*6442Swnj if (cp) 215*6442Swnj cp++; 216*6442Swnj else 217*6442Swnj cp = pwd->pw_shell; 218*6442Swnj execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); 219*6442Swnj perror(pwd->pw_shell); 220*6442Swnj exit(1); 221*6442Swnj } 222*6442Swnj 223*6442Swnj /* VARARGS 1 */ 224*6442Swnj error(fmt, a1, a2, a3) 225*6442Swnj char *fmt; 226*6442Swnj int a1, a2, a3; 227*6442Swnj { 228*6442Swnj char buf[BUFSIZ]; 229*6442Swnj 230*6442Swnj buf[0] = 1; 231*6442Swnj (void) sprintf(buf+1, fmt, a1, a2, a3); 232*6442Swnj (void) write(2, buf, strlen(buf)); 233*6442Swnj } 234*6442Swnj 235*6442Swnj getstr(buf, cnt, err) 236*6442Swnj char *buf; 237*6442Swnj int cnt; 238*6442Swnj char *err; 239*6442Swnj { 240*6442Swnj char c; 241*6442Swnj 242*6442Swnj do { 243*6442Swnj if (read(0, &c, 1) != 1) 244*6442Swnj exit(1); 245*6442Swnj *buf++ = c; 246*6442Swnj if (--cnt == 0) { 247*6442Swnj error("%s too long\n", err); 248*6442Swnj exit(1); 249*6442Swnj } 250*6442Swnj } while (c != 0); 251*6442Swnj } 252