home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume39 / tcp_wrappers / part03 / safe_finger.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-29  |  4.6 KB  |  181 lines

  1.  /*
  2.   * safe_finger - finger client wrapper that protects against nasty stuff
  3.   * from finger servers. Use this program for automatic reverse finger
  4.   * probes, not the raw finger command.
  5.   * 
  6.   * Build with: cc -o safe_finger safe_finger.c
  7.   * 
  8.   * The problem: some programs may react to stuff in the first column. Other
  9.   * programs may get upset by thrash anywhere on a line. File systems may
  10.   * fill up as the finger server keeps sending data. Text editors may bomb
  11.   * out on extremely long lines. The code below takes care of all this
  12.   * badness.
  13.   * 
  14.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  15.   */
  16.  
  17. #ifndef lint
  18. static char sccsid[] = "@(#) safe_finger.c 1.2 93/08/26 23:49:40";
  19. #endif
  20.  
  21. /* System libraries */
  22.  
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <pwd.h>
  28.  
  29. extern void exit();
  30.  
  31. /* Local stuff */
  32.  
  33. char    path[] = "PATH=/bin:/usr/bin:/usr/ucb:/etc:/usr/etc:/usr/sbin";
  34.  
  35. #define    INPUT_LENGTH    100000        /* Do not keep listinging forever */
  36. #define    LINE_LENGTH    128        /* Editors can choke on long lines */
  37. #define    FINGER_PROGRAM    "finger"    /* Most, if not all, UNIX systems */
  38. #define    UNPRIV_NAME    "nobody"    /* Preferred privilege level */
  39. #define    UNPRIV_UGID    32767        /* Default uid and gid */
  40.  
  41. main(argc, argv)
  42. int     argc;
  43. char  **argv;
  44. {
  45.     int     c;
  46.     int     line_length = 0;
  47.     int     finger_status;
  48.     int     wait_pid;
  49.     int     finger_pid;
  50.     int     input_count = 0;
  51.     struct passwd *pwd;
  52.  
  53.     /*
  54.      * First of all, let's don't run with superuser privileges.
  55.      */
  56.     if (getuid() == 0 || geteuid() == 0) {
  57.     if ((pwd = getpwnam(UNPRIV_NAME)) && pwd->pw_uid > 0) {
  58.         setgid(pwd->pw_gid);
  59.         setuid(pwd->pw_uid);
  60.     } else {
  61.         setgid(UNPRIV_UGID);
  62.         setuid(UNPRIV_UGID);
  63.     }
  64.     }
  65.  
  66.     /*
  67.      * Redirect our standard input through the raw finger command.
  68.      */
  69.     if (putenv(path)) {
  70.     fprintf(stderr, "putenv: out of memory");
  71.     exit(1);
  72.     }
  73.     argv[0] = FINGER_PROGRAM;
  74.     finger_pid = pipe_stdin(argv);
  75.  
  76.     /*
  77.      * Main filter loop.
  78.      */
  79.     while ((c = getchar()) != EOF) {
  80.     if (input_count++ >= INPUT_LENGTH) {    /* don't listen forever */
  81.         fclose(stdin);
  82.         printf("\n\n Input truncated to %d bytes...\n", input_count - 1);
  83.         break;
  84.     }
  85.     if (c == '\n') {            /* good: end of line */
  86.         putchar(c);
  87.         line_length = 0;
  88.     } else {
  89.         if (line_length >= LINE_LENGTH) {    /* force end of line */
  90.         printf("\\\n");
  91.         line_length = 0;
  92.         }
  93.         if (line_length == 0) {        /* protect left margin */
  94.         putchar(' ');
  95.         line_length++;
  96.         }
  97.         if (isascii(c) && (isprint(c) || isspace(c))) {    /* text */
  98.         if (c == '\\') {
  99.             putchar(c);
  100.             line_length++;
  101.         }
  102.         putchar(c);
  103.         line_length++;
  104.         } else {                /* quote all other thash */
  105.         printf("\\%03o", c & 0377);
  106.         line_length += 4;
  107.         }
  108.     }
  109.     }
  110.  
  111.     /*
  112.      * Wait until the finger child process has terminated and account for its
  113.      * exit status. Which will always be zero on most systems.
  114.      */
  115.     while ((wait_pid = wait(&finger_status)) != -1 && wait_pid != finger_pid)
  116.      /* void */ ;
  117.     return (wait_pid != finger_pid || finger_status != 0);
  118. }
  119.  
  120. /* perror_exit - report system error text and terminate */
  121.  
  122. void    perror_exit(text)
  123. char   *text;
  124. {
  125.     perror(text);
  126.     exit(1);
  127. }
  128.  
  129. /* pipe_stdin - pipe stdin through program (from my ANSI to OLD C converter) */
  130.  
  131. int     pipe_stdin(argv)
  132. char  **argv;
  133. {
  134.     int     pipefds[2];
  135.     int     pid;
  136.     int     i;
  137.     struct stat st;
  138.  
  139.     /*
  140.      * The code that sets up the pipe requires that file descriptors 0,1,2
  141.      * are already open. All kinds of mysterious things will happen if that
  142.      * is not the case. The following loops makes sure that descriptors 0,1,2
  143.      * are set up properly.
  144.      */
  145.  
  146.     for (i = 0; i < 3; i++) {
  147.     if (fstat(i, &st) == -1 && open("/dev/null", 2) != i)
  148.         perror_exit("open /dev/null");
  149.     }
  150.  
  151.     /*
  152.      * Set up the pipe that interposes the command into our standard input
  153.      * stream.
  154.      */
  155.  
  156.     if (pipe(pipefds))
  157.     perror_exit("pipe");
  158.  
  159.     switch (pid = fork()) {
  160.     case -1:                    /* error */
  161.     perror_exit("fork");
  162.     /* NOTREACHED */
  163.     case 0:                    /* child */
  164.     (void) close(pipefds[0]);        /* close reading end */
  165.     (void) close(1);            /* connect stdout to pipe */
  166.     if (dup(pipefds[1]) != 1)
  167.         perror_exit("dup");
  168.     (void) close(pipefds[1]);        /* close redundant fd */
  169.     (void) execvp(argv[0], argv);
  170.     perror_exit(argv[0]);
  171.     /* NOTREACHED */
  172.     default:                    /* parent */
  173.     (void) close(pipefds[1]);        /* close writing end */
  174.     (void) close(0);            /* connect stdin to pipe */
  175.     if (dup(pipefds[0]) != 0)
  176.         perror_exit("dup");
  177.     (void) close(pipefds[0]);        /* close redundant fd */
  178.     return (pid);
  179.     }
  180. }
  181.