diff options
Diffstat (limited to 'src/libcharon/sa/ikev2/tasks/ike_cert_post.c')
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_cert_post.c | 139 |
1 files changed, 102 insertions, 37 deletions
diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_post.c b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c index a93e5137e..6dbc4dec3 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_cert_post.c +++ b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c @@ -22,6 +22,7 @@ #include <encoding/payloads/certreq_payload.h> #include <encoding/payloads/auth_payload.h> #include <credentials/certificates/x509.h> +#include <credentials/certificates/ac.h> typedef struct private_ike_cert_post_t private_ike_cert_post_t; @@ -105,12 +106,109 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, } /** + * Add subject certificate to message + */ +static bool add_subject_cert(private_ike_cert_post_t *this, auth_cfg_t *auth, + message_t *message) +{ + cert_payload_t *payload; + certificate_t *cert; + + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (!cert) + { + return FALSE; + } + payload = build_cert_payload(this, cert); + if (!payload) + { + return FALSE; + } + DBG1(DBG_IKE, "sending end entity cert \"%Y\"", cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + return TRUE; +} + +/** + * Add intermediate CA certificates to message + */ +static void add_im_certs(private_ike_cert_post_t *this, auth_cfg_t *auth, + message_t *message) +{ + cert_payload_t *payload; + enumerator_t *enumerator; + certificate_t *cert; + auth_rule_t type; + + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &type, &cert)) + { + if (type == AUTH_RULE_IM_CERT) + { + payload = cert_payload_create_from_cert(CERTIFICATE, cert); + if (payload) + { + DBG1(DBG_IKE, "sending issuer cert \"%Y\"", + cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + } + enumerator->destroy(enumerator); +} + +/** + * Add any valid attribute certificates of subject to message + */ +static void add_attribute_certs(private_ike_cert_post_t *this, + auth_cfg_t *auth, message_t *message) +{ + certificate_t *subject, *cert; + + subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (subject && subject->get_type(subject) == CERT_X509) + { + x509_t *x509 = (x509_t*)subject; + identification_t *id, *serial; + enumerator_t *enumerator; + cert_payload_t *payload; + ac_t *ac; + + /* we look for attribute certs having our serial and holder issuer, + * which is recommended by RFC 5755 */ + serial = identification_create_from_encoding(ID_KEY_ID, + x509->get_serial(x509)); + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_X509_AC, KEY_ANY, serial, FALSE); + while (enumerator->enumerate(enumerator, &ac)) + { + cert = &ac->certificate; + id = ac->get_holderIssuer(ac); + if (id && id->equals(id, subject->get_issuer(subject)) && + cert->get_validity(cert, NULL, NULL, NULL)) + { + payload = cert_payload_create_from_cert(CERTIFICATE, cert); + if (payload) + { + DBG1(DBG_IKE, "sending attribute certificate " + "issued by \"%Y\"", cert->get_issuer(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + } + enumerator->destroy(enumerator); + serial->destroy(serial); + } +} + +/** * add certificates to message */ static void build_certs(private_ike_cert_post_t *this, message_t *message) { peer_cfg_t *peer_cfg; auth_payload_t *payload; + auth_cfg_t *auth; payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION); peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); @@ -130,46 +228,13 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message) } /* FALL */ case CERT_ALWAYS_SEND: - { - cert_payload_t *payload; - enumerator_t *enumerator; - certificate_t *cert; - auth_rule_t type; - auth_cfg_t *auth; - auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); - - /* get subject cert first, then issuing certificates */ - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (!cert) + if (add_subject_cert(this, auth, message)) { - break; + add_im_certs(this, auth, message); + add_attribute_certs(this, auth, message); } - payload = build_cert_payload(this, cert); - if (!payload) - { - break; - } - DBG1(DBG_IKE, "sending end entity cert \"%Y\"", - cert->get_subject(cert)); - message->add_payload(message, (payload_t*)payload); - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &cert)) - { - if (type == AUTH_RULE_IM_CERT) - { - payload = cert_payload_create_from_cert(CERTIFICATE, cert); - if (payload) - { - DBG1(DBG_IKE, "sending issuer cert \"%Y\"", - cert->get_subject(cert)); - message->add_payload(message, (payload_t*)payload); - } - } - } - enumerator->destroy(enumerator); - } + break; } } |