home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3543 / undomserver.c < prev   
Encoding:
C/C++ Source or Header  |  1991-06-26  |  5.5 KB  |  219 lines

  1. /* Public domain. */
  2.  
  3. #include <stdio.h>
  4. #include <signal.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/stat.h>
  8. #include <sys/wait.h>
  9. #include <sys/un.h>
  10. #include <sys/time.h>
  11. #include "dupdup.h"
  12. #include "malloc.h"
  13. #include "errno.h"
  14. #include "username.h"
  15. #include "env.h"
  16. #include "getopt.h"
  17. #include "numfiles.h"
  18.  
  19. static int flagprintlocal = 0;
  20. static int flagverbose = 1;
  21. static struct sockaddr_un sabind;
  22. static int flagbindok = 0;
  23.  
  24. SIGRET sigterm()
  25. {
  26.  if (flagbindok)
  27.    unlink(sabind.sun_path);
  28.  exit(0);
  29. }
  30.  
  31. SIGRET sigchld()
  32. {
  33.  wait((union wait *) 0); /*XXX*/
  34. }
  35.  
  36. static char errbuf[500];
  37. void die(n,s) int n; char *s;
  38. { if (flagverbose) fprintf(stderr,"undomserver: fatal: %s\n",s); exit(n); }
  39. void dies(n,s,t) int n; char *s; char *t;
  40. { if (flagverbose) fprintf(stderr,"undomserver: fatal: %s%s\n",s,t); exit(n); }
  41. void diep(n,s) int n; char *s;
  42. { if (flagverbose) sprintf(errbuf,"undomserver: fatal: %s",s); perror(errbuf); exit(n); }
  43. void warnp(s) char *s;
  44. { if (flagverbose) sprintf(errbuf,"undomserver: warning: %s",s); perror(errbuf); }
  45. void warnsp(s,t) char *s; char *t;
  46. { if (flagverbose) sprintf(errbuf,"undomserver: warning: %s%s",s,t); perror(errbuf); }
  47.  
  48. main(argc,argv,envp)
  49. int argc;
  50. char *argv[];
  51. char *envp[];
  52. {
  53.  int s;
  54.  int dummy;
  55.  int t;
  56.  int *d;
  57.  int tdup;
  58.  int numfiles;
  59.  static struct sockaddr_un sa;
  60.  int uid;
  61.  int arguid;
  62.  int i;
  63.  char undomlocal[200]; /*XXX*/
  64.  char undomremote[300]; /*XXX*/
  65.  unsigned char urlen;
  66.  int opt;
  67.  
  68.  while ((opt = getopt(argc,argv,"qQ4")) != EOF)
  69.    switch(opt)
  70.     {
  71.      case 'q':
  72.        flagverbose = 0;
  73.        break;
  74.      case 'Q':
  75.        flagverbose = 1;
  76.        break;
  77.      case '4':
  78.        flagprintlocal = 1;
  79.        break;
  80.      case '?':
  81.        break; /*XXX*/
  82.      default:
  83.        break; /*XXX*/
  84.     }
  85.  argc -= optind; argv += optind;
  86.  
  87.  if (argc < 3)
  88.    die(1,"need at least three arguments");
  89.  
  90.  uid = getuid();
  91.  if (username2uid(argv[0],&arguid) == -1)
  92.    dies(2,"cannot figure out username ",argv[0]);
  93.  if (uid && (uid != arguid))
  94.    dies(3,"permission denied for username ",argv[0]);
  95.  
  96.  for (i = 0;argv[0][i];++i)
  97.    if ((argv[0][i] == '/') || (argv[0][i] == ':') || (argv[0][i] == '.') || (argv[0][i] == '\n'))
  98.      dies(4,"illegal characters in username ",argv[0]);
  99.  
  100.  for (i = 0;argv[1][i];++i)
  101.    if ((argv[1][i] == '/') || (argv[1][i] == '.') || (argv[0][i] == '\n'))
  102.      dies(5,"illegal characters in service ",argv[1]);
  103.  
  104.  close(6);
  105.  close(7); /* XXX: these have implications that should be documented */
  106.  
  107.  numfiles = NUMFILES;
  108.  d = (int *) malloc(numfiles * sizeof(int));
  109.  if (!d)
  110.    die(6,"cannot malloc");
  111.  for (i = 0;i < numfiles;++i)
  112.    d[i] = -1;
  113.  
  114.  if (strlen(UNDOMDIR) + strlen(argv[0]) + strlen(argv[1]) + 1 > 100) /*XXX*/
  115.    die(8,"server socket name too long");
  116.  sprintf(sabind.sun_path,"%s/%s:%s",UNDOMDIR,argv[0],argv[1]);
  117.  
  118.  signal(SIGTERM,sigterm);
  119.  signal(SIGINT,sigterm);
  120.  signal(SIGCHLD,sigchld);
  121.  
  122.  if (env_init() == -1)
  123.    die(11,"cannot init environment");
  124.  if (env_put("PROTO=UNDOM") == -1)
  125.    die(11,"out of memory putting PROTO into environment");
  126.  sprintf(undomlocal,"UNDOMLOCAL=%s:%s",argv[0],argv[1]);
  127.  if (env_put(undomlocal) == -1)
  128.    die(11,"out of memory putting UNDOMLOCAL into environment");
  129.  sprintf(undomremote,"UNDOMREMOTE=");
  130.  
  131.  if (flagprintlocal)
  132.   {
  133.    FILE *fd4;
  134.    fd4 = fdopen(4,"w");
  135.    if (!fd4)
  136.      die(1,"cannot print UNDOMLOCAL on fd 4");
  137.    fprintf(fd4,"%s:%s\n",argv[0],argv[1]);
  138.    fclose(fd4);
  139.    close(4); /* just in case */
  140.   }
  141.  
  142.  s = socket(AF_UNIX,SOCK_STREAM,0);
  143.  if (s == -1)
  144.    diep(7,"cannot create server socket");
  145.  sabind.sun_family = AF_UNIX;
  146.  if (bind(s,(struct sockaddr *) &sabind,strlen(sabind.sun_path) + 2) == -1)
  147.    dies(9,"cannot bind server socket ",sabind.sun_path);
  148.  /* XXX: there's a race right here */
  149.  flagbindok = 1;
  150.  if (listen(s,5) == -1) 
  151.   {
  152.    unlink(sabind.sun_path);
  153.    diep(10,"cannot listen on server socket");
  154.   }
  155.  
  156.  for (;;)
  157.   {
  158.    /* XXX: don't accept too many requests at once? */
  159.    dummy = sizeof(sa);
  160.    t = accept(s,(struct sockaddr *) &sa,&dummy);
  161.    if (t == -1) /* so when can this happen? */
  162.     {
  163.      switch(errno)
  164.       {
  165.        case SIGCHLD: break; /*XXX*/
  166.        case EINTR: break; /*XXX*/
  167.        case EMFILE: sleep(1); break; /*XXX*/
  168.        case ENFILE: sleep(1); break; /*XXX*/
  169.        default: ; /*XXX*/
  170.       }
  171.      continue;
  172.     }
  173.  
  174.    if (((i = read(t,&urlen,1)) == -1) || (!i))
  175.      continue; /* XXX: error message? */
  176.    if (urlen == 0) /* XXX: undomkiller */
  177.      sigterm();
  178.  
  179.    switch(fork())
  180.     {
  181.      case -1:
  182.        warnp("cannot fork");
  183.        break;
  184.  
  185.      case 0:
  186.  
  187.        if (urlen > sizeof(undomremote) - strlen(undomremote) - 5)
  188.      die(1,"remote username too long");
  189.        if (read(t,undomremote + strlen(undomremote),urlen) < urlen)
  190.      die(1,"cannot read remote username");
  191.        undomremote[sizeof(undomremote) - 1] = 0; /* just in case */
  192.        /* XXX: warn if it's not already just the right length? */
  193.  
  194.        if (env_put(undomremote) == -1)
  195.      die(1,"out of memory putting UNDOMREMOTE into environment");
  196.  
  197.        tdup = dup(t);
  198.        if (tdup == -1)
  199.      diep(1,"cannot dup connection to client");
  200.  
  201.        /* Now put t into descriptor 6 and tdup into descriptor 7. */
  202.        /* XXX: should check that t and tdup are small enough */
  203.        d[t] = 6;
  204.        d[tdup] = 7;
  205.        if (dupdup(d,numfiles) == -1)
  206.      diep(1,"cannot dup connection to client");
  207.  
  208.        if (setreuid(uid,uid) == -1)
  209.      diep(1,"cannot setreuid"); /* will never happen */
  210.        execvp(argv[2],argv + 2);
  211.        warnsp("cannot exec ",argv[2]);
  212.        exit(1);
  213.  
  214.      default:
  215.        close(t);
  216.     }
  217.   }
  218. }
  219.