aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-10-27 17:25:22 +0100
committerTobias Brunner <tobias@strongswan.org>2016-03-10 11:07:14 +0100
commit1b9c1ae018aa176aaf9e1f11503b72cc622ba771 (patch)
tree66877eb13a7859ead856f61aad1c337ff4cfd045
parentef9171ad1ee9145a7139c365524006abb930a41d (diff)
downloadstrongswan-1b9c1ae018aa176aaf9e1f11503b72cc622ba771.tar.bz2
strongswan-1b9c1ae018aa176aaf9e1f11503b72cc622ba771.tar.xz
ike-sa: Add method to verify certificates in completed authentication rounds
-rw-r--r--src/libcharon/sa/ike_sa.c103
-rw-r--r--src/libcharon/sa/ike_sa.h8
2 files changed, 111 insertions, 0 deletions
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index b07ff0e74..3384c0278 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -58,6 +58,7 @@
#include <sa/ikev2/tasks/ike_auth_lifetime.h>
#include <sa/ikev2/tasks/ike_reauth_complete.h>
#include <sa/ikev2/tasks/ike_redirect.h>
+#include <credentials/sets/auth_cfg_wrapper.h>
#ifdef ME
#include <sa/ikev2/tasks/ike_me.h>
@@ -462,6 +463,107 @@ METHOD(ike_sa_t, create_auth_cfg_enumerator, enumerator_t*,
return array_create_enumerator(this->other_auths);
}
+METHOD(ike_sa_t, verify_peer_certificate, bool,
+ private_ike_sa_t *this)
+{
+ enumerator_t *e1, *e2, *certs;
+ auth_cfg_t *cfg, *cfg_done;
+ certificate_t *peer, *cert;
+ public_key_t *key;
+ auth_cfg_t *auth;
+ auth_cfg_wrapper_t *wrapper;
+ time_t not_before, not_after;
+ bool valid = TRUE, found;
+
+ if (this->state != IKE_ESTABLISHED)
+ {
+ DBG1(DBG_IKE, "unable to verify peer certificate in state %N",
+ ike_sa_state_names, this->state);
+ return FALSE;
+ }
+
+ if (lib->settings->get_bool(lib->settings,
+ "%s.flush_auth_cfg", FALSE, lib->ns))
+ {
+ DBG1(DBG_IKE, "unable to verify peer certificate as authentication "
+ "information has been flushed");
+ return FALSE;
+ }
+
+ e1 = this->peer_cfg->create_auth_cfg_enumerator(this->peer_cfg, FALSE);
+ e2 = array_create_enumerator(this->other_auths);
+ while (e1->enumerate(e1, &cfg))
+ {
+ if (!e2->enumerate(e2, &cfg_done))
+ { /* this should not happen as the authentication should never have
+ * succeeded */
+ valid = FALSE;
+ break;
+ }
+ if ((uintptr_t)cfg_done->get(cfg_done,
+ AUTH_RULE_AUTH_CLASS) != AUTH_CLASS_PUBKEY)
+ {
+ continue;
+ }
+ peer = cfg_done->get(cfg_done, AUTH_RULE_SUBJECT_CERT);
+ if (!peer)
+ {
+ DBG1(DBG_IKE, "no subject certificate found, skipping certificate "
+ "verification");
+ continue;
+ }
+ if (!peer->get_validity(peer, NULL, &not_before, &not_after))
+ {
+ /* FIXME: theoretically we could find a newer cert with the same
+ * identity and public key below...but it's not the cert used by
+ * the peer during the original authentication so... */
+ DBG1(DBG_IKE, "peer certificate invalid (valid from %T to %T)",
+ &not_before, FALSE, &not_after, FALSE);
+ valid = FALSE;
+ break;
+ }
+ key = peer->get_public_key(peer);
+ if (!key)
+ {
+ DBG1(DBG_IKE, "unable to retrieve public key, skipping certificate "
+ "verification");
+ continue;
+ }
+ DBG1(DBG_IKE, "verifying peer certificate");
+ /* serve received certificates */
+ wrapper = auth_cfg_wrapper_create(cfg_done);
+ lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
+ certs = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+ key->get_type(key), peer->get_subject(peer), TRUE);
+ key->destroy(key);
+
+ found = FALSE;
+ while (certs->enumerate(certs, &cert, &auth))
+ {
+ if (peer->equals(peer, cert))
+ {
+ cfg_done->add(cfg_done, AUTH_RULE_CERT_VALIDATION_SUSPENDED,
+ FALSE);
+ cfg_done->merge(cfg_done, auth, FALSE);
+ valid = cfg_done->complies(cfg_done, cfg, TRUE);
+ found = TRUE;
+ break;
+ }
+ }
+ certs->destroy(certs);
+ lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
+ wrapper->destroy(wrapper);
+ if (!found || !valid)
+ {
+ valid = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return valid;
+}
+
/**
* Flush the stored authentication round information
*/
@@ -2750,6 +2852,7 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id, bool initiator,
.set_peer_cfg = _set_peer_cfg,
.get_auth_cfg = _get_auth_cfg,
.create_auth_cfg_enumerator = _create_auth_cfg_enumerator,
+ .verify_peer_certificate = _verify_peer_certificate,
.add_auth_cfg = _add_auth_cfg,
.get_proposal = _get_proposal,
.set_proposal = _set_proposal,
diff --git a/src/libcharon/sa/ike_sa.h b/src/libcharon/sa/ike_sa.h
index 158a690df..0f47ad31f 100644
--- a/src/libcharon/sa/ike_sa.h
+++ b/src/libcharon/sa/ike_sa.h
@@ -522,6 +522,14 @@ struct ike_sa_t {
enumerator_t* (*create_auth_cfg_enumerator)(ike_sa_t *this, bool local);
/**
+ * Verify the trustchains (validity, revocation) in completed public key
+ * auth rounds.
+ *
+ * @return TRUE if certificates were valid, FALSE otherwise
+ */
+ bool (*verify_peer_certificate)(ike_sa_t *this);
+
+ /**
* Get the selected proposal of this IKE_SA.
*
* @return selected proposal