generating basic IKE_SA sync messages

pushing to statically configured failover node
This commit is contained in:
Martin Willi
2010-04-07 13:55:11 +02:00
committed by Martin Willi
parent e5e91eec29
commit 12ec91ba3a
3 changed files with 289 additions and 57 deletions
+102
View File
@@ -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;
}
+137 -37
View File
@@ -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;
+50 -20
View File
@@ -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;
};