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.
This commit is contained in:
committed by
Tobias Brunner
parent
464eb54ba4
commit
351bd59de2
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user