}
}
+/**
+ * Process messages of type IKE_IV
+ */
+static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message)
+{
+ ha_message_attribute_t attribute;
+ ha_message_value_t value;
+ enumerator_t *enumerator;
+ ike_sa_t *ike_sa = NULL;
+ chunk_t iv = chunk_empty;
+
+ enumerator = message->create_attribute_enumerator(message);
+ while (enumerator->enumerate(enumerator, &attribute, &value))
+ {
+ switch (attribute)
+ {
+ case HA_IKE_ID:
+ ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
+ value.ike_sa_id);
+ break;
+ case HA_IV:
+ iv = value.chunk;
+ break;
+ default:
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (ike_sa)
+ {
+ if (ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ if (iv.len)
+ {
+ keymat_v1_t *keymat;
+
+ keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ keymat->update_iv(keymat, 0, iv);
+ keymat->confirm_iv(keymat, 0);
+ }
+ }
+ this->cache->cache(this->cache, ike_sa, message);
+ charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+ }
+ else
+ {
+ message->destroy(message);
+ }
+}
+
/**
* Process messages of type IKE_DELETE
*/
case HA_IKE_MID_RESPONDER:
process_ike_mid(this, message, FALSE);
break;
+ case HA_IKE_IV:
+ process_ike_iv(this, message);
+ break;
case HA_IKE_DELETE:
process_ike_delete(this, message);
break;
#include "ha_ike.h"
#include <sa/ikev2/keymat_v2.h>
+#include <sa/ikev1/keymat_v1.h>
typedef struct private_ha_ike_t private_ha_ike_t;
return TRUE;
}
- if (message->get_exchange_type(message) != IKE_SA_INIT &&
- message->get_request(message))
- { /* we sync on requests, but skip it on IKE_SA_INIT */
- ha_message_t *m;
-
- if (incoming)
- {
- m = ha_message_create(HA_IKE_MID_RESPONDER);
+ if (plain && ike_sa->get_version(ike_sa) == IKEV2)
+ {
+ if (message->get_exchange_type(message) != IKE_SA_INIT &&
+ message->get_request(message))
+ { /* we sync on requests, but skip it on IKE_SA_INIT */
+ ha_message_t *m;
+
+ if (incoming)
+ {
+ m = ha_message_create(HA_IKE_MID_RESPONDER);
+ }
+ else
+ {
+ m = ha_message_create(HA_IKE_MID_INITIATOR);
+ }
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
}
- else
- {
- m = ha_message_create(HA_IKE_MID_INITIATOR);
+ if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
+ message->get_exchange_type(message) == IKE_AUTH &&
+ !message->get_request(message))
+ { /* After IKE_SA has been established, sync peers virtual IP.
+ * We cannot sync it in the state_change hook, it is installed later.
+ * TODO: where to sync local VIP? */
+ ha_message_t *m;
+ host_t *vip;
+
+ vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
+ if (vip)
+ {
+ m = ha_message_create(HA_IKE_UPDATE);
+ m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
+ m->add_attribute(m, HA_REMOTE_VIP, vip);
+ this->socket->push(this->socket, m);
+ this->cache->cache(this->cache, ike_sa, m);
+ }
}
- m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_MID, message->get_message_id(message) + 1);
- this->socket->push(this->socket, m);
- this->cache->cache(this->cache, ike_sa, m);
}
- if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
- message->get_exchange_type(message) == IKE_AUTH &&
- !message->get_request(message))
- { /* After IKE_SA has been established, sync peers virtual IP.
- * We cannot sync it in the state_change hook, it is installed later.
- * TODO: where to sync local VIP? */
+ if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
+ {
ha_message_t *m;
- host_t *vip;
+ keymat_v1_t *keymat;
+ u_int32_t mid;
+ chunk_t iv;
- vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
- if (vip)
+ mid = message->get_message_id(message);
+ if (mid == 0)
{
- m = ha_message_create(HA_IKE_UPDATE);
+ keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
+ iv = keymat->get_iv(keymat, mid);
+ m = ha_message_create(HA_IKE_IV);
m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa));
- m->add_attribute(m, HA_REMOTE_VIP, vip);
+ m->add_attribute(m, HA_IV, iv);
+ free(iv.ptr);
this->socket->push(this->socket, m);
this->cache->cache(this->cache, ike_sa, m);
}