|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)rshd.c 4.17 (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: int errno;
19: int reapchild();
20: struct sockaddr_in sin = { AF_INET };
21: struct passwd *getpwnam();
22: char *index(), *rindex(), *sprintf();
23: int options;
24: /* VARARGS 1 */
25: int error();
26: /*
27: * remote shell server:
28: * remuser\0
29: * locuser\0
30: * command\0
31: * data
32: */
33: main(argc, argv)
34: int argc;
35: char **argv;
36: {
37: int errcnt = 0;
38: int f, linger;
39: struct sockaddr_in from;
40: struct servent *sp;
41:
42: sp = getservbyname("shell", "tcp");
43: if (sp == 0) {
44: fprintf(stderr, "rshd: tcp/shell: unknown service\n");
45: exit(1);
46: }
47: #ifndef DEBUG
48: if (fork())
49: exit(0);
50: close(0);
51: if ( open("/dev/console", 2) <0) {
52: fprintf(stderr,"rshd: 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: sin.sin_port = sp->s_port;
67: argc--, argv++;
68: if (argc > 0 && !strcmp(argv[0], "-d")) {
69: options |= SO_DEBUG;
70: argc--, argv++;
71: }
72: if (argc > 0) {
73: int port = atoi(argv[0]);
74:
75: if (port < 0) {
76: fprintf(stderr, "%s: bad port #\n", argv[0]);
77: exit(1);
78: }
79: sin.sin_port = htons((u_short)port);
80: argc--, argv++;
81: }
82: f = socket(AF_INET, SOCK_STREAM, 0, 0);
83: if (f < 0) {
84: perror("rshd: socket");
85: exit(1);
86: }
87: if (options & SO_DEBUG && setsockopt(f, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
88: perror("rshd: setsockopt (SO_DEBUG)");
89: if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE, 0, 0) < 0)
90: perror("rshd: setsockopt (SO_KEEPALIVE)");
91: linger = 60; /* XXX */
92: if (setsockopt(f, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) < 0)
93: perror("rshd: setsockopt (SO_LINGER)");
94: if (bind(f, (caddr_t)&sin, sizeof (sin), 0) < 0) {
95: perror("rshd: bind");
96: exit(1);
97: }
98: signal(SIGCHLD, reapchild);
99: listen(f, 10);
100: for (;errcnt < 20;) {
101: int child;
102: int g, len = sizeof (from);
103:
104: g = accept(f, &from, &len, 0);
105: if (g < 0) {
106: if (errno == EINTR)
107: continue;
108: perror("rshd: accept");
109: errcnt++;
110: sleep(5);
111: continue;
112: }
113: child = fork();
114: if (child < 0) {
115: perror("rshd: cannot fork");
116: sleep(5);
117: continue;
118: }
119: if (child == 0) {
120: signal(SIGCHLD, SIG_IGN);
121: close(f);
122: errcnt = 0;
123: doit(g, &from);
124: }
125: /* when we get here, all is okay */
126: errcnt = 0;
127: close(g);
128: }
129: fprintf(stderr,"rshd: terminated due to too many errors\n");
130: }
131:
132: reapchild()
133: {
134: union wait status;
135:
136: while (wait3(&status, WNOHANG, 0) > 0)
137: ;
138: }
139:
140: char username[20] = "USER=";
141: char homedir[64] = "HOME=";
142: char shell[64] = "SHELL=";
143: char *envinit[] =
144: {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
145: char **environ;
146:
147: doit(f, fromp)
148: int f;
149: struct sockaddr_in *fromp;
150: {
151: char cmdbuf[NCARGS+1], *cp;
152: char locuser[16], remuser[16];
153: struct passwd *pwd;
154: int s, backoff;
155: struct hostent *hp;
156: short port;
157: int pv[2], pid, ready, readfrom, cc;
158: char buf[BUFSIZ], sig;
159: int one = 1;
160:
161: (void) signal(SIGINT, SIG_DFL);
162: (void) signal(SIGQUIT, SIG_DFL);
163: (void) signal(SIGTERM, SIG_DFL);
164: #ifdef DEBUG
165: { int t = open("/dev/tty", 2);
166: if (t >= 0) {
167: ioctl(t, TIOCNOTTY, (char *)0);
168: (void) close(t);
169: }
170: }
171: #endif
172: fromp->sin_port = ntohs((u_short)fromp->sin_port);
173: if (fromp->sin_family != AF_INET ||
174: fromp->sin_port >= IPPORT_RESERVED) {
175: fprintf(stderr, "rshd: malformed from address\n");
176: exit(1);
177: }
178: (void) alarm(60);
179: port = 0;
180: for (;;) {
181: char c;
182: if (read(f, &c, 1) != 1) {
183: perror("rshd: read");
184: shutdown(f, 1+1);
185: exit(1);
186: }
187: if (c == 0)
188: break;
189: port = port * 10 + c - '0';
190: }
191: (void) alarm(0);
192: if (port != 0) {
193: int lport = IPPORT_RESERVED - 1, retryshift;
194: s = rresvport(&lport);
195: if (s < 0) {
196: perror("rshd: can't get stderr port");
197: exit(1);
198: }
199: if (port >= IPPORT_RESERVED) {
200: fprintf(stderr, "rshd: 2nd port not reserved\n");
201: exit(1);
202: }
203: fromp->sin_port = htons((u_short)port);
204: if (connect(s, fromp, sizeof (*fromp), 0) < 0) {
205: perror("rshd: connect");
206: exit(1);
207: }
208: }
209: dup2(f, 0);
210: dup2(f, 1);
211: dup2(f, 2);
212: hp = gethostbyaddr(&fromp->sin_addr, sizeof (struct in_addr),
213: fromp->sin_family);
214: if (hp == 0) {
215: error("Host name for your address unknown\n");
216: exit(1);
217: }
218: getstr(remuser, sizeof(remuser), "remuser");
219: getstr(locuser, sizeof(locuser), "locuser");
220: getstr(cmdbuf, sizeof(cmdbuf), "command");
221: setpwent();
222: pwd = getpwnam(locuser);
223: if (pwd == NULL) {
224: error("Login incorrect.\n");
225: exit(1);
226: }
227: endpwent();
228: if (chdir(pwd->pw_dir) < 0) {
229: error("No remote directory.\n");
230: exit(1);
231: }
232: if (ruserok(hp->h_name, pwd->pw_uid == 0, remuser, locuser) < 0) {
233: error("Permission denied.\n");
234: exit(1);
235: }
236: (void) write(2, "\0", 1);
237: if (port) {
238: if (pipe(pv) < 0) {
239: error("Can't make pipe.\n");
240: exit(1);
241: }
242: pid = fork();
243: if (pid == -1) {
244: error("Try again.\n");
245: exit(1);
246: }
247: if (pid) {
248: (void) close(0); (void) close(1); (void) close(2);
249: (void) close(f); (void) close(pv[1]);
250: readfrom = (1<<s) | (1<<pv[0]);
251: ioctl(pv[1], FIONBIO, (char *)&one);
252: /* should set s nbio! */
253: do {
254: ready = readfrom;
255: if (select(16, &ready, 0, 0, 0) < 0)
256: break;
257: if (ready & (1<<s)) {
258: if (read(s, &sig, 1) <= 0)
259: readfrom &= ~(1<<s);
260: else
261: killpg(pid, sig);
262: }
263: if (ready & (1<<pv[0])) {
264: errno = 0;
265: cc = read(pv[0], buf, sizeof (buf));
266: if (cc <= 0) {
267: shutdown(s, 1+1);
268: readfrom &= ~(1<<pv[0]);
269: } else
270: (void) write(s, buf, cc);
271: }
272: } while (readfrom);
273: exit(0);
274: }
275: setpgrp(0, getpid());
276: (void) close(s); (void) close(pv[0]);
277: dup2(pv[1], 2);
278: }
279: if (*pwd->pw_shell == '\0')
280: pwd->pw_shell = "/bin/sh";
281: (void) close(f);
282: initgroups(pwd->pw_name, pwd->pw_gid);
283: (void) setgid(pwd->pw_gid);
284: (void) setuid(pwd->pw_uid);
285: environ = envinit;
286: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
287: strncat(shell, pwd->pw_shell, sizeof(shell)-7);
288: strncat(username, pwd->pw_name, sizeof(username)-6);
289: cp = rindex(pwd->pw_shell, '/');
290: if (cp)
291: cp++;
292: else
293: cp = pwd->pw_shell;
294: execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
295: perror(pwd->pw_shell);
296: exit(1);
297: protofail:
298: error("rsh: protocol failure detected by remote\n");
299: exit(1);
300: }
301:
302: /* VARARGS 1 */
303: error(fmt)
304: char *fmt;
305: {
306: char buf[BUFSIZ];
307:
308: buf[0] = 1;
309: (void) sprintf(buf+1, fmt);
310: (void) write(2, buf, strlen(buf));
311: }
312:
313: getstr(buf, cnt, err)
314: char *buf;
315: int cnt;
316: char *err;
317: {
318: char c;
319:
320: do {
321: if (read(0, &c, 1) != 1)
322: exit(1);
323: *buf++ = c;
324: if (--cnt == 0) {
325: error("%s too long\n", err);
326: exit(1);
327: }
328: } while (c != 0);
329: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.