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