identification_t.matches() supports multiple wildcard counts

This commit is contained in:
Andreas Steffen
2006-07-11 06:11:59 +00:00
parent abba7ecb9d
commit 40f29769fa
2 changed files with 124 additions and 85 deletions
+79 -60
View File
@@ -37,18 +37,25 @@
/** /**
* String mappings for id_type_t. * String mappings for id_type_t.
*/ */
mapping_t id_type_m[] = {
{ID_IPV4_ADDR, "ID_IPV4_ADDR"}, static const char *const id_type_name[] = {
{ID_FQDN, "ID_FQDN"}, "ID_ANY",
{ID_RFC822_ADDR, "ID_RFC822_ADDR"}, "ID_IPV4_ADDR",
{ID_IPV6_ADDR, "ID_IPV6_ADDR"}, "ID_FQDN",
{ID_DER_ASN1_DN, "ID_DER_ASN1_DN"}, "ID_RFC822_ADDR",
{ID_DER_ASN1_GN, "ID_DER_ASN1_GN"}, "ID_IPV4_ADDR_SUBNET",
{ID_KEY_ID, "ID_KEY_ID"}, "ID_IPV6_ADDR",
{ID_ANY, "ID_ANY"}, "ID_IPV6_ADDR_SUBNET",
{MAPPING_END, NULL} "ID_IPV4_ADDR_RANGE",
"ID_IPV6_ADDR_RANGE",
"ID_DER_ASN1_DN",
"ID_DER_ASN1_GN",
"ID_KEY_ID",
}; };
enum_names id_type_names =
{ ID_ANY, ID_KEY_ID, id_type_name, NULL };
/** /**
* X.501 acronyms for well known object identifiers (OIDs) * X.501 acronyms for well known object identifiers (OIDs)
*/ */
@@ -513,7 +520,9 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards)
{ {
return FALSE; return FALSE;
} }
/* the two DNs match! */ /* the two DNs match! */
*wildcards = min(*wildcards, MAX_WILDCARDS);
return TRUE; return TRUE;
} }
@@ -680,11 +689,11 @@ static char *get_string(private_identification_t *this)
*/ */
static bool contains_wildcards(private_identification_t *this) static bool contains_wildcards(private_identification_t *this)
{ {
return this->type == ID_ANY || memchr(this->encoded.ptr, '*', this->encoded.len) != NULL; return this->type == ID_ANY || strchr(this->string, '*') != NULL;
} }
/** /**
* Default implementation of identification_t.equals and identification_t.belongs_to. * Default implementation of identification_t.equals.
* compares encoded chunk for equality. * compares encoded chunk for equality.
*/ */
static bool equals_binary(private_identification_t *this, private_identification_t *other) static bool equals_binary(private_identification_t *this, private_identification_t *other)
@@ -693,7 +702,7 @@ static bool equals_binary(private_identification_t *this, private_identification
} }
/** /**
* Special implementation of identification_t.equals for ID_DER_ASN1_DN * Special implementation of identification_t.equals for ID_DER_ASN1_DN.
*/ */
static bool equals_dn(private_identification_t *this, private_identification_t *other) static bool equals_dn(private_identification_t *this, private_identification_t *other)
{ {
@@ -701,76 +710,86 @@ static bool equals_dn(private_identification_t *this, private_identification_t *
} }
/** /**
* Special implementation of identification_t.belongs_to for ID_RFC822_ADDR/ID_FQDN. * Default implementation of identification_t.matches.
* checks for a wildcard in other-string, and compares it against this-string.
*/ */
static bool belongs_to_wc_string(private_identification_t *this, private_identification_t *other) static bool matches_binary(private_identification_t *this, private_identification_t *other,
int *wildcards)
{ {
char *this_str, *other_str, *pos; *wildcards = 0;
return this->type == other->type && chunk_equals(this->encoded, other->encoded);
}
/**
* Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN.
* Checks for a wildcard in other-string, and compares it against this-string.
*/
static bool matches_string(private_identification_t *this, private_identification_t *other,
int *wildcards)
{
u_int len = other->encoded.len;
if (other->type == ID_ANY) if (other->type == ID_ANY)
{ {
*wildcards = MAX_WILDCARDS;
return TRUE; return TRUE;
} }
if (this->type == other->type) if (this->type != other->type)
return FALSE;
/* try a binary comparison first */
if (equals_binary(this, other))
{ {
/* try a binary comparison first */ *wildcards = 0;
if (equals_binary(this, other)) return TRUE;
{
return TRUE;
}
} }
if (other->encoded.len > 0 &&
*(other->encoded.ptr) == '*') if (len == 0 || this->encoded.len < len)
return FALSE;
/* check for single wildcard at the head of the string */
if (*other->encoded.ptr == '*')
{ {
if (other->encoded.len == 1) *wildcards = 1;
{
/* other contains just a wildcard, and therefore matches anything */ /* single asterisk matches any string */
if (len-- == 1)
return TRUE;
if (memeq(this->encoded.ptr + this->encoded.len - len, other->encoded.ptr + 1, len))
return TRUE; return TRUE;
}
/* We strdup chunks, since they are NOT null-terminated */
this_str = strndupa(this->encoded.ptr, this->encoded.len);
other_str = strndupa(other->encoded.ptr + 1, other->encoded.len - 1);
pos = strstr(this_str, other_str);
if (pos != NULL)
{
/* ok, other is contained in this, but there may be more characters, so check it */
if (strlen(pos) == strlen(other_str))
{
return TRUE;
}
}
} }
return FALSE; return FALSE;
} }
/** /**
* Special implementation of identification_t.belongs_to for ID_ANY. * Special implementation of identification_t.matches for ID_ANY.
* ANY matches only another ANY, but nothing other * ANY matches only another ANY, but nothing other
*/ */
static bool belongs_to_any(private_identification_t *this, private_identification_t *other) static bool matches_any(private_identification_t *this, private_identification_t *other,
int *wildcards)
{ {
*wildcards = 0;
return other->type == ID_ANY; return other->type == ID_ANY;
} }
/** /**
* Special implementation of identification_t.belongs_to for ID_DER_ASN1_DN. * Special implementation of identification_t.matches for ID_DER_ASN1_DN.
* ANY matches any, even ANY, thats why its there... * ANY matches any, even ANY, thats why its there...
*/ */
static bool belongs_to_dn(private_identification_t *this, private_identification_t *other) static bool matches_dn(private_identification_t *this, private_identification_t *other,
int *wildcards)
{ {
int wildcards;
if (other->type == ID_ANY) if (other->type == ID_ANY)
{ {
*wildcards = MAX_WILDCARDS;
return TRUE; return TRUE;
} }
if (this->type == other->type) if (this->type == other->type)
{ {
return match_dn(this->encoded, other->encoded, &wildcards); return match_dn(this->encoded, other->encoded, wildcards);
} }
return FALSE; return FALSE;
} }
@@ -788,7 +807,7 @@ static identification_t *clone(private_identification_t *this)
strcpy(clone->string, this->string); strcpy(clone->string, this->string);
clone->public.equals = this->public.equals; clone->public.equals = this->public.equals;
clone->public.belongs_to = this->public.belongs_to; clone->public.matches = this->public.matches;
return &clone->public; return &clone->public;
} }
@@ -818,7 +837,7 @@ static private_identification_t *identification_create(void)
this->public.destroy = (void (*) (identification_t*))destroy; this->public.destroy = (void (*) (identification_t*))destroy;
/* we use these as defaults, the may be overloaded for special ID types */ /* we use these as defaults, the may be overloaded for special ID types */
this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary;
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))equals_binary; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_binary;
this->string = NULL; this->string = NULL;
this->encoded = CHUNK_INITIALIZER; this->encoded = CHUNK_INITIALIZER;
@@ -849,7 +868,7 @@ identification_t *identification_create_from_string(char *string)
this->string = strdup(string); this->string = strdup(string);
this->type = ID_DER_ASN1_DN; this->type = ID_DER_ASN1_DN;
this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_dn; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_dn;
return &this->public; return &this->public;
} }
else if (strchr(string, '@') == NULL) else if (strchr(string, '@') == NULL)
@@ -863,7 +882,7 @@ identification_t *identification_create_from_string(char *string)
/* any ID will be accepted */ /* any ID will be accepted */
this->type = ID_ANY; this->type = ID_ANY;
this->string = strdup("%any"); this->string = strdup("%any");
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_any; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_any;
return &this->public; return &this->public;
} }
else else
@@ -908,8 +927,7 @@ identification_t *identification_create_from_string(char *string)
{ {
if (*(string + 1) == '#') if (*(string + 1) == '#')
{ {
/* TODO: Pluto handles '#' as hex encoded ASN1/KEY ID. Do we need this, too? /* TODO: Pluto handles '#' as hex encoded ID_KEY_ID. */
Yes, key IDs are needed */
free(this); free(this);
return NULL; return NULL;
} }
@@ -919,7 +937,7 @@ identification_t *identification_create_from_string(char *string)
this->string = strdup(string); this->string = strdup(string);
this->encoded.ptr = strdup(string + 1); this->encoded.ptr = strdup(string + 1);
this->encoded.len = strlen(string + 1); this->encoded.len = strlen(string + 1);
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
return &(this->public); return &(this->public);
} }
} }
@@ -929,7 +947,7 @@ identification_t *identification_create_from_string(char *string)
this->string = strdup(string); this->string = strdup(string);
this->encoded.ptr = strdup(string); this->encoded.ptr = strdup(string);
this->encoded.len = strlen(string); this->encoded.len = strlen(string);
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
return &(this->public); return &(this->public);
} }
} }
@@ -946,11 +964,12 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
private_identification_t *this = identification_create(); private_identification_t *this = identification_create();
this->type = type; this->type = type;
switch (type) switch (type)
{ {
case ID_ANY: case ID_ANY:
this->string = strdup("%any"); this->string = strdup("%any");
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_any; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_any;
break; break;
case ID_IPV4_ADDR: case ID_IPV4_ADDR:
if (encoded.len < sizeof(struct in_addr) || if (encoded.len < sizeof(struct in_addr) ||
@@ -977,12 +996,12 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
case ID_FQDN: case ID_FQDN:
snprintf(buf, sizeof(buf), "@%.*s", encoded.len, encoded.ptr); snprintf(buf, sizeof(buf), "@%.*s", encoded.len, encoded.ptr);
this->string = strdup(buf); this->string = strdup(buf);
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
break; break;
case ID_RFC822_ADDR: case ID_RFC822_ADDR:
snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr); snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
this->string = strdup(buf); this->string = strdup(buf);
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_wc_string; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_string;
break; break;
case ID_DER_ASN1_DN: case ID_DER_ASN1_DN:
snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr); snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr);
@@ -990,7 +1009,7 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en
dntoa(encoded, &buf_chunk); dntoa(encoded, &buf_chunk);
this->string = strdup(buf); this->string = strdup(buf);
this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn;
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to_dn; this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_dn;
break; break;
case ID_DER_ASN1_GN: case ID_DER_ASN1_GN:
this->string = strdup("ASN.1 coded generalName"); this->string = strdup("ASN.1 coded generalName");
+39 -19
View File
@@ -25,9 +25,10 @@
#ifndef IDENTIFICATION_H_ #ifndef IDENTIFICATION_H_
#define IDENTIFICATION_H_ #define IDENTIFICATION_H_
#include "types.h" #include "types.h"
#define MAX_WILDCARDS 14
typedef enum id_type_t id_type_t; typedef enum id_type_t id_type_t;
/** /**
@@ -49,40 +50,58 @@ enum id_type_t {
/** /**
* ID data is a fully-qualified domain name string. * ID data is a fully-qualified domain name string.
* An example of a ID_FQDN is, "example.com". * An example of a ID_FQDN is "example.com".
* The string MUST not contain any terminators (e.g., NULL, CR, etc.). * The string MUST not contain any terminators (e.g., NULL, CR, etc.).
*/ */
ID_FQDN = 2, ID_FQDN = 2,
/** /**
* ID data is a fully-qualified RFC822 email address string, An example of * ID data is a fully-qualified RFC822 email address string.
* a ID_RFC822_ADDR is, "[email protected]". The string MUST * An example of an ID_RFC822_ADDR is "[email protected]".
* not contain any terminators. * The string MUST NOT contain any terminators.
*/ */
ID_RFC822_ADDR = 3, ID_RFC822_ADDR = 3,
/**
* ID data is an IPv4 subnet (IKEv1 only)
*/
ID_IPV4_ADDR_SUBNET = 4,
/** /**
* ID data is a single sixteen (16) octet IPv6 address. * ID data is a single sixteen (16) octet IPv6 address.
*/ */
ID_IPV6_ADDR = 5, ID_IPV6_ADDR = 5,
/** /**
* ID data is the binary DER encoding of an ASN.1 X.500 Distinguished Name * ID data is an IPv6 subnet (IKEv1 only)
* [X.501]. */
*/ ID_IPV6_ADDR_SUBNET = 6,
/**
* ID data is an IPv4 address range (IKEv1 only)
*/
ID_IPV4_ADDR_RANGE = 7,
/**
* ID data is an IPv6 address range (IKEv1 only)
*/
ID_IPV6_ADDR_RANGE = 8,
/**
* ID data is the binary DER encoding of an ASN.1 X.501 Distinguished Name
*/
ID_DER_ASN1_DN = 9, ID_DER_ASN1_DN = 9,
/** /**
* ID data is the binary DER encoding of an ASN.1 X.500 GeneralName * ID data is the binary DER encoding of an ASN.1 X.509 GeneralName
* [X.509]. */
*/
ID_DER_ASN1_GN = 10, ID_DER_ASN1_GN = 10,
/** /**
* ID data is an opaque octet stream which may be used to pass vendor- * ID data is an opaque octet stream which may be used to pass vendor-
* specific information necessary to do certain proprietary * specific information necessary to do certain proprietary
* types of identification. * types of identification.
*/ */
ID_KEY_ID = 11, ID_KEY_ID = 11,
/** /**
@@ -95,7 +114,7 @@ enum id_type_t {
/** /**
* String mappings for id_type_t. * String mappings for id_type_t.
*/ */
extern mapping_t id_type_m[]; extern enum_names id_type_names;
typedef struct identification_t identification_t; typedef struct identification_t identification_t;
@@ -162,7 +181,7 @@ struct identification_t {
bool (*equals) (identification_t *this, identification_t *other); bool (*equals) (identification_t *this, identification_t *other);
/** /**
* @brief Check if an ID belongs to a wildcard ID. * @brief Check if an ID matches a wildcard ID.
* *
* An identification_t may contain wildcards, such as * An identification_t may contain wildcards, such as
* *@strongswan.org. This call checks if a given ID * *@strongswan.org. This call checks if a given ID
@@ -174,9 +193,10 @@ struct identification_t {
* *
* @param this the ID without wildcard * @param this the ID without wildcard
* @param other the ID containing a wildcard * @param other the ID containing a wildcard
* @return TRUE if other belongs to this * @param wildcards returns the number of wildcards
* @return TRUE if match is found
*/ */
bool (*belongs_to) (identification_t *this, identification_t *other); bool (*matches) (identification_t *this, identification_t *other, int *wildcards);
/** /**
* @brief Check if an ID is a wildcard ID. * @brief Check if an ID is a wildcard ID.
@@ -243,7 +263,7 @@ identification_t * identification_create_from_string(char *string);
* @return identification_t object * @return identification_t object
* *
* In contrast to identification_create_from_string(), this constructor never * In contrast to identification_create_from_string(), this constructor never
* returns NULL, even when the conversion to a sring representation fails. * returns NULL, even when the conversion to a string representation fails.
* *
* @ingroup utils * @ingroup utils
*/ */