home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / rsh / rsh.c < prev   
C/C++ Source or Header  |  1996-09-28  |  11KB  |  506 lines

  1. /*-
  2.  * Copyright (c) 1983, 1990, 1993, 1994
  3.  *    The Regents of the University of California.  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. static char copyright[] =
  36. "@(#) Copyright (c) 1983, 1990, 1993, 1994\n\
  37.     The Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)rsh.c    8.4 (Berkeley) 4/29/95";
  42. #endif /* not lint */
  43.  
  44. /*
  45.  * $Source: /gd4/gnu/inetutils/rsh/RCS/rsh.c,v $
  46.  * $Header: /gd4/gnu/inetutils/rsh/RCS/rsh.c,v 1.6 1996/08/16 20:06:55 miles Exp $
  47.  */
  48.  
  49. #ifdef HAVE_CONFIG_H
  50. #include <config.h>
  51. #endif
  52.  
  53. #include <sys/types.h>
  54. #include <sys/signal.h>
  55. #include <sys/socket.h>
  56. #include <sys/ioctl.h>
  57. #include <sys/file.h>
  58. #ifdef HAVE_FD_SET_MACROS_IN_SYS_TIME_H
  59. #include <sys/time.h>
  60. #endif
  61.  
  62. #include <netinet/in.h>
  63. #include <netdb.h>
  64.  
  65. #include <err.h>
  66. #include <errno.h>
  67. #include <pwd.h>
  68. #include <signal.h>
  69. #include <stdio.h>
  70. #include <stdlib.h>
  71. #include <string.h>
  72. #include <unistd.h>
  73. #ifdef HAVE_STDARG_H
  74. #include <stdarg.h>
  75. #else
  76. #include <varargs.h>
  77. #endif
  78. #include <getopt.h>
  79.  
  80. #ifdef KERBEROS
  81. #include <kerberosIV/des.h>
  82. #include <kerberosIV/krb.h>
  83.  
  84. CREDENTIALS cred;
  85. Key_schedule schedule;
  86. int use_kerberos = 1, doencrypt;
  87. char dst_realm_buf[REALM_SZ], *dest_realm;
  88. extern char *krb_realmofhost();
  89. #endif
  90.  
  91. /*
  92.  * rsh - remote shell
  93.  */
  94. int    rfd2;
  95.  
  96. char   *copyargs __P((char **));
  97. void    sendsig __P((int));
  98. void    talk __P((int, long, pid_t, int));
  99. void    usage __P((void));
  100. void    warning __P(());
  101.  
  102. int
  103. main(argc, argv)
  104.     int argc;
  105.     char **argv;
  106. {
  107.     struct passwd *pw;
  108.     struct servent *sp;
  109.     long omask;
  110.     int argoff, asrsh, ch, dflag, nflag, one, rem;
  111.     pid_t pid;
  112.     uid_t uid;
  113.     char *args, *host, *p, *user;
  114.  
  115. #ifndef HAVE___PROGNAME
  116.     extern char *__progname;
  117.     __progname = argv[0];
  118. #endif
  119.  
  120.     argoff = asrsh = dflag = nflag = 0;
  121.     one = 1;
  122.     host = user = NULL;
  123.  
  124.     /* if called as something other than "rsh", use it as the host name */
  125.     if (p = strrchr(argv[0], '/'))
  126.         ++p;
  127.     else
  128.         p = argv[0];
  129.     if (strcmp(p, "rsh"))
  130.         host = p;
  131.     else
  132.         asrsh = 1;
  133.  
  134.     /* handle "rsh host flags" */
  135.     if (!host && argc > 2 && argv[1][0] != '-') {
  136.         host = argv[1];
  137.         argoff = 1;
  138.     }
  139.  
  140. #ifdef KERBEROS
  141. #ifdef CRYPT
  142. #define    OPTIONS    "8KLdek:l:nwx"
  143. #else
  144. #define    OPTIONS    "8KLdek:l:nw"
  145. #endif
  146. #else
  147. #define    OPTIONS    "8KLdel:nw"
  148. #endif
  149.     while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
  150.         switch(ch) {
  151.         case 'K':
  152. #ifdef KERBEROS
  153.             use_kerberos = 0;
  154. #endif
  155.             break;
  156.         case 'L':    /* -8Lew are ignored to allow rlogin aliases */
  157.         case 'e':
  158.         case 'w':
  159.         case '8':
  160.             break;
  161.         case 'd':
  162.             dflag = 1;
  163.             break;
  164.         case 'l':
  165.             user = optarg;
  166.             break;
  167. #ifdef KERBEROS
  168.         case 'k':
  169.             dest_realm = dst_realm_buf;
  170.             strncpy(dest_realm, optarg, REALM_SZ);
  171.             break;
  172. #endif
  173.         case 'n':
  174.             nflag = 1;
  175.             break;
  176. #ifdef KERBEROS
  177. #ifdef CRYPT
  178.         case 'x':
  179.             doencrypt = 1;
  180.             des_set_key(cred.session, schedule);
  181.             break;
  182. #endif
  183. #endif
  184.         case '?':
  185.         default:
  186.             usage();
  187.         }
  188.     optind += argoff;
  189.  
  190.     /* if haven't gotten a host yet, do so */
  191.     if (!host && !(host = argv[optind++]))
  192.         usage();
  193.  
  194.     /* if no further arguments, must have been called as rlogin. */
  195.     if (!argv[optind]) {
  196.         if (asrsh)
  197.             *argv = "rlogin";
  198.         execv(PATH_RLOGIN, argv);
  199.         err(1, "can't exec %s", PATH_RLOGIN);
  200.     }
  201.  
  202.     argc -= optind;
  203.     argv += optind;
  204.  
  205.     if (!(pw = getpwuid(uid = getuid())))
  206.         errx(1, "unknown user id");
  207.     /* Accept user1@host format, though "-l user2" overrides user1 */
  208.     p = strchr(host, '@');
  209.     if (p) {
  210.         *p = '\0';
  211.         if (!user && p > host)
  212.             user = host;
  213.         host = p + 1;
  214.         if (*host == '\0')
  215.             usage();
  216.     }
  217.     if (!user)
  218.         user = pw->pw_name;
  219.  
  220. #ifdef KERBEROS
  221. #ifdef CRYPT
  222.     /* -x turns off -n */
  223.     if (doencrypt)
  224.         nflag = 0;
  225. #endif
  226. #endif
  227.  
  228.     args = copyargs(argv);
  229.  
  230.     sp = NULL;
  231. #ifdef KERBEROS
  232.     if (use_kerberos) {
  233.         sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
  234.         if (sp == NULL) {
  235.             use_kerberos = 0;
  236.             warning("can't get entry for %s/tcp service",
  237.                 doencrypt ? "ekshell" : "kshell");
  238.         }
  239.     }
  240. #endif
  241.     if (sp == NULL)
  242.         sp = getservbyname("shell", "tcp");
  243.     if (sp == NULL)
  244.         errx(1, "shell/tcp: unknown service");
  245.  
  246. #ifdef KERBEROS
  247. try_connect:
  248.     if (use_kerberos) {
  249.         struct hostent *hp;
  250.  
  251.         /* fully qualify hostname (needed for krb_realmofhost) */
  252.         hp = gethostbyname(host);
  253.         if (hp != NULL && !(host = strdup(hp->h_name)))
  254.             err(1, NULL);
  255.  
  256.         rem = KSUCCESS;
  257.         errno = 0;
  258.         if (dest_realm == NULL)
  259.             dest_realm = krb_realmofhost(host);
  260.  
  261. #ifdef CRYPT
  262.         if (doencrypt)
  263.             rem = krcmd_mutual(&host, sp->s_port, user, args,
  264.                 &rfd2, dest_realm, &cred, schedule);
  265.         else
  266. #endif
  267.             rem = krcmd(&host, sp->s_port, user, args, &rfd2,
  268.                 dest_realm);
  269.         if (rem < 0) {
  270.             use_kerberos = 0;
  271.             sp = getservbyname("shell", "tcp");
  272.             if (sp == NULL)
  273.                 errx(1, "shell/tcp: unknown service");
  274.             if (errno == ECONNREFUSED)
  275.                 warning("remote host doesn't support Kerberos");
  276.             if (errno == ENOENT)
  277.                 warning("can't provide Kerberos auth data");
  278.             goto try_connect;
  279.         }
  280.     } else {
  281.         if (doencrypt)
  282.             errx(1, "the -x flag requires Kerberos authentication");
  283.         rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
  284.     }
  285. #else
  286.     rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
  287. #endif
  288.  
  289.     if (rem < 0)
  290.         exit(1);
  291.  
  292.     if (rfd2 < 0)
  293.         errx(1, "can't establish stderr");
  294.     if (dflag) {
  295.         if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
  296.             sizeof(one)) < 0)
  297.             warn("setsockopt");
  298.         if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
  299.             sizeof(one)) < 0)
  300.             warn("setsockopt");
  301.     }
  302.  
  303.     (void)setuid(uid);
  304.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
  305.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  306.         (void)signal(SIGINT, sendsig);
  307.     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  308.         (void)signal(SIGQUIT, sendsig);
  309.     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
  310.         (void)signal(SIGTERM, sendsig);
  311.  
  312.     if (!nflag) {
  313.         pid = fork();
  314.         if (pid < 0)
  315.             err(1, "fork");
  316.     }
  317.  
  318. #ifdef KERBEROS
  319. #ifdef CRYPT
  320.     if (!doencrypt)
  321. #endif
  322. #endif
  323.     {
  324.         (void)ioctl(rfd2, FIONBIO, &one);
  325.         (void)ioctl(rem, FIONBIO, &one);
  326.     }
  327.  
  328.     talk(nflag, omask, pid, rem);
  329.  
  330.     if (!nflag)
  331.         (void)kill(pid, SIGKILL);
  332.     exit(0);
  333. }
  334.  
  335. void
  336. talk(nflag, omask, pid, rem)
  337.     int nflag;
  338.     long omask;
  339.     pid_t pid;
  340.     int rem;
  341. {
  342.     int cc, wc;
  343.     fd_set readfrom, ready, rembits;
  344.     char *bp, buf[BUFSIZ];
  345.  
  346.     if (!nflag && pid == 0) {
  347.         (void)close(rfd2);
  348.  
  349. reread:        errno = 0;
  350.         if ((cc = read(0, buf, sizeof buf)) <= 0)
  351.             goto done;
  352.         bp = buf;
  353.  
  354. rewrite:    
  355.         FD_ZERO(&rembits);
  356.         FD_SET(rem, &rembits);
  357.         if (select(16, 0, &rembits, 0, 0) < 0) {
  358.             if (errno != EINTR)
  359.                 err(1, "select");
  360.             goto rewrite;
  361.         }
  362.         if (!FD_ISSET(rem, &rembits))
  363.             goto rewrite;
  364. #ifdef KERBEROS
  365. #ifdef CRYPT
  366.         if (doencrypt)
  367.             wc = des_write(rem, bp, cc);
  368.         else
  369. #endif
  370. #endif
  371.             wc = write(rem, bp, cc);
  372.         if (wc < 0) {
  373.             if (errno == EWOULDBLOCK)
  374.                 goto rewrite;
  375.             goto done;
  376.         }
  377.         bp += wc;
  378.         cc -= wc;
  379.         if (cc == 0)
  380.             goto reread;
  381.         goto rewrite;
  382. done:
  383.         (void)shutdown(rem, 1);
  384.         exit(0);
  385.     }
  386.  
  387.     (void)sigsetmask(omask);
  388.     FD_ZERO(&readfrom);
  389.     FD_SET(rfd2, &readfrom);
  390.     FD_SET(rem, &readfrom);
  391.     do {
  392.         ready = readfrom;
  393.         if (select(16, &ready, 0, 0, 0) < 0) {
  394.             if (errno != EINTR)
  395.                 err(1, "select");
  396.             continue;
  397.         }
  398.         if (FD_ISSET(rfd2, &ready)) {
  399.             errno = 0;
  400. #ifdef KERBEROS
  401. #ifdef CRYPT
  402.             if (doencrypt)
  403.                 cc = des_read(rfd2, buf, sizeof buf);
  404.             else
  405. #endif
  406. #endif
  407.                 cc = read(rfd2, buf, sizeof buf);
  408.             if (cc <= 0) {
  409.                 if (errno != EWOULDBLOCK)
  410.                     FD_CLR(rfd2, &readfrom);
  411.             } else
  412.                 (void)write(2, buf, cc);
  413.         }
  414.         if (FD_ISSET(rem, &ready)) {
  415.             errno = 0;
  416. #ifdef KERBEROS
  417. #ifdef CRYPT
  418.             if (doencrypt)
  419.                 cc = des_read(rem, buf, sizeof buf);
  420.             else
  421. #endif
  422. #endif
  423.                 cc = read(rem, buf, sizeof buf);
  424.             if (cc <= 0) {
  425.                 if (errno != EWOULDBLOCK)
  426.                     FD_CLR(rem, &readfrom);
  427.             } else
  428.                 (void)write(1, buf, cc);
  429.         }
  430.     } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom));
  431. }
  432.  
  433. void
  434. sendsig(sig)
  435.     int sig;
  436. {
  437.     char signo;
  438.  
  439.     signo = sig;
  440. #ifdef KERBEROS
  441. #ifdef CRYPT
  442.     if (doencrypt)
  443.         (void)des_write(rfd2, &signo, 1);
  444.     else
  445. #endif
  446. #endif
  447.         (void)write(rfd2, &signo, 1);
  448. }
  449.  
  450. #ifdef KERBEROS
  451. /* VARARGS */
  452. void
  453. warning(va_alist)
  454. va_dcl
  455. {
  456.     va_list ap;
  457.     char *fmt;
  458.  
  459.     (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
  460.     va_start(ap);
  461.     fmt = va_arg(ap, char *);
  462.     vfprintf(stderr, fmt, ap);
  463.     va_end(ap);
  464.     (void)fprintf(stderr, ".\n");
  465. }
  466. #endif
  467.  
  468. char *
  469. copyargs(argv)
  470.     char **argv;
  471. {
  472.     int cc;
  473.     char **ap, *args, *p;
  474.  
  475.     cc = 0;
  476.     for (ap = argv; *ap; ++ap)
  477.         cc += strlen(*ap) + 1;
  478.     if (!(args = malloc((u_int)cc)))
  479.         err(1, NULL);
  480.     for (p = args, ap = argv; *ap; ++ap) {
  481.         (void)strcpy(p, *ap);
  482.         for (p = strcpy(p, *ap); *p; ++p);
  483.         if (ap[1])
  484.             *p++ = ' ';
  485.     }
  486.     return (args);
  487. }
  488.  
  489. void
  490. usage()
  491. {
  492.  
  493.     (void)fprintf(stderr,
  494.         "usage: rsh [-nd%s]%s[-l login] [login@]host [command]\n",
  495. #ifdef KERBEROS
  496. #ifdef CRYPT
  497.         "x", " [-k realm] ");
  498. #else
  499.         "", " [-k realm] ");
  500. #endif
  501. #else
  502.         "", " ");
  503. #endif
  504.     exit(1);
  505. }
  506.