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