|
|
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
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF 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.21 (Berkeley) 5/15/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:nwx"
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: case 'x':
136: encrypt = 1;
137: des_set_key(cred.session, schedule);
138: break;
139: #endif
140: case '?':
141: default:
142: usage();
143: }
144: optind += argoff;
145:
146: /* if haven't gotten a host yet, do so */
147: if (!host && !(host = argv[optind++]))
148: usage();
149:
150: /* if no further arguments, must have been called as rlogin. */
151: if (!argv[optind]) {
152: if (asrsh)
153: *argv = "rlogin";
154: execv(_PATH_RLOGIN, argv);
155: (void)fprintf(stderr, "rsh: can't exec %s.\n", _PATH_RLOGIN);
156: exit(1);
157: }
158:
159: argc -= optind;
160: argv += optind;
161:
162: if (!(pw = getpwuid(uid = getuid()))) {
163: (void)fprintf(stderr, "rsh: unknown user id.\n");
164: exit(1);
165: }
166: if (!user)
167: user = pw->pw_name;
168:
169: #ifdef KERBEROS
170: /* -x turns off -n */
171: if (encrypt)
172: nflag = 0;
173: #endif
174:
175: args = copyargs(argv);
176:
177: sp = NULL;
178: #ifdef KERBEROS
179: if (use_kerberos) {
180: sp = getservbyname((encrypt ? "ekshell" : "kshell"), "tcp");
181: if (sp == NULL) {
182: use_kerberos = 0;
183: warning("can't get entry for %s/tcp service",
184: encrypt ? "ekshell" : "kshell");
185: }
186: }
187: #endif
188: if (sp == NULL)
189: sp = getservbyname("shell", "tcp");
190: if (sp == NULL) {
191: (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
192: exit(1);
193: }
194:
195: #ifdef KERBEROS
196: try_connect:
197: if (use_kerberos) {
198: rem = KSUCCESS;
199: errno = 0;
200: if (dest_realm == NULL)
201: dest_realm = krb_realmofhost(host);
202:
203: if (encrypt)
204: rem = krcmd_mutual(&host, sp->s_port, user, args,
205: &rfd2, dest_realm, &cred, schedule);
206: else
207: rem = krcmd(&host, sp->s_port, user, args, &rfd2,
208: dest_realm);
209: if (rem < 0) {
210: use_kerberos = 0;
211: sp = getservbyname("shell", "tcp");
212: if (sp == NULL) {
213: (void)fprintf(stderr,
214: "rsh: unknown service shell/tcp.\n");
215: exit(1);
216: }
217: if (errno == ECONNREFUSED)
218: warning("remote host doesn't support Kerberos");
219: if (errno == ENOENT)
220: warning("can't provide Kerberos auth data");
221: goto try_connect;
222: }
223: } else {
224: if (encrypt) {
225: (void)fprintf(stderr,
226: "rsh: the -x flag requires Kerberos authentication.\n");
227: exit(1);
228: }
229: rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
230: }
231: #else
232: rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
233: #endif
234:
235: if (rem < 0)
236: exit(1);
237:
238: if (rfd2 < 0) {
239: (void)fprintf(stderr, "rsh: can't establish stderr.\n");
240: exit(1);
241: }
242: if (dflag) {
243: if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
244: sizeof(one)) < 0)
245: (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
246: strerror(errno));
247: if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
248: sizeof(one)) < 0)
249: (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
250: strerror(errno));
251: }
252:
253: (void)setuid(uid);
254: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
255: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
256: (void)signal(SIGINT, sendsig);
257: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
258: (void)signal(SIGQUIT, sendsig);
259: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
260: (void)signal(SIGTERM, sendsig);
261:
262: if (!nflag) {
263: pid = fork();
264: if (pid < 0) {
265: (void)fprintf(stderr,
266: "rsh: fork: %s.\n", strerror(errno));
267: exit(1);
268: }
269: }
270:
271: #ifdef KERBEROS
272: if (!encrypt)
273: #endif
274: {
275: (void)ioctl(rfd2, FIONBIO, &one);
276: (void)ioctl(rem, FIONBIO, &one);
277: }
278:
279: talk(nflag, omask, pid, rem);
280:
281: if (!nflag)
282: (void)kill(pid, SIGKILL);
283: exit(0);
284: }
285:
286: talk(nflag, omask, pid, rem)
287: int nflag, pid;
288: long omask;
289: register int rem;
290: {
291: register int cc, wc;
292: register char *bp;
293: int readfrom, ready, rembits;
294: char buf[BUFSIZ];
295:
296: if (!nflag && pid == 0) {
297: (void)close(rfd2);
298:
299: reread: errno = 0;
300: if ((cc = read(0, buf, sizeof buf)) <= 0)
301: goto done;
302: bp = buf;
303:
304: rewrite: rembits = 1 << rem;
305: if (select(16, 0, &rembits, 0, 0) < 0) {
306: if (errno != EINTR) {
307: (void)fprintf(stderr,
308: "rsh: select: %s.\n", strerror(errno));
309: exit(1);
310: }
311: goto rewrite;
312: }
313: if ((rembits & (1 << rem)) == 0)
314: goto rewrite;
315: #ifdef KERBEROS
316: if (encrypt)
317: wc = des_write(rem, bp, cc);
318: else
319: #endif
320: wc = write(rem, bp, cc);
321: if (wc < 0) {
322: if (errno == EWOULDBLOCK)
323: goto rewrite;
324: goto done;
325: }
326: bp += wc;
327: cc -= wc;
328: if (cc == 0)
329: goto reread;
330: goto rewrite;
331: done:
332: (void)shutdown(rem, 1);
333: exit(0);
334: }
335:
336: (void)sigsetmask(omask);
337: readfrom = (1 << rfd2) | (1 << rem);
338: do {
339: ready = readfrom;
340: if (select(16, &ready, 0, 0, 0) < 0) {
341: if (errno != EINTR) {
342: (void)fprintf(stderr,
343: "rsh: select: %s.\n", strerror(errno));
344: exit(1);
345: }
346: continue;
347: }
348: if (ready & (1 << rfd2)) {
349: errno = 0;
350: #ifdef KERBEROS
351: if (encrypt)
352: cc = des_read(rfd2, buf, sizeof buf);
353: else
354: #endif
355: cc = read(rfd2, buf, sizeof buf);
356: if (cc <= 0) {
357: if (errno != EWOULDBLOCK)
358: readfrom &= ~(1 << rfd2);
359: } else
360: (void)write(2, buf, cc);
361: }
362: if (ready & (1 << rem)) {
363: errno = 0;
364: #ifdef KERBEROS
365: if (encrypt)
366: cc = des_read(rem, buf, sizeof buf);
367: else
368: #endif
369: cc = read(rem, buf, sizeof buf);
370: if (cc <= 0) {
371: if (errno != EWOULDBLOCK)
372: readfrom &= ~(1 << rem);
373: } else
374: (void)write(1, buf, cc);
375: }
376: } while (readfrom);
377: }
378:
379: void
380: sendsig(signo)
381: char signo;
382: {
383: #ifdef KERBEROS
384: if (encrypt)
385: (void)des_write(rfd2, &signo, 1);
386: else
387: #endif
388: (void)write(rfd2, &signo, 1);
389: }
390:
391: #ifdef KERBEROS
392: /* VARARGS */
393: warning(va_alist)
394: va_dcl
395: {
396: va_list ap;
397: char *fmt;
398:
399: (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
400: va_start(ap);
401: fmt = va_arg(ap, char *);
402: vfprintf(stderr, fmt, ap);
403: va_end(ap);
404: (void)fprintf(stderr, ".\n");
405: }
406: #endif
407:
408: char *
409: copyargs(argv)
410: char **argv;
411: {
412: register int cc;
413: register char **ap, *p;
414: char *args, *malloc();
415:
416: cc = 0;
417: for (ap = argv; *ap; ++ap)
418: cc += strlen(*ap) + 1;
419: if (!(args = malloc((u_int)cc))) {
420: (void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
421: exit(1);
422: }
423: for (p = args, ap = argv; *ap; ++ap) {
424: (void)strcpy(p, *ap);
425: for (p = strcpy(p, *ap); *p; ++p);
426: if (ap[1])
427: *p++ = ' ';
428: }
429: return(args);
430: }
431:
432: usage()
433: {
434: (void)fprintf(stderr,
435: "usage: rsh [-ndx]%s[-l login] host [command]\n",
436: #ifdef KERBEROS
437: " [-k realm] ");
438: #else
439: " ");
440: #endif
441: exit(1);
442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.