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.
This commit is contained in:
Tobias Brunner 2021-06-09 16:36:57 +02:00
parent ae71f8357d
commit 8dbf40d19a
1 changed files with 13 additions and 53 deletions

View File

@ -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, static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
certificate_type_t cert, key_type_t key) 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( return enumerator_create_cleaner(
enumerator_create_single(this->usercert, NULL), enumerator_create_single(this->usercert, NULL),
(void*)this->lock->unlock, this->lock); (void*)this->lock->unlock, this->lock);
@ -114,6 +93,8 @@ static enumerator_t *create_usercert_enumerator(private_nm_creds_t *this,
typedef struct { typedef struct {
/** ref to credential credential store */ /** ref to credential credential store */
private_nm_creds_t *this; private_nm_creds_t *this;
/** certificate type we are looking for */
certificate_type_t type;
/** type of key we are looking for */ /** type of key we are looking for */
key_type_t key; key_type_t key;
/** CA certificate ID */ /** CA certificate ID */
@ -131,55 +112,36 @@ CALLBACK(cert_filter, bool,
cert_data_t *data, enumerator_t *orig, va_list args) cert_data_t *data, enumerator_t *orig, va_list args)
{ {
certificate_t *cert, **out; certificate_t *cert, **out;
public_key_t *public;
VA_ARGS_VGET(args, out); VA_ARGS_VGET(args, out);
while (orig->enumerate(orig, &cert)) while (orig->enumerate(orig, &cert))
{ {
public = cert->get_public_key(cert); if (certificate_matches(cert, data->type, data->key, data->id))
if (!public)
{ {
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; *out = cert;
return TRUE; return TRUE;
} }
public->destroy(public);
if (data->id && !cert->has_subject(cert, data->id))
{
continue;
}
*out = cert;
return TRUE;
} }
return FALSE; 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, 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; cert_data_t *data;
INIT(data, INIT(data,
.this = this, .this = this,
.id = id, .type = type,
.key = key, .key = key,
.id = id,
); );
this->lock->read_lock(this->lock);
return enumerator_create_filter( return enumerator_create_filter(
this->certs->create_enumerator(this->certs), this->certs->create_enumerator(this->certs),
cert_filter, data, cert_data_destroy); 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, private_nm_creds_t *this, certificate_type_t cert, key_type_t key,
identification_t *id, bool trusted) identification_t *id, bool trusted)
{ {
this->lock->read_lock(this->lock);
if (id && this->usercert && 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); return create_usercert_enumerator(this, cert, key);
} }
if (cert == CERT_X509 || cert == CERT_ANY) return create_trusted_cert_enumerator(this, cert, key, id);
{
return create_trusted_cert_enumerator(this, key, id);
}
return NULL;
} }
METHOD(credential_set_t, create_private_enumerator, enumerator_t*, METHOD(credential_set_t, create_private_enumerator, enumerator_t*,