summaryrefslogtreecommitdiffhomepage
path: root/src/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/acl.c')
-rw-r--r--src/acl.c161
1 files changed, 22 insertions, 139 deletions
diff --git a/src/acl.c b/src/acl.c
index 75216c3..2d141ba 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -29,16 +29,7 @@
#include "network.h"
#include "sock.h"
#include "sblist.h"
-
-#include <limits.h>
-
-/* Define how long an IPv6 address is in bytes (128 bits, 16 bytes) */
-#define IPV6_LEN 16
-
-enum acl_type {
- ACL_STRING,
- ACL_NUMERIC
-};
+#include "hostspec.h"
/*
* Hold the information about a particular access control. We store
@@ -47,66 +38,9 @@ enum acl_type {
*/
struct acl_s {
acl_access_t access;
- enum acl_type type;
- union {
- char *string;
- struct {
- unsigned char network[IPV6_LEN];
- unsigned char mask[IPV6_LEN];
- } ip;
- } address;
+ struct hostspec h;
};
-/*
- * Fills in the netmask array given a numeric value.
- *
- * Returns:
- * 0 on success
- * -1 on failure (invalid mask value)
- *
- */
-static int
-fill_netmask_array (char *bitmask_string, int v6,
- unsigned char array[], size_t len)
-{
- unsigned int i;
- unsigned long int mask;
- char *endptr;
-
- errno = 0; /* to distinguish success/failure after call */
- mask = strtoul (bitmask_string, &endptr, 10);
-
- /* check for various conversion errors */
- if ((errno == ERANGE && mask == ULONG_MAX)
- || (errno != 0 && mask == 0) || (endptr == bitmask_string))
- return -1;
-
- if (v6 == 0) {
- /* The mask comparison is done as an IPv6 address, so
- * convert to a longer mask in the case of IPv4
- * addresses. */
- mask += 12 * 8;
- }
-
- /* check valid range for a bit mask */
- if (mask > (8 * len))
- return -1;
-
- /* we have a valid range to fill in the array */
- for (i = 0; i != len; ++i) {
- if (mask >= 8) {
- array[i] = 0xff;
- mask -= 8;
- } else if (mask > 0) {
- array[i] = (unsigned char) (0xff << (8 - mask));
- mask = 0;
- } else {
- array[i] = 0;
- }
- }
-
- return 0;
-}
/**
* If the access list has not been set up, create it.
@@ -138,74 +72,19 @@ int
insert_acl (char *location, acl_access_t access_type, acl_list_t *access_list)
{
struct acl_s acl;
- int ret;
- char *p, ip_dst[IPV6_LEN];
assert (location != NULL);
- ret = init_access_list(access_list);
- if (ret != 0) {
+ if (init_access_list(access_list) != 0)
return -1;
- }
/*
* Start populating the access control structure.
*/
memset (&acl, 0, sizeof (struct acl_s));
acl.access = access_type;
-
- /*
- * Check for a valid IP address (the simplest case) first.
- */
- if (full_inet_pton (location, ip_dst) > 0) {
- acl.type = ACL_NUMERIC;
- memcpy (acl.address.ip.network, ip_dst, IPV6_LEN);
- memset (acl.address.ip.mask, 0xff, IPV6_LEN);
- } else {
- int i;
-
- /*
- * At this point we're either a hostname or an
- * IP address with a slash.
- */
- p = strchr (location, '/');
- if (p != NULL) {
- char dst[sizeof(struct in6_addr)];
- int v6;
-
- /*
- * We have a slash, so it's intended to be an
- * IP address with mask
- */
- *p = '\0';
- if (full_inet_pton (location, ip_dst) <= 0)
- return -1;
-
- acl.type = ACL_NUMERIC;
-
- /* Check if the IP address before the netmask is
- * an IPv6 address */
- if (inet_pton(AF_INET6, location, dst) > 0)
- v6 = 1;
- else
- v6 = 0;
-
- if (fill_netmask_array
- (p + 1, v6, &(acl.address.ip.mask[0]), IPV6_LEN)
- < 0)
- return -1;
-
- for (i = 0; i < IPV6_LEN; i++)
- acl.address.ip.network[i] = ip_dst[i] &
- acl.address.ip.mask[i];
- } else {
- /* In all likelihood a string */
- acl.type = ACL_STRING;
- acl.address.string = safestrdup (location);
- if (!acl.address.string)
- return -1;
- }
- }
+ if(hostspec_parse(location, &acl.h) || acl.h.type == HST_NONE)
+ return -1;
if(!sblist_add(*access_list, &acl)) return -1;
return 0;
@@ -229,7 +108,7 @@ acl_string_processing (struct acl_s *acl, const char *ip_address,
size_t test_length, match_length;
char ipbuf[512];
- assert (acl && acl->type == ACL_STRING);
+ assert (acl && acl->h.type == HST_STRING);
assert (ip_address && strlen (ip_address) > 0);
/*
@@ -237,11 +116,11 @@ acl_string_processing (struct acl_s *acl, const char *ip_address,
* do a string based test only; otherwise, we can do a reverse
* lookup test as well.
*/
- if (acl->address.string[0] != '.') {
+ if (acl->h.address.string[0] != '.') {
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
- if (getaddrinfo (acl->address.string, NULL, &hints, &res) != 0)
+ if (getaddrinfo (acl->h.address.string, NULL, &hints, &res) != 0)
goto STRING_TEST;
ressave = res;
@@ -275,7 +154,7 @@ STRING_TEST:
}
test_length = strlen (string_addr);
- match_length = strlen (acl->address.string);
+ match_length = strlen (acl->h.address.string);
/*
* If the string length is shorter than AC string, return a -1 so
@@ -286,7 +165,7 @@ STRING_TEST:
if (strcasecmp
(string_addr + (test_length - match_length),
- acl->address.string) == 0) {
+ acl->h.address.string) == 0) {
if (acl->access == ACL_DENY)
return 0;
else
@@ -310,11 +189,11 @@ static int check_numeric_acl (const struct acl_s *acl, uint8_t addr[IPV6_LEN])
uint8_t x, y;
int i;
- assert (acl && acl->type == ACL_NUMERIC);
+ assert (acl && acl->h.type == HST_NUMERIC);
for (i = 0; i != IPV6_LEN; ++i) {
- x = addr[i] & acl->address.ip.mask[i];
- y = acl->address.ip.network[i];
+ x = addr[i] & acl->h.address.ip.mask[i];
+ y = acl->h.address.ip.network[i];
/* If x and y don't match, the IP addresses don't match */
if (x != y)
@@ -355,12 +234,12 @@ int check_acl (const char *ip, union sockaddr_union *addr, acl_list_t access_lis
for (i = 0; i < sblist_getsize (access_list); ++i) {
acl = sblist_get (access_list, i);
- switch (acl->type) {
- case ACL_STRING:
+ switch (acl->h.type) {
+ case HST_STRING:
perm = acl_string_processing (acl, ip, addr, string_addr);
break;
- case ACL_NUMERIC:
+ case HST_NUMERIC:
if (ip[0] == '\0')
continue;
@@ -368,6 +247,10 @@ int check_acl (const char *ip, union sockaddr_union *addr, acl_list_t access_lis
? check_numeric_acl (acl, numeric_addr)
: -1;
break;
+
+ case HST_NONE:
+ perm = -1;
+ break;
}
/*
@@ -404,8 +287,8 @@ void flush_access_list (acl_list_t access_list)
*/
for (i = 0; i < sblist_getsize (access_list); ++i) {
acl = sblist_get (access_list, i);
- if (acl->type == ACL_STRING) {
- safefree (acl->address.string);
+ if (acl->h.type == HST_STRING) {
+ safefree (acl->h.address.string);
}
}