generating basic IKE_SA sync messages
pushing to statically configured failover node
This commit is contained in:
committed by
Martin Willi
parent
e5e91eec29
commit
12ec91ba3a
@@ -35,6 +35,30 @@ struct private_ha_sync_ike_t {
|
||||
ha_sync_socket_t *socket;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return condition if it is set on ike_sa
|
||||
*/
|
||||
static ike_condition_t copy_condition(ike_sa_t *ike_sa, ike_condition_t cond)
|
||||
{
|
||||
if (ike_sa->has_condition(ike_sa, cond))
|
||||
{
|
||||
return cond;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extension if it is supported by peers IKE_SA
|
||||
*/
|
||||
static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext)
|
||||
{
|
||||
if (ike_sa->supports_extension(ike_sa, ext))
|
||||
{
|
||||
return ext;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of listener_t.ike_keys
|
||||
*/
|
||||
@@ -42,6 +66,84 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa,
|
||||
diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r,
|
||||
ike_sa_t *rekey)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
ha_sync_message_t *m;
|
||||
peer_cfg_t *peer_cfg;
|
||||
u_int32_t extension, condition;
|
||||
host_t *local_vip, *remote_vip, *addr;
|
||||
identification_t *eap_id;
|
||||
chunk_t secret;
|
||||
|
||||
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
|
||||
|
||||
condition = copy_condition(ike_sa, COND_NAT_ANY)
|
||||
| copy_condition(ike_sa, COND_NAT_HERE)
|
||||
| copy_condition(ike_sa, COND_NAT_THERE)
|
||||
| copy_condition(ike_sa, COND_NAT_FAKE)
|
||||
| copy_condition(ike_sa, COND_EAP_AUTHENTICATED)
|
||||
| copy_condition(ike_sa, COND_CERTREQ_SEEN)
|
||||
| copy_condition(ike_sa, COND_ORIGINAL_INITIATOR);
|
||||
|
||||
extension = copy_extension(ike_sa, EXT_NATT)
|
||||
| copy_extension(ike_sa, EXT_MOBIKE)
|
||||
| copy_extension(ike_sa, EXT_HASH_AND_URL);
|
||||
|
||||
local_vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
|
||||
remote_vip = ike_sa->get_virtual_ip(ike_sa, FALSE);
|
||||
eap_id = ike_sa->get_eap_identity(ike_sa);
|
||||
|
||||
if (dh->get_shared_secret(dh, &secret) != SUCCESS)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (rekey == NULL)
|
||||
{
|
||||
m = ha_sync_message_create(HA_SYNC_IKE_ADD);
|
||||
|
||||
m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_SYNC_LOCAL_ID, ike_sa->get_my_id(ike_sa));
|
||||
m->add_attribute(m, HA_SYNC_REMOTE_ID, ike_sa->get_other_id(ike_sa));
|
||||
m->add_attribute(m, HA_SYNC_LOCAL_ADDR, ike_sa->get_my_host(ike_sa));
|
||||
m->add_attribute(m, HA_SYNC_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
|
||||
m->add_attribute(m, HA_SYNC_CONFIG_NAME, peer_cfg->get_name(peer_cfg));
|
||||
m->add_attribute(m, HA_SYNC_CONDITIONS, condition);
|
||||
m->add_attribute(m, HA_SYNC_EXTENSIONS, extension);
|
||||
if (local_vip)
|
||||
{
|
||||
m->add_attribute(m, HA_SYNC_LOCAL_VIP, local_vip);
|
||||
}
|
||||
if (remote_vip)
|
||||
{
|
||||
m->add_attribute(m, HA_SYNC_REMOTE_VIP, remote_vip);
|
||||
}
|
||||
if (eap_id)
|
||||
{
|
||||
m->add_attribute(m, HA_SYNC_EAP_ID, eap_id);
|
||||
}
|
||||
iterator = ike_sa->create_additional_address_iterator(ike_sa);
|
||||
while (iterator->iterate(iterator, (void**)&addr))
|
||||
{
|
||||
m->add_attribute(m, HA_SYNC_ADDITIONAL_ADDR, addr);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = ha_sync_message_create(HA_SYNC_IKE_REKEY);
|
||||
|
||||
m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa));
|
||||
m->add_attribute(m, HA_SYNC_IKE_REKEY_ID, rekey->get_id(rekey));
|
||||
}
|
||||
|
||||
m->add_attribute(m, HA_SYNC_NONCE_I, nonce_i);
|
||||
m->add_attribute(m, HA_SYNC_NONCE_R, nonce_r);
|
||||
m->add_attribute(m, HA_SYNC_SECRET, secret);
|
||||
chunk_clear(&secret);
|
||||
|
||||
this->socket->push(this->socket, m);
|
||||
m->destroy(m);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
#define ALLOCATION_BLOCK 64
|
||||
|
||||
typedef struct private_ha_sync_message_t private_ha_sync_message_t;
|
||||
|
||||
/**
|
||||
@@ -34,7 +36,7 @@ struct private_ha_sync_message_t {
|
||||
ha_sync_message_t public;
|
||||
|
||||
/**
|
||||
* Number of bytes allocted in buffer
|
||||
* Allocated size of buf
|
||||
*/
|
||||
size_t allocated;
|
||||
|
||||
@@ -44,6 +46,39 @@ struct private_ha_sync_message_t {
|
||||
chunk_t buf;
|
||||
};
|
||||
|
||||
typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t;
|
||||
|
||||
/**
|
||||
* Encoding if an ike_sa_id_t
|
||||
*/
|
||||
struct ike_sa_id_encoding_t {
|
||||
u_int64_t initiator_spi;
|
||||
u_int64_t responder_spi;
|
||||
u_int8_t initiator;
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct identification_encoding_t identification_encoding_t;
|
||||
|
||||
/**
|
||||
* Encoding of a identification_t
|
||||
*/
|
||||
struct identification_encoding_t {
|
||||
u_int8_t type;
|
||||
u_int8_t len;
|
||||
char encoding[];
|
||||
} __attribute__((packed));
|
||||
|
||||
typedef struct host_encoding_t host_encoding_t;
|
||||
|
||||
/**
|
||||
* encoding of a host_t
|
||||
*/
|
||||
struct host_encoding_t {
|
||||
u_int16_t port;
|
||||
u_int8_t family;
|
||||
char encoding[];
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Implementation of ha_sync_message_t.get_type
|
||||
*/
|
||||
@@ -57,9 +92,15 @@ static ha_sync_message_type_t get_type(private_ha_sync_message_t *this)
|
||||
*/
|
||||
static void check_buf(private_ha_sync_message_t *this, size_t len)
|
||||
{
|
||||
int increased = 0;
|
||||
|
||||
while (this->buf.len + len > this->allocated)
|
||||
{ /* double size */
|
||||
this->allocated = this->allocated * 2;
|
||||
this->allocated += ALLOCATION_BLOCK;
|
||||
increased++;
|
||||
}
|
||||
if (increased)
|
||||
{
|
||||
this->buf.ptr = realloc(this->buf.ptr, this->allocated);
|
||||
}
|
||||
}
|
||||
@@ -68,60 +109,119 @@ static void check_buf(private_ha_sync_message_t *this, size_t len)
|
||||
* Implementation of ha_sync_message_t.add_attribute
|
||||
*/
|
||||
static void add_attribute(private_ha_sync_message_t *this,
|
||||
ha_sync_message_attribute_t attribute,
|
||||
ha_sync_message_value_t value)
|
||||
ha_sync_message_attribute_t attribute, ...)
|
||||
{
|
||||
size_t len;
|
||||
va_list args;
|
||||
|
||||
check_buf(this, sizeof(u_int8_t));
|
||||
this->buf.ptr[this->buf.len] = attribute;
|
||||
this->buf.len += sizeof(u_int8_t);
|
||||
|
||||
va_start(args, attribute);
|
||||
switch (attribute)
|
||||
{
|
||||
case HA_SYNC_ENCAP_U8:
|
||||
case HA_SYNC_MODE_U8:
|
||||
case HA_SYNC_IPCOMP_U8:
|
||||
check_buf(this, sizeof(value.u8));
|
||||
this->buf.ptr[this->buf.len] = value.u8;
|
||||
this->buf.len += sizeof(value.u8);
|
||||
/* ike_sa_id_t* */
|
||||
case HA_SYNC_IKE_ID:
|
||||
case HA_SYNC_IKE_REKEY_ID:
|
||||
{
|
||||
ike_sa_id_encoding_t *enc;
|
||||
ike_sa_id_t *id;
|
||||
|
||||
id = va_arg(args, ike_sa_id_t*);
|
||||
check_buf(this, sizeof(ike_sa_id_encoding_t));
|
||||
enc = (ike_sa_id_encoding_t*)(this->buf.ptr + this->buf.len);
|
||||
this->buf.len += sizeof(ike_sa_id_encoding_t);
|
||||
enc->initiator = id->is_initiator(id);
|
||||
enc->initiator_spi = id->get_initiator_spi(id);
|
||||
enc->responder_spi = id->get_responder_spi(id);
|
||||
break;
|
||||
case HA_SYNC_PORT_L_U16:
|
||||
case HA_SYNC_PORT_R_U16:
|
||||
case HA_SYNC_CPI_L_U16:
|
||||
case HA_SYNC_CPI_R_U16:
|
||||
case HA_SYNC_ALG_INTEG_U16:
|
||||
case HA_SYNC_ALG_ENC_U16:
|
||||
check_buf(this, sizeof(value.u16));
|
||||
this->buf.ptr[this->buf.len] = htons(value.u16);
|
||||
this->buf.len += sizeof(value.u16);
|
||||
}
|
||||
/* identification_t* */
|
||||
case HA_SYNC_LOCAL_ID:
|
||||
case HA_SYNC_REMOTE_ID:
|
||||
case HA_SYNC_EAP_ID:
|
||||
{
|
||||
identification_encoding_t *enc;
|
||||
identification_t *id;
|
||||
chunk_t data;
|
||||
|
||||
id = va_arg(args, identification_t*);
|
||||
data = id->get_encoding(id);
|
||||
check_buf(this, sizeof(identification_encoding_t) + data.len);
|
||||
enc = (identification_encoding_t*)(this->buf.ptr + this->buf.len);
|
||||
this->buf.len += sizeof(identification_encoding_t) + data.len;
|
||||
enc->type = id->get_type(id);
|
||||
enc->len = data.len;
|
||||
memcpy(enc->encoding, data.ptr, data.len);
|
||||
break;
|
||||
case HA_SYNC_SPI_L_U32:
|
||||
case HA_SYNC_SPI_R_U32:
|
||||
check_buf(this, sizeof(value.u32));
|
||||
this->buf.ptr[this->buf.len] = htonl(value.u32);
|
||||
this->buf.len += sizeof(value.u32);
|
||||
}
|
||||
/* host_t* */
|
||||
case HA_SYNC_LOCAL_ADDR:
|
||||
case HA_SYNC_REMOTE_ADDR:
|
||||
case HA_SYNC_LOCAL_VIP:
|
||||
case HA_SYNC_REMOTE_VIP:
|
||||
case HA_SYNC_ADDITIONAL_ADDR:
|
||||
{
|
||||
host_encoding_t *enc;
|
||||
host_t *host;
|
||||
chunk_t data;
|
||||
|
||||
host = va_arg(args, host_t*);
|
||||
data = host->get_address(host);
|
||||
check_buf(this, sizeof(host_encoding_t) + data.len);
|
||||
enc = (host_encoding_t*)(this->buf.ptr + this->buf.len);
|
||||
this->buf.len += sizeof(host_encoding_t) + data.len;
|
||||
enc->family = host->get_family(host);
|
||||
enc->port = htons(host->get_port(host));
|
||||
memcpy(enc->encoding, data.ptr, data.len);
|
||||
break;
|
||||
case HA_SYNC_IPV4_L_CHNK:
|
||||
case HA_SYNC_IPV4_R_CHNK:
|
||||
case HA_SYNC_NONCE_I_CHNK:
|
||||
case HA_SYNC_NONCE_R_CHNK:
|
||||
case HA_SYNC_SECRET_CHNK:
|
||||
check_buf(this, value.chnk.len);
|
||||
memcpy(this->buf.ptr + this->buf.len, value.chnk.ptr, value.chnk.len);
|
||||
this->buf.len += value.chnk.len;
|
||||
break;
|
||||
case HA_SYNC_CONFIG_STR:
|
||||
len = strlen(value.str) + 1;
|
||||
}
|
||||
/* char* */
|
||||
case HA_SYNC_CONFIG_NAME:
|
||||
{
|
||||
char *str;
|
||||
|
||||
str = va_arg(args, char*);
|
||||
len = strlen(str) + 1;
|
||||
check_buf(this, len);
|
||||
memcpy(this->buf.ptr + this->buf.len, value.str, len);
|
||||
memcpy(this->buf.ptr + this->buf.len, str, len);
|
||||
this->buf.len += len;
|
||||
break;
|
||||
}
|
||||
/** u_int32_t */
|
||||
case HA_SYNC_CONDITIONS:
|
||||
case HA_SYNC_EXTENSIONS:
|
||||
{
|
||||
u_int32_t val;
|
||||
|
||||
val = va_arg(args, u_int32_t);
|
||||
check_buf(this, sizeof(val));
|
||||
this->buf.ptr[this->buf.len] = htonl(val);
|
||||
this->buf.len += sizeof(val);
|
||||
break;
|
||||
}
|
||||
/** chunk_t */
|
||||
case HA_SYNC_NONCE_I:
|
||||
case HA_SYNC_NONCE_R:
|
||||
case HA_SYNC_SECRET:
|
||||
{
|
||||
chunk_t chunk;
|
||||
|
||||
chunk = va_arg(args, chunk_t);
|
||||
check_buf(this, chunk.len);
|
||||
memcpy(this->buf.ptr + this->buf.len, chunk.ptr, chunk.len);
|
||||
this->buf.len += chunk.len;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
DBG1(DBG_CFG, "unable to encode, attribute %d unknown", attribute);
|
||||
this->buf.len -= sizeof(u_int8_t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +270,7 @@ ha_sync_message_t *ha_sync_message_create(ha_sync_message_type_t type)
|
||||
{
|
||||
private_ha_sync_message_t *this = ha_sync_message_create_generic();
|
||||
|
||||
this->allocated = 64;
|
||||
this->allocated = ALLOCATION_BLOCK;
|
||||
this->buf.ptr = malloc(this->allocated);
|
||||
this->buf.len = 2;
|
||||
this->buf.ptr[0] = HA_SYNC_MESSAGE_VERSION;
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
#define HA_SYNC_MESSAGE_H_
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/host.h>
|
||||
#include <utils/identification.h>
|
||||
#include <sa/ike_sa_id.h>
|
||||
|
||||
/**
|
||||
* Protocol version of this implementation
|
||||
@@ -39,32 +42,56 @@ typedef union ha_sync_message_value_t ha_sync_message_value_t;
|
||||
* Type of a sync message
|
||||
*/
|
||||
enum ha_sync_message_type_t {
|
||||
HA_SYNC_CHILD_SA = 0,
|
||||
HA_SYNC_IKE_SA,
|
||||
HA_SYNC_IKE_MID,
|
||||
/** add a completely new IKE_SA */
|
||||
HA_SYNC_IKE_ADD = 1,
|
||||
/** update an existing IKE_SA (message IDs, address update, ...) */
|
||||
HA_SYNC_IKE_UPDATE,
|
||||
/** delete an existing IKE_SA */
|
||||
HA_SYNC_IKE_DELETE,
|
||||
/** rekeying an existing IKE_SA, transferring CHILD_SAs to a new one */
|
||||
HA_SYNC_IKE_REKEY,
|
||||
/** add a new CHILD_SA */
|
||||
HA_SYNC_CHILD_ADD,
|
||||
/** delete an existing CHILD_SA */
|
||||
HA_SYNC_CHILD_DELETE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of attributes contained in a message
|
||||
*/
|
||||
enum ha_sync_message_attribute_t {
|
||||
HA_SYNC_CONFIG_STR = 0,
|
||||
HA_SYNC_IPV4_L_CHNK,
|
||||
HA_SYNC_IPV4_R_CHNK,
|
||||
HA_SYNC_PORT_L_U16,
|
||||
HA_SYNC_PORT_R_U16,
|
||||
HA_SYNC_SPI_L_U32,
|
||||
HA_SYNC_SPI_R_U32,
|
||||
HA_SYNC_CPI_L_U16,
|
||||
HA_SYNC_CPI_R_U16,
|
||||
HA_SYNC_ENCAP_U8,
|
||||
HA_SYNC_MODE_U8,
|
||||
HA_SYNC_IPCOMP_U8,
|
||||
HA_SYNC_NONCE_I_CHNK,
|
||||
HA_SYNC_NONCE_R_CHNK,
|
||||
HA_SYNC_SECRET_CHNK,
|
||||
HA_SYNC_ALG_INTEG_U16,
|
||||
HA_SYNC_ALG_ENC_U16,
|
||||
/** ike_sa_id_t*, to identify IKE_SA */
|
||||
HA_SYNC_IKE_ID = 1,
|
||||
/** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */
|
||||
HA_SYNC_IKE_REKEY_ID,
|
||||
/** identification_t*, local identity */
|
||||
HA_SYNC_LOCAL_ID,
|
||||
/** identification_t*, remote identity */
|
||||
HA_SYNC_REMOTE_ID,
|
||||
/** identification_t*, EAP identity */
|
||||
HA_SYNC_EAP_ID,
|
||||
/** host_t*, local address */
|
||||
HA_SYNC_LOCAL_ADDR,
|
||||
/** host_t*, remote address */
|
||||
HA_SYNC_REMOTE_ADDR,
|
||||
/** char*, name of configuration */
|
||||
HA_SYNC_CONFIG_NAME,
|
||||
/** u_int32_t, bitset of ike_condition_t */
|
||||
HA_SYNC_CONDITIONS,
|
||||
/** u_int32_t, bitset of ike_extension_t */
|
||||
HA_SYNC_EXTENSIONS,
|
||||
/** host_t*, local virtual IP */
|
||||
HA_SYNC_LOCAL_VIP,
|
||||
/** host_t*, remote virtual IP */
|
||||
HA_SYNC_REMOTE_VIP,
|
||||
/** host_t*, additional MOBIKE peer address */
|
||||
HA_SYNC_ADDITIONAL_ADDR,
|
||||
/** chunk_t, initiators nonce */
|
||||
HA_SYNC_NONCE_I,
|
||||
/** chunk_t, responders nonce */
|
||||
HA_SYNC_NONCE_R,
|
||||
/** chunk_t, diffie hellman shared secret */
|
||||
HA_SYNC_SECRET,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -75,6 +102,9 @@ union ha_sync_message_value_t {
|
||||
u_int32_t u32;
|
||||
u_int16_t u16;
|
||||
chunk_t chnk;
|
||||
host_t *host;
|
||||
identification_t *id;
|
||||
ike_sa_id_t *ike_sa_id;
|
||||
char *str;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user