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