diff options
Diffstat (limited to '')
-rw-r--r-- | src/acl.c | 214 | ||||
-rw-r--r-- | src/acl.h | 26 |
2 files changed, 240 insertions, 0 deletions
diff --git a/src/acl.c b/src/acl.c new file mode 100644 index 0000000..88f25b2 --- /dev/null +++ b/src/acl.c @@ -0,0 +1,214 @@ +/* $Id: acl.c,v 1.1 2000-09-12 00:08:48 rjkaes Exp $ + * + * This system handles Access Control for use of this daemon. A list of + * domains, or IP addresses (including IP blocks) are stored in a list + * which is then used to compare incoming connections. + * + * Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include "tinyproxy.h" + +#include <ctype.h> + +#include "acl.h" +#include "log.h" +#include "sock.h" + +struct acl_s { + acl_access_t access; + enum { ACL_STRING, ACL_NUMERIC } type; + char *location; + int netmask; + struct acl_s *next; +}; + +static struct acl_s *access_list = NULL; + +/* + * Take a netmask number (between 0 and 32) and returns a network ordered + * value for comparison. Somebody please clean this up. :) + */ +static in_addr_t make_netmask(int netmask_num) +{ + in_addr_t netmasks[] = { + 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, + 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, + 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, + 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, + 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, + 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, + 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, + 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe, + 0xffffffff + }; + + return htonl(netmasks[netmask_num]); +} + +/* + * Inserts a new access control into the list. The function will figure out + * whether the location is an IP address (with optional netmask) or a + * domain name. + * + * Returns: + * -1 on failure + * 0 otherwise. + */ +int insert_acl(char *location, acl_access_t access_type) +{ + unsigned int i; + struct acl_s **rev_acl_ptr, *acl_ptr, *new_acl_ptr; + char *nptr; + + /* + * First check to see if the location is a string or numeric. + */ + for (i = 0; i < strlen(location); i++) { + if (isdigit(location[i]) != 0 && location[i] != '.') { + break; + } + } + + /* + * Add a new ACL to the list. + */ + rev_acl_ptr = &access_list; + acl_ptr = access_list; + while (acl_ptr) { + rev_acl_ptr = &acl_ptr->next; + acl_ptr = acl_ptr->next; + } + new_acl_ptr = malloc(sizeof(struct acl_s)); + if (!new_acl_ptr) { + return -1; + } + + new_acl_ptr->access = access_type; + + if (i != strlen(location)) { + /* We did break early, so this a numeric location. + * Check for a netmask. + */ + new_acl_ptr->type = ACL_NUMERIC; + nptr = strchr(location, '/'); + if (nptr) { + *nptr++ = '\0'; + + new_acl_ptr->netmask = atoi(nptr); + if (new_acl_ptr->netmask < 0 || new_acl_ptr->netmask > 32) { + free(new_acl_ptr); + return -1; + } + } else { + new_acl_ptr->netmask = 32; + } + } else { + new_acl_ptr->type = ACL_STRING; + new_acl_ptr->netmask = 32; + } + + new_acl_ptr->location = strdup(location); + if (!new_acl_ptr->location) { + free(new_acl_ptr); + return -1; + } + + *rev_acl_ptr = new_acl_ptr; + new_acl_ptr->next = acl_ptr; + + return 0; +} + +/* + * Checks where file descriptor is allowed. + * + * Returns: + * 1 if allowed + * 0 if denied + * -1 if error + */ +int check_acl(int fd) +{ + struct acl_s *aclptr; + char ip_address[PEER_IP_LENGTH]; + char string_address[PEER_STRING_LENGTH]; + + /* + * If there is no access list allow everything. + */ + aclptr = access_list; + if (!aclptr) + return 1; + + /* + * Get the IP address and the string domain. + */ + getpeer_ip(fd, ip_address); + getpeer_string(fd, string_address); + + while (aclptr) { + if (aclptr->type == ACL_STRING) { + int test_length = strlen(string_address); + int match_length = strlen(aclptr->location); + + if (test_length < match_length) { + aclptr = aclptr->next; + continue; + } + + if (strcasecmp(string_address + (test_length - match_length), aclptr->location) == 0) { + if (aclptr->access == ACL_DENY) { + log(LOG_NOTICE, "Unauthorized access from %s", string_address); + return 0; + } else { + return 1; + } + } + } else { + struct in_addr test_addr, match_addr; + in_addr_t netmask_addr; + + if (ip_address[0] == 0) { + aclptr = aclptr->next; + continue; + } + + inet_aton(ip_address, &test_addr); + inet_aton(aclptr->location, &match_addr); + + netmask_addr = make_netmask(aclptr->netmask); + + if ((test_addr.s_addr & netmask_addr) == (match_addr.s_addr & netmask_addr)) { + if (aclptr->access == ACL_DENY) { + log(LOG_NOTICE, "Unauthorized access from %s", ip_address); + return 0; + } else { + return 1; + } + } + } + + /* + * Dropped through... go on to the next one. + */ + aclptr = aclptr->next; + } + + + /* + * Deny all connections by default. + */ + log(LOG_NOTICE, "Unauthorized connection from %s [%s]", string_address, ip_address); + return 0; +} diff --git a/src/acl.h b/src/acl.h new file mode 100644 index 0000000..9a4cc2b --- /dev/null +++ b/src/acl.h @@ -0,0 +1,26 @@ +/* $Id: acl.h,v 1.1 2000-09-12 00:08:48 rjkaes Exp $ + * + * See 'acl.c' for detailed information. + * + * Copyright (C) 2000 Robert James Kaes (rjkaes@flarenet.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef _TINYPROXY_ACL_H_ +#define _TINYPROXY_ACL_H_ + +typedef enum { ACL_ALLOW, ACL_DENY } acl_access_t; + +extern int insert_acl(char *location, acl_access_t access_type); +extern int check_acl(int fd); + +#endif |