1 /*- 2 * Copyright (c) 1983, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)rsh.c 5.24.1.1 (Berkeley) 08/20/91"; 16 #endif /* not lint */ 17 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 23 #include <sys/types.h> 24 #include <sys/signal.h> 25 #include <sys/socket.h> 26 #include <sys/ioctl.h> 27 #include <sys/file.h> 28 29 #include <netinet/in.h> 30 #include <netdb.h> 31 32 #include <pwd.h> 33 #include <stdio.h> 34 #include <errno.h> 35 #include <string.h> 36 #include <varargs.h> 37 #include "pathnames.h" 38 39 #ifdef KERBEROS 40 #include <kerberosIV/des.h> 41 #include <kerberosIV/krb.h> 42 43 CREDENTIALS cred; 44 Key_schedule schedule; 45 int use_kerberos = 1, doencrypt; 46 char dst_realm_buf[REALM_SZ], *dest_realm; 47 extern char *krb_realmofhost(); 48 #endif 49 50 /* 51 * rsh - remote shell 52 */ 53 extern int errno; 54 int rfd2; 55 56 main(argc, argv) 57 int argc; 58 char **argv; 59 { 60 extern char *optarg; 61 extern int optind; 62 struct passwd *pw; 63 struct servent *sp; 64 long omask; 65 int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid; 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; 73 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; 81 else 82 asrsh = 1; 83 84 /* handle "rsh host flags" */ 85 if (!host && argc > 2 && argv[1][0] != '-') { 86 host = argv[1]; 87 argoff = 1; 88 } 89 90 #ifdef KERBEROS 91 #define OPTIONS "8KLdek:l:nw" 92 #else 93 #define OPTIONS "8KLdel:nw" 94 #endif 95 while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) 96 switch(ch) { 97 case 'K': 98 #ifdef KERBEROS 99 use_kerberos = 0; 100 #endif 101 break; 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; 118 #endif 119 case 'n': 120 nflag = 1; 121 break; 122 #ifdef KERBEROS 123 #endif 124 case '?': 125 default: 126 usage(); 127 } 128 optind += argoff; 129 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]) { 136 if (asrsh) 137 *argv = "rlogin"; 138 execv(_PATH_RLOGIN, argv); 139 (void)fprintf(stderr, "rsh: can't exec %s.\n", _PATH_RLOGIN); 140 exit(1); 141 } 142 143 argc -= optind; 144 argv += optind; 145 146 if (!(pw = getpwuid(uid = getuid()))) { 147 (void)fprintf(stderr, "rsh: unknown user id.\n"); 148 exit(1); 149 } 150 if (!user) 151 user = pw->pw_name; 152 153 #ifdef KERBEROS 154 #endif 155 156 args = copyargs(argv); 157 158 sp = NULL; 159 #ifdef KERBEROS 160 if (use_kerberos) { 161 sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp"); 162 if (sp == NULL) { 163 use_kerberos = 0; 164 warning("can't get entry for %s/tcp service", 165 doencrypt ? "ekshell" : "kshell"); 166 } 167 } 168 #endif 169 if (sp == NULL) 170 sp = getservbyname("shell", "tcp"); 171 if (sp == NULL) { 172 (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n"); 173 exit(1); 174 } 175 176 #ifdef KERBEROS 177 try_connect: 178 if (use_kerberos) { 179 rem = KSUCCESS; 180 errno = 0; 181 if (dest_realm == NULL) 182 dest_realm = krb_realmofhost(host); 183 184 rem = krcmd(&host, sp->s_port, user, args, &rfd2, 185 dest_realm); 186 if (rem < 0) { 187 use_kerberos = 0; 188 sp = getservbyname("shell", "tcp"); 189 if (sp == NULL) { 190 (void)fprintf(stderr, 191 "rsh: unknown service shell/tcp.\n"); 192 exit(1); 193 } 194 if (errno == ECONNREFUSED) 195 warning("remote host doesn't support Kerberos"); 196 if (errno == ENOENT) 197 warning("can't provide Kerberos auth data"); 198 goto try_connect; 199 } 200 } else { 201 if (doencrypt) { 202 (void)fprintf(stderr, 203 "rsh: the -x flag requires Kerberos authentication.\n"); 204 exit(1); 205 } 206 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); 207 } 208 #else 209 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); 210 #endif 211 212 if (rem < 0) 213 exit(1); 214 215 if (rfd2 < 0) { 216 (void)fprintf(stderr, "rsh: can't establish stderr.\n"); 217 exit(1); 218 } 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)); 224 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, 225 sizeof(one)) < 0) 226 (void)fprintf(stderr, "rsh: setsockopt: %s.\n", 227 strerror(errno)); 228 } 229 230 (void)setuid(uid); 231 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)); 232 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 233 (void)signal(SIGINT, sendsig); 234 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 235 (void)signal(SIGQUIT, sendsig); 236 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 237 (void)signal(SIGTERM, sendsig); 238 239 if (!nflag) { 240 pid = fork(); 241 if (pid < 0) { 242 (void)fprintf(stderr, 243 "rsh: fork: %s.\n", strerror(errno)); 244 exit(1); 245 } 246 } 247 248 #ifdef KERBEROS 249 #endif 250 { 251 (void)ioctl(rfd2, FIONBIO, &one); 252 (void)ioctl(rem, FIONBIO, &one); 253 } 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) 277 goto done; 278 bp = buf; 279 280 rewrite: rembits = 1 << rem; 281 if (select(16, 0, &rembits, 0, 0) < 0) { 282 if (errno != EINTR) { 283 (void)fprintf(stderr, 284 "rsh: select: %s.\n", strerror(errno)); 285 exit(1); 286 } 287 goto rewrite; 288 } 289 if ((rembits & (1 << rem)) == 0) 290 goto rewrite; 291 #ifdef KERBEROS 292 #endif 293 wc = write(rem, bp, cc); 294 if (wc < 0) { 295 if (errno == EWOULDBLOCK) 296 goto rewrite; 297 goto done; 298 } 299 bp += wc; 300 cc -= wc; 301 if (cc == 0) 302 goto reread; 303 goto rewrite; 304 done: 305 (void)shutdown(rem, 1); 306 exit(0); 307 } 308 309 (void)sigsetmask(omask); 310 readfrom = (1 << rfd2) | (1 << rem); 311 do { 312 ready = readfrom; 313 if (select(16, &ready, 0, 0, 0) < 0) { 314 if (errno != EINTR) { 315 (void)fprintf(stderr, 316 "rsh: select: %s.\n", strerror(errno)); 317 exit(1); 318 } 319 continue; 320 } 321 if (ready & (1 << rfd2)) { 322 errno = 0; 323 #ifdef KERBEROS 324 #endif 325 cc = read(rfd2, buf, sizeof buf); 326 if (cc <= 0) { 327 if (errno != EWOULDBLOCK) 328 readfrom &= ~(1 << rfd2); 329 } else 330 (void)write(2, buf, cc); 331 } 332 if (ready & (1 << rem)) { 333 errno = 0; 334 #ifdef KERBEROS 335 #endif 336 cc = read(rem, buf, sizeof buf); 337 if (cc <= 0) { 338 if (errno != EWOULDBLOCK) 339 readfrom &= ~(1 << rem); 340 } else 341 (void)write(1, buf, cc); 342 } 343 } while (readfrom); 344 } 345 346 void 347 sendsig(signo) 348 char signo; 349 { 350 #ifdef KERBEROS 351 #endif 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"); 369 } 370 #endif 371 372 char * 373 copyargs(argv) 374 char **argv; 375 { 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); 394 } 395 396 usage() 397 { 398 (void)fprintf(stderr, 399 "usage: rsh [-nd%s]%s[-l login] host [command]\n", 400 #ifdef KERBEROS 401 "", " [-k realm] "); 402 #else 403 "", " "); 404 #endif 405 exit(1); 406 } 407