From 8dbf40d19a7d328406d8a063314d86e795214239 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 9 Jun 2021 16:36:57 +0200 Subject: [PATCH] charon-nm: Simplify certificate enumeration and allow IDs other than DNs This allows using SANs as identity instead of having to use the subject DN. References strongswan/strongswan#437. --- src/charon-nm/nm/nm_creds.c | 66 ++++++++----------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/src/charon-nm/nm/nm_creds.c b/src/charon-nm/nm/nm_creds.c index 2660d6f5a..2aede7ff0 100644 --- a/src/charon-nm/nm/nm_creds.c +++ b/src/charon-nm/nm/nm_creds.c @@ -77,32 +77,11 @@ struct private_nm_creds_t { }; /** - * Enumerator for user certificate + * Enumerator for user certificate (lock has to be locked) */ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this, certificate_type_t cert, key_type_t key) { - public_key_t *public; - - if (cert != CERT_ANY && cert != this->usercert->get_type(this->usercert)) - { - return NULL; - } - if (key != KEY_ANY) - { - public = this->usercert->get_public_key(this->usercert); - if (!public) - { - return NULL; - } - if (public->get_type(public) != key) - { - public->destroy(public); - return NULL; - } - public->destroy(public); - } - this->lock->read_lock(this->lock); return enumerator_create_cleaner( enumerator_create_single(this->usercert, NULL), (void*)this->lock->unlock, this->lock); @@ -114,6 +93,8 @@ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this, typedef struct { /** ref to credential credential store */ private_nm_creds_t *this; + /** certificate type we are looking for */ + certificate_type_t type; /** type of key we are looking for */ key_type_t key; /** CA certificate ID */ @@ -131,55 +112,36 @@ CALLBACK(cert_filter, bool, cert_data_t *data, enumerator_t *orig, va_list args) { certificate_t *cert, **out; - public_key_t *public; VA_ARGS_VGET(args, out); while (orig->enumerate(orig, &cert)) { - public = cert->get_public_key(cert); - if (!public) + if (certificate_matches(cert, data->type, data->key, data->id)) { - continue; - } - if (data->key != KEY_ANY && public->get_type(public) != data->key) - { - public->destroy(public); - continue; - } - if (data->id && data->id->get_type(data->id) == ID_KEY_ID && - public->has_fingerprint(public, data->id->get_encoding(data->id))) - { - public->destroy(public); *out = cert; return TRUE; } - public->destroy(public); - if (data->id && !cert->has_subject(cert, data->id)) - { - continue; - } - *out = cert; - return TRUE; } return FALSE; } /** - * Create enumerator for trusted certificates + * Create enumerator for trusted certificates (lock has to be locked) */ static enumerator_t *create_trusted_cert_enumerator(private_nm_creds_t *this, - key_type_t key, identification_t *id) + certificate_type_t type, key_type_t key, + identification_t *id) { cert_data_t *data; INIT(data, .this = this, - .id = id, + .type = type, .key = key, + .id = id, ); - this->lock->read_lock(this->lock); return enumerator_create_filter( this->certs->create_enumerator(this->certs), cert_filter, data, cert_data_destroy); @@ -189,16 +151,14 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, private_nm_creds_t *this, certificate_type_t cert, key_type_t key, identification_t *id, bool trusted) { + this->lock->read_lock(this->lock); + if (id && this->usercert && - id->equals(id, this->usercert->get_subject(this->usercert))) + certificate_matches(this->usercert, cert, key, id)) { return create_usercert_enumerator(this, cert, key); } - if (cert == CERT_X509 || cert == CERT_ANY) - { - return create_trusted_cert_enumerator(this, key, id); - } - return NULL; + return create_trusted_cert_enumerator(this, cert, key, id); } METHOD(credential_set_t, create_private_enumerator, enumerator_t*,