|
|
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.