diff options
author | Adrian-Ken Rueegsegger <ken@codelabs.ch> | 2012-09-25 15:21:11 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-03-19 15:23:49 +0100 |
commit | 351bd59de26ef94fac418e730329815021cfd062 (patch) | |
tree | ff66bb37b993f52ef546f5359e936c9e6f2ef1b9 /src/charon-tkm | |
parent | 464eb54ba4c425ff6aa61fb5944583a2e1f12c3a (diff) | |
download | strongswan-351bd59de26ef94fac418e730329815021cfd062.tar.bz2 strongswan-351bd59de26ef94fac418e730329815021cfd062.tar.xz |
Build cc context in tkm listener authorize hook
Extract peer certificate information and build a TKM certificate chain
context in the authorize hook of the tkm_listener_t. The cc context will
be used for ISA authentication using certificates.
Diffstat (limited to 'src/charon-tkm')
-rw-r--r-- | src/charon-tkm/src/tkm/tkm_listener.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c index 8bf92f4e7..5820990f4 100644 --- a/src/charon-tkm/src/tkm/tkm_listener.c +++ b/src/charon-tkm/src/tkm/tkm_listener.c @@ -21,6 +21,7 @@ #include <tkm/constants.h> #include <tkm/client.h> +#include "tkm.h" #include "tkm_listener.h" #include "tkm_keymat.h" #include "tkm_utils.h" @@ -39,6 +40,133 @@ struct private_tkm_listener_t { }; +/** + * Build a TKM certificate chain context with given cc id. + * + * @param ike_sa IKE SA containing auth config to build certificate chain from + * @param cc_id Certificate chain ID + * @return TRUE if certificate chain was built successfully, + * FALSE otherwise + */ +static bool build_cert_chain(const ike_sa_t * const ike_sa, cc_id_type cc_id) +{ + DBG1(DBG_IKE, "building certificate chain context %llu for IKE SA %s", + cc_id, ike_sa->get_name((ike_sa_t *)ike_sa)); + + auth_cfg_t *auth; + certificate_t *cert; + enumerator_t *rounds; + rounds = ike_sa->create_auth_cfg_enumerator((ike_sa_t *)ike_sa, FALSE); + while(rounds->enumerate(rounds, &auth)) + { + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (cert) + { + /* set user certificate */ + chunk_t enc_user_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert)) + { + DBG1(DBG_IKE, "unable to extract encoded user certificate"); + rounds->destroy(rounds); + return FALSE; + } + + certificate_type user_cert; + chunk_to_sequence(&enc_user_cert, &user_cert, + sizeof(certificate_type)); + chunk_free(&enc_user_cert); + if (ike_cc_set_user_certificate(cc_id, 1, 1, user_cert) != TKM_OK) + { + DBG1(DBG_IKE, "error setting user certificate of cert chain" + " (cc_id: %llu)", cc_id); + rounds->destroy(rounds); + return FALSE; + } + + /* process intermediate CA certificates */ + auth_rule_t rule; + enumerator_t *enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &cert)) + { + if (rule == AUTH_RULE_IM_CERT) + { + chunk_t enc_im_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert)) + { + DBG1(DBG_IKE, "unable to extract encoded intermediate CA" + " certificate"); + rounds->destroy(rounds); + enumerator->destroy(enumerator); + return FALSE; + } + + certificate_type im_cert; + chunk_to_sequence(&enc_im_cert, &im_cert, + sizeof(certificate_type)); + chunk_free(&enc_im_cert); + if (ike_cc_add_certificate(cc_id, 1, im_cert) != TKM_OK) + { + DBG1(DBG_IKE, "error adding intermediate certificate to" + " cert chain (cc_id: %llu)", cc_id); + rounds->destroy(rounds); + enumerator->destroy(enumerator); + return FALSE; + } + } + } + enumerator->destroy(enumerator); + + /* finally add CA certificate */ + cert = auth->get(auth, AUTH_RULE_CA_CERT); + if (cert) + { + chunk_t enc_ca_cert; + if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert)) + { + DBG1(DBG_IKE, "unable to extract encoded CA certificate"); + rounds->destroy(rounds); + return FALSE; + } + + const ca_id_type ca_id = 1; + certificate_type ca_cert; + chunk_to_sequence(&enc_ca_cert, &ca_cert, + sizeof(certificate_type)); + chunk_free(&enc_ca_cert); + if (ike_cc_add_certificate(cc_id, 1, ca_cert) != TKM_OK) + { + DBG1(DBG_IKE, "error adding CA certificate to cert chain " + "(cc_id: %llu)", cc_id); + rounds->destroy(rounds); + return FALSE; + } + + if (ike_cc_check_ca(cc_id, ca_id) != TKM_OK) + { + DBG1(DBG_IKE, "certificate chain (cc_id: %llu) not based on" + " trusted CA (ca_id: %llu)", cc_id, ca_id); + rounds->destroy(rounds); + return FALSE; + } + + rounds->destroy(rounds); + return TRUE; + } + else + { + DBG1(DBG_IKE, "no CA certificate"); + } + } + else + { + DBG1(DBG_IKE, "no subject certificate for remote peer"); + } + } + + rounds->destroy(rounds); + return FALSE; +} + METHOD(listener_t, authorize, bool, private_tkm_listener_t *this, ike_sa_t *ike_sa, bool final, bool *success) @@ -52,6 +180,21 @@ METHOD(listener_t, authorize, bool, const isa_id_type isa_id = keymat->get_isa_id(keymat); DBG1(DBG_IKE, "TKM authorize listener called for ISA context %llu", isa_id); + const cc_id_type cc_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_CC); + if (!cc_id) + { + DBG1(DBG_IKE, "unable to acquire CC context id"); + *success = FALSE; + return TRUE; + } + const bool cc_success = build_cert_chain(ike_sa, cc_id); + if (!cc_success) + { + DBG1(DBG_IKE, "unable to build certificate chain"); + *success = FALSE; + return TRUE; + } + const chunk_t * const auth = keymat->get_auth_payload(keymat); if (!auth->ptr) { |