source: trunk/minix/commands/simple/in.rshd.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 8.6 KB
Line 
1/*
2in.rshd.c
3*/
4
5/*
6 main channel:
7
8 back channel\0
9 remuser\0
10 locuser\0
11 command\0
12 data
13
14 back channel:
15 signal\0
16
17*/
18
19#include <sys/types.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <limits.h>
23#include <pwd.h>
24#include <grp.h>
25#include <signal.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include <sys/ioctl.h>
31#include <net/gen/in.h>
32#include <net/gen/inet.h>
33#include <net/gen/netdb.h>
34#include <net/gen/socket.h>
35#include <net/gen/tcp.h>
36#include <net/gen/tcp_io.h>
37#include <net/hton.h>
38#include <net/netlib.h>
39
40#define DEBUG 0
41
42#if DEBUG
43#define where() fprintf(stderr, "%s, %d: ", __FILE__, __LINE__)
44#endif
45
46char cmdbuf[_POSIX_ARG_MAX+1], locuser[16], remuser[16];
47extern char **environ;
48char username[20]="USER=";
49char homedir[64]="HOME=";
50char shell[64]="SHELL=";
51char tz[1024]="TZ=";
52char *envinit[]= {homedir, shell, username, tz, "PATH=:/bin:/usr/bin", 0};
53char *prog_name;
54char buffer[PIPE_BUF];
55
56#if __STDC__
57#define PROTO(func, args) func args
58#else
59#define PROTO(func, args) func ()
60#endif
61
62PROTO (int main, (int argc, char *argv[]));
63PROTO (void getstr, (char*buf, int cnt, char *err));
64PROTO (void close_on_exec, (int fd));
65
66int main(argc, argv)
67int argc;
68char *argv[];
69{
70 int result, result1;
71 nwio_tcpconf_t tcpconf, err_tcpconf;
72 nwio_tcpcl_t tcpconnopt;
73 nwio_tcpatt_t tcpattachopt;
74 tcpport_t tcpport;
75 tcpport_t err_port;
76 int err_fd, pds[2];
77 pid_t pid, pid1, new_pg;
78#if USEATTACH
79 int err2_fd;
80#endif
81 struct passwd *pwent;
82 char *cp, *buff_ptr, *TZ;
83 char sig;
84
85 prog_name= argv[0];
86 if (argc != 1)
87 {
88 fprintf(stderr, "%s: wrong number of arguments (%d)\n",
89 prog_name, argc);
90 exit(1);
91 }
92
93 signal(SIGINT, SIG_DFL);
94 signal(SIGQUIT, SIG_DFL);
95 signal(SIGTERM, SIG_DFL);
96
97#if DEBUG
98 { where(); fprintf(stderr, "\n"); }
99#endif
100 result= ioctl (0, NWIOGTCPCONF, &tcpconf);
101 if (result<0)
102 {
103 fprintf(stderr, "%s: ioctl(NWIOGTCPCONF)= %d : %s\n",
104 prog_name, errno, strerror(errno));
105 exit(1);
106 }
107#if DEBUG
108 { where(); fprintf(stderr, "\n"); }
109#endif
110
111 tcpport= ntohs(tcpconf.nwtc_remport);
112 if (tcpport >= TCPPORT_RESERVED || tcpport < TCPPORT_RESERVED/2)
113 {
114 printf("\1%s: unprotected port (%d)\n", prog_name, tcpport);
115 exit(1);
116 }
117 alarm(60);
118 err_port= 0;
119 for (;;)
120 {
121 char c;
122 result= read(0, &c, 1);
123 if (result <0)
124 {
125 fprintf(stderr, "%s: read= %d : %s\n", prog_name,
126 errno, strerror(errno));
127 }
128 if (result<1)
129 exit(1);
130 if (c == 0)
131 break;
132 err_port= err_port*10 + c - '0';
133 }
134 alarm(0);
135 if (err_port != 0)
136 {
137 int n, pid, lport;
138
139 pid= getpid();
140 lport= 1;
141 do {
142 lport= (lport << 1) | (pid & 1);
143 pid >>= 1;
144 } while (lport < TCPPORT_RESERVED/2);
145
146 n= TCPPORT_RESERVED/2;
147 do
148 {
149 if (--lport < TCPPORT_RESERVED/2)
150 lport= TCPPORT_RESERVED-1;
151 err_fd= open ("/dev/tcp", O_RDWR);
152 if (err_fd<0)
153 {
154 fprintf(stderr, "%s: open= %d : %s\n",
155 prog_name, errno, strerror(errno));
156 exit(1);
157 }
158 close_on_exec(err_fd);
159 err_tcpconf.nwtc_flags= NWTC_LP_SET | NWTC_SET_RA |
160 NWTC_SET_RP | NWTC_EXCL;
161 err_tcpconf.nwtc_locport= htons(lport);
162 err_tcpconf.nwtc_remport= htons(err_port);
163 err_tcpconf.nwtc_remaddr= tcpconf.nwtc_remaddr;
164
165#if DEBUG
166 { where(); fprintf(stderr, "\n"); }
167#endif
168 result= ioctl (err_fd, NWIOSTCPCONF, &err_tcpconf);
169 if (result == 0) break;
170 if (errno != EADDRINUSE)
171 {
172 fprintf(stderr,
173 "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
174 prog_name, errno, strerror(errno));
175 exit(1);
176 }
177 close(err_fd);
178 } while (--n > 0);
179 if (n == 0)
180 {
181 printf("\1can't get stderr port\n");
182 exit(1);
183 }
184
185 err_tcpconf.nwtc_flags= NWTC_SHARED;
186#if DEBUG
187{ where(); fprintf(stderr, "\n"); }
188#endif
189 result= ioctl (err_fd, NWIOSTCPCONF, &err_tcpconf);
190 if (result<0)
191 {
192 fprintf(stderr,
193 "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
194 prog_name, errno, strerror(errno));
195 exit(1);
196 }
197#if DEBUG
198{ where(); fprintf(stderr, "\n"); }
199#endif
200 tcpconnopt.nwtcl_flags= 0;
201
202 n= 20;
203 for (;;)
204 {
205#if DEBUG
206{ where(); fprintf(stderr, "\n"); }
207#endif
208 result= ioctl (err_fd, NWIOTCPCONN, &tcpconnopt);
209 if (result == 0) break;
210 if (errno != EAGAIN && errno != ECONNREFUSED)
211 {
212 fprintf(stderr,
213 "%s: ioctl(NWIOTCPCONN)= %d : %s\n",
214 prog_name, errno, strerror(errno));
215 exit(1);
216 }
217 if (--n == 0) break;
218 sleep(1);
219#if DEBUG
220{ where(); fprintf(stderr, "\n"); }
221#endif
222 }
223#if USEATTACH
224 err2_fd= open ("/dev/tcp", O_RDWR);
225 close_on_exec(err2_fd);
226 if (err2_fd<0)
227 {
228 fprintf(stderr, "%s: open= %d : %s\n", errno,
229 prog_name, strerror(errno));
230 exit(1);
231 }
232#if DEBUG
233 { where(); fprintf(stderr, "\n"); }
234#endif
235 result= ioctl (err2_fd, NWIOSTCPCONF, &err_tcpconf);
236 if (result<0)
237 {
238 fprintf(stderr, "%s: ioctl(NWIOSTCPCONF)= %d : %s\n",
239 prog_name, errno, strerror(errno));
240 exit(1);
241 }
242#if DEBUG
243 { where(); fprintf(stderr, "\n"); }
244#endif
245 tcpattachopt.nwta_flags= 0;
246#if DEBUG
247 { where(); fprintf(stderr, "\n"); }
248#endif
249 result= ioctl (err2_fd, NWIOTCPATTACH, &tcpattachopt);
250 if (result<0)
251 {
252 fprintf(stderr, "%s: ioctl(NWIOTCPATTACH)= %d : %s\n",
253 prog_name, errno, strerror(errno));
254 exit(1);
255 }
256#if DEBUG
257 { where(); fprintf(stderr, "\n"); }
258#endif
259#endif
260 }
261 getstr(remuser, sizeof(remuser), "remuser");
262 getstr(locuser, sizeof(locuser), "locuser");
263 getstr(cmdbuf, sizeof(cmdbuf), "cmdbuf");
264 setpwent();
265 pwent= getpwnam(locuser);
266 if (!pwent)
267 {
268 printf("\1Login incorrect.\n");
269 exit(1);
270 }
271 endpwent();
272 if (chdir(pwent->pw_dir) < 0)
273 {
274 chdir("/");
275 }
276#if DEBUG
277 { where(); fprintf(stderr, "calling iruserok(%s, %d, %s, %s)\n",
278 inet_ntoa(tcpconf.nwtc_remaddr), 0, remuser, locuser); }
279#endif
280 if (iruserok(tcpconf.nwtc_remaddr, 0, remuser, locuser) < 0)
281 {
282 printf("\1Permission denied.\n");
283 exit(1);
284 }
285 if (err_port)
286 {
287 /* Let's go to a different process group. */
288 new_pg= setsid();
289 pid= fork();
290 if (pid<0)
291 {
292 if (errno != EAGAIN)
293 {
294 fprintf(stderr, "%s: fork()= %d : %s\n",
295 prog_name, errno, strerror(errno));
296 }
297 printf("\1Try again.\n");
298 exit(1);
299 }
300 if (pid)
301 {
302 close(0); /* stdin */
303 close(1); /* stdout */
304#if USEATTACH
305 close(err_fd); /* stderr for shell */
306#endif
307 dup2(2,0);
308 dup2(2,1);
309 for (;;)
310 {
311#if !USEATTACH
312 if (read(err_fd, &sig, 1) <= 0)
313#else
314 if (read(err2_fd, &sig, 1) <= 0)
315#endif
316 {
317#if 0
318 printf("read failed: %d\n", errno);
319#endif
320 exit(0);
321 }
322 pid= 0;
323#if 0
324 printf("killing %d with %d\n", -new_pg, sig);
325#endif
326 kill(-new_pg, sig);
327 }
328 }
329#if USEATTACH
330 close(err2_fd); /* signal channel for parent */
331#endif
332 result= pipe(pds);
333 if (result<0)
334 {
335 printf("\1Can't make pipe\n");
336 kill(getppid(), SIGTERM);
337 exit(1);
338 }
339 pid1= fork();
340 if (pid1<0)
341 {
342 if (errno != EAGAIN)
343 {
344 fprintf(stderr, "%s: fork()= %d : %s\n",
345 prog_name, errno, strerror(errno));
346 }
347 printf("\1Try again.\n");
348 kill(-new_pg, SIGTERM);
349 exit(1);
350 }
351 if (pid1)
352 {
353 close(pds[1]); /* write side of pipe */
354 for (;;)
355 {
356 result= read(pds[0], buffer, sizeof(buffer));
357 if (result<=0)
358 {
359 kill(pid, SIGTERM);
360 exit(0);
361 }
362 buff_ptr= buffer;
363 while (result>0)
364 {
365 result1= write (err_fd, buff_ptr,
366 result);
367 if (result1 <= 0)
368 {
369 fprintf(stderr,
370 "%s: write()= %d : %s\n",
371 prog_name, errno,
372 strerror(errno));
373 kill(-new_pg, SIGTERM);
374 exit(1);
375 }
376 result -= result1;
377 }
378 }
379 }
380 close(err_fd); /* file descriptor for error channel */
381 close (pds[0]); /* read side of pipe */
382 dup2(pds[1], 2);
383 close (pds[1]); /* write side of pipe */
384 }
385 if (*pwent->pw_shell == '\0')
386 pwent->pw_shell= "/bin/sh";
387#if __minix_vmd
388 initgroups(pwent->pw_name, pwent->pw_gid);
389#endif
390 setgid(pwent->pw_gid);
391 setuid(pwent->pw_uid);
392 TZ=getenv("TZ");
393 environ= envinit;
394 strncat(homedir, pwent->pw_dir, sizeof(homedir)-6);
395 strncat(shell, pwent->pw_shell, sizeof(shell)-7);
396 strncat(username, pwent->pw_name, sizeof(username)-6);
397 if (TZ)
398 strncat(tz, TZ, sizeof(tz)-4);
399 else
400 envinit[3]= NULL;
401
402 cp= strrchr(pwent->pw_shell, '/');
403 if (cp)
404 cp++;
405 else
406 cp= pwent->pw_shell;
407
408 if (!err_port)
409 dup2(1, 2);
410 write(1, "\0", 1);
411
412 execl(pwent->pw_shell, cp, "-c", cmdbuf, 0);
413 close(2);
414 open("/dev/tty", O_RDWR);
415 fprintf(stderr, "%s: execl(%s, %s, .., %s)= %d : %s\n", prog_name,
416 pwent->pw_shell, cp, cmdbuf, errno, strerror(errno));
417 kill(getppid(), SIGTERM);
418 exit(1);
419}
420
421void getstr(buf, cnt, err)
422char *buf;
423int cnt;
424char *err;
425{
426 char c;
427
428 do
429 {
430 if (read(0, &c, 1) != 1)
431 exit(1);
432 *buf++ = c;
433 if (--cnt == 0)
434 {
435 printf("\1%s too long", err);
436 exit(1);
437 }
438 } while (c != 0);
439}
440
441void close_on_exec(fd)
442int fd;
443{
444 (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
445}
Note: See TracBrowser for help on using the repository browser.