# 2.11BSD#431 - /usr/src/libexec/tcpd/safe_finger.c

##### Functions

    cleanup           X
    main              X
    perror_exit       X
    pipe_stdin        X

##### Variables

    finger_pid        X
    path              X

##### Macros

    FINGER_PROGRAM    X
    INPUT_LENGTH      X
    LINE_LENGTH       X
    TIME_LIMIT        X
    UNPRIV_NAME       X
    UNPRIV_UGID       X

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

#### Defined functions

cleanup defined in line 45; used 1 times

- in line 89

main defined in line 52; never used
perror_exit defined in line 138; used 6 times

- in line 164, 173-177(2), 183-186(2), 192

pipe_stdin defined in line 147; used 1 times

- in line 84

#### Defined variables

finger_pid defined in line 43; used 4 times

- in line 48, 84, 131-133(2)

path defined in line 34; used 1 times

- in line 79

sccsid defined in line 18; never used

#### Defined macros

FINGER_PROGRAM defined in line 39; used 1 times

- in line 83

INPUT_LENGTH defined in line 37; used 1 times

- in line 96

LINE_LENGTH defined in line 38; used 1 times

- in line 105

TIME_LIMIT defined in line 36; used 1 times

- in line 90

UNPRIV_NAME defined in line 40; used 1 times

- in line 67

UNPRIV_UGID defined in line 41; used 2 times

- in line 71-72(2)

Last modified: 1994-12-28 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 970 |