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