home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / securelib / part02 / _okaddr.c next >
Encoding:
C/C++ Source or Header  |  1993-03-12  |  7.8 KB  |  281 lines

  1. /*
  2.  *  securelib:  a package to enhance network security.
  3.  *
  4.  *  Written by William LeFebvre, EECS Department, Northwestern University
  5.  *  Internet address:  phil@eecs.nwu.edu
  6.  *
  7.  *  Configuration file code added by Sam Horrocks (sam@ics.uci.edu).
  8.  */
  9.  
  10. /* Edit these def's to customize for your site. */
  11.  
  12. #ifndef CONF_FILE
  13. #define CONF_FILE "/etc/securelib.conf" /* Name of the config file           *
  14.                      * (may be overridden by cc)         */
  15. #endif
  16.  
  17. #define MAX_LINES 8                     /* Maximum number of config lines    *
  18.                                          * that can apply to one process     */
  19.  
  20. #define ENV_NAME "SL_NAME"              /* Name of the environment variable  *
  21.                                          * to use to filter the config file. */
  22.  
  23. #define ALL_NAME "all"                  /* Name used in config file for      *
  24.                                          * lines that apply to all processes */
  25.  
  26. #define STAT_TIMEOUT (60*60)            /* Time to wait before stat'ing      *
  27.                                          * the config file again.            */
  28.  
  29. #define MAX_TOKEN 40                    /* Maximum size of one token in the  *
  30.                                          * configuration file                */
  31.  
  32. #define BUF_SIZE 80                     /* Size of buffer used to read file. */
  33.  
  34.  
  35. #include <sys/types.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <sys/stat.h>
  39. #include <sys/time.h>
  40. #include <stdio.h>
  41. #include <ctype.h>
  42.  
  43. struct conf_line {                      /* Info about config file line */
  44.     u_long adr, mask
  45. };
  46.  
  47. static int next_token();
  48. extern char *getenv();
  49. extern time_t time();
  50. extern u_long inet_addr();
  51.  
  52.  
  53. /*
  54.  * _ok_address - check the sockaddr "addr" (of length "addrlen") to see
  55.  *               if it corresponds to an acceptable host.  Return true
  56.  *               (non-zero) if acceptable, otherwise return false (zero).
  57.  *               If "addr" is NULL or if "addrlen" is not long enough,
  58.  *               then use "getpeername" on socket "s" to determine the
  59.  *               address of the connecting host.
  60.  */
  61.  
  62. _ok_address(s, addr, addrlen)
  63.  
  64. int s;
  65. struct sockaddr *addr;
  66. int addrlen;
  67.  
  68. {
  69.     struct sockaddr peername;    /* in case we need to use getpeername */
  70.     int peernamelen;             /* ditto */
  71.     u_long ip_addr;
  72.  
  73.     /* was addr actually used and was it sufficient? */
  74.     if (addr == (struct sockaddr *)0 || addrlen < (2+2+sizeof(struct in_addr)))
  75.     {
  76.     /* no, so get the info with getpeername */
  77.     peernamelen = sizeof(peername);
  78.     if (getpeername(s, &peername, &peernamelen) < 0)
  79.     {
  80.         /* not sure what the appropriate thing to do here is... */
  81.         /* so we will return "not ok" just to be safe */
  82.         return(0);
  83.     }
  84.  
  85.     /* for remainder of this function: */
  86.     addr = &peername;
  87.     }
  88.  
  89.     /* now, verify the socket type */
  90.     if (addr->sa_family == AF_INET)
  91.     {
  92.     static struct conf_line conf[MAX_LINES];
  93.     static int nconf;
  94.     static time_t last_stat_time, last_mtime;
  95.     struct timeval now;
  96.     int i;
  97.  
  98.     (void) gettimeofday(&now, (struct timezone*)0);
  99.  
  100.     /* Decide whether to read our config file */
  101.     if (last_stat_time == 0 ||
  102.         (now.tv_sec - last_stat_time) > STAT_TIMEOUT)
  103.     {
  104.         struct stat stbuf;
  105.         char *conf_file = CONF_FILE;
  106.         char *my_name = getenv(ENV_NAME);
  107.         char fil_buf[BUF_SIZE], buf[MAX_TOKEN];
  108.         FILE fil;
  109.  
  110.         last_stat_time = now.tv_sec;
  111.         bzero((char*)&fil, sizeof(fil));
  112.  
  113.         /* Stat the config file.  If it changed, open it */
  114.         if (stat(conf_file, &stbuf) != -1 &&
  115.         last_mtime != stbuf.st_mtime &&
  116.         freopen(conf_file, "r", &fil) == &fil)
  117.         {
  118.         /* Update the timestamp */
  119.         last_mtime = stbuf.st_mtime;
  120.         nconf = 0;
  121.  
  122.         /* Use the buffer on the stack instead of malloc'ing */
  123.         setbuffer(&fil, fil_buf, sizeof(fil_buf));
  124.  
  125.         /* Grab the "name" */
  126.         while ((i = next_token(&fil, buf, sizeof(buf))) != EOF)
  127.         {
  128.             /* If only token on the line, ignore */
  129.             if (i == '\n') continue;
  130.  
  131.             /* Comment -- read until end of line then next line */
  132.             if (buf[0] == '#') {
  133.             while (next_token(&fil, buf, sizeof(buf)) == 0) ;
  134.             continue;
  135.             }
  136.  
  137.             /*
  138.              * Check to make sure this says "all" or that it matches
  139.              * the name given in the environment variable.
  140.              */
  141.             if (strcmp(buf, ALL_NAME) == 0 ||
  142.                 (my_name != NULL && strcmp(buf, my_name) == 0))
  143.             {
  144.             /* Get next token, if last on line, ignore */
  145.             if (next_token(&fil, buf, sizeof(buf)) != 0)
  146.                 continue;
  147.  
  148.             /* Got address */
  149.             conf[nconf].adr = inet_addr(buf);
  150.  
  151.             /* Get next token (mask) */
  152.             i = next_token(&fil, buf, sizeof(buf));
  153.  
  154.             /* Only ignore if we got no text at all */
  155.             if (i != EOF)
  156.             {
  157.                 /* Add to list, quit if array is full */
  158.                 conf[nconf++].mask = inet_addr(buf);
  159.                 if (nconf == MAX_LINES) break;
  160.             }
  161.  
  162.             /* If not at end-of-line, keep reading til we are */
  163.             /* why isn't this outside the if(strcmp...) ??? */
  164.             while (i == 0)
  165.             {
  166.                 i = next_token(&fil, buf, sizeof(buf));
  167.             }
  168.             }
  169.         }
  170.         (void) fclose(&fil);
  171.         }
  172.     }
  173.  
  174.     /* Config lines now in memory so start checking address */
  175.     /* grab just the address */
  176.     ip_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  177.  
  178.     /*
  179.      * Go through the conf array, turn off the bits given by the mask
  180.      * and then compare the result with the address.  A match means
  181.      * that this address is ok.
  182.      */
  183.     for (i = 0; i < nconf; ++i)
  184.     {
  185.         if ((ip_addr & ~conf[i].mask) == conf[i].adr) return 1;
  186.     }
  187.  
  188.     /* no match, so we can't approve the address */
  189.     return 0;
  190.     }
  191.     else
  192.     {
  193.     /* we don't know how to handle non-Internet connections, so
  194.        we will give them all blanket approval */
  195.     return 1;
  196.     }
  197.     /*NOTREACHED*/
  198. }
  199.  
  200. /*
  201.  * Grab one token out of fp.  Defined as the next string of non-whitespace
  202.  * in the file.  After we get the token, continue reading until EOF, end of
  203.  * line or the next token.  If it's the last token on the line, return '\n'
  204.  * for the value.  If we get EOF before reading a token, return EOF.  In all
  205.  * other cases return 0.
  206.  */
  207. static int next_token(fp, buf, bufsz)
  208.  
  209. FILE *fp;
  210. char *buf;
  211. int bufsz;
  212.  
  213. {
  214.     int c;
  215.     char *eb = buf+(bufsz-1);
  216.  
  217.     /* Discard inital whitespace */
  218.     while (isspace(c = getc(fp))) ;
  219.  
  220.     /* EOF seen before any token so return EOF */
  221.     if (c == EOF) return -1;
  222.  
  223.     /* Form a token in buf */
  224.     do {
  225.     if (buf < eb) *buf++ = c;
  226.     c = getc(fp);
  227.     } while (!isspace(c) && c != EOF);
  228.     *buf = '\0';
  229.  
  230.     /* Discard trailing tabs and spaces */
  231.     while (c == ' ' || c == '\t') c = getc(fp);
  232.  
  233.     /* Put back the char that was non-whitespace (putting back EOF is ok) */
  234.     (void) ungetc(c, fp);
  235.  
  236.     /* If we ended with a newline, return that, otherwise return 0 */
  237.     return (c == '\n' ? '\n' : 0);
  238. }
  239.  
  240. /*
  241.  * _addrcpy(to, tolenptr, from, fromlen)
  242.  *
  243.  * copy an address from "from" to "to".  "fromlen" is the length of the
  244.  * from address.  "tolenptr" points to the length that is available in
  245.  * the buffer "to" and will be modified the reflect the actual number of
  246.  * bytes copied.  Under no circumstances will more than *tolenptr bytes
  247.  * be copied (even if *tolenptr == 0).
  248.  *
  249.  * This is a global routine and is used in the modified accept call.
  250.  */
  251.  
  252. _addrcpy(to, tolenp, from, fromlen)
  253.  
  254. struct sockaddr *to, *from;
  255. int *tolenp;
  256. int fromlen;
  257.  
  258. {
  259.     register int amt = 0;
  260.  
  261.     /*
  262.      *  Explanation:  amt is initialized to 0.  If to is null, then the
  263.      *  second half of the && conditional is not done (K&R guarantees
  264.      *  this).  Therefore, amt gets set to *tolenp iff amt != NULL.
  265.      *  Then, if *tolenp is greater than 0, the lesser of amt (*tolenp)
  266.      *  and fromlen is used as the length of the copy.  Thus, amt is always
  267.      *  the number of bytes copied, even if that number is 0 (indicating
  268.      *  that no copying was done).
  269.      */
  270.  
  271.     if (to != (struct sockaddr *)0 && (amt = *tolenp) > 0)
  272.     {
  273.     if (fromlen < amt)
  274.     {
  275.         amt = fromlen;
  276.     }
  277.     bcopy((char *)from, (char *)to, amt);
  278.     }
  279.     *tolenp = amt;
  280. }
  281.