summaryrefslogtreecommitdiff
path: root/src/acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/acl.c')
-rw-r--r--src/acl.c482
1 files changed, 226 insertions, 256 deletions
diff --git a/src/acl.c b/src/acl.c
index ece859e..da3e76e 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -33,10 +33,9 @@
/* Define how long an IPv6 address is in bytes (128 bits, 16 bytes) */
#define IPV6_LEN 16
-enum acl_type
-{
- ACL_STRING,
- ACL_NUMERIC,
+enum acl_type {
+ ACL_STRING,
+ ACL_NUMERIC,
};
/*
@@ -44,19 +43,16 @@ enum acl_type
* whether it's an ALLOW or DENY entry, and also whether it's a string
* entry (like a domain name) or an IP entry.
*/
-struct acl_s
-{
- acl_access_t access;
- enum acl_type type;
- union
- {
- char *string;
- struct
- {
- unsigned char octet[IPV6_LEN];
- unsigned char mask[IPV6_LEN];
- } ip;
- } address;
+struct acl_s {
+ acl_access_t access;
+ enum acl_type type;
+ union {
+ char *string;
+ struct {
+ unsigned char octet[IPV6_LEN];
+ unsigned char mask[IPV6_LEN];
+ } ip;
+ } address;
};
/*
@@ -64,7 +60,6 @@ struct acl_s
*/
static vector_t access_list = NULL;
-
/*
* Fills in the netmask array given a numeric value.
*
@@ -77,45 +72,38 @@ inline static int
fill_netmask_array (char *bitmask_string, unsigned char array[],
unsigned int len)
{
- unsigned int i;
- long int mask;
- char *endptr;
-
- errno = 0; /* to distinguish success/failure after call */
- mask = strtol (bitmask_string, &endptr, 10);
-
- /* check for various conversion errors */
- if ((errno == ERANGE && (mask == LONG_MIN || mask == LONG_MAX))
- || (errno != 0 && mask == 0) || (endptr == bitmask_string))
- return -1;
-
- /* valid range for a bit mask */
- if (mask < 0 || 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;
+ unsigned int i;
+ long int mask;
+ char *endptr;
+
+ errno = 0; /* to distinguish success/failure after call */
+ mask = strtol (bitmask_string, &endptr, 10);
+
+ /* check for various conversion errors */
+ if ((errno == ERANGE && (mask == LONG_MIN || mask == LONG_MAX))
+ || (errno != 0 && mask == 0) || (endptr == bitmask_string))
+ return -1;
+
+ /* valid range for a bit mask */
+ if (mask < 0 || 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;
+ return 0;
}
-
/*
* 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
@@ -125,83 +113,76 @@ fill_netmask_array (char *bitmask_string, unsigned char array[],
* -1 on failure
* 0 otherwise.
*/
-int
-insert_acl (char *location, acl_access_t access_type)
+int insert_acl (char *location, acl_access_t access_type)
{
- struct acl_s acl;
- int ret;
- char *p, ip_dst[IPV6_LEN];
-
- assert (location != NULL);
-
- /*
- * If the access list has not been set up, create it.
- */
- if (!access_list)
- {
- access_list = vector_create ();
- if (!access_list)
- {
- log_message (LOG_ERR, "Unable to allocate memory for access list");
- 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.octet, ip_dst, IPV6_LEN);
- memset (acl.address.ip.mask, 0xff, IPV6_LEN);
- }
- else
- {
- /*
- * At this point we're either a hostname or an
- * IP address with a slash.
- */
- p = strchr (location, '/');
- if (p != NULL)
- {
- /*
- * 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;
- memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN);
-
- if (fill_netmask_array (p + 1, &(acl.address.ip.mask[0]), IPV6_LEN)
- < 0)
- return -1;
+ struct acl_s acl;
+ int ret;
+ char *p, ip_dst[IPV6_LEN];
+
+ assert (location != NULL);
+
+ /*
+ * If the access list has not been set up, create it.
+ */
+ if (!access_list) {
+ access_list = vector_create ();
+ if (!access_list) {
+ log_message (LOG_ERR,
+ "Unable to allocate memory for access list");
+ return -1;
+ }
}
- else
- {
- /* In all likelihood a string */
- acl.type = ACL_STRING;
- acl.address.string = safestrdup (location);
- if (!acl.address.string)
- 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.octet, ip_dst, IPV6_LEN);
+ memset (acl.address.ip.mask, 0xff, IPV6_LEN);
+ } else {
+ /*
+ * At this point we're either a hostname or an
+ * IP address with a slash.
+ */
+ p = strchr (location, '/');
+ if (p != NULL) {
+ /*
+ * 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;
+ memcpy (acl.address.ip.octet, ip_dst, IPV6_LEN);
+
+ if (fill_netmask_array
+ (p + 1, &(acl.address.ip.mask[0]), IPV6_LEN)
+ < 0)
+ return -1;
+ } else {
+ /* In all likelihood a string */
+ acl.type = ACL_STRING;
+ acl.address.string = safestrdup (location);
+ if (!acl.address.string)
+ return -1;
+ }
}
- }
-
- /*
- * Add the entry and then clean up.
- */
- ret = vector_append (access_list, &acl, sizeof (struct acl_s));
- safefree (acl.address.string);
- return ret;
+
+ /*
+ * Add the entry and then clean up.
+ */
+ ret = vector_append (access_list, &acl, sizeof (struct acl_s));
+ safefree (acl.address.string);
+ return ret;
}
/*
@@ -217,76 +198,70 @@ static int
acl_string_processing (struct acl_s *acl,
const char *ip_address, const char *string_address)
{
- int match;
- struct addrinfo hints, *res, *ressave;
- size_t test_length, match_length;
- char ipbuf[512];
-
- assert (acl && acl->type == ACL_STRING);
- assert (ip_address && strlen (ip_address) > 0);
- assert (string_address && strlen (string_address) > 0);
-
- /*
- * If the first character of the ACL string is a period, we need to
- * do a string based test only; otherwise, we can do a reverse
- * lookup test as well.
- */
- if (acl->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)
- goto STRING_TEST;
-
- ressave = res;
-
- match = FALSE;
- do
- {
- get_ip_string (res->ai_addr, ipbuf, sizeof (ipbuf));
- if (strcmp (ip_address, ipbuf) == 0)
- {
- match = TRUE;
- break;
- }
+ int match;
+ struct addrinfo hints, *res, *ressave;
+ size_t test_length, match_length;
+ char ipbuf[512];
+
+ assert (acl && acl->type == ACL_STRING);
+ assert (ip_address && strlen (ip_address) > 0);
+ assert (string_address && strlen (string_address) > 0);
+
+ /*
+ * If the first character of the ACL string is a period, we need to
+ * do a string based test only; otherwise, we can do a reverse
+ * lookup test as well.
+ */
+ if (acl->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)
+ goto STRING_TEST;
+
+ ressave = res;
+
+ match = FALSE;
+ do {
+ get_ip_string (res->ai_addr, ipbuf, sizeof (ipbuf));
+ if (strcmp (ip_address, ipbuf) == 0) {
+ match = TRUE;
+ break;
+ }
+ } while ((res = res->ai_next) != NULL);
+
+ freeaddrinfo (ressave);
+
+ if (match) {
+ if (acl->access == ACL_DENY)
+ return 0;
+ else
+ return 1;
+ }
}
- while ((res = res->ai_next) != NULL);
-
- freeaddrinfo (ressave);
-
- if (match)
- {
- if (acl->access == ACL_DENY)
- return 0;
- else
- return 1;
- }
- }
STRING_TEST:
- test_length = strlen (string_address);
- match_length = strlen (acl->address.string);
-
- /*
- * If the string length is shorter than AC string, return a -1 so
- * that the "driver" will skip onto the next control in the list.
- */
- if (test_length < match_length)
- return -1;
-
- if (strcasecmp
- (string_address + (test_length - match_length),
- acl->address.string) == 0)
- {
- if (acl->access == ACL_DENY)
- return 0;
- else
- return 1;
- }
+ test_length = strlen (string_address);
+ match_length = strlen (acl->address.string);
+
+ /*
+ * If the string length is shorter than AC string, return a -1 so
+ * that the "driver" will skip onto the next control in the list.
+ */
+ if (test_length < match_length)
+ return -1;
+
+ if (strcasecmp
+ (string_address + (test_length - match_length),
+ acl->address.string) == 0) {
+ if (acl->access == ACL_DENY)
+ return 0;
+ else
+ return 1;
+ }
- /* Indicate that no tests succeeded, so skip to next control. */
- return -1;
+ /* Indicate that no tests succeeded, so skip to next control. */
+ return -1;
}
/*
@@ -297,30 +272,28 @@ STRING_TEST:
* 0 IP address is denied
* -1 neither allowed nor denied.
*/
-static int
-check_numeric_acl (const struct acl_s *acl, const char *ip)
+static int check_numeric_acl (const struct acl_s *acl, const char *ip)
{
- uint8_t addr[IPV6_LEN], x, y;
- int i;
+ uint8_t addr[IPV6_LEN], x, y;
+ int i;
- assert (acl && acl->type == ACL_NUMERIC);
- assert (ip && strlen (ip) > 0);
+ assert (acl && acl->type == ACL_NUMERIC);
+ assert (ip && strlen (ip) > 0);
- if (full_inet_pton (ip, &addr) <= 0)
- return -1;
+ if (full_inet_pton (ip, &addr) <= 0)
+ return -1;
- for (i = 0; i != IPV6_LEN; ++i)
- {
- x = addr[i] & acl->address.ip.mask[i];
- y = acl->address.ip.octet[i] & acl->address.ip.mask[i];
+ for (i = 0; i != IPV6_LEN; ++i) {
+ x = addr[i] & acl->address.ip.mask[i];
+ y = acl->address.ip.octet[i] & acl->address.ip.mask[i];
- /* If x and y don't match, the IP addresses don't match */
- if (x != y)
- return 0;
- }
+ /* If x and y don't match, the IP addresses don't match */
+ if (x != y)
+ return 0;
+ }
- /* The addresses match, return the permission */
- return (acl->access == ACL_ALLOW);
+ /* The addresses match, return the permission */
+ return (acl->access == ACL_ALLOW);
}
/*
@@ -330,52 +303,49 @@ check_numeric_acl (const struct acl_s *acl, const char *ip)
* 1 if allowed
* 0 if denied
*/
-int
-check_acl (const char *ip, const char *host)
+int check_acl (const char *ip, const char *host)
{
- struct acl_s *acl;
- int perm = 0;
- size_t i;
-
- assert (ip != NULL);
- assert (host != NULL);
-
- /*
- * If there is no access list allow everything.
- */
- if (!access_list)
- return 1;
-
- for (i = 0; i != (size_t)vector_length (access_list); ++i)
- {
- acl = (struct acl_s *)vector_getentry (access_list, i, NULL);
- switch (acl->type)
- {
- case ACL_STRING:
- perm = acl_string_processing (acl, ip, host);
- break;
-
- case ACL_NUMERIC:
- if (ip[0] == '\0')
- continue;
- perm = check_numeric_acl (acl, ip);
- break;
+ struct acl_s *acl;
+ int perm = 0;
+ size_t i;
+
+ assert (ip != NULL);
+ assert (host != NULL);
+
+ /*
+ * If there is no access list allow everything.
+ */
+ if (!access_list)
+ return 1;
+
+ for (i = 0; i != (size_t) vector_length (access_list); ++i) {
+ acl = (struct acl_s *) vector_getentry (access_list, i, NULL);
+ switch (acl->type) {
+ case ACL_STRING:
+ perm = acl_string_processing (acl, ip, host);
+ break;
+
+ case ACL_NUMERIC:
+ if (ip[0] == '\0')
+ continue;
+ perm = check_numeric_acl (acl, ip);
+ break;
+ }
+
+ /*
+ * Check the return value too see if the IP address is
+ * allowed or denied.
+ */
+ if (perm == 0)
+ break;
+ else if (perm == 1)
+ return perm;
}
- /*
- * Check the return value too see if the IP address is
- * allowed or denied.
- */
- if (perm == 0)
- break;
- else if (perm == 1)
- return perm;
- }
-
- /*
- * Deny all connections by default.
- */
- log_message (LOG_NOTICE, "Unauthorized connection from \"%s\" [%s].",
- host, ip);
- return 0;
+ /*
+ * Deny all connections by default.
+ */
+ log_message (LOG_NOTICE, "Unauthorized connection from \"%s\" [%s].",
+ host, ip);
+ return 0;
}