Added support for Phase1 IV synchronization to HA plugin
This commit is contained in:
@@ -88,6 +88,8 @@ typedef struct {
|
|||||||
ha_message_t *midi;
|
ha_message_t *midi;
|
||||||
/* last responder mid */
|
/* last responder mid */
|
||||||
ha_message_t *midr;
|
ha_message_t *midr;
|
||||||
|
/* last IV update */
|
||||||
|
ha_message_t *iv;
|
||||||
} entry_t;
|
} entry_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,6 +116,7 @@ static void entry_destroy(entry_t *entry)
|
|||||||
entry->add->destroy(entry->add);
|
entry->add->destroy(entry->add);
|
||||||
DESTROY_IF(entry->midi);
|
DESTROY_IF(entry->midi);
|
||||||
DESTROY_IF(entry->midr);
|
DESTROY_IF(entry->midr);
|
||||||
|
DESTROY_IF(entry->iv);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +167,16 @@ METHOD(ha_cache_t, cache, void,
|
|||||||
}
|
}
|
||||||
message->destroy(message);
|
message->destroy(message);
|
||||||
break;
|
break;
|
||||||
|
case HA_IKE_IV:
|
||||||
|
entry = this->cache->get(this->cache, ike_sa);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
DESTROY_IF(entry->iv);
|
||||||
|
entry->iv = message;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
message->destroy(message);
|
||||||
|
break;
|
||||||
case HA_IKE_DELETE:
|
case HA_IKE_DELETE:
|
||||||
entry = this->cache->remove(this->cache, ike_sa);
|
entry = this->cache->remove(this->cache, ike_sa);
|
||||||
if (entry)
|
if (entry)
|
||||||
@@ -309,6 +322,10 @@ METHOD(ha_cache_t, resync, void,
|
|||||||
{
|
{
|
||||||
this->socket->push(this->socket, entry->midr);
|
this->socket->push(this->socket, entry->midr);
|
||||||
}
|
}
|
||||||
|
if (entry->iv)
|
||||||
|
{
|
||||||
|
this->socket->push(this->socket, entry->iv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|||||||
@@ -478,6 +478,57 @@ static void process_ike_mid(private_ha_dispatcher_t *this,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Process messages of type IKE_DELETE
|
||||||
*/
|
*/
|
||||||
@@ -932,6 +983,9 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this)
|
|||||||
case HA_IKE_MID_RESPONDER:
|
case HA_IKE_MID_RESPONDER:
|
||||||
process_ike_mid(this, message, FALSE);
|
process_ike_mid(this, message, FALSE);
|
||||||
break;
|
break;
|
||||||
|
case HA_IKE_IV:
|
||||||
|
process_ike_iv(this, message);
|
||||||
|
break;
|
||||||
case HA_IKE_DELETE:
|
case HA_IKE_DELETE:
|
||||||
process_ike_delete(this, message);
|
process_ike_delete(this, message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "ha_ike.h"
|
#include "ha_ike.h"
|
||||||
|
|
||||||
#include <sa/ikev2/keymat_v2.h>
|
#include <sa/ikev2/keymat_v2.h>
|
||||||
|
#include <sa/ikev1/keymat_v1.h>
|
||||||
|
|
||||||
typedef struct private_ha_ike_t private_ha_ike_t;
|
typedef struct private_ha_ike_t private_ha_ike_t;
|
||||||
|
|
||||||
@@ -245,39 +246,62 @@ METHOD(listener_t, message_hook, bool,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message->get_exchange_type(message) != IKE_SA_INIT &&
|
if (plain && ike_sa->get_version(ike_sa) == IKEV2)
|
||||||
message->get_request(message))
|
{
|
||||||
{ /* we sync on requests, but skip it on IKE_SA_INIT */
|
if (message->get_exchange_type(message) != IKE_SA_INIT &&
|
||||||
ha_message_t *m;
|
message->get_request(message))
|
||||||
|
{ /* we sync on requests, but skip it on IKE_SA_INIT */
|
||||||
|
ha_message_t *m;
|
||||||
|
|
||||||
if (incoming)
|
if (incoming)
|
||||||
{
|
{
|
||||||
m = ha_message_create(HA_IKE_MID_RESPONDER);
|
m = ha_message_create(HA_IKE_MID_RESPONDER);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m = ha_message_create(HA_IKE_MID_INITIATOR);
|
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);
|
|
||||||
}
|
|
||||||
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_IKE_ID, ike_sa->get_id(ike_sa));
|
||||||
m->add_attribute(m, HA_REMOTE_VIP, vip);
|
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? */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!plain && ike_sa->get_version(ike_sa) == IKEV1)
|
||||||
|
{
|
||||||
|
ha_message_t *m;
|
||||||
|
keymat_v1_t *keymat;
|
||||||
|
u_int32_t mid;
|
||||||
|
chunk_t iv;
|
||||||
|
|
||||||
|
mid = message->get_message_id(message);
|
||||||
|
if (mid == 0)
|
||||||
|
{
|
||||||
|
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_IV, iv);
|
||||||
|
free(iv.ptr);
|
||||||
this->socket->push(this->socket, m);
|
this->socket->push(this->socket, m);
|
||||||
this->cache->cache(this->cache, ike_sa, m);
|
this->cache->cache(this->cache, ike_sa, m);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ struct private_ha_message_t {
|
|||||||
chunk_t buf;
|
chunk_t buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
|
ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV,
|
||||||
"IKE_ADD",
|
"IKE_ADD",
|
||||||
"IKE_UPDATE",
|
"IKE_UPDATE",
|
||||||
"IKE_MID_INITIATOR",
|
"IKE_MID_INITIATOR",
|
||||||
@@ -58,6 +58,7 @@ ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC,
|
|||||||
"SEGMENT_TAKE",
|
"SEGMENT_TAKE",
|
||||||
"STATUS",
|
"STATUS",
|
||||||
"RESYNC",
|
"RESYNC",
|
||||||
|
"IKE_IV",
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
|
typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
|
||||||
@@ -267,6 +268,7 @@ METHOD(ha_message_t, add_attribute, void,
|
|||||||
case HA_LOCAL_DH:
|
case HA_LOCAL_DH:
|
||||||
case HA_REMOTE_DH:
|
case HA_REMOTE_DH:
|
||||||
case HA_PSK:
|
case HA_PSK:
|
||||||
|
case HA_IV:
|
||||||
case HA_OLD_SKD:
|
case HA_OLD_SKD:
|
||||||
{
|
{
|
||||||
chunk_t chunk;
|
chunk_t chunk;
|
||||||
@@ -487,6 +489,7 @@ METHOD(enumerator_t, attribute_enumerate, bool,
|
|||||||
case HA_LOCAL_DH:
|
case HA_LOCAL_DH:
|
||||||
case HA_REMOTE_DH:
|
case HA_REMOTE_DH:
|
||||||
case HA_PSK:
|
case HA_PSK:
|
||||||
|
case HA_IV:
|
||||||
case HA_OLD_SKD:
|
case HA_OLD_SKD:
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ enum ha_message_type_t {
|
|||||||
HA_STATUS,
|
HA_STATUS,
|
||||||
/** segments the receiving node is requested to resync */
|
/** segments the receiving node is requested to resync */
|
||||||
HA_RESYNC,
|
HA_RESYNC,
|
||||||
|
/** IV synchronization for IKEv1 Main/Aggressive mode */
|
||||||
|
HA_IKE_IV,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,6 +152,8 @@ enum ha_message_attribute_t {
|
|||||||
HA_REMOTE_DH,
|
HA_REMOTE_DH,
|
||||||
/** chunk_t, shared secret for IKEv1 key derivation */
|
/** chunk_t, shared secret for IKEv1 key derivation */
|
||||||
HA_PSK,
|
HA_PSK,
|
||||||
|
/** chunk_t, IV for next IKEv1 message */
|
||||||
|
HA_IV,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user