diff options
Diffstat (limited to 'src/libstrongswan/credentials/auth_cfg.c')
-rw-r--r-- | src/libstrongswan/credentials/auth_cfg.c | 330 |
1 files changed, 207 insertions, 123 deletions
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 0646b0e2c..fd2cee607 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -1,6 +1,6 @@ /* + * Copyright (C) 2008-2012 Tobias Brunner * Copyright (C) 2007-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -56,6 +56,42 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, "HELPER_REVOCATION_CERT", ); +/** + * Check if the given rule is a rule for which there may be multiple values. + */ +static inline bool is_multi_value_rule(auth_rule_t type) +{ + switch (type) + { + case AUTH_RULE_AUTH_CLASS: + case AUTH_RULE_EAP_TYPE: + case AUTH_RULE_EAP_VENDOR: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_IDENTITY: + case AUTH_RULE_EAP_IDENTITY: + case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: + case AUTH_RULE_SUBJECT_CERT: + case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_SUBJECT_HASH_URL: + case AUTH_RULE_MAX: + return FALSE; + case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_CRL_VALIDATION: + case AUTH_RULE_GROUP: + case AUTH_RULE_CA_CERT: + case AUTH_RULE_IM_CERT: + case AUTH_RULE_CERT_POLICY: + case AUTH_HELPER_IM_CERT: + case AUTH_HELPER_IM_HASH_URL: + case AUTH_HELPER_REVOCATION_CERT: + return TRUE; + } + return FALSE; +} + typedef struct private_auth_cfg_t private_auth_cfg_t; /** @@ -93,6 +129,8 @@ typedef struct { enumerator_t *inner; /** current entry */ entry_t *current; + /** types we have already enumerated */ + bool enumerated[AUTH_RULE_MAX]; } entry_enumerator_t; /** @@ -102,11 +140,22 @@ static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value) { entry_t *entry; - if (this->inner->enumerate(this->inner, &entry)) + while (this->inner->enumerate(this->inner, &entry)) { + if (!is_multi_value_rule(entry->type) && this->enumerated[entry->type]) + { + continue; + } + this->enumerated[entry->type] = TRUE; this->current = entry; - *type = entry->type; - *value = entry->value; + if (type) + { + *type = entry->type; + } + if (value) + { + *value = entry->value; + } return TRUE; } return FALSE; @@ -126,15 +175,123 @@ METHOD(auth_cfg_t, create_enumerator, enumerator_t*, { entry_enumerator_t *enumerator; - enumerator = malloc_thing(entry_enumerator_t); - enumerator->inner = this->entries->create_enumerator(this->entries); - enumerator->public.enumerate = (void*)enumerate; - enumerator->public.destroy = (void*)entry_enumerator_destroy; - enumerator->current = NULL; + INIT(enumerator, + .public = { + .enumerate = (void*)enumerate, + .destroy = (void*)entry_enumerator_destroy, + }, + .inner = this->entries->create_enumerator(this->entries), + ); return &enumerator->public; } /** + * Create an entry from the given arguments. + */ +static entry_t *entry_create(auth_rule_t type, va_list args) +{ + entry_t *this = malloc_thing(entry_t); + + this->type = type; + switch (type) + { + case AUTH_RULE_AUTH_CLASS: + case AUTH_RULE_EAP_TYPE: + case AUTH_RULE_EAP_VENDOR: + case AUTH_RULE_CRL_VALIDATION: + case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: + /* integer type */ + this->value = (void*)(uintptr_t)va_arg(args, u_int); + break; + case AUTH_RULE_IDENTITY: + case AUTH_RULE_EAP_IDENTITY: + case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_BACKEND: + case AUTH_RULE_XAUTH_IDENTITY: + case AUTH_RULE_GROUP: + case AUTH_RULE_CA_CERT: + case AUTH_RULE_IM_CERT: + case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_CERT_POLICY: + case AUTH_HELPER_IM_CERT: + case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_IM_HASH_URL: + case AUTH_HELPER_SUBJECT_HASH_URL: + case AUTH_HELPER_REVOCATION_CERT: + /* pointer type */ + this->value = va_arg(args, void*); + break; + case AUTH_RULE_MAX: + this->value = NULL; + break; + } + return this; +} + +/** + * Compare two entries for equality. + */ +static bool entry_equals(entry_t *e1, entry_t *e2) +{ + if (e1->type != e2->type) + { + return FALSE; + } + switch (e1->type) + { + case AUTH_RULE_AUTH_CLASS: + case AUTH_RULE_EAP_TYPE: + case AUTH_RULE_EAP_VENDOR: + case AUTH_RULE_CRL_VALIDATION: + case AUTH_RULE_OCSP_VALIDATION: + case AUTH_RULE_RSA_STRENGTH: + case AUTH_RULE_ECDSA_STRENGTH: + { + return e1->value == e2->value; + } + case AUTH_RULE_CA_CERT: + case AUTH_RULE_IM_CERT: + case AUTH_RULE_SUBJECT_CERT: + case AUTH_HELPER_IM_CERT: + case AUTH_HELPER_SUBJECT_CERT: + case AUTH_HELPER_REVOCATION_CERT: + { + certificate_t *c1, *c2; + + c1 = (certificate_t*)e1->value; + c2 = (certificate_t*)e2->value; + + return c1->equals(c1, c2); + } + case AUTH_RULE_IDENTITY: + case AUTH_RULE_EAP_IDENTITY: + case AUTH_RULE_AAA_IDENTITY: + case AUTH_RULE_XAUTH_IDENTITY: + case AUTH_RULE_GROUP: + { + identification_t *id1, *id2; + + id1 = (identification_t*)e1->value; + id2 = (identification_t*)e2->value; + + return id1->equals(id1, id2); + } + case AUTH_RULE_CERT_POLICY: + case AUTH_RULE_XAUTH_BACKEND: + case AUTH_HELPER_IM_HASH_URL: + case AUTH_HELPER_SUBJECT_HASH_URL: + { + return streq(e1->value, e2->value); + } + case AUTH_RULE_MAX: + break; + } + return FALSE; +} + +/** * Destroy the value associated with an entry */ static void destroy_entry_value(entry_t *entry) @@ -177,6 +334,7 @@ static void destroy_entry_value(entry_t *entry) case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: + case AUTH_RULE_MAX: break; } } @@ -189,12 +347,13 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, { if (enumerator->current) { + entry_t *entry; va_list args; va_start(args, type); - - destroy_entry_value(enumerator->current); - enumerator->current->type = type; + entry = enumerator->current; + destroy_entry_value(entry); + entry->type = type; switch (type) { case AUTH_RULE_AUTH_CLASS: @@ -205,7 +364,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: /* integer type */ - enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int); + entry->value = (void*)(uintptr_t)va_arg(args, u_int); break; case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: @@ -223,7 +382,10 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: /* pointer type */ - enumerator->current->value = va_arg(args, void*); + entry->value = va_arg(args, void*); + break; + case AUTH_RULE_MAX: + entry->value = NULL; break; } va_end(args); @@ -292,9 +454,10 @@ METHOD(auth_cfg_t, get, void*, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: - default: - return NULL; + case AUTH_RULE_MAX: + break; } + return NULL; } /** @@ -302,44 +465,22 @@ METHOD(auth_cfg_t, get, void*, */ static void add(private_auth_cfg_t *this, auth_rule_t type, ...) { - entry_t *entry = malloc_thing(entry_t); + entry_t *entry; va_list args; va_start(args, type); - entry->type = type; - switch (type) - { - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - case AUTH_RULE_RSA_STRENGTH: - case AUTH_RULE_ECDSA_STRENGTH: - /* integer type */ - entry->value = (void*)(uintptr_t)va_arg(args, u_int); - break; - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AAA_IDENTITY: - case AUTH_RULE_XAUTH_BACKEND: - case AUTH_RULE_XAUTH_IDENTITY: - case AUTH_RULE_GROUP: - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_RULE_CERT_POLICY: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - case AUTH_HELPER_REVOCATION_CERT: - /* pointer type */ - entry->value = va_arg(args, void*); - break; - } + entry = entry_create(type, args); va_end(args); - this->entries->insert_last(this->entries, entry); + + if (is_multi_value_rule(type)) + { /* insert rules that may occur multiple times at the end */ + this->entries->insert_last(this->entries, entry); + } + else + { /* insert rules we expect only once at the front (get() will return + * the latest value) */ + this->entries->insert_first(this->entries, entry); + } } METHOD(auth_cfg_t, complies, bool, @@ -599,6 +740,7 @@ METHOD(auth_cfg_t, complies, bool, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_RULE_MAX: /* skip helpers */ continue; } @@ -635,6 +777,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy auth_rule_t type; void *value; + /* this enumerator skips duplicates for rules we expect only once */ enumerator = create_enumerator(other); while (enumerator->enumerate(enumerator, &type, &value)) { @@ -682,6 +825,8 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy add(this, type, strdup((char*)value)); break; } + case AUTH_RULE_MAX: + break; } } enumerator->destroy(enumerator); @@ -707,87 +852,23 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) entry_t *i1, *i2; bool equal = TRUE, found; - if (this->entries->get_count(this->entries) != - other->entries->get_count(other->entries)) - { - return FALSE; - } + /* the rule count does not have to be equal for the two, as we only compare + * the first value found for some rules */ e1 = this->entries->create_enumerator(this->entries); while (e1->enumerate(e1, &i1)) { found = FALSE; + e2 = other->entries->create_enumerator(other->entries); while (e2->enumerate(e2, &i2)) { - if (i1->type == i2->type) + if (entry_equals(i1, i2)) { - switch (i1->type) - { - case AUTH_RULE_AUTH_CLASS: - case AUTH_RULE_EAP_TYPE: - case AUTH_RULE_EAP_VENDOR: - case AUTH_RULE_CRL_VALIDATION: - case AUTH_RULE_OCSP_VALIDATION: - case AUTH_RULE_RSA_STRENGTH: - case AUTH_RULE_ECDSA_STRENGTH: - { - if (i1->value == i2->value) - { - found = TRUE; - break; - } - continue; - } - case AUTH_RULE_CA_CERT: - case AUTH_RULE_IM_CERT: - case AUTH_RULE_SUBJECT_CERT: - case AUTH_HELPER_IM_CERT: - case AUTH_HELPER_SUBJECT_CERT: - case AUTH_HELPER_REVOCATION_CERT: - { - certificate_t *c1, *c2; - - c1 = (certificate_t*)i1->value; - c2 = (certificate_t*)i2->value; - - if (c1->equals(c1, c2)) - { - found = TRUE; - break; - } - continue; - } - case AUTH_RULE_IDENTITY: - case AUTH_RULE_EAP_IDENTITY: - case AUTH_RULE_AAA_IDENTITY: - case AUTH_RULE_GROUP: - case AUTH_RULE_XAUTH_IDENTITY: - { - identification_t *id1, *id2; - - id1 = (identification_t*)i1->value; - id2 = (identification_t*)i2->value; - - if (id1->equals(id1, id2)) - { - found = TRUE; - break; - } - continue; - } - case AUTH_RULE_XAUTH_BACKEND: - case AUTH_RULE_CERT_POLICY: - case AUTH_HELPER_IM_HASH_URL: - case AUTH_HELPER_SUBJECT_HASH_URL: - { - if (streq(i1->value, i2->value)) - { - found = TRUE; - break; - } - continue; - } - } + found = TRUE; + break; + } + else if (i1->type == i2->type && !is_multi_value_rule(i1->type)) + { /* we continue our search, only for multi valued rules */ break; } } @@ -836,6 +917,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, entry_t *entry; clone = auth_cfg_create(); + /* this enumerator skips duplicates for rules we expect only once */ enumerator = this->entries->create_enumerator(this->entries); while (enumerator->enumerate(enumerator, &entry)) { @@ -879,6 +961,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_RULE_ECDSA_STRENGTH: clone->add(clone, entry->type, (uintptr_t)entry->value); break; + case AUTH_RULE_MAX: + break; } } enumerator->destroy(enumerator); |