diff options
Diffstat (limited to 'src/libstrongswan/credentials/auth_cfg.c')
-rw-r--r-- | src/libstrongswan/credentials/auth_cfg.c | 413 |
1 files changed, 254 insertions, 159 deletions
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 23a3f62d9..12f75b240 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 @@ -30,6 +30,63 @@ ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP, "EAP", ); +ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, + "RULE_IDENTITY", + "RULE_AUTH_CLASS", + "RULE_AAA_IDENTITY", + "RULE_EAP_IDENTITY", + "RULE_EAP_TYPE", + "RULE_EAP_VENDOR", + "RULE_CA_CERT", + "RULE_IM_CERT", + "RULE_SUBJECT_CERT", + "RULE_CRL_VALIDATION", + "RULE_OCSP_VALIDATION", + "RULE_GROUP", + "RULE_RSA_STRENGTH", + "RULE_ECDSA_STRENGTH", + "RULE_CERT_POLICY", + "HELPER_IM_CERT", + "HELPER_SUBJECT_CERT", + "HELPER_IM_HASH_URL", + "HELPER_SUBJECT_HASH_URL", + "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_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; /** @@ -67,6 +124,8 @@ typedef struct { enumerator_t *inner; /** current entry */ entry_t *current; + /** types we have already enumerated */ + bool enumerated[AUTH_RULE_MAX]; } entry_enumerator_t; /** @@ -76,11 +135,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; @@ -95,22 +165,124 @@ static void entry_enumerator_destroy(entry_enumerator_t *this) free(this); } -/** - * Implementation of auth_cfg_t.create_enumerator. - */ -static enumerator_t* create_enumerator(private_auth_cfg_t *this) +METHOD(auth_cfg_t, create_enumerator, enumerator_t*, + private_auth_cfg_t *this) { 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_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_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_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) @@ -151,6 +323,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; } } @@ -158,17 +331,18 @@ static void destroy_entry_value(entry_t *entry) /** * Implementation of auth_cfg_t.replace. */ -static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator, +static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, auth_rule_t type, ...) { 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: @@ -179,7 +353,7 @@ static void replace(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: @@ -195,17 +369,18 @@ static void replace(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); } } -/** - * Implementation of auth_cfg_t.get. - */ -static void* get(private_auth_cfg_t *this, auth_rule_t type) +METHOD(auth_cfg_t, get, void*, + private_auth_cfg_t *this, auth_rule_t type) { enumerator_t *enumerator; void *current_value, *best_value = NULL; @@ -264,9 +439,10 @@ static void* get(private_auth_cfg_t *this, auth_rule_t type) 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; } /** @@ -274,49 +450,26 @@ static void* get(private_auth_cfg_t *this, auth_rule_t type) */ 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_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); + } } -/** - * Implementation of auth_cfg_t.complies. - */ -static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints, - bool log_error) +METHOD(auth_cfg_t, complies, bool, + private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error) { enumerator_t *e1, *e2; bool success = TRUE, has_group = FALSE, group_match = FALSE; @@ -566,6 +719,7 @@ static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_RULE_MAX: /* skip helpers */ continue; } @@ -602,6 +756,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)) { @@ -647,6 +802,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); @@ -672,85 +829,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: - { - 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_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; } } @@ -765,10 +860,8 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other) return equal; } -/** - * Implementation of auth_cfg_t.purge - */ -static void purge(private_auth_cfg_t *this, bool keep_ca) +METHOD(auth_cfg_t, purge, void, + private_auth_cfg_t *this, bool keep_ca) { entry_t *entry; linked_list_t *cas; @@ -793,16 +886,15 @@ static void purge(private_auth_cfg_t *this, bool keep_ca) cas->destroy(cas); } -/** - * Implementation of auth_cfg_t.clone - */ -static auth_cfg_t* clone_(private_auth_cfg_t *this) +METHOD(auth_cfg_t, clone_, auth_cfg_t*, + private_auth_cfg_t *this) { enumerator_t *enumerator; auth_cfg_t *clone; 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)) { @@ -844,16 +936,16 @@ static auth_cfg_t* clone_(private_auth_cfg_t *this) case AUTH_RULE_ECDSA_STRENGTH: clone->add(clone, entry->type, (uintptr_t)entry->value); break; + case AUTH_RULE_MAX: + break; } } enumerator->destroy(enumerator); return clone; } -/** - * Implementation of auth_cfg_t.destroy - */ -static void destroy(private_auth_cfg_t *this) +METHOD(auth_cfg_t, destroy, void, + private_auth_cfg_t *this) { purge(this, FALSE); this->entries->destroy(this->entries); @@ -865,20 +957,23 @@ static void destroy(private_auth_cfg_t *this) */ auth_cfg_t *auth_cfg_create() { - private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t); - - this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add; - this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get; - this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator; - this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace; - this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies; - this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge; - this->public.purge = (void(*)(auth_cfg_t*,bool))purge; - this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals; - this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_; - this->public.destroy = (void(*)(auth_cfg_t*))destroy; - - this->entries = linked_list_create(); + private_auth_cfg_t *this; + + INIT(this, + .public = { + .add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add, + .get = _get, + .create_enumerator = _create_enumerator, + .replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace, + .complies = _complies, + .merge = (void(*)(auth_cfg_t*,auth_cfg_t*,bool))merge, + .purge = _purge, + .equals = (bool(*)(auth_cfg_t*,auth_cfg_t*))equals, + .clone = _clone_, + .destroy = _destroy, + }, + .entries = linked_list_create(), + ); return &this->public; } |