#include <inttypes.h>
#include <daemon.h>
+#include <collections/array.h>
#include <collections/hashtable.h>
#include <encoding/payloads/auth_payload.h>
#include <utils/chunk.h>
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);
+ cert = auth->get(auth, AUTH_RULE_CA_CERT);
if (cert)
{
- chunk_t enc_user_cert;
- ri_id_type ri_id;
- certificate_type user_cert;
auth_rule_t rule;
enumerator_t *enumerator;
+ ca_id_type ca_id;
+ public_key_t *pubkey;
+ certificate_type ca_cert;
+ chunk_t enc_ca_cert, fp;
+ array_t *im_certs = NULL;
+ uint64_t *raw_id;
+
+ pubkey = cert->get_public_key(cert);
+ if (!pubkey)
+ {
+ DBG1(DBG_IKE, "unable to get CA certificate pubkey");
+ rounds->destroy(rounds);
+ return FALSE;
+ }
+ if (!pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp))
+ {
+ DBG1(DBG_IKE, "unable to extract CA certificate fingerprint");
+ rounds->destroy(rounds);
+ pubkey->destroy(pubkey);
+ return FALSE;
+ }
+ pubkey->destroy(pubkey);
+
+ raw_id = ca_map->get(ca_map, &fp);
+ if (!raw_id || *raw_id == 0)
+ {
+ DBG1(DBG_IKE, "error mapping CA certificate (fp: %#B) to "
+ "ID", &fp);
+ rounds->destroy(rounds);
+ return FALSE;
+ }
+ ca_id = *raw_id;
- /* set user certificate */
- if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert))
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert))
{
- DBG1(DBG_IKE, "unable to extract encoded user certificate");
+ DBG1(DBG_IKE, "unable to extract encoded CA certificate");
rounds->destroy(rounds);
return FALSE;
}
- ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa));
- chunk_to_sequence(&enc_user_cert, &user_cert, sizeof(certificate_type));
- chunk_free(&enc_user_cert);
- if (ike_cc_set_user_certificate(cc_id, ri_id, 1, user_cert) != TKM_OK)
+ chunk_to_sequence(&enc_ca_cert, &ca_cert,
+ sizeof(certificate_type));
+ chunk_free(&enc_ca_cert);
+
+ if (ike_cc_check_ca(cc_id, ca_id, ca_cert) != TKM_OK)
{
- DBG1(DBG_IKE, "error setting user certificate of cert chain"
- " (cc_id: %llu)", cc_id);
+ DBG1(DBG_IKE, "CA certificate (fp: %#B, cc_id: %llu) does not"
+ " match trusted CA (ca_id: %llu)", &fp, cc_id, ca_id);
rounds->destroy(rounds);
return FALSE;
}
- /* process intermediate CA certificates */
+ /* process intermediate CA certificates in reverse order */
enumerator = auth->create_enumerator(auth);
while (enumerator->enumerate(enumerator, &rule, &cert))
{
if (rule == AUTH_RULE_IM_CERT)
{
- chunk_t enc_im_cert;
- certificate_type 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;
- }
-
- 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;
- }
+ array_insert_create(&im_certs, ARRAY_TAIL, cert);
}
}
enumerator->destroy(enumerator);
- /* finally add CA certificate */
- cert = auth->get(auth, AUTH_RULE_CA_CERT);
- if (cert)
+ while (array_remove(im_certs, ARRAY_TAIL, &cert))
{
- ca_id_type ca_id;
- public_key_t *pubkey;
- certificate_type ca_cert;
- chunk_t enc_ca_cert, fp;
- uint64_t *raw_id;
-
- pubkey = cert->get_public_key(cert);
- if (!pubkey)
- {
- DBG1(DBG_IKE, "unable to get CA certificate pubkey");
- rounds->destroy(rounds);
- return FALSE;
- }
- if (!pubkey->get_fingerprint(pubkey, KEYID_PUBKEY_SHA1, &fp))
+ chunk_t enc_im_cert;
+ certificate_type im_cert;
+
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_im_cert))
{
- DBG1(DBG_IKE, "unable to extract CA certificate fingerprint");
+ DBG1(DBG_IKE, "unable to extract encoded intermediate CA"
+ " certificate");
rounds->destroy(rounds);
- pubkey->destroy(pubkey);
+ array_destroy(im_certs);
return FALSE;
}
- pubkey->destroy(pubkey);
- raw_id = ca_map->get(ca_map, &fp);
- if (!raw_id || *raw_id == 0)
+ 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 mapping CA certificate (fp: %#B) to "
- "ID", &fp);
+ DBG1(DBG_IKE, "error adding intermediate certificate to"
+ " cert chain (cc_id: %llu)", cc_id);
rounds->destroy(rounds);
+ array_destroy(im_certs);
return FALSE;
}
- ca_id = *raw_id;
+ }
+ array_destroy(im_certs);
- if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_ca_cert))
+ /* finally add user certificate and check chain */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ chunk_t enc_user_cert;
+ ri_id_type ri_id;
+ certificate_type user_cert;
+
+ /* set user certificate */
+ if (!cert->get_encoding(cert, CERT_ASN1_DER, &enc_user_cert))
{
- DBG1(DBG_IKE, "unable to extract encoded CA certificate");
+ DBG1(DBG_IKE, "unable to extract encoded user certificate");
rounds->destroy(rounds);
return FALSE;
}
- 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)
+ chunk_to_sequence(&enc_user_cert, &user_cert, sizeof(certificate_type));
+ chunk_free(&enc_user_cert);
+ if (ike_cc_add_certificate(cc_id, 1, user_cert) != TKM_OK)
{
- DBG1(DBG_IKE, "error adding CA certificate to cert chain "
- "(cc_id: %llu)", cc_id);
+ DBG1(DBG_IKE, "error adding user 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)
+ ri_id = get_remote_identity_id(ike_sa->get_peer_cfg((ike_sa_t *)ike_sa));
+ if (ike_cc_check_chain(cc_id, ri_id) != TKM_OK)
{
- DBG1(DBG_IKE, "certificate chain (cc_id: %llu) not based on"
- " trusted CA (ca_id: %llu)", cc_id, ca_id);
+ DBG1(DBG_IKE, "error checking cert chain (cc_id: %llu)", cc_id);
rounds->destroy(rounds);
return FALSE;
}
}
else
{
- DBG1(DBG_IKE, "no CA certificate");
+ DBG1(DBG_IKE, "no subject certificate for remote peer");
}
}
else
{
- DBG1(DBG_IKE, "no subject certificate for remote peer");
+ DBG1(DBG_IKE, "no CA certificate");
}
}