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