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