home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume16 / log_tcp / part01 / hosts_access.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-01-10  |  4.0 KB  |  143 lines

  1. #ifdef HOSTS_ACCESS
  2.  
  3.  /*
  4.   * This module implements a simple but effective form of access control
  5.   * based on host (or domain) names and service names, with wild card
  6.   * support. Diagnostics are logged through syslog(3).
  7.   * 
  8.   * Compile with -DHOSTS_ACCESS in order to enable access control. See the
  9.   * hosts_access(5) manual page for details.
  10.   * 
  11.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  12.   */
  13.  
  14. #ifndef lint
  15. static char sccsid[] = "@(#) hosts_access.c 1.1 91/01/06 22:30:28";
  16. #endif
  17.  
  18. #include <stdio.h>
  19. #include <syslog.h>
  20.  
  21. extern char *fgets();
  22. extern char *strchr();
  23. extern char *strtok();
  24. extern void exit();
  25.  
  26.  /* Path names of the access control files. */
  27.  
  28. #define HOSTS_ALLOW    "/etc/hosts.allow"
  29. #define HOSTS_DENY    "/etc/hosts.deny"
  30.  
  31.  /* Delimiters for lists of services or hosts or domains. */
  32.  
  33. static char sep[] = ", \t";
  34.  
  35.  /* Constants to be used in assignments only, not in comparisons... */
  36.  
  37. #define    YES        1
  38. #define    NO        0
  39.  
  40. /* hosts_access - host access control facility */
  41.  
  42. hosts_access(service, host)
  43. char   *service;
  44. char   *host;
  45. {
  46.  
  47.     /*
  48.      * If the (service,host) pair is found in the /etc/hosts.allow file,
  49.      * access is granted. Otherwise, if the (service,host) pair is found in
  50.      * the /etc/hosts.deny file, access is denied. Otherwise, access is
  51.      * granted. 
  52.      * 
  53.      * If a connection is refused, we write a syslog record, but do not notify
  54.      * the client.
  55.      */
  56.  
  57.     if (table_match(HOSTS_ALLOW, service, host))
  58.     return;
  59.     if (table_match(HOSTS_DENY, service, host)) {
  60.     syslog(LOG_WARNING, "refused connect from %s", host);
  61.     exit(0);
  62.     }
  63. }
  64.  
  65. /* table_match - match table entries with (service, host) pair */
  66.  
  67. table_match(table, service, host)
  68. char   *table;
  69. char   *service;
  70. char   *host;
  71. {
  72.     FILE   *fp;
  73.     char    sv_list[BUFSIZ];        /* becomes list of services */
  74.     char   *cl_list;            /* becomes list of clients */
  75.     int     match = NO;
  76.     int     end;
  77.  
  78.     /*
  79.      * Process the table one line at a time. Lines that begin with a '#'
  80.      * character are ignored. Non-comment lines are broken at the ':'
  81.      * character (we complain if there is none). The left part is matched
  82.      * against the service name (argv[0]), the right part against the host
  83.      * name. A non-existing table is treated as if it were an empty table.
  84.      */
  85.  
  86.     if (fp = fopen(table, "r")) {
  87.     while (!match && fgets(sv_list, sizeof(sv_list), fp)) {
  88.         if (sv_list[end = strlen(sv_list) - 1] != '\n') {
  89.         syslog(LOG_ERR, "%s: line exceeds STDIO buffer size", table);
  90.         } else {
  91.         sv_list[end] = '\0';        /* strip trailing newline */
  92.         }
  93.         if (sv_list[0] == '#') {        /* skip comments */
  94.         continue;
  95.         } else if ((cl_list = strchr(sv_list, ':')) == 0) {
  96.         syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
  97.         continue;
  98.         } else {
  99.         *cl_list++ = '\0';        /* break line at ":" */
  100.         match = (list_match(sv_list, service)
  101.              && list_match(cl_list, host));
  102.         }
  103.     }
  104.     (void) fclose(fp);
  105.     }
  106.     return (match);
  107. }
  108.  
  109. /* list_match - match a string against a list of tokens */
  110.  
  111. list_match(list, string)
  112. char   *list;
  113. char   *string;
  114. {
  115.     char   *token;
  116.     int     tok_len;
  117.     int     str_len;
  118.  
  119.     /*
  120.      * Process tokens one at a time. If a token has the magic value "ALL" the
  121.      * match always succeeds. If the token is a domain name, return YES if it
  122.      * matches the last fields of the string. Otherwise, return YES if the
  123.      * token fully matches the string. Note: we assume that a service name
  124.      * never begins with a "." character.
  125.      */
  126.  
  127.     for (token = strtok(list, sep); token; token = strtok((char *) 0, sep)) {
  128.     if (strcasecmp(token, "ALL") == 0) {    /* magic: always matches */
  129.         return (YES);
  130.     } else if (token[0] == '.') {        /* domain: match last fields */
  131.         if ((str_len = strlen(string)) >= (tok_len = strlen(token))
  132.         && strcasecmp(token, string + str_len - tok_len) == 0)
  133.         return (YES);
  134.     } else {                /* other: match full string */
  135.         if (strcasecmp(token, string) == 0)
  136.         return (YES);
  137.     }
  138.     }
  139.     return (NO);
  140. }
  141.  
  142. #endif
  143.