|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T h
Length: 5582 (0x15ce) Types: TextFile Names: »hosts_access.c«
└─⟦4f9d7c866⟧ Bits:30007245 EUUGD6: Sikkerheds distributionen └─⟦62b59102f⟧ »./log_tcp/3.1.tar.Z« └─⟦1de3ed35f⟧ └─⟦this⟧ »log_tcp/hosts_access.c«
#ifdef HOSTS_ACCESS /* * This module implements a simple but effective form of access control * based on host (or domain) names, netgroup, internet addresses (or network * numbers) and daemon process names, with wild card support. Upon the first * match with an entry in the access-control tables, an optional shell * command is executed. * * Diagnostics are reported through syslog(3). * * Compile with -DHOSTS_ACCESS in order to enable access control. See the * hosts_access(5) manual page for details. * * Compile with -DNETGROUP if your library provides support for netgroups. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. */ #ifndef lint static char sccsid[] = "@(#) hosts_access.c 1.6 91/10/02 23:01:49"; #endif /* System libraries. */ #include <sys/types.h> #include <sys/param.h> #include <stdio.h> #include <syslog.h> #include <ctype.h> extern char *fgets(); extern char *strchr(); extern char *strtok(); extern void exit(); /* Local stuff. */ #include "log_tcp.h" /* Path names of the access control files. */ #define HOSTS_ALLOW "/etc/hosts.allow" #define HOSTS_DENY "/etc/hosts.deny" /* Delimiters for lists of daemons or clients. */ static char sep[] = ", \t"; /* Constants to be used in assignments only, not in comparisons... */ #define YES 1 #define NO 0 /* Forward declarations. */ static int table_match(); static int list_match(); /* hosts_access - host access control facility */ int hosts_access(daemon, client) char *daemon; char *client; { /* * If the (daemon, client) pair is matched by an entry in the file * /etc/hosts.allow, access is granted. Otherwise, if the (daemon, * client) pair is matched by an entry in the file /etc/hosts.deny, * access is denied. Otherwise, access is granted. A non-existent * access-control file is treated as an empty file. */ if (table_match(HOSTS_ALLOW, daemon, client)) return (YES); if (table_match(HOSTS_DENY, daemon, client)) return (NO); return (YES); } /* table_match - match table entries with (daemon, client) pair */ static int table_match(table, daemon, client) char *table; char *daemon; char *client; { FILE *fp; char sv_list[BUFSIZ]; /* becomes list of daemons */ char *cl_list; /* becomes list of clients */ char *sh_cmd; /* becomes optional shell command */ 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 first field is matched * against the daemon process name (argv[0]), the second field against * the host name. A non-existing table is treated as if it were an empty * table. The optional shell command (third field) is executed when the * first match is found. */ if (fp = fopen(table, "r")) { while (match == 0 && 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); continue; } 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'; /* split 1st and 2nd fields */ if ((sh_cmd = strchr(cl_list, ':')) != 0) *sh_cmd++ = '\0'; /* split 2nd and 3rd fields */ match = (list_match(sv_list, daemon) && list_match(cl_list, client)); } } (void) fclose(fp); } if (match && sh_cmd) shell_cmd(sh_cmd, daemon, client); return (match); } /* list_match - match a string against a list of tokens */ static int list_match(list, string) char *list; char *string; { char *tok; 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. If the token has the magic * value "LOCAL", return YES if the string does not contain a "." * character. If the token is a network number, return YES if it matches * the head of the string. If the token looks like a netgroup name, * return YES if the string is a (host) member of the netgroup. * Otherwise, return YES if the token fully matches the string. Note: we * assume that a daemon process name never begins or ends with a "." or * "@" character. */ for (tok = strtok(list, sep); tok; tok = strtok((char *) 0, sep)) { if (tok[0] == '.') { /* domain: match last fields */ if ((str_len = strlen(string)) > (tok_len = strlen(tok)) && strcasecmp(tok, string + str_len - tok_len) == 0) return (YES); #ifdef NETGROUP } else if (tok[0] == '@') { /* netgroup: look it up */ if (innetgr(tok + 1, string, (char *) 0, (char *) 0)) return (YES); #endif } else if (strcasecmp(tok, "ALL") == 0) { /* all: match any */ return (YES); } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ if (strchr(string, '.') == 0) return (YES); } else if (!strcasecmp(tok, string)) { /* match host name or address */ return (YES); } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* net number */ && strncmp(tok, string, tok_len) == 0) { return (YES); } } return (NO); } #endif