home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-A.06 / NETKIT-A / NetKit-A-0.06 / tcp_wrapper-6.3 / safe_finger.c,v < prev    next >
Encoding:
Text File  |  1994-05-23  |  4.8 KB  |  206 lines

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