diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2006-07-11 06:11:59 +0000 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2006-07-11 06:11:59 +0000 |
commit | 40f29769fa884017e8b49a18151a7aa72f0c301a (patch) | |
tree | 8937cc098001ebf9b1de8cbda332384fdc82479e | |
parent | abba7ecb9d454d2cf0b51b17c3442132435b05b0 (diff) | |
download | strongswan-40f29769fa884017e8b49a18151a7aa72f0c301a.tar.bz2 strongswan-40f29769fa884017e8b49a18151a7aa72f0c301a.tar.xz |
identification_t.matches() supports multiple wildcard counts
-rw-r--r-- | src/libstrongswan/utils/identification.c | 139 | ||||
-rw-r--r-- | src/libstrongswan/utils/identification.h | 70 |
2 files changed, 124 insertions, 85 deletions
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 69de9b359..f80e21c63 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -37,18 +37,25 @@ /** * String mappings for id_type_t. */ -mapping_t id_type_m[] = { - {ID_IPV4_ADDR, "ID_IPV4_ADDR"}, - {ID_FQDN, "ID_FQDN"}, - {ID_RFC822_ADDR, "ID_RFC822_ADDR"}, - {ID_IPV6_ADDR, "ID_IPV6_ADDR"}, - {ID_DER_ASN1_DN, "ID_DER_ASN1_DN"}, - {ID_DER_ASN1_GN, "ID_DER_ASN1_GN"}, - {ID_KEY_ID, "ID_KEY_ID"}, - {ID_ANY, "ID_ANY"}, - {MAPPING_END, NULL} + +static const char *const id_type_name[] = { + "ID_ANY", + "ID_IPV4_ADDR", + "ID_FQDN", + "ID_RFC822_ADDR", + "ID_IPV4_ADDR_SUBNET", + "ID_IPV6_ADDR", + "ID_IPV6_ADDR_SUBNET", + "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) */ @@ -513,7 +520,9 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards) { return FALSE; } + /* the two DNs match! */ + *wildcards = min(*wildcards, MAX_WILDCARDS); return TRUE; } @@ -680,11 +689,11 @@ static char *get_string(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. */ 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) { @@ -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. - * checks for a wildcard in other-string, and compares it against this-string. + * Default implementation of identification_t.matches. */ -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) +{ + *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) { - char *this_str, *other_str, *pos; + u_int len = other->encoded.len; if (other->type == ID_ANY) { + *wildcards = MAX_WILDCARDS; 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 */ - if (equals_binary(this, other)) - { - return TRUE; - } + *wildcards = 0; + 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) - { - /* other contains just a wildcard, and therefore matches anything */ + *wildcards = 1; + + /* 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; - } - /* 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; } /** - * 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 */ -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; } /** - * 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... */ -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) { + *wildcards = MAX_WILDCARDS; return TRUE; } if (this->type == other->type) { - return match_dn(this->encoded, other->encoded, &wildcards); + return match_dn(this->encoded, other->encoded, wildcards); } return FALSE; } @@ -788,7 +807,7 @@ static identification_t *clone(private_identification_t *this) strcpy(clone->string, this->string); clone->public.equals = this->public.equals; - clone->public.belongs_to = this->public.belongs_to; + clone->public.matches = this->public.matches; return &clone->public; } @@ -818,7 +837,7 @@ static private_identification_t *identification_create(void) this->public.destroy = (void (*) (identification_t*))destroy; /* 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.belongs_to = (bool (*) (identification_t*,identification_t*))equals_binary; + this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_binary; this->string = NULL; this->encoded = CHUNK_INITIALIZER; @@ -849,7 +868,7 @@ identification_t *identification_create_from_string(char *string) this->string = strdup(string); this->type = ID_DER_ASN1_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; } else if (strchr(string, '@') == NULL) @@ -863,7 +882,7 @@ identification_t *identification_create_from_string(char *string) /* any ID will be accepted */ this->type = ID_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; } else @@ -908,8 +927,7 @@ identification_t *identification_create_from_string(char *string) { if (*(string + 1) == '#') { - /* TODO: Pluto handles '#' as hex encoded ASN1/KEY ID. Do we need this, too? - Yes, key IDs are needed */ + /* TODO: Pluto handles '#' as hex encoded ID_KEY_ID. */ free(this); return NULL; } @@ -919,7 +937,7 @@ identification_t *identification_create_from_string(char *string) this->string = strdup(string); this->encoded.ptr = strdup(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); } } @@ -929,7 +947,7 @@ identification_t *identification_create_from_string(char *string) this->string = strdup(string); this->encoded.ptr = strdup(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); } } @@ -946,11 +964,12 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en private_identification_t *this = identification_create(); this->type = type; + switch (type) { case ID_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; case ID_IPV4_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: snprintf(buf, sizeof(buf), "@%.*s", encoded.len, encoded.ptr); 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; case ID_RFC822_ADDR: snprintf(buf, sizeof(buf), "%.*s", encoded.len, encoded.ptr); 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; case ID_DER_ASN1_DN: 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); this->string = strdup(buf); 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; case ID_DER_ASN1_GN: this->string = strdup("ASN.1 coded generalName"); diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index f6b82e97f..5b13d02a0 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -25,9 +25,10 @@ #ifndef IDENTIFICATION_H_ #define IDENTIFICATION_H_ - #include "types.h" +#define MAX_WILDCARDS 14 + typedef enum id_type_t id_type_t; /** @@ -36,7 +37,7 @@ typedef enum id_type_t id_type_t; * @ingroup utils */ enum id_type_t { - + /** * private type which matches any other id. */ @@ -49,40 +50,58 @@ enum id_type_t { /** * 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.). */ ID_FQDN = 2, - + /** - * ID data is a fully-qualified RFC822 email address string, An example of - * a ID_RFC822_ADDR is, "jsmith@example.com". The string MUST - * not contain any terminators. + * ID data is a fully-qualified RFC822 email address string. + * An example of an ID_RFC822_ADDR is "jsmith@example.com". + * The string MUST NOT contain any terminators. */ 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_IPV6_ADDR = 5, - + /** - * ID data is the binary DER encoding of an ASN.1 X.500 Distinguished Name - * [X.501]. - */ + * ID data is an IPv6 subnet (IKEv1 only) + */ + 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 data is the binary DER encoding of an ASN.1 X.500 GeneralName - * [X.509]. - */ + * ID data is the binary DER encoding of an ASN.1 X.509 GeneralName + */ ID_DER_ASN1_GN = 10, - + /** * ID data is an opaque octet stream which may be used to pass vendor- - * specific information necessary to do certain proprietary - * types of identification. - */ + * specific information necessary to do certain proprietary + * types of identification. + */ ID_KEY_ID = 11, /** @@ -95,7 +114,7 @@ enum 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; @@ -162,7 +181,7 @@ struct identification_t { 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 * *@strongswan.org. This call checks if a given ID @@ -174,9 +193,10 @@ struct identification_t { * * @param this the ID without 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. @@ -243,7 +263,7 @@ identification_t * identification_create_from_string(char *string); * @return identification_t object * * 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 */ |