|
|
1.1 root 1: /*-
2: * Copyright (c) 1983, 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)rsh.c 5.23.1.1 (Berkeley) 10/21/90";
28: #endif /* not lint */
29:
30: /*
31: * $Source: mit/rsh/RCS/rsh.c,v $
32: * $Header: mit/rsh/RCS/rsh.c,v 5.1 89/07/31 19:28:59 kfall Exp Locker: kfall $
33: */
34:
35: #include <sys/types.h>
36: #include <sys/signal.h>
37: #include <sys/socket.h>
38: #include <sys/ioctl.h>
39: #include <sys/file.h>
40:
41: #include <netinet/in.h>
42: #include <netdb.h>
43:
44: #include <pwd.h>
45: #include <stdio.h>
46: #include <errno.h>
47: #include <string.h>
48: #include <varargs.h>
49: #include "pathnames.h"
50:
51: #ifdef KERBEROS
52: #include <kerberosIV/des.h>
53: #include <kerberosIV/krb.h>
54:
55: CREDENTIALS cred;
56: Key_schedule schedule;
57: int use_kerberos = 1, encrypt;
58: char dst_realm_buf[REALM_SZ], *dest_realm;
59: extern char *krb_realmofhost();
60: #endif
61:
62: /*
63: * rsh - remote shell
64: */
65: extern int errno;
66: int rfd2;
67:
68: main(argc, argv)
69: int argc;
70: char **argv;
71: {
72: extern char *optarg;
73: extern int optind;
74: struct passwd *pw;
75: struct servent *sp;
76: long omask;
77: int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid;
78: register char *p;
79: char *args, *host, *user, *copyargs();
80: void sendsig();
81:
82: argoff = asrsh = dflag = nflag = 0;
83: one = 1;
84: host = user = NULL;
85:
86: /* if called as something other than "rsh", use it as the host name */
87: if (p = rindex(argv[0], '/'))
88: ++p;
89: else
90: p = argv[0];
91: if (strcmp(p, "rsh"))
92: host = p;
93: else
94: asrsh = 1;
95:
96: /* handle "rsh host flags" */
97: if (!host && argc > 2 && argv[1][0] != '-') {
98: host = argv[1];
99: argoff = 1;
100: }
101:
102: #ifdef KERBEROS
103: #define OPTIONS "8KLdek:l:nw"
104: #else
105: #define OPTIONS "8KLdel:nw"
106: #endif
107: while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
108: switch(ch) {
109: case 'K':
110: #ifdef KERBEROS
111: use_kerberos = 0;
112: #endif
113: break;
114: case 'L': /* -8Lew are ignored to allow rlogin aliases */
115: case 'e':
116: case 'w':
117: case '8':
118: break;
119: case 'd':
120: dflag = 1;
121: break;
122: case 'l':
123: user = optarg;
124: break;
125: #ifdef KERBEROS
126: case 'k':
127: dest_realm = dst_realm_buf;
128: strncpy(dest_realm, optarg, REALM_SZ);
129: break;
130: #endif
131: case 'n':
132: nflag = 1;
133: break;
134: #ifdef KERBEROS
135: #endif
136: case '?':
137: default:
138: usage();
139: }
140: optind += argoff;
141:
142: /* if haven't gotten a host yet, do so */
143: if (!host && !(host = argv[optind++]))
144: usage();
145:
146: /* if no further arguments, must have been called as rlogin. */
147: if (!argv[optind]) {
148: if (asrsh)
149: *argv = "rlogin";
150: execv(_PATH_RLOGIN, argv);
151: (void)fprintf(stderr, "rsh: can't exec %s.\n", _PATH_RLOGIN);
152: exit(1);
153: }
154:
155: argc -= optind;
156: argv += optind;
157:
158: if (!(pw = getpwuid(uid = getuid()))) {
159: (void)fprintf(stderr, "rsh: unknown user id.\n");
160: exit(1);
161: }
162: if (!user)
163: user = pw->pw_name;
164:
165: #ifdef KERBEROS
166: #endif
167:
168: args = copyargs(argv);
169:
170: sp = NULL;
171: #ifdef KERBEROS
172: if (use_kerberos) {
173: sp = getservbyname((encrypt ? "ekshell" : "kshell"), "tcp");
174: if (sp == NULL) {
175: use_kerberos = 0;
176: warning("can't get entry for %s/tcp service",
177: encrypt ? "ekshell" : "kshell");
178: }
179: }
180: #endif
181: if (sp == NULL)
182: sp = getservbyname("shell", "tcp");
183: if (sp == NULL) {
184: (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
185: exit(1);
186: }
187:
188: #ifdef KERBEROS
189: try_connect:
190: if (use_kerberos) {
191: rem = KSUCCESS;
192: errno = 0;
193: if (dest_realm == NULL)
194: dest_realm = krb_realmofhost(host);
195:
196: rem = krcmd(&host, sp->s_port, user, args, &rfd2,
197: dest_realm);
198: if (rem < 0) {
199: use_kerberos = 0;
200: sp = getservbyname("shell", "tcp");
201: if (sp == NULL) {
202: (void)fprintf(stderr,
203: "rsh: unknown service shell/tcp.\n");
204: exit(1);
205: }
206: if (errno == ECONNREFUSED)
207: warning("remote host doesn't support Kerberos");
208: if (errno == ENOENT)
209: warning("can't provide Kerberos auth data");
210: goto try_connect;
211: }
212: } else {
213: if (encrypt) {
214: (void)fprintf(stderr,
215: "rsh: the -x flag requires Kerberos authentication.\n");
216: exit(1);
217: }
218: rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
219: }
220: #else
221: rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
222: #endif
223:
224: if (rem < 0)
225: exit(1);
226:
227: if (rfd2 < 0) {
228: (void)fprintf(stderr, "rsh: can't establish stderr.\n");
229: exit(1);
230: }
231: if (dflag) {
232: if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
233: sizeof(one)) < 0)
234: (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
235: strerror(errno));
236: if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
237: sizeof(one)) < 0)
238: (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
239: strerror(errno));
240: }
241:
242: (void)setuid(uid);
243: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
244: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
245: (void)signal(SIGINT, sendsig);
246: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
247: (void)signal(SIGQUIT, sendsig);
248: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
249: (void)signal(SIGTERM, sendsig);
250:
251: if (!nflag) {
252: pid = fork();
253: if (pid < 0) {
254: (void)fprintf(stderr,
255: "rsh: fork: %s.\n", strerror(errno));
256: exit(1);
257: }
258: }
259:
260: #ifdef KERBEROS
261: #endif
262: {
263: (void)ioctl(rfd2, FIONBIO, &one);
264: (void)ioctl(rem, FIONBIO, &one);
265: }
266:
267: talk(nflag, omask, pid, rem);
268:
269: if (!nflag)
270: (void)kill(pid, SIGKILL);
271: exit(0);
272: }
273:
274: talk(nflag, omask, pid, rem)
275: int nflag, pid;
276: long omask;
277: register int rem;
278: {
279: register int cc, wc;
280: register char *bp;
281: int readfrom, ready, rembits;
282: char buf[BUFSIZ];
283:
284: if (!nflag && pid == 0) {
285: (void)close(rfd2);
286:
287: reread: errno = 0;
288: if ((cc = read(0, buf, sizeof buf)) <= 0)
289: goto done;
290: bp = buf;
291:
292: rewrite: rembits = 1 << rem;
293: if (select(16, 0, &rembits, 0, 0) < 0) {
294: if (errno != EINTR) {
295: (void)fprintf(stderr,
296: "rsh: select: %s.\n", strerror(errno));
297: exit(1);
298: }
299: goto rewrite;
300: }
301: if ((rembits & (1 << rem)) == 0)
302: goto rewrite;
303: #ifdef KERBEROS
304: #endif
305: wc = write(rem, bp, cc);
306: if (wc < 0) {
307: if (errno == EWOULDBLOCK)
308: goto rewrite;
309: goto done;
310: }
311: bp += wc;
312: cc -= wc;
313: if (cc == 0)
314: goto reread;
315: goto rewrite;
316: done:
317: (void)shutdown(rem, 1);
318: exit(0);
319: }
320:
321: (void)sigsetmask(omask);
322: readfrom = (1 << rfd2) | (1 << rem);
323: do {
324: ready = readfrom;
325: if (select(16, &ready, 0, 0, 0) < 0) {
326: if (errno != EINTR) {
327: (void)fprintf(stderr,
328: "rsh: select: %s.\n", strerror(errno));
329: exit(1);
330: }
331: continue;
332: }
333: if (ready & (1 << rfd2)) {
334: errno = 0;
335: #ifdef KERBEROS
336: #endif
337: cc = read(rfd2, buf, sizeof buf);
338: if (cc <= 0) {
339: if (errno != EWOULDBLOCK)
340: readfrom &= ~(1 << rfd2);
341: } else
342: (void)write(2, buf, cc);
343: }
344: if (ready & (1 << rem)) {
345: errno = 0;
346: #ifdef KERBEROS
347: #endif
348: cc = read(rem, buf, sizeof buf);
349: if (cc <= 0) {
350: if (errno != EWOULDBLOCK)
351: readfrom &= ~(1 << rem);
352: } else
353: (void)write(1, buf, cc);
354: }
355: } while (readfrom);
356: }
357:
358: void
359: sendsig(signo)
360: char signo;
361: {
362: #ifdef KERBEROS
363: #endif
364: (void)write(rfd2, &signo, 1);
365: }
366:
367: #ifdef KERBEROS
368: /* VARARGS */
369: warning(va_alist)
370: va_dcl
371: {
372: va_list ap;
373: char *fmt;
374:
375: (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
376: va_start(ap);
377: fmt = va_arg(ap, char *);
378: vfprintf(stderr, fmt, ap);
379: va_end(ap);
380: (void)fprintf(stderr, ".\n");
381: }
382: #endif
383:
384: char *
385: copyargs(argv)
386: char **argv;
387: {
388: register int cc;
389: register char **ap, *p;
390: char *args, *malloc();
391:
392: cc = 0;
393: for (ap = argv; *ap; ++ap)
394: cc += strlen(*ap) + 1;
395: if (!(args = malloc((u_int)cc))) {
396: (void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
397: exit(1);
398: }
399: for (p = args, ap = argv; *ap; ++ap) {
400: (void)strcpy(p, *ap);
401: for (p = strcpy(p, *ap); *p; ++p);
402: if (ap[1])
403: *p++ = ' ';
404: }
405: return(args);
406: }
407:
408: usage()
409: {
410: (void)fprintf(stderr,
411: "usage: rsh [-nd%s]%s[-l login] host [command]\n",
412: #ifdef KERBEROS
413: "", " [-k realm] ");
414: #else
415: "", " ");
416: #endif
417: exit(1);
418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.