52 |
#include <netinet/in.h> |
#include <netinet/in.h> |
53 |
#include <netdb.h> |
#include <netdb.h> |
54 |
|
|
55 |
#include <err.h> |
#include <error.h> |
56 |
#include <errno.h> |
#include <errno.h> |
57 |
#include <pwd.h> |
#include <pwd.h> |
58 |
#include <signal.h> |
#include <signal.h> |
70 |
# include <sys/select.h> |
# include <sys/select.h> |
71 |
#endif |
#endif |
72 |
|
|
73 |
|
#ifdef SHISHI |
74 |
|
#define REALM_SZ 1040 |
75 |
|
#endif |
76 |
|
|
77 |
|
#if defined(KERBEROS) || defined(SHISHI) |
78 |
|
int use_kerberos = 1, doencrypt; |
79 |
#ifdef KERBEROS |
#ifdef KERBEROS |
80 |
#include <kerberosIV/des.h> |
#include <kerberosIV/des.h> |
81 |
#include <kerberosIV/krb.h> |
#include <kerberosIV/krb.h> |
82 |
|
char dest_realm_buf[REALM_SZ], *dest_realm = NULL; |
83 |
CREDENTIALS cred; |
CREDENTIALS cred; |
84 |
Key_schedule schedule; |
Key_schedule schedule; |
|
int use_kerberos = 1, doencrypt; |
|
|
char dest_realm_buf[REALM_SZ], *dest_realm; |
|
85 |
extern char *krb_realmofhost(); |
extern char *krb_realmofhost(); |
86 |
|
|
87 |
|
# elif defined(SHISHI) |
88 |
|
# include <shishi.h> |
89 |
|
# include "shishi_def.h" |
90 |
|
char dest_realm_buf[REALM_SZ], *dest_realm = NULL; |
91 |
|
|
92 |
|
Shishi * h; |
93 |
|
Shishi_key * enckey; |
94 |
|
shishi_ivector iv1, iv2, iv3, iv4; |
95 |
|
shishi_ivector * ivtab[4]; |
96 |
|
|
97 |
|
int keytype; |
98 |
|
int keylen; |
99 |
|
int rc; |
100 |
|
int wlen; |
101 |
#endif |
#endif |
102 |
|
#endif /* KERBEROS */ |
103 |
|
|
104 |
/* |
/* |
105 |
* rsh - remote shell |
* rsh - remote shell |
107 |
int rfd2; |
int rfd2; |
108 |
|
|
109 |
char *copyargs __P ((char **)); |
char *copyargs __P ((char **)); |
110 |
void sendsig __P ((int)); |
RETSIGTYPE sendsig __P ((int)); |
111 |
void talk __P ((int, sigset_t *, pid_t, int)); |
void talk __P ((int, sigset_t *, pid_t, int)); |
112 |
void usage __P ((void)); |
void usage __P ((void)); |
113 |
void warning __P ((const char *, ...)); |
void warning __P ((const char *, ...)); |
133 |
{ "8-bit", no_argument, 0, '8' }, |
{ "8-bit", no_argument, 0, '8' }, |
134 |
{ "kerberos", no_argument, 0, 'K' }, |
{ "kerberos", no_argument, 0, 'K' }, |
135 |
{ "no-input", no_argument, 0, 'n' }, |
{ "no-input", no_argument, 0, 'n' }, |
136 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
137 |
{ "realm", required_argument, 0, 'k' }, |
{ "realm", required_argument, 0, 'k' }, |
138 |
{ "encrypt", no_argument, 0, 'x' }, |
{ "encrypt", no_argument, 0, 'x' }, |
139 |
#endif |
#endif |
148 |
fprintf (stream, |
fprintf (stream, |
149 |
"Usage: %s [-nd%s]%s[-l USER] [USER@]HOST [COMMAND [ARG...]]\n", |
"Usage: %s [-nd%s]%s[-l USER] [USER@]HOST [COMMAND [ARG...]]\n", |
150 |
__progname, |
__progname, |
151 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
152 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
153 |
"x", " [-k REALM] " |
"x", " [-k REALM] " |
154 |
#else |
#else |
180 |
which is ``~'' by default"); |
which is ``~'' by default"); |
181 |
puts ("\ |
puts ("\ |
182 |
-l, --user USER run as USER on the remote system"); |
-l, --user USER run as USER on the remote system"); |
183 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
184 |
puts ("\ |
puts ("\ |
185 |
-K, --kerberos turns off all Kerberos authentication"); |
-K, --kerberos turns off all Kerberos authentication"); |
186 |
puts ("\ |
puts ("\ |
270 |
break; |
break; |
271 |
|
|
272 |
case 'K': |
case 'K': |
273 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
274 |
use_kerberos = 0; |
use_kerberos = 0; |
275 |
#endif |
#endif |
276 |
break; |
break; |
277 |
|
|
278 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
279 |
case 'k': |
case 'k': |
280 |
strncpy (dest_realm_buf, optarg, sizeof dest_realm_buf); |
strncpy (dest_realm_buf, optarg, sizeof dest_realm_buf); |
281 |
dest_realm_buf [REALM_SZ - 1] = '\0'; |
dest_realm_buf [REALM_SZ - 1] = '\0'; |
285 |
# ifdef ENCRYPTION |
# ifdef ENCRYPTION |
286 |
case 'x': |
case 'x': |
287 |
doencrypt = 1; |
doencrypt = 1; |
288 |
|
#ifdef KERBEROS |
289 |
des_set_key (cred.session, schedule); |
des_set_key (cred.session, schedule); |
290 |
|
#endif |
291 |
break; |
break; |
292 |
# endif |
# endif |
293 |
#endif |
#endif |
326 |
seteuid (getuid ()); |
seteuid (getuid ()); |
327 |
setuid (getuid ()); |
setuid (getuid ()); |
328 |
execv (PATH_RLOGIN, argv); |
execv (PATH_RLOGIN, argv); |
329 |
errx (1, "can't exec %s", PATH_RLOGIN); |
error (1, errno, "can't exec %s", PATH_RLOGIN); |
330 |
} |
} |
331 |
|
|
332 |
argc -= optind; |
argc -= optind; |
334 |
|
|
335 |
/* We must be setuid root. */ |
/* We must be setuid root. */ |
336 |
if (geteuid ()) |
if (geteuid ()) |
337 |
errx (1, "must be setuid root.\n"); |
error (1, 0, "must be setuid root.\n"); |
338 |
|
|
339 |
if (!(pw = getpwuid (uid = getuid ()))) |
if (!(pw = getpwuid (uid = getuid ()))) |
340 |
errx(1, "unknown user id"); |
error (1, 0, "unknown user id"); |
341 |
|
|
342 |
/* Accept user1@host format, though "-l user2" overrides user1 */ |
/* Accept user1@host format, though "-l user2" overrides user1 */ |
343 |
{ |
{ |
351 |
if (*host == '\0') |
if (*host == '\0') |
352 |
usage (); |
usage (); |
353 |
} |
} |
|
if (!user) |
|
|
user = pw->pw_name; |
|
354 |
} |
} |
355 |
|
|
356 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
357 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
358 |
/* -x turns off -n */ |
/* -x turns off -n */ |
359 |
if (doencrypt) |
if (doencrypt) |
375 |
doencrypt ? "ekshell" : "kshell"); |
doencrypt ? "ekshell" : "kshell"); |
376 |
} |
} |
377 |
} |
} |
378 |
|
#elif defined(SHISHI) |
379 |
|
if (use_kerberos) |
380 |
|
{ |
381 |
|
sp = getservbyname ("kshell", "tcp"); |
382 |
|
if (sp == NULL) |
383 |
|
{ |
384 |
|
use_kerberos = 0; |
385 |
|
warning ("can't get entry for %s/tcp service", |
386 |
|
"kshell"); |
387 |
|
} |
388 |
|
} |
389 |
#endif |
#endif |
390 |
if (sp == NULL) |
if (sp == NULL) |
391 |
sp = getservbyname("shell", "tcp"); |
sp = getservbyname("shell", "tcp"); |
392 |
if (sp == NULL) |
if (sp == NULL) |
393 |
errx (1, "shell/tcp: unknown service"); |
error (1, 0, "shell/tcp: unknown service"); |
394 |
|
|
395 |
#ifdef KERBEROS |
|
396 |
|
#if defined (KERBEROS) || defined(SHISHI) |
397 |
try_connect: |
try_connect: |
398 |
if (use_kerberos) |
if (use_kerberos) |
399 |
{ |
{ |
402 |
/* fully qualify hostname (needed for krb_realmofhost) */ |
/* fully qualify hostname (needed for krb_realmofhost) */ |
403 |
hp = gethostbyname(host); |
hp = gethostbyname(host); |
404 |
if (hp != NULL && !(host = strdup (hp->h_name))) |
if (hp != NULL && !(host = strdup (hp->h_name))) |
405 |
err (1, NULL); |
error (1, errno, "strdup"); |
406 |
|
|
407 |
|
#if defined (KERBEROS) |
408 |
rem = KSUCCESS; |
rem = KSUCCESS; |
409 |
errno = 0; |
errno = 0; |
410 |
if (dest_realm == NULL) |
if (dest_realm == NULL) |
411 |
dest_realm = krb_realmofhost (host); |
dest_realm = krb_realmofhost (host); |
412 |
|
#elif defined (SHISHI) |
413 |
|
rem = SHISHI_OK; |
414 |
|
errno = 0; |
415 |
|
#endif |
416 |
|
|
417 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
418 |
if (doencrypt) |
if (doencrypt) |
419 |
rem = krcmd_mutual (&host, sp->s_port, user, args, |
#if defined(SHISHI) |
420 |
&rfd2, dest_realm, &cred, schedule); |
{ |
421 |
|
int i; |
422 |
|
char * term; |
423 |
|
|
424 |
|
term = (char *)xmalloc (strlen(args)+4); |
425 |
|
strcpy (term, "-x "); |
426 |
|
strcat (term, args); |
427 |
|
|
428 |
|
rem = krcmd_mutual (&h, &host, sp->s_port, &user, term, &rfd2, |
429 |
|
dest_realm, &enckey); |
430 |
|
if (rem > 0) |
431 |
|
{ |
432 |
|
keytype = shishi_key_type (enckey); |
433 |
|
keylen = shishi_cipher_blocksize (keytype); |
434 |
|
|
435 |
|
ivtab[0] = &iv1; |
436 |
|
ivtab[1] = &iv2; |
437 |
|
ivtab[2] = &iv3; |
438 |
|
ivtab[3] = &iv4; |
439 |
|
|
440 |
|
for (i=0; i<4; i++) |
441 |
|
{ |
442 |
|
ivtab[i]->ivlen = keylen; |
443 |
|
|
444 |
|
switch (keytype) |
445 |
|
{ |
446 |
|
case SHISHI_DES_CBC_CRC: |
447 |
|
case SHISHI_DES_CBC_MD4: |
448 |
|
case SHISHI_DES_CBC_MD5: |
449 |
|
case SHISHI_DES_CBC_NONE: |
450 |
|
case SHISHI_DES3_CBC_HMAC_SHA1_KD: |
451 |
|
ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; |
452 |
|
ivtab[i]->iv = malloc (ivtab[i]->ivlen); |
453 |
|
memset (ivtab[i]->iv, 2*i + 1*(i<2) - 4*(i>=2), ivtab[i]->ivlen); |
454 |
|
ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), |
455 |
|
ivtab[i]->iv, ivtab[i]->ivlen); |
456 |
|
break; |
457 |
|
case SHISHI_ARCFOUR_HMAC: |
458 |
|
case SHISHI_ARCFOUR_HMAC_EXP: |
459 |
|
ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4*i; |
460 |
|
ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), |
461 |
|
NULL, 0); |
462 |
|
break; |
463 |
|
default : |
464 |
|
ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4*i; |
465 |
|
ivtab[i]->iv = malloc (ivtab[i]->ivlen); |
466 |
|
memset (ivtab[i]->iv, 0, ivtab[i]->ivlen); |
467 |
|
ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), |
468 |
|
ivtab[i]->iv, ivtab[i]->ivlen); |
469 |
|
} |
470 |
|
} |
471 |
|
} |
472 |
|
free (term); |
473 |
|
} |
474 |
else |
else |
475 |
|
#else |
476 |
|
rem = krcmd_mutual (&host, sp->s_port, user, args, &rfd2, |
477 |
|
dest_realm, &cred, schedule); |
478 |
|
else |
479 |
|
#endif |
480 |
|
#endif |
481 |
|
rem = krcmd ( |
482 |
|
#if defined (SHISHI) |
483 |
|
&h, &host, sp->s_port, &user, args, &rfd2, dest_realm); |
484 |
|
#else |
485 |
|
&host, sp->s_port, user, args, &rfd2, dest_realm); |
486 |
#endif |
#endif |
|
rem = krcmd (&host, sp->s_port, user, args, &rfd2, |
|
|
dest_realm); |
|
487 |
if (rem < 0) |
if (rem < 0) |
488 |
{ |
{ |
489 |
use_kerberos = 0; |
use_kerberos = 0; |
490 |
sp = getservbyname ("shell", "tcp"); |
sp = getservbyname ("shell", "tcp"); |
491 |
if (sp == NULL) |
if (sp == NULL) |
492 |
errx (1, "shell/tcp: unknown service"); |
error (1, 0, "shell/tcp: unknown service"); |
493 |
if (errno == ECONNREFUSED) |
if (errno == ECONNREFUSED) |
494 |
warning ("remote host doesn't support Kerberos"); |
warning ("remote host doesn't support Kerberos"); |
495 |
if (errno == ENOENT) |
if (errno == ENOENT) |
499 |
} |
} |
500 |
else |
else |
501 |
{ |
{ |
502 |
|
if (!user) |
503 |
|
user = pw->pw_name; |
504 |
if (doencrypt) |
if (doencrypt) |
505 |
errx (1, "the -x flag requires Kerberos authentication"); |
error (1, 0, "the -x flag requires Kerberos authentication"); |
506 |
rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2); |
rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2); |
507 |
} |
} |
508 |
#else |
#else |
509 |
|
if (!user) |
510 |
|
user = pw->pw_name; |
511 |
rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2); |
rem = rcmd (&host, sp->s_port, pw->pw_name, user, args, &rfd2); |
512 |
#endif |
#endif |
513 |
|
|
515 |
exit (1); |
exit (1); |
516 |
|
|
517 |
if (rfd2 < 0) |
if (rfd2 < 0) |
518 |
errx (1, "can't establish stderr"); |
error (1, 0, "can't establish stderr"); |
519 |
|
|
520 |
if (dflag) |
if (dflag) |
521 |
{ |
{ |
522 |
int one = 1; |
int one = 1; |
523 |
if (setsockopt (rem, SOL_SOCKET, SO_DEBUG, (char *) &one, |
if (setsockopt (rem, SOL_SOCKET, SO_DEBUG, (char *) &one, |
524 |
sizeof one) < 0) |
sizeof one) < 0) |
525 |
warn ("setsockopt"); |
error (0, errno, "setsockopt"); |
526 |
if (setsockopt (rfd2, SOL_SOCKET, SO_DEBUG, (char *) &one, |
if (setsockopt (rfd2, SOL_SOCKET, SO_DEBUG, (char *) &one, |
527 |
sizeof one) < 0) |
sizeof one) < 0) |
528 |
warn ("setsockopt"); |
error (0, errno, "setsockopt"); |
529 |
} |
} |
530 |
|
|
531 |
seteuid (uid); |
seteuid (uid); |
551 |
{ |
{ |
552 |
pid = fork (); |
pid = fork (); |
553 |
if (pid < 0) |
if (pid < 0) |
554 |
err (1, "fork"); |
error (1, errno, "fork"); |
555 |
} |
} |
556 |
|
|
557 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
558 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
559 |
if (!doencrypt) |
if (!doencrypt) |
560 |
#endif |
#endif |
567 |
|
|
568 |
talk (nflag, &osigs, pid, rem); |
talk (nflag, &osigs, pid, rem); |
569 |
|
|
570 |
|
|
571 |
|
#ifdef SHISHI |
572 |
|
if (use_kerberos) |
573 |
|
{ |
574 |
|
int i; |
575 |
|
|
576 |
|
shishi_done (h); |
577 |
|
#ifdef ENCRYPTION |
578 |
|
if (doencrypt) |
579 |
|
{ |
580 |
|
shishi_key_done (enckey); |
581 |
|
for (i = 0; i < 4; i++) |
582 |
|
{ |
583 |
|
shishi_crypto_close (ivtab[i]->ctx); |
584 |
|
free (ivtab[i]->iv); |
585 |
|
} |
586 |
|
} |
587 |
|
#endif |
588 |
|
} |
589 |
|
#endif |
590 |
|
|
591 |
if (!nflag) |
if (!nflag) |
592 |
kill (pid, SIGKILL); |
kill (pid, SIGKILL); |
593 |
return 0; |
return 0; |
616 |
if (select (rem + 1, 0, &rembits, 0, 0) < 0) |
if (select (rem + 1, 0, &rembits, 0, 0) < 0) |
617 |
{ |
{ |
618 |
if (errno != EINTR) |
if (errno != EINTR) |
619 |
err (1, "select"); |
error (1, errno, "select"); |
620 |
goto rewrite; |
goto rewrite; |
621 |
} |
} |
622 |
if (!FD_ISSET (rem, &rembits)) |
if (!FD_ISSET (rem, &rembits)) |
623 |
goto rewrite; |
goto rewrite; |
|
#ifdef KERBEROS |
|
624 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
625 |
|
#ifdef KERBEROS |
626 |
if (doencrypt) |
if (doencrypt) |
627 |
wc = des_write (rem, bp, cc); |
wc = des_write (rem, bp, cc); |
628 |
else |
else |
629 |
|
#elif defined(SHISHI) |
630 |
|
if (doencrypt) |
631 |
|
writeenc (h, rem, bp, cc, &wc, &iv3, enckey, 2); |
632 |
|
else |
633 |
#endif |
#endif |
634 |
#endif |
#endif |
635 |
wc = write (rem, bp, cc); |
wc = write (rem, bp, cc); |
666 |
if (select (maxfd + 1, &ready, 0, 0, 0) < 0) |
if (select (maxfd + 1, &ready, 0, 0, 0) < 0) |
667 |
{ |
{ |
668 |
if (errno != EINTR) |
if (errno != EINTR) |
669 |
err (1, "select"); |
error (1, errno, "select"); |
670 |
continue; |
continue; |
671 |
} |
} |
672 |
if (FD_ISSET (rfd2, &ready)) |
if (FD_ISSET (rfd2, &ready)) |
678 |
cc = des_read (rfd2, buf, sizeof buf); |
cc = des_read (rfd2, buf, sizeof buf); |
679 |
else |
else |
680 |
#endif |
#endif |
681 |
|
#elif defined(SHISHI) && defined(ENCRYPTION) |
682 |
|
if (doencrypt) |
683 |
|
readenc (h, rfd2, buf, &cc, &iv2, enckey, 2); |
684 |
|
else |
685 |
#endif |
#endif |
686 |
cc = read (rfd2, buf, sizeof buf); |
cc = read (rfd2, buf, sizeof buf); |
687 |
if (cc <= 0) |
if (cc <= 0) |
701 |
cc = des_read (rem, buf, sizeof buf); |
cc = des_read (rem, buf, sizeof buf); |
702 |
else |
else |
703 |
#endif |
#endif |
704 |
|
#elif defined(SHISHI) && defined(ENCRYPTION) |
705 |
|
if (doencrypt) |
706 |
|
readenc (h, rem, buf, &cc, &iv1, enckey, 2); |
707 |
|
else |
708 |
#endif |
#endif |
709 |
cc = read (rem, buf, sizeof buf); |
cc = read (rem, buf, sizeof buf); |
710 |
if (cc <= 0) |
if (cc <= 0) |
722 |
sendsig (int sig) |
sendsig (int sig) |
723 |
{ |
{ |
724 |
char signo; |
char signo; |
725 |
|
int n; |
726 |
|
|
727 |
signo = sig; |
signo = sig; |
728 |
#ifdef KERBEROS |
#ifdef KERBEROS |
731 |
des_write (rfd2, &signo, 1); |
des_write (rfd2, &signo, 1); |
732 |
else |
else |
733 |
#endif |
#endif |
734 |
|
#elif defined(SHISHI) && defined (ENCRYPTION) |
735 |
|
if (doencrypt) |
736 |
|
writeenc (h, rfd2, &signo, 1, &n, &iv4, enckey, 2); |
737 |
|
else |
738 |
#endif |
#endif |
739 |
|
|
740 |
write (rfd2, &signo, 1); |
write (rfd2, &signo, 1); |
741 |
} |
} |
742 |
|
|
743 |
#ifdef KERBEROS |
#if defined(KERBEROS) || defined(SHISHI) |
744 |
/* VARARGS */ |
/* VARARGS */ |
745 |
void |
void |
|
#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ |
|
746 |
warning (const char * fmt, ...) |
warning (const char * fmt, ...) |
|
#else |
|
|
warning (va_alist) |
|
|
va_dcl |
|
|
#endif |
|
747 |
{ |
{ |
748 |
va_list ap; |
va_list ap; |
|
#if !(defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__) |
|
|
const char *fmt; |
|
|
#endif |
|
749 |
|
|
750 |
fprintf (stderr, "%s: warning, using standard rsh: ", __progname); |
fprintf (stderr, "%s: warning, using standard rsh: ", __progname); |
|
#if defined(HAVE_STDARG_H) && defined(__STDC__) && __STDC__ |
|
751 |
va_start (ap, fmt); |
va_start (ap, fmt); |
|
#else |
|
|
va_start (ap); |
|
|
#endif |
|
752 |
fmt = va_arg (ap, char *); |
fmt = va_arg (ap, char *); |
753 |
vfprintf (stderr, fmt, ap); |
vfprintf (stderr, fmt, ap); |
754 |
va_end (ap); |
va_end (ap); |
766 |
for (ap = argv; *ap; ++ap) |
for (ap = argv; *ap; ++ap) |
767 |
cc += strlen (*ap) + 1; |
cc += strlen (*ap) + 1; |
768 |
if (!(args = malloc ((u_int)cc))) |
if (!(args = malloc ((u_int)cc))) |
769 |
err (1, NULL); |
error (1, errno, "copyargs"); |
770 |
for (p = args, ap = argv; *ap; ++ap) |
for (p = args, ap = argv; *ap; ++ap) |
771 |
{ |
{ |
772 |
strcpy (p, *ap); |
strcpy (p, *ap); |