home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / rsh / rsh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  10.1 KB  |  481 lines

  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, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. char copyright[] =
  36. "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
  37.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)rsh.c    5.24 (Berkeley) 7/1/91";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * $Source: mit/rsh/RCS/rsh.c,v $
  46.  * $Header: mit/rsh/RCS/rsh.c,v 5.1 89/07/31 19:28:59 kfall Exp Locker: kfall $
  47.  */
  48.  
  49. #include <sys/types.h>
  50. #include <sys/signal.h>
  51. #include <sys/socket.h>
  52. #include <sys/ioctl.h>
  53. #include <sys/file.h>
  54.  
  55. #include <netinet/in.h>
  56. #include <netdb.h>
  57.  
  58. #include <pwd.h>
  59. #include <stdio.h>
  60. #include <errno.h>
  61. #include <string.h>
  62. #include <varargs.h>
  63. #include "pathnames.h"
  64.  
  65. #ifdef KERBEROS
  66. #include <kerberosIV/des.h>
  67. #include <kerberosIV/krb.h>
  68.  
  69. CREDENTIALS cred;
  70. Key_schedule schedule;
  71. int use_kerberos = 1, doencrypt;
  72. char dst_realm_buf[REALM_SZ], *dest_realm;
  73. extern char *krb_realmofhost();
  74. #endif
  75.  
  76. /*
  77.  * rsh - remote shell
  78.  */
  79. extern int errno;
  80. int rfd2;
  81.  
  82. main(argc, argv)
  83.     int argc;
  84.     char **argv;
  85. {
  86.     extern char *optarg;
  87.     extern int optind;
  88.     struct passwd *pw;
  89.     struct servent *sp;
  90.     long omask;
  91.     int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid;
  92.     register char *p;
  93.     char *args, *host, *user, *copyargs();
  94.     void sendsig();
  95.  
  96.     argoff = asrsh = dflag = nflag = 0;
  97.     one = 1;
  98.     host = user = NULL;
  99.  
  100.     /* if called as something other than "rsh", use it as the host name */
  101.     if (p = rindex(argv[0], '/'))
  102.         ++p;
  103.     else
  104.         p = argv[0];
  105.     if (strcmp(p, "rsh"))
  106.         host = p;
  107.     else
  108.         asrsh = 1;
  109.  
  110.     /* handle "rsh host flags" */
  111.     if (!host && argc > 2 && argv[1][0] != '-') {
  112.         host = argv[1];
  113.         argoff = 1;
  114.     }
  115.  
  116. #ifdef KERBEROS
  117. #ifdef CRYPT
  118. #define    OPTIONS    "8KLdek:l:nwx"
  119. #else
  120. #define    OPTIONS    "8KLdek:l:nw"
  121. #endif
  122. #else
  123. #define    OPTIONS    "8KLdel:nw"
  124. #endif
  125.     while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
  126.         switch(ch) {
  127.         case 'K':
  128. #ifdef KERBEROS
  129.             use_kerberos = 0;
  130. #endif
  131.             break;
  132.         case 'L':    /* -8Lew are ignored to allow rlogin aliases */
  133.         case 'e':
  134.         case 'w':
  135.         case '8':
  136.             break;
  137.         case 'd':
  138.             dflag = 1;
  139.             break;
  140.         case 'l':
  141.             user = optarg;
  142.             break;
  143. #ifdef KERBEROS
  144.         case 'k':
  145.             dest_realm = dst_realm_buf;
  146.             strncpy(dest_realm, optarg, REALM_SZ);
  147.             break;
  148. #endif
  149.         case 'n':
  150.             nflag = 1;
  151.             break;
  152. #ifdef KERBEROS
  153. #ifdef CRYPT
  154.         case 'x':
  155.             doencrypt = 1;
  156.             des_set_key(cred.session, schedule);
  157.             break;
  158. #endif
  159. #endif
  160.         case '?':
  161.         default:
  162.             usage();
  163.         }
  164.     optind += argoff;
  165.  
  166.     /* if haven't gotten a host yet, do so */
  167.     if (!host && !(host = argv[optind++]))
  168.         usage();
  169.  
  170.     /* if no further arguments, must have been called as rlogin. */
  171.     if (!argv[optind]) {
  172.         if (asrsh)
  173.             *argv = "rlogin";
  174.         execv(_PATH_RLOGIN, argv);
  175.         (void)fprintf(stderr, "rsh: can't exec %s.\n", _PATH_RLOGIN);
  176.         exit(1);
  177.     }
  178.  
  179.     argc -= optind;
  180.     argv += optind;
  181.  
  182.     if (!(pw = getpwuid(uid = getuid()))) {
  183.         (void)fprintf(stderr, "rsh: unknown user id.\n");
  184.         exit(1);
  185.     }
  186.     if (!user)
  187.         user = pw->pw_name;
  188.  
  189. #ifdef KERBEROS
  190. #ifdef CRYPT
  191.     /* -x turns off -n */
  192.     if (doencrypt)
  193.         nflag = 0;
  194. #endif
  195. #endif
  196.  
  197.     args = copyargs(argv);
  198.  
  199.     sp = NULL;
  200. #ifdef KERBEROS
  201.     if (use_kerberos) {
  202.         sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
  203.         if (sp == NULL) {
  204.             use_kerberos = 0;
  205.             warning("can't get entry for %s/tcp service",
  206.                 doencrypt ? "ekshell" : "kshell");
  207.         }
  208.     }
  209. #endif
  210.     if (sp == NULL)
  211.         sp = getservbyname("shell", "tcp");
  212.     if (sp == NULL) {
  213.         (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
  214.         exit(1);
  215.     }
  216.  
  217. #ifdef KERBEROS
  218. try_connect:
  219.     if (use_kerberos) {
  220.         rem = KSUCCESS;
  221.         errno = 0;
  222.         if (dest_realm == NULL)
  223.             dest_realm = krb_realmofhost(host);
  224.  
  225. #ifdef CRYPT
  226.         if (doencrypt)
  227.             rem = krcmd_mutual(&host, sp->s_port, user, args,
  228.                 &rfd2, dest_realm, &cred, schedule);
  229.         else
  230. #endif
  231.             rem = krcmd(&host, sp->s_port, user, args, &rfd2,
  232.                 dest_realm);
  233.         if (rem < 0) {
  234.             use_kerberos = 0;
  235.             sp = getservbyname("shell", "tcp");
  236.             if (sp == NULL) {
  237.                 (void)fprintf(stderr,
  238.                     "rsh: unknown service shell/tcp.\n");
  239.                 exit(1);
  240.             }
  241.             if (errno == ECONNREFUSED)
  242.                 warning("remote host doesn't support Kerberos");
  243.             if (errno == ENOENT)
  244.                 warning("can't provide Kerberos auth data");
  245.             goto try_connect;
  246.         }
  247.     } else {
  248.         if (doencrypt) {
  249.             (void)fprintf(stderr,
  250.                 "rsh: the -x flag requires Kerberos authentication.\n");
  251.             exit(1);
  252.         }
  253.         rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
  254.     }
  255. #else
  256.     rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
  257. #endif
  258.  
  259.     if (rem < 0)
  260.         exit(1);
  261.  
  262.     if (rfd2 < 0) {
  263.         (void)fprintf(stderr, "rsh: can't establish stderr.\n");
  264.         exit(1);
  265.     }
  266.     if (dflag) {
  267.         if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
  268.             sizeof(one)) < 0)
  269.             (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
  270.                 strerror(errno));
  271.         if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
  272.             sizeof(one)) < 0)
  273.             (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
  274.                 strerror(errno));
  275.     }
  276.  
  277.     (void)setuid(uid);
  278.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
  279.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  280.         (void)signal(SIGINT, sendsig);
  281.     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  282.         (void)signal(SIGQUIT, sendsig);
  283.     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  284.         (void)signal(SIGTERM, sendsig);
  285.  
  286.     if (!nflag) {
  287.         pid = fork();
  288.         if (pid < 0) {
  289.             (void)fprintf(stderr,
  290.                 "rsh: fork: %s.\n", strerror(errno));
  291.             exit(1);
  292.         }
  293.     }
  294.  
  295. #ifdef KERBEROS
  296. #ifdef CRYPT
  297.     if (!doencrypt)
  298. #endif
  299. #endif
  300.     {
  301.         (void)ioctl(rfd2, FIONBIO, &one);
  302.         (void)ioctl(rem, FIONBIO, &one);
  303.     }
  304.  
  305.     talk(nflag, omask, pid, rem);
  306.  
  307.     if (!nflag)
  308.         (void)kill(pid, SIGKILL);
  309.     exit(0);
  310. }
  311.  
  312. talk(nflag, omask, pid, rem)
  313.     int nflag, pid;
  314.     long omask;
  315.     register int rem;
  316. {
  317.     register int cc, wc;
  318.     register char *bp;
  319.     int readfrom, ready, rembits;
  320.     char buf[BUFSIZ];
  321.  
  322.     if (!nflag && pid == 0) {
  323.         (void)close(rfd2);
  324.  
  325. reread:        errno = 0;
  326.         if ((cc = read(0, buf, sizeof buf)) <= 0)
  327.             goto done;
  328.         bp = buf;
  329.  
  330. rewrite:    rembits = 1 << rem;
  331.         if (select(16, 0, &rembits, 0, 0) < 0) {
  332.             if (errno != EINTR) {
  333.                 (void)fprintf(stderr,
  334.                     "rsh: select: %s.\n", strerror(errno));
  335.                 exit(1);
  336.             }
  337.             goto rewrite;
  338.         }
  339.         if ((rembits & (1 << rem)) == 0)
  340.             goto rewrite;
  341. #ifdef KERBEROS
  342. #ifdef CRYPT
  343.         if (doencrypt)
  344.             wc = des_write(rem, bp, cc);
  345.         else
  346. #endif
  347. #endif
  348.             wc = write(rem, bp, cc);
  349.         if (wc < 0) {
  350.             if (errno == EWOULDBLOCK)
  351.                 goto rewrite;
  352.             goto done;
  353.         }
  354.         bp += wc;
  355.         cc -= wc;
  356.         if (cc == 0)
  357.             goto reread;
  358.         goto rewrite;
  359. done:
  360.         (void)shutdown(rem, 1);
  361.         exit(0);
  362.     }
  363.  
  364.     (void)sigsetmask(omask);
  365.     readfrom = (1 << rfd2) | (1 << rem);
  366.     do {
  367.         ready = readfrom;
  368.         if (select(16, &ready, 0, 0, 0) < 0) {
  369.             if (errno != EINTR) {
  370.                 (void)fprintf(stderr,
  371.                     "rsh: select: %s.\n", strerror(errno));
  372.                 exit(1);
  373.             }
  374.             continue;
  375.         }
  376.         if (ready & (1 << rfd2)) {
  377.             errno = 0;
  378. #ifdef KERBEROS
  379. #ifdef CRYPT
  380.             if (doencrypt)
  381.                 cc = des_read(rfd2, buf, sizeof buf);
  382.             else
  383. #endif
  384. #endif
  385.                 cc = read(rfd2, buf, sizeof buf);
  386.             if (cc <= 0) {
  387.                 if (errno != EWOULDBLOCK)
  388.                     readfrom &= ~(1 << rfd2);
  389.             } else
  390.                 (void)write(2, buf, cc);
  391.         }
  392.         if (ready & (1 << rem)) {
  393.             errno = 0;
  394. #ifdef KERBEROS
  395. #ifdef CRYPT
  396.             if (doencrypt)
  397.                 cc = des_read(rem, buf, sizeof buf);
  398.             else
  399. #endif
  400. #endif
  401.                 cc = read(rem, buf, sizeof buf);
  402.             if (cc <= 0) {
  403.                 if (errno != EWOULDBLOCK)
  404.                     readfrom &= ~(1 << rem);
  405.             } else
  406.                 (void)write(1, buf, cc);
  407.         }
  408.     } while (readfrom);
  409. }
  410.  
  411. void
  412. sendsig(signo)
  413.     char signo;
  414. {
  415. #ifdef KERBEROS
  416. #ifdef CRYPT
  417.     if (doencrypt)
  418.         (void)des_write(rfd2, &signo, 1);
  419.     else
  420. #endif
  421. #endif
  422.         (void)write(rfd2, &signo, 1);
  423. }
  424.  
  425. #ifdef KERBEROS
  426. /* VARARGS */
  427. warning(va_alist)
  428. va_dcl
  429. {
  430.     va_list ap;
  431.     char *fmt;
  432.  
  433.     (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
  434.     va_start(ap);
  435.     fmt = va_arg(ap, char *);
  436.     vfprintf(stderr, fmt, ap);
  437.     va_end(ap);
  438.     (void)fprintf(stderr, ".\n");
  439. }
  440. #endif
  441.  
  442. char *
  443. copyargs(argv)
  444.     char **argv;
  445. {
  446.     register int cc;
  447.     register char **ap, *p;
  448.     char *args, *malloc();
  449.  
  450.     cc = 0;
  451.     for (ap = argv; *ap; ++ap)
  452.         cc += strlen(*ap) + 1;
  453.     if (!(args = malloc((u_int)cc))) {
  454.         (void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
  455.         exit(1);
  456.     }
  457.     for (p = args, ap = argv; *ap; ++ap) {
  458.         (void)strcpy(p, *ap);
  459.         for (p = strcpy(p, *ap); *p; ++p);
  460.         if (ap[1])
  461.             *p++ = ' ';
  462.     }
  463.     return(args);
  464. }
  465.  
  466. usage()
  467. {
  468.     (void)fprintf(stderr,
  469.         "usage: rsh [-nd%s]%s[-l login] host [command]\n",
  470. #ifdef KERBEROS
  471. #ifdef CRYPT
  472.         "x", " [-k realm] ");
  473. #else
  474.         "", " [-k realm] ");
  475. #endif
  476. #else
  477.         "", " ");
  478. #endif
  479.     exit(1);
  480. }
  481.