|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)rshd.c 5.7 (Berkeley) 5/9/86";
15: #endif not lint
16:
17: /*
18: * remote shell server:
19: * remuser\0
20: * locuser\0
21: * command\0
22: * data
23: */
24: #include <sys/ioctl.h>
25: #include <sys/param.h>
26: #include <sys/socket.h>
27: #include <sys/time.h>
28:
29: #include <netinet/in.h>
30:
31: #include <arpa/inet.h>
32:
33: #include <stdio.h>
34: #include <errno.h>
35: #include <pwd.h>
36: #include <signal.h>
37: #include <netdb.h>
38: #include <syslog.h>
39:
40: int errno;
41: char *index(), *rindex(), *strncat();
42: /*VARARGS1*/
43: int error();
44:
45: /*ARGSUSED*/
46: main(argc, argv)
47: int argc;
48: char **argv;
49: {
50: struct linger linger;
51: int on = 1, fromlen;
52: struct sockaddr_in from;
53:
54: openlog("rsh", LOG_PID | LOG_ODELAY, LOG_DAEMON);
55: fromlen = sizeof (from);
56: if (getpeername(0, &from, &fromlen) < 0) {
57: fprintf(stderr, "%s: ", argv[0]);
58: perror("getpeername");
59: _exit(1);
60: }
61: if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
62: sizeof (on)) < 0)
63: syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
64: linger.l_onoff = 1;
65: linger.l_linger = 60; /* XXX */
66: if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
67: sizeof (linger)) < 0)
68: syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
69: doit(dup(0), &from);
70: }
71:
72: char username[20] = "USER=";
73: char homedir[64] = "HOME=";
74: char shell[64] = "SHELL=";
75: char *envinit[] =
76: {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
77: char **environ;
78:
79: doit(f, fromp)
80: int f;
81: struct sockaddr_in *fromp;
82: {
83: char cmdbuf[NCARGS+1], *cp;
84: char locuser[16], remuser[16];
85: struct passwd *pwd;
86: int s;
87: struct hostent *hp;
88: char *hostname;
89: short port;
90: int pv[2], pid, ready, readfrom, cc;
91: char buf[BUFSIZ], sig;
92: int one = 1;
93:
94: (void) signal(SIGINT, SIG_DFL);
95: (void) signal(SIGQUIT, SIG_DFL);
96: (void) signal(SIGTERM, SIG_DFL);
97: #ifdef DEBUG
98: { int t = open("/dev/tty", 2);
99: if (t >= 0) {
100: ioctl(t, TIOCNOTTY, (char *)0);
101: (void) close(t);
102: }
103: }
104: #endif
105: fromp->sin_port = ntohs((u_short)fromp->sin_port);
106: if (fromp->sin_family != AF_INET ||
107: fromp->sin_port >= IPPORT_RESERVED) {
108: syslog(LOG_ERR, "malformed from address\n");
109: exit(1);
110: }
111: (void) alarm(60);
112: port = 0;
113: for (;;) {
114: char c;
115: if (read(f, &c, 1) != 1) {
116: syslog(LOG_ERR, "read: %m");
117: shutdown(f, 1+1);
118: exit(1);
119: }
120: if (c == 0)
121: break;
122: port = port * 10 + c - '0';
123: }
124: (void) alarm(0);
125: if (port != 0) {
126: int lport = IPPORT_RESERVED - 1;
127: s = rresvport(&lport);
128: if (s < 0) {
129: syslog(LOG_ERR, "can't get stderr port: %m");
130: exit(1);
131: }
132: if (port >= IPPORT_RESERVED) {
133: syslog(LOG_ERR, "2nd port not reserved\n");
134: exit(1);
135: }
136: fromp->sin_port = htons((u_short)port);
137: if (connect(s, fromp, sizeof (*fromp)) < 0) {
138: syslog(LOG_INFO, "connect second port: %m");
139: exit(1);
140: }
141: }
142: dup2(f, 0);
143: dup2(f, 1);
144: dup2(f, 2);
145: hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
146: fromp->sin_family);
147: if (hp)
148: hostname = hp->h_name;
149: else
150: hostname = inet_ntoa(fromp->sin_addr);
151: getstr(remuser, sizeof(remuser), "remuser");
152: getstr(locuser, sizeof(locuser), "locuser");
153: getstr(cmdbuf, sizeof(cmdbuf), "command");
154: setpwent();
155: pwd = getpwnam(locuser);
156: if (pwd == NULL) {
157: error("Login incorrect.\n");
158: exit(1);
159: }
160: endpwent();
161: if (chdir(pwd->pw_dir) < 0) {
162: (void) chdir("/");
163: #ifdef notdef
164: error("No remote directory.\n");
165: exit(1);
166: #endif
167: }
168: if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
169: ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
170: error("Permission denied.\n");
171: exit(1);
172: }
173: (void) write(2, "\0", 1);
174: if (port) {
175: if (pipe(pv) < 0) {
176: error("Can't make pipe.\n");
177: exit(1);
178: }
179: pid = fork();
180: if (pid == -1) {
181: error("Try again.\n");
182: exit(1);
183: }
184: if (pid) {
185: (void) close(0); (void) close(1); (void) close(2);
186: (void) close(f); (void) close(pv[1]);
187: readfrom = (1<<s) | (1<<pv[0]);
188: ioctl(pv[1], FIONBIO, (char *)&one);
189: /* should set s nbio! */
190: do {
191: ready = readfrom;
192: if (select(16, &ready, (fd_set *)0,
193: (fd_set *)0, (struct timeval *)0) < 0)
194: break;
195: if (ready & (1<<s)) {
196: if (read(s, &sig, 1) <= 0)
197: readfrom &= ~(1<<s);
198: else
199: killpg(pid, sig);
200: }
201: if (ready & (1<<pv[0])) {
202: errno = 0;
203: cc = read(pv[0], buf, sizeof (buf));
204: if (cc <= 0) {
205: shutdown(s, 1+1);
206: readfrom &= ~(1<<pv[0]);
207: } else
208: (void) write(s, buf, cc);
209: }
210: } while (readfrom);
211: exit(0);
212: }
213: setpgrp(0, getpid());
214: (void) close(s); (void) close(pv[0]);
215: dup2(pv[1], 2);
216: }
217: if (*pwd->pw_shell == '\0')
218: pwd->pw_shell = "/bin/sh";
219: (void) close(f);
220: (void) setgid((gid_t)pwd->pw_gid);
221: initgroups(pwd->pw_name, pwd->pw_gid);
222: (void) setuid((uid_t)pwd->pw_uid);
223: environ = envinit;
224: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
225: strncat(shell, pwd->pw_shell, sizeof(shell)-7);
226: strncat(username, pwd->pw_name, sizeof(username)-6);
227: cp = rindex(pwd->pw_shell, '/');
228: if (cp)
229: cp++;
230: else
231: cp = pwd->pw_shell;
232: execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
233: perror(pwd->pw_shell);
234: exit(1);
235: }
236:
237: /*VARARGS1*/
238: error(fmt, a1, a2, a3)
239: char *fmt;
240: int a1, a2, a3;
241: {
242: char buf[BUFSIZ];
243:
244: buf[0] = 1;
245: (void) sprintf(buf+1, fmt, a1, a2, a3);
246: (void) write(2, buf, strlen(buf));
247: }
248:
249: getstr(buf, cnt, err)
250: char *buf;
251: int cnt;
252: char *err;
253: {
254: char c;
255:
256: do {
257: if (read(0, &c, 1) != 1)
258: exit(1);
259: *buf++ = c;
260: if (--cnt == 0) {
261: error("%s too long\n", err);
262: exit(1);
263: }
264: } while (c != 0);
265: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.