create errors directory if DNE
[unix-history] / usr / src / libexec / rshd / rshd.c
CommitLineData
8c5eec2f
DF
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
8char copyright[] =
9"@(#) Copyright (c) 1983 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
1d68cba5 13#ifndef lint
c9db37f1 14static char sccsid[] = "@(#)rshd.c 5.9 (Berkeley) %G%";
8c5eec2f 15#endif not lint
1d68cba5 16
bb933cc2
MK
17/*
18 * remote shell server:
19 * remuser\0
20 * locuser\0
21 * command\0
22 * data
23 */
1d68cba5
BJ
24#include <sys/ioctl.h>
25#include <sys/param.h>
26#include <sys/socket.h>
c9db37f1 27#include <sys/file.h>
d4413a13 28#include <sys/time.h>
e7d6d17a
SL
29
30#include <netinet/in.h>
31
4c99408e
JB
32#include <arpa/inet.h>
33
e7d6d17a 34#include <stdio.h>
1d68cba5
BJ
35#include <errno.h>
36#include <pwd.h>
1d68cba5 37#include <signal.h>
3f5b52bc 38#include <netdb.h>
3f99c0f7 39#include <syslog.h>
1d68cba5
BJ
40
41int errno;
d4413a13
JL
42char *index(), *rindex(), *strncat();
43/*VARARGS1*/
1d68cba5 44int error();
bb933cc2 45
d4413a13 46/*ARGSUSED*/
1d68cba5
BJ
47main(argc, argv)
48 int argc;
49 char **argv;
50{
bcb894cb
SL
51 struct linger linger;
52 int on = 1, fromlen;
1d68cba5 53 struct sockaddr_in from;
3f5b52bc 54
076ae92c 55 openlog("rsh", LOG_PID | LOG_ODELAY, LOG_DAEMON);
bb933cc2
MK
56 fromlen = sizeof (from);
57 if (getpeername(0, &from, &fromlen) < 0) {
58 fprintf(stderr, "%s: ", argv[0]);
59 perror("getpeername");
60 _exit(1);
3f5b52bc 61 }
d4413a13
JL
62 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
63 sizeof (on)) < 0)
3f99c0f7 64 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
bcb894cb
SL
65 linger.l_onoff = 1;
66 linger.l_linger = 60; /* XXX */
d4413a13
JL
67 if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
68 sizeof (linger)) < 0)
3f99c0f7 69 syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
bb933cc2 70 doit(dup(0), &from);
a8e3386b
SL
71}
72
1d68cba5
BJ
73char username[20] = "USER=";
74char homedir[64] = "HOME=";
75char shell[64] = "SHELL=";
76char *envinit[] =
77 {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
78char **environ;
79
80doit(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;
d4413a13 87 int s;
3f5b52bc 88 struct hostent *hp;
7ad57ed0 89 char *hostname;
1d68cba5
BJ
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);
27890867 98#ifdef DEBUG
1d68cba5
BJ
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
1d68cba5 106 fromp->sin_port = ntohs((u_short)fromp->sin_port);
1d68cba5 107 if (fromp->sin_family != AF_INET ||
d173f55d 108 fromp->sin_port >= IPPORT_RESERVED) {
3f99c0f7 109 syslog(LOG_ERR, "malformed from address\n");
1d68cba5 110 exit(1);
d173f55d 111 }
1d68cba5
BJ
112 (void) alarm(60);
113 port = 0;
114 for (;;) {
115 char c;
d173f55d 116 if (read(f, &c, 1) != 1) {
3f99c0f7 117 syslog(LOG_ERR, "read: %m");
fadc6b8f 118 shutdown(f, 1+1);
1d68cba5 119 exit(1);
d173f55d 120 }
1d68cba5
BJ
121 if (c == 0)
122 break;
123 port = port * 10 + c - '0';
124 }
125 (void) alarm(0);
126 if (port != 0) {
d4413a13 127 int lport = IPPORT_RESERVED - 1;
3b0e7dec 128 s = rresvport(&lport);
d173f55d 129 if (s < 0) {
3f99c0f7 130 syslog(LOG_ERR, "can't get stderr port: %m");
d173f55d
SL
131 exit(1);
132 }
133 if (port >= IPPORT_RESERVED) {
3f99c0f7 134 syslog(LOG_ERR, "2nd port not reserved\n");
1d68cba5 135 exit(1);
d173f55d 136 }
e23c0837 137 fromp->sin_port = htons((u_short)port);
d4413a13 138 if (connect(s, fromp, sizeof (*fromp)) < 0) {
7ad57ed0 139 syslog(LOG_INFO, "connect second port: %m");
1d68cba5 140 exit(1);
d173f55d 141 }
1d68cba5 142 }
d173f55d
SL
143 dup2(f, 0);
144 dup2(f, 1);
145 dup2(f, 2);
d4413a13 146 hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
3f5b52bc 147 fromp->sin_family);
7ad57ed0
MK
148 if (hp)
149 hostname = hp->h_name;
150 else
151 hostname = inet_ntoa(fromp->sin_addr);
1d68cba5
BJ
152 getstr(remuser, sizeof(remuser), "remuser");
153 getstr(locuser, sizeof(locuser), "locuser");
154 getstr(cmdbuf, sizeof(cmdbuf), "command");
155 setpwent();
156 pwd = getpwnam(locuser);
157 if (pwd == NULL) {
158 error("Login incorrect.\n");
159 exit(1);
160 }
161 endpwent();
162 if (chdir(pwd->pw_dir) < 0) {
d4413a13 163 (void) chdir("/");
bb933cc2 164#ifdef notdef
1d68cba5
BJ
165 error("No remote directory.\n");
166 exit(1);
bb933cc2 167#endif
1d68cba5 168 }
792e68a4 169 if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
7ad57ed0 170 ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
1d68cba5
BJ
171 error("Permission denied.\n");
172 exit(1);
173 }
c9db37f1
KB
174 if (!access("/etc/nologin", F_OK)) {
175 error("Logins currently disabled.\n");
176 exit(1);
177 }
1d68cba5
BJ
178 (void) write(2, "\0", 1);
179 if (port) {
180 if (pipe(pv) < 0) {
181 error("Can't make pipe.\n");
182 exit(1);
183 }
184 pid = fork();
185 if (pid == -1) {
186 error("Try again.\n");
187 exit(1);
188 }
189 if (pid) {
190 (void) close(0); (void) close(1); (void) close(2);
191 (void) close(f); (void) close(pv[1]);
192 readfrom = (1<<s) | (1<<pv[0]);
71419d2d 193 ioctl(pv[0], FIONBIO, (char *)&one);
1d68cba5
BJ
194 /* should set s nbio! */
195 do {
196 ready = readfrom;
d4413a13
JL
197 if (select(16, &ready, (fd_set *)0,
198 (fd_set *)0, (struct timeval *)0) < 0)
e7d6d17a 199 break;
1d68cba5
BJ
200 if (ready & (1<<s)) {
201 if (read(s, &sig, 1) <= 0)
202 readfrom &= ~(1<<s);
203 else
204 killpg(pid, sig);
205 }
206 if (ready & (1<<pv[0])) {
fadc6b8f 207 errno = 0;
1d68cba5
BJ
208 cc = read(pv[0], buf, sizeof (buf));
209 if (cc <= 0) {
ff24c640 210 shutdown(s, 1+1);
1d68cba5
BJ
211 readfrom &= ~(1<<pv[0]);
212 } else
213 (void) write(s, buf, cc);
214 }
215 } while (readfrom);
216 exit(0);
217 }
218 setpgrp(0, getpid());
219 (void) close(s); (void) close(pv[0]);
220 dup2(pv[1], 2);
221 }
222 if (*pwd->pw_shell == '\0')
223 pwd->pw_shell = "/bin/sh";
224 (void) close(f);
d4413a13 225 (void) setgid((gid_t)pwd->pw_gid);
80aca4ff 226 initgroups(pwd->pw_name, pwd->pw_gid);
d4413a13 227 (void) setuid((uid_t)pwd->pw_uid);
1d68cba5
BJ
228 environ = envinit;
229 strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
230 strncat(shell, pwd->pw_shell, sizeof(shell)-7);
231 strncat(username, pwd->pw_name, sizeof(username)-6);
232 cp = rindex(pwd->pw_shell, '/');
233 if (cp)
234 cp++;
235 else
236 cp = pwd->pw_shell;
237 execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
238 perror(pwd->pw_shell);
239 exit(1);
1d68cba5
BJ
240}
241
d4413a13 242/*VARARGS1*/
35db6ea0 243error(fmt, a1, a2, a3)
1d68cba5 244 char *fmt;
35db6ea0 245 int a1, a2, a3;
1d68cba5
BJ
246{
247 char buf[BUFSIZ];
248
249 buf[0] = 1;
35db6ea0 250 (void) sprintf(buf+1, fmt, a1, a2, a3);
1d68cba5
BJ
251 (void) write(2, buf, strlen(buf));
252}
253
254getstr(buf, cnt, err)
255 char *buf;
256 int cnt;
257 char *err;
258{
259 char c;
260
261 do {
262 if (read(0, &c, 1) != 1)
263 exit(1);
264 *buf++ = c;
265 if (--cnt == 0) {
266 error("%s too long\n", err);
267 exit(1);
268 }
269 } while (c != 0);
270}