home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / permissions / part01 / in.rshd / in.rshd.c next >
Encoding:
C/C++ Source or Header  |  1992-03-22  |  6.4 KB  |  308 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. char copyright[] =
  9. "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10.  All rights reserved.\n";
  11. #endif not lint
  12.  
  13. #ifndef lint
  14. static char sccsid[] = "@(#)rshd.c    5.7 (Berkeley) 5/9/86";
  15. #endif not lint
  16.  
  17. /*
  18.  * remote shell server:
  19.  *    remuser\0
  20.  *    locuser\0
  21.  *    command\0
  22.  *    data
  23.  */
  24. #include <sys/ioctl.h>
  25. #include <sys/param.h>
  26. #include <sys/socket.h>
  27. #include <sys/time.h>
  28.  
  29. #include <netinet/in.h>
  30.  
  31. #include <arpa/inet.h>
  32.  
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <pwd.h>
  36. #include <signal.h>
  37. #include <netdb.h>
  38. #include <syslog.h>
  39.  
  40.  
  41. #ifdef PERMS
  42. #include <grp.h>
  43. char *strdup(), *grpnames[NGROUPS+1];
  44. int ngrps, lp;
  45. struct group *grp;
  46. extern int permcheck();
  47. #endif
  48.  
  49. int    errno;
  50. char    *index(), *rindex(), *strncat();
  51. /*VARARGS1*/
  52. int    error();
  53.  
  54. /*ARGSUSED*/
  55. main(argc, argv)
  56.     int argc;
  57.     char **argv;
  58. {
  59.     struct linger linger;
  60.     int on = 1, fromlen;
  61.     struct sockaddr_in from;
  62.  
  63.     openlog("rsh", LOG_PID | LOG_ODELAY, LOG_DAEMON);
  64.     fromlen = sizeof (from);
  65.     if (getpeername(0, &from, &fromlen) < 0) {
  66.         fprintf(stderr, "%s: ", argv[0]);
  67.         perror("getpeername");
  68.         _exit(1);
  69.     }
  70.     if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
  71.         sizeof (on)) < 0)
  72.         syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
  73.     linger.l_onoff = 1;
  74.     linger.l_linger = 60;            /* XXX */
  75.     if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger,
  76.         sizeof (linger)) < 0)
  77.         syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
  78.     doit(dup(0), &from);
  79. }
  80.  
  81. char    username[20] = "USER=";
  82. char    homedir[64] = "HOME=";
  83. char    shell[64] = "SHELL=";
  84. char    *envinit[] =
  85.         {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
  86. char    **environ;
  87.  
  88. doit(f, fromp)
  89.     int f;
  90.     struct sockaddr_in *fromp;
  91. {
  92.     char cmdbuf[NCARGS+1], *cp;
  93.     char locuser[16], remuser[16];
  94.     struct passwd *pwd;
  95.     int s;
  96.     struct hostent *hp;
  97.     char *hostname;
  98.     short port;
  99.     int pv[2], pid, ready, readfrom, cc;
  100.     char buf[BUFSIZ], sig;
  101.     int one = 1;
  102.  
  103.     (void) signal(SIGINT, SIG_DFL);
  104.     (void) signal(SIGQUIT, SIG_DFL);
  105.     (void) signal(SIGTERM, SIG_DFL);
  106. #ifdef DEBUG
  107.     { int t = open("/dev/tty", 2);
  108.       if (t >= 0) {
  109.         ioctl(t, TIOCNOTTY, (char *)0);
  110.         (void) close(t);
  111.       }
  112.     }
  113. #endif
  114.     fromp->sin_port = ntohs((u_short)fromp->sin_port);
  115.     if (fromp->sin_family != AF_INET ||
  116.         fromp->sin_port >= IPPORT_RESERVED) {
  117.         syslog(LOG_ERR, "malformed from address\n");
  118.         exit(1);
  119.     }
  120.     (void) alarm(60);
  121.     port = 0;
  122.     for (;;) {
  123.         char c;
  124.         if (read(f, &c, 1) != 1) {
  125.             syslog(LOG_ERR, "read: %m");
  126.             shutdown(f, 1+1);
  127.             exit(1);
  128.         }
  129.         if (c == 0)
  130.             break;
  131.         port = port * 10 + c - '0';
  132.     }
  133.     (void) alarm(0);
  134.     if (port != 0) {
  135.         int lport = IPPORT_RESERVED - 1;
  136.         s = rresvport(&lport);
  137.         if (s < 0) {
  138.             syslog(LOG_ERR, "can't get stderr port: %m");
  139.             exit(1);
  140.         }
  141.         if (port >= IPPORT_RESERVED) {
  142.             syslog(LOG_ERR, "2nd port not reserved\n");
  143.             exit(1);
  144.         }
  145.         fromp->sin_port = htons((u_short)port);
  146.         if (connect(s, fromp, sizeof (*fromp)) < 0) {
  147.             syslog(LOG_INFO, "connect second port: %m");
  148.             exit(1);
  149.         }
  150.     }
  151.     dup2(f, 0);
  152.     dup2(f, 1);
  153.     dup2(f, 2);
  154.     hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr),
  155.         fromp->sin_family);
  156.     if (hp)
  157.         hostname = hp->h_name;
  158.     else
  159.         hostname = inet_ntoa(fromp->sin_addr);
  160.     getstr(remuser, sizeof(remuser), "remuser");
  161.     getstr(locuser, sizeof(locuser), "locuser");
  162.     getstr(cmdbuf, sizeof(cmdbuf), "command");
  163.     setpwent();
  164.     pwd = getpwnam(locuser);
  165.     if (pwd == NULL) {
  166.         error("Login incorrect.\n");
  167.         exit(1);
  168.     }
  169.     endpwent();
  170.     if (chdir(pwd->pw_dir) < 0) {
  171.         (void) chdir("/");
  172. #ifdef notdef
  173.         error("No remote directory.\n");
  174.         exit(1);
  175. #endif
  176.     }
  177.     if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
  178.         ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
  179.         error("Permission denied.\n");
  180.         exit(1);
  181.     }
  182.  
  183. #ifdef PERMS
  184.     /* build groups so we can look them up in 'permissions'
  185.      * this check is not run for uid 0
  186.      */
  187.     if(pwd->pw_uid != 0) {
  188.         setgrent();
  189.         ngrps = 0;
  190.         grp=getgrgid(pwd->pw_gid);
  191.         grpnames[ngrps++] = strdup(grp->gr_name);
  192.         while( grp=getgrent() ) {
  193.             if(pwd->pw_gid == grp->gr_gid)
  194.                 continue;
  195.             while(*grp->gr_mem) {
  196.                 if( !strcmp(locuser, *grp->gr_mem)) {
  197.                     grpnames[ngrps++] = strdup(grp->gr_name);
  198.                 }
  199.                 grp->gr_mem++;
  200.             }
  201.         }
  202.         endgrent();
  203.         grpnames[ngrps] = NULL;
  204.  
  205.         lp = permcheck(locuser, "rsh", grpnames, NULL);
  206.         if(!lp) {
  207.             syslog(LOG_CRIT,
  208.                 "rsh:%s not permitted", locuser);
  209.             error("Permission denied.\n");
  210.             exit(1);
  211.         }        
  212.     }
  213. #endif
  214.  
  215.     (void) write(2, "\0", 1);
  216.     if (port) {
  217.         if (pipe(pv) < 0) {
  218.             error("Can't make pipe.\n");
  219.             exit(1);
  220.         }
  221.         pid = fork();
  222.         if (pid == -1)  {
  223.             error("Try again.\n");
  224.             exit(1);
  225.         }
  226.         if (pid) {
  227.             (void) close(0); (void) close(1); (void) close(2);
  228.             (void) close(f); (void) close(pv[1]);
  229.             readfrom = (1<<s) | (1<<pv[0]);
  230.             ioctl(pv[0], FIONBIO, (char *)&one);
  231.             /* should set s nbio! */
  232.             do {
  233.                 ready = readfrom;
  234.                 if (select(16, &ready, (fd_set *)0,
  235.                     (fd_set *)0, (struct timeval *)0) < 0)
  236.                     break;
  237.                 if (ready & (1<<s)) {
  238.                     if (read(s, &sig, 1) <= 0)
  239.                         readfrom &= ~(1<<s);
  240.                     else
  241.                         killpg(pid, sig);
  242.                 }
  243.                 if (ready & (1<<pv[0])) {
  244.                     errno = 0;
  245.                     cc = read(pv[0], buf, sizeof (buf));
  246.                     if (cc <= 0) {
  247.                         shutdown(s, 1+1);
  248.                         readfrom &= ~(1<<pv[0]);
  249.                     } else
  250.                         (void) write(s, buf, cc);
  251.                 }
  252.             } while (readfrom);
  253.             exit(0);
  254.         }
  255.         setpgrp(0, getpid());
  256.         (void) close(s); (void) close(pv[0]);
  257.         dup2(pv[1], 2);
  258.     }
  259.     if (*pwd->pw_shell == '\0')
  260.         pwd->pw_shell = "/bin/sh";
  261.     (void) close(f);
  262.     (void) setgid((gid_t)pwd->pw_gid);
  263.     initgroups(pwd->pw_name, pwd->pw_gid);
  264.     (void) setuid((uid_t)pwd->pw_uid);
  265.     environ = envinit;
  266.     strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
  267.     strncat(shell, pwd->pw_shell, sizeof(shell)-7);
  268.     strncat(username, pwd->pw_name, sizeof(username)-6);
  269.     cp = rindex(pwd->pw_shell, '/');
  270.     if (cp)
  271.         cp++;
  272.     else
  273.         cp = pwd->pw_shell;
  274.     execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
  275.     perror(pwd->pw_shell);
  276.     exit(1);
  277. }
  278.  
  279. /*VARARGS1*/
  280. error(fmt, a1, a2, a3)
  281.     char *fmt;
  282.     int a1, a2, a3;
  283. {
  284.     char buf[BUFSIZ];
  285.  
  286.     buf[0] = 1;
  287.     (void) sprintf(buf+1, fmt, a1, a2, a3);
  288.     (void) write(2, buf, strlen(buf));
  289. }
  290.  
  291. getstr(buf, cnt, err)
  292.     char *buf;
  293.     int cnt;
  294.     char *err;
  295. {
  296.     char c;
  297.  
  298.     do {
  299.         if (read(0, &c, 1) != 1)
  300.             exit(1);
  301.         *buf++ = c;
  302.         if (--cnt == 0) {
  303.             error("%s too long\n", err);
  304.             exit(1);
  305.         }
  306.     } while (c != 0);
  307. }
  308.