home *** CD-ROM | disk | FTP | other *** search
- #ifdef HOSTS_ACCESS
-
- /*
- * This module implements a simple but effective form of access control
- * based on host (or domain) names and service names, with wild card
- * support. Diagnostics are logged through syslog(3).
- *
- * Compile with -DHOSTS_ACCESS in order to enable access control. See the
- * hosts_access(5) manual page for details.
- *
- * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#) hosts_access.c 1.1 91/01/06 22:30:28";
- #endif
-
- #include <stdio.h>
- #include <syslog.h>
-
- extern char *fgets();
- extern char *strchr();
- extern char *strtok();
- extern void exit();
-
- /* Path names of the access control files. */
-
- #define HOSTS_ALLOW "/etc/hosts.allow"
- #define HOSTS_DENY "/etc/hosts.deny"
-
- /* Delimiters for lists of services or hosts or domains. */
-
- static char sep[] = ", \t";
-
- /* Constants to be used in assignments only, not in comparisons... */
-
- #define YES 1
- #define NO 0
-
- /* hosts_access - host access control facility */
-
- hosts_access(service, host)
- char *service;
- char *host;
- {
-
- /*
- * If the (service,host) pair is found in the /etc/hosts.allow file,
- * access is granted. Otherwise, if the (service,host) pair is found in
- * the /etc/hosts.deny file, access is denied. Otherwise, access is
- * granted.
- *
- * If a connection is refused, we write a syslog record, but do not notify
- * the client.
- */
-
- if (table_match(HOSTS_ALLOW, service, host))
- return;
- if (table_match(HOSTS_DENY, service, host)) {
- syslog(LOG_WARNING, "refused connect from %s", host);
- exit(0);
- }
- }
-
- /* table_match - match table entries with (service, host) pair */
-
- table_match(table, service, host)
- char *table;
- char *service;
- char *host;
- {
- FILE *fp;
- char sv_list[BUFSIZ]; /* becomes list of services */
- char *cl_list; /* becomes list of clients */
- int match = NO;
- int end;
-
- /*
- * Process the table one line at a time. Lines that begin with a '#'
- * character are ignored. Non-comment lines are broken at the ':'
- * character (we complain if there is none). The left part is matched
- * against the service name (argv[0]), the right part against the host
- * name. A non-existing table is treated as if it were an empty table.
- */
-
- if (fp = fopen(table, "r")) {
- while (!match && fgets(sv_list, sizeof(sv_list), fp)) {
- if (sv_list[end = strlen(sv_list) - 1] != '\n') {
- syslog(LOG_ERR, "%s: line exceeds STDIO buffer size", table);
- } else {
- sv_list[end] = '\0'; /* strip trailing newline */
- }
- if (sv_list[0] == '#') { /* skip comments */
- continue;
- } else if ((cl_list = strchr(sv_list, ':')) == 0) {
- syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
- continue;
- } else {
- *cl_list++ = '\0'; /* break line at ":" */
- match = (list_match(sv_list, service)
- && list_match(cl_list, host));
- }
- }
- (void) fclose(fp);
- }
- return (match);
- }
-
- /* list_match - match a string against a list of tokens */
-
- list_match(list, string)
- char *list;
- char *string;
- {
- char *token;
- int tok_len;
- int str_len;
-
- /*
- * Process tokens one at a time. If a token has the magic value "ALL" the
- * match always succeeds. If the token is a domain name, return YES if it
- * matches the last fields of the string. Otherwise, return YES if the
- * token fully matches the string. Note: we assume that a service name
- * never begins with a "." character.
- */
-
- for (token = strtok(list, sep); token; token = strtok((char *) 0, sep)) {
- if (strcasecmp(token, "ALL") == 0) { /* magic: always matches */
- return (YES);
- } else if (token[0] == '.') { /* domain: match last fields */
- if ((str_len = strlen(string)) >= (tok_len = strlen(token))
- && strcasecmp(token, string + str_len - tok_len) == 0)
- return (YES);
- } else { /* other: match full string */
- if (strcasecmp(token, string) == 0)
- return (YES);
- }
- }
- return (NO);
- }
-
- #endif
-