From: Martin Willi Date: Thu, 13 Nov 2008 12:46:01 +0000 (+0000) Subject: generating basic IKE_SA sync messages X-Git-Tag: 4.4.0~108 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=12ec91ba3a08dc8e8976011ffbe7442857cfa8a9;p=thirdparty%2Fstrongswan.git generating basic IKE_SA sync messages pushing to statically configured failover node --- diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.c b/src/charon/plugins/ha_sync/ha_sync_ike.c index e894e39368..46af18694b 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.c +++ b/src/charon/plugins/ha_sync/ha_sync_ike.c @@ -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; } diff --git a/src/charon/plugins/ha_sync/ha_sync_message.c b/src/charon/plugins/ha_sync/ha_sync_message.c index fcb601c204..ee3aa245cb 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.c +++ b/src/charon/plugins/ha_sync/ha_sync_message.c @@ -21,6 +21,8 @@ #include +#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); - 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); + /* 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_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); + } + /* 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_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; + } + /* 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_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; diff --git a/src/charon/plugins/ha_sync/ha_sync_message.h b/src/charon/plugins/ha_sync/ha_sync_message.h index 714becfc14..ebe0c2df4a 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.h +++ b/src/charon/plugins/ha_sync/ha_sync_message.h @@ -24,6 +24,9 @@ #define HA_SYNC_MESSAGE_H_ #include +#include +#include +#include /** * 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; };