From: Martin Willi Date: Mon, 17 Nov 2008 15:58:39 +0000 (+0000) Subject: basic syncing of IKE_SAs X-Git-Tag: 4.4.0~106 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=765935c8f681bebd28c7f54226917a8326065827;p=thirdparty%2Fstrongswan.git basic syncing of IKE_SAs recreating SAs with keymat derivation --- diff --git a/src/charon/plugins/ha_sync/Makefile.am b/src/charon/plugins/ha_sync/Makefile.am index fd15a6e286..b48a6cf4bb 100644 --- a/src/charon/plugins/ha_sync/Makefile.am +++ b/src/charon/plugins/ha_sync/Makefile.am @@ -9,6 +9,7 @@ libstrongswan_ha_sync_la_SOURCES = \ ha_sync_message.h ha_sync_message.c \ ha_sync_socket.h ha_sync_socket.c \ ha_sync_dispatcher.h ha_sync_dispatcher.c \ + ha_sync_dispatcher.h ha_sync_cache.c \ ha_sync_ike.h ha_sync_ike.c \ ha_sync_child.h ha_sync_child.c libstrongswan_ha_sync_la_LDFLAGS = -module diff --git a/src/charon/plugins/ha_sync/ha_sync_cache.c b/src/charon/plugins/ha_sync/ha_sync_cache.c new file mode 100644 index 0000000000..9924b084a6 --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_cache.c @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "ha_sync_cache.h" + +#include + +typedef struct private_ha_sync_cache_t private_ha_sync_cache_t; + +/** + * Private data of an ha_sync_cache_t object. + */ +struct private_ha_sync_cache_t { + + /** + * Public ha_sync_cache_t interface. + */ + ha_sync_cache_t public; + + /** + * Linked list of IKE_SAs, ike_sa_t + */ + linked_list_t *list; +}; + +/** + * Implementation of ha_sync_cache_t.get_ike_sa + */ +static ike_sa_t* get_ike_sa(private_ha_sync_cache_t *this, ike_sa_id_t *id) +{ + enumerator_t *enumerator; + ike_sa_t *current, *found = NULL; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (id->equals(id, current->get_id(current))) + { + found = current; + break; + } + } + enumerator->destroy(enumerator); + + if (!found) + { + found = ike_sa_create(id); + this->list->insert_first(this->list, found); + } + return found; +} + +/** + * Implementation of ha_sync_cache_t.delete_ike_sa + */ +static void delete_ike_sa(private_ha_sync_cache_t *this, ike_sa_id_t *id) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (id->equals(id, ike_sa->get_id(ike_sa))) + { + this->list->remove_at(this->list, enumerator); + ike_sa->destroy(ike_sa); + break; + } + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of ha_sync_cache_t.activate_segment + */ +static void activate_segment(private_ha_sync_cache_t *this, u_int segment) +{ + ike_sa_t *ike_sa; + + /* TODO: activate only segment, not all */ + while (this->list->remove_last(this->list, (void**)&ike_sa) == SUCCESS) + { + /* TODO: fix checkin of inexisting IKE_SA in manager */ + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } +} + +/** + * Implementation of ha_sync_cache_t.destroy. + */ +static void destroy(private_ha_sync_cache_t *this) +{ + this->list->destroy_offset(this->list, offsetof(ike_sa_t, destroy)); + free(this); +} + +/** + * See header + */ +ha_sync_cache_t *ha_sync_cache_create() +{ + private_ha_sync_cache_t *this = malloc_thing(private_ha_sync_cache_t); + + this->public.get_ike_sa = (ike_sa_t*(*)(ha_sync_cache_t*, ike_sa_id_t *id))get_ike_sa; + this->public.delete_ike_sa = (void(*)(ha_sync_cache_t*, ike_sa_id_t *id))delete_ike_sa; + this->public.activate_segment = (void(*)(ha_sync_cache_t*, u_int segment))activate_segment; + this->public.destroy = (void(*)(ha_sync_cache_t*))destroy; + + this->list = linked_list_create(); + + return &this->public; +} + diff --git a/src/charon/plugins/ha_sync/ha_sync_cache.h b/src/charon/plugins/ha_sync/ha_sync_cache.h new file mode 100644 index 0000000000..20880116ef --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_cache.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +/** + * @defgroup ha_sync_cache ha_sync_cache + * @{ @ingroup ha_sync + */ + +#ifndef HA_SYNC_CACHE_H_ +#define HA_SYNC_CACHE_H_ + +#include + +typedef struct ha_sync_cache_t ha_sync_cache_t; + +/** + * Locally cached HA state synced from other nodes. + */ +struct ha_sync_cache_t { + + /** + * Get a synced and cached IKE_SA entry. + * + * If no cached IKE_SA with such an id exists, it gets created. + * + * @param id IKE_SA identifier of cached SA. + * @return cached IKE_SA + */ + ike_sa_t* (*get_ike_sa)(ha_sync_cache_t *this, ike_sa_id_t *id); + + /** + * Delete a synced and cached IKE_SA entry. + * + * @param id IKE_SA identifier of cached SA to delete. + */ + void (*delete_ike_sa)(ha_sync_cache_t *this, ike_sa_id_t *id); + + /** + * Activate a set of IKE_SAs identified by a segment. + * + * Activating means do a takeover of SAs as the responsible node has failed. + * This involves moving all SAs to the daemons IKE_SA manager and handle + * them actively now. + * + * @param segment numerical segment to takeover + */ + void (*activate_segment)(ha_sync_cache_t *this, u_int segment); + + /** + * Destroy a ha_sync_cache_t. + */ + void (*destroy)(ha_sync_cache_t *this); +}; + +/** + * Create a ha_sync_cache instance. + */ +ha_sync_cache_t *ha_sync_cache_create(); + +#endif /* HA_SYNC_CACHE_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c index d5279da952..b42ca51489 100644 --- a/src/charon/plugins/ha_sync/ha_sync_dispatcher.c +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.c @@ -37,12 +37,26 @@ struct private_ha_sync_dispatcher_t { */ ha_sync_socket_t *socket; + /** + * Synced SA state cache + */ + ha_sync_cache_t *cache; + /** * Dispatcher job */ callback_job_t *job; }; +/** + * Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret + */ +static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret) +{ + *secret = chunk_clone((*(chunk_t*)this->destroy)); + return SUCCESS; +} + /** * Process messages of type IKE_ADD */ @@ -52,49 +66,204 @@ static void process_ike_add(private_ha_sync_dispatcher_t *this, ha_sync_message_attribute_t attribute; ha_sync_message_value_t value; enumerator_t *enumerator; + ike_sa_t *ike_sa = NULL; + u_int16_t encr = 0, len = 0, integ = 0, prf = 0; + chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) { switch (attribute) { - /* ike_sa_id_t* */ case HA_SYNC_IKE_ID: + ike_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); + break; case HA_SYNC_IKE_REKEY_ID: - DBG1(DBG_IKE, " %d -> %llu:%llu %s", attribute, - value.ike_sa_id->get_initiator_spi(value.ike_sa_id), - value.ike_sa_id->get_responder_spi(value.ike_sa_id), - value.ike_sa_id->is_initiator(value.ike_sa_id) ? - "initiator" : "responder"); + DBG1(DBG_IKE, "TODO: rekey HA sync"); + break; + case HA_SYNC_NONCE_I: + nonce_i = value.chunk; + break; + case HA_SYNC_NONCE_R: + nonce_r = value.chunk; + break; + case HA_SYNC_SECRET: + secret = value.chunk; + break; + case HA_SYNC_ALG_ENCR: + encr = value.u16; + break; + case HA_SYNC_ALG_ENCR_LEN: + len = value.u16; + break; + case HA_SYNC_ALG_INTEG: + integ = value.u16; + break; + case HA_SYNC_ALG_PRF: + prf = value.u16; + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + + if (ike_sa) + { + proposal_t *proposal; + keymat_t *keymat; + /* quick and dirty hack of a DH implementation ;-) */ + diffie_hellman_t dh = { .get_shared_secret = get_shared_secret, + .destroy = (void*)&secret }; + + proposal = proposal_create(PROTO_IKE); + keymat = ike_sa->get_keymat(ike_sa); + if (integ) + { + proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0); + } + if (encr) + { + proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); + } + if (prf) + { + proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); + } + if (!keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r, + ike_sa->get_id(ike_sa), NULL)) + { + DBG1(DBG_IKE, "HA sync keymat derivation failed"); + } + proposal->destroy(proposal); + } +} + +/** + * Apply a condition flag to the IKE_SA if it is in set + */ +static void set_condition(ike_sa_t *ike_sa, ike_condition_t set, + ike_condition_t flag) +{ + ike_sa->set_condition(ike_sa, flag, flag & set); +} + +/** + * Apply a extension flag to the IKE_SA if it is in set + */ +static void set_extension(ike_sa_t *ike_sa, ike_extension_t set, + ike_extension_t flag) +{ + if (flag & set) + { + ike_sa->enable_extension(ike_sa, flag); + } +} + +/** + * Process messages of type IKE_UPDATE + */ +static void process_ike_update(private_ha_sync_dispatcher_t *this, + ha_sync_message_t *message) +{ + ha_sync_message_attribute_t attribute; + ha_sync_message_value_t value; + enumerator_t *enumerator; + ike_sa_t *ike_sa = NULL; + peer_cfg_t *peer_cfg = NULL; + + enumerator = message->create_attribute_enumerator(message); + while (enumerator->enumerate(enumerator, &attribute, &value)) + { + if (attribute != HA_SYNC_IKE_ID && ike_sa == NULL) + { + DBG1(DBG_IKE, "HA_SYNC_IKE_ID must be first attribute"); + break; + } + switch (attribute) + { + case HA_SYNC_IKE_ID: + ike_sa = this->cache->get_ike_sa(this->cache, value.ike_sa_id); break; - /* identification_t* */ case HA_SYNC_LOCAL_ID: + ike_sa->set_my_id(ike_sa, value.id->clone(value.id)); + break; case HA_SYNC_REMOTE_ID: + ike_sa->set_other_id(ike_sa, value.id->clone(value.id)); + break; case HA_SYNC_EAP_ID: - DBG1(DBG_IKE, " %d -> %D", attribute, value.id); + ike_sa->set_eap_identity(ike_sa, value.id->clone(value.id)); break; - /* host_t* */ case HA_SYNC_LOCAL_ADDR: + ike_sa->set_my_host(ike_sa, value.host->clone(value.host)); + break; case HA_SYNC_REMOTE_ADDR: + ike_sa->set_other_host(ike_sa, value.host->clone(value.host)); + break; case HA_SYNC_LOCAL_VIP: case HA_SYNC_REMOTE_VIP: + ike_sa->set_virtual_ip(ike_sa, attribute == HA_SYNC_LOCAL_VIP, + value.host->clone(value.host)); + break; case HA_SYNC_ADDITIONAL_ADDR: - DBG1(DBG_IKE, " %d -> %H", attribute, value.host); + ike_sa->add_additional_address(ike_sa, + value.host->clone(value.host)); break; - /* char* */ case HA_SYNC_CONFIG_NAME: - DBG1(DBG_IKE, " %d -> %s", attribute, value.str); + peer_cfg = charon->backends->get_peer_cfg_by_name( + charon->backends, value.str); break; - /** u_int32_t */ case HA_SYNC_CONDITIONS: + set_condition(ike_sa, value.u32, EXT_NATT); + set_condition(ike_sa, value.u32, EXT_MOBIKE); + set_condition(ike_sa, value.u32, EXT_HASH_AND_URL); + break; case HA_SYNC_EXTENSIONS: - DBG1(DBG_IKE, " %d -> %lu", attribute, value.u32); + set_extension(ike_sa, value.u32, COND_NAT_ANY); + set_extension(ike_sa, value.u32, COND_NAT_HERE); + set_extension(ike_sa, value.u32, COND_NAT_THERE); + set_extension(ike_sa, value.u32, COND_NAT_FAKE); + set_extension(ike_sa, value.u32, COND_EAP_AUTHENTICATED); + set_extension(ike_sa, value.u32, COND_CERTREQ_SEEN); + set_extension(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); break; - /** chunk_t */ - case HA_SYNC_NONCE_I: - case HA_SYNC_NONCE_R: - case HA_SYNC_SECRET: - DBG1(DBG_IKE, " %d -> %B", attribute, &value.chunk); + default: + break; + } + } + enumerator->destroy(enumerator); + + if (peer_cfg) + { + ike_sa->set_peer_cfg(ike_sa, peer_cfg); + peer_cfg->destroy(peer_cfg); + } + else + { + DBG1(DBG_IKE, "HA sync is missing nodes configuration"); + } +} + +/** + * Process messages of type IKE_DELETE + */ +static void process_ike_delete(private_ha_sync_dispatcher_t *this, + ha_sync_message_t *message) +{ + ha_sync_message_attribute_t attribute; + ha_sync_message_value_t value; + enumerator_t *enumerator; + + enumerator = message->create_attribute_enumerator(message); + while (enumerator->enumerate(enumerator, &attribute, &value)) + { + switch (attribute) + { + case HA_SYNC_IKE_ID: + this->cache->delete_ike_sa(this->cache, value.ike_sa_id); + break; + default: break; } } @@ -115,8 +284,10 @@ static job_requeue_t dispatch(private_ha_sync_dispatcher_t *this) process_ike_add(this, message); break; case HA_SYNC_IKE_UPDATE: + process_ike_update(this, message); break; case HA_SYNC_IKE_DELETE: + process_ike_delete(this, message); break; case HA_SYNC_IKE_REKEY: break; @@ -146,13 +317,15 @@ static void destroy(private_ha_sync_dispatcher_t *this) /** * See header */ -ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket) +ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket, + ha_sync_cache_t *cache) { private_ha_sync_dispatcher_t *this = malloc_thing(private_ha_sync_dispatcher_t); this->public.destroy = (void(*)(ha_sync_dispatcher_t*))destroy; this->socket = socket; + this->cache = cache; this->job = callback_job_create((callback_job_cb_t)dispatch, this, NULL, NULL); charon->processor->queue_job(charon->processor, (job_t*)this->job); diff --git a/src/charon/plugins/ha_sync/ha_sync_dispatcher.h b/src/charon/plugins/ha_sync/ha_sync_dispatcher.h index eb2817e916..eda4c4ddbc 100644 --- a/src/charon/plugins/ha_sync/ha_sync_dispatcher.h +++ b/src/charon/plugins/ha_sync/ha_sync_dispatcher.h @@ -24,6 +24,7 @@ #define HA_SYNC_DISPATCHER_H_ #include "ha_sync_socket.h" +#include "ha_sync_cache.h" typedef struct ha_sync_dispatcher_t ha_sync_dispatcher_t; @@ -42,8 +43,10 @@ struct ha_sync_dispatcher_t { * Create a ha_sync_dispatcher instance pulling from socket. * * @param socket socket to pull messages from + * @param cache cache to push synced SAs to * @return dispatcher object */ -ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket); +ha_sync_dispatcher_t *ha_sync_dispatcher_create(ha_sync_socket_t *socket, + ha_sync_cache_t *cache); #endif /* HA_SYNC_DISPATCHER_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.c b/src/charon/plugins/ha_sync/ha_sync_ike.c index 083b6a0fe7..2984f57c31 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.c +++ b/src/charon/plugins/ha_sync/ha_sync_ike.c @@ -66,31 +66,10 @@ 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); + proposal_t *proposal; + u_int16_t alg, len; if (dh->get_shared_secret(dh, &secret) != SUCCESS) { @@ -102,30 +81,6 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, 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_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 { @@ -135,6 +90,23 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, m->add_attribute(m, HA_SYNC_IKE_REKEY_ID, rekey->get_id(rekey)); } + proposal = ike_sa->get_proposal(ike_sa); + if (proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &alg, &len)) + { + m->add_attribute(m, HA_SYNC_ALG_ENCR, alg); + if (len) + { + m->add_attribute(m, HA_SYNC_ALG_ENCR_LEN, len); + } + } + if (proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &alg, NULL)) + { + m->add_attribute(m, HA_SYNC_ALG_INTEG, alg); + } + if (proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &alg, NULL)) + { + m->add_attribute(m, HA_SYNC_ALG_PRF, alg); + } 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); @@ -146,6 +118,85 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, return TRUE; } +/** + * Implementation of listener_t.ike_state_change + */ +static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, + ike_sa_state_t state) +{ + ha_sync_message_t *m; + + switch (state) + { + case IKE_ESTABLISHED: + { + iterator_t *iterator; + peer_cfg_t *peer_cfg; + u_int32_t extension, condition; + host_t *local_vip, *remote_vip, *addr; + identification_t *eap_id; + + 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); + + m = ha_sync_message_create(HA_SYNC_IKE_UPDATE); + 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_CONDITIONS, condition); + m->add_attribute(m, HA_SYNC_EXTENSIONS, extension); + m->add_attribute(m, HA_SYNC_CONFIG_NAME, peer_cfg->get_name(peer_cfg)); + 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); + break; + } + case IKE_DESTROYING: + { + m = ha_sync_message_create(HA_SYNC_IKE_DELETE); + m->add_attribute(m, HA_SYNC_IKE_ID, ike_sa->get_id(ike_sa)); + break; + } + default: + return TRUE; + } + this->socket->push(this->socket, m); + m->destroy(m); + return TRUE; +} + /** * Implementation of ha_sync_ike_t.destroy. */ @@ -163,6 +214,7 @@ ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket) memset(&this->public.listener, 0, sizeof(listener_t)); this->public.listener.ike_keys = (bool(*)(listener_t*, ike_sa_t *ike_sa, diffie_hellman_t *dh,chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey))ike_keys; + this->public.listener.ike_state_change = (bool(*)(listener_t*,ike_sa_t *ike_sa, ike_sa_state_t state))ike_state_change; this->public.destroy = (void(*)(ha_sync_ike_t*))destroy; this->socket = socket; diff --git a/src/charon/plugins/ha_sync/ha_sync_message.c b/src/charon/plugins/ha_sync/ha_sync_message.c index f8a81dc74f..7a1fc71343 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.c +++ b/src/charon/plugins/ha_sync/ha_sync_message.c @@ -191,6 +191,20 @@ static void add_attribute(private_ha_sync_message_t *this, this->buf.len += len; break; } + /* u_int16_t */ + case HA_SYNC_ALG_PRF: + case HA_SYNC_ALG_ENCR: + case HA_SYNC_ALG_ENCR_LEN: + case HA_SYNC_ALG_INTEG: + { + u_int16_t val; + + val = (u_int16_t)va_arg(args, u_int32_t); + check_buf(this, sizeof(val)); + *(u_int16_t*)(this->buf.ptr + this->buf.len) = htons(val); + this->buf.len += sizeof(val); + break; + } /** u_int32_t */ case HA_SYNC_CONDITIONS: case HA_SYNC_EXTENSIONS: @@ -199,7 +213,7 @@ static void add_attribute(private_ha_sync_message_t *this, val = va_arg(args, u_int32_t); check_buf(this, sizeof(val)); - this->buf.ptr[this->buf.len] = htonl(val); + *(u_int32_t*)(this->buf.ptr + this->buf.len) = htonl(val); this->buf.len += sizeof(val); break; } @@ -349,6 +363,21 @@ static bool attribute_enumerate(attribute_enumerator_t *this, this->buf = chunk_skip(this->buf, len + 1); return TRUE; } + /** u_int16_t */ + case HA_SYNC_ALG_PRF: + case HA_SYNC_ALG_ENCR: + case HA_SYNC_ALG_ENCR_LEN: + case HA_SYNC_ALG_INTEG: + { + if (this->buf.len < sizeof(u_int16_t)) + { + return FALSE; + } + value->u16 = ntohs(*(u_int16_t*)this->buf.ptr); + *attr_out = attr; + this->buf = chunk_skip(this->buf, sizeof(u_int16_t)); + return TRUE; + } /** u_int32_t */ case HA_SYNC_CONDITIONS: case HA_SYNC_EXTENSIONS: diff --git a/src/charon/plugins/ha_sync/ha_sync_message.h b/src/charon/plugins/ha_sync/ha_sync_message.h index 53701e12df..e7d358ccc1 100644 --- a/src/charon/plugins/ha_sync/ha_sync_message.h +++ b/src/charon/plugins/ha_sync/ha_sync_message.h @@ -92,6 +92,14 @@ enum ha_sync_message_attribute_t { HA_SYNC_NONCE_R, /** chunk_t, diffie hellman shared secret */ HA_SYNC_SECRET, + /** u_int16_t, pseudo random function */ + HA_SYNC_ALG_PRF, + /** u_int16_t, encryption algorithm */ + HA_SYNC_ALG_ENCR, + /** u_int16_t, encryption key size in bytes */ + HA_SYNC_ALG_ENCR_LEN, + /** u_int16_t, integrity protection algorithm */ + HA_SYNC_ALG_INTEG, }; /** @@ -99,6 +107,7 @@ enum ha_sync_message_attribute_t { */ union ha_sync_message_value_t { u_int32_t u32; + u_int16_t u16; char *str; chunk_t chunk; ike_sa_id_t *ike_sa_id; diff --git a/src/charon/plugins/ha_sync/ha_sync_plugin.c b/src/charon/plugins/ha_sync/ha_sync_plugin.c index 8a73512c86..aae51aa727 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.c +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.c @@ -20,6 +20,7 @@ #include "ha_sync_child.h" #include "ha_sync_socket.h" #include "ha_sync_dispatcher.h" +#include "ha_sync_cache.h" #include #include @@ -55,6 +56,11 @@ struct private_ha_sync_plugin_t { * Dispatcher to process incoming messages */ ha_sync_dispatcher_t *dispatcher; + + /** + * Local cache of a nodes synced SAs + */ + ha_sync_cache_t *cache; }; /** @@ -67,6 +73,7 @@ static void destroy(private_ha_sync_plugin_t *this) this->ike->destroy(this->ike); this->child->destroy(this->child); this->dispatcher->destroy(this->dispatcher); + this->cache->destroy(this->cache); this->socket->destroy(this->socket); free(this); } @@ -86,7 +93,8 @@ plugin_t *plugin_create() free(this); return NULL; } - this->dispatcher = ha_sync_dispatcher_create(this->socket); + this->cache = ha_sync_cache_create(); + this->dispatcher = ha_sync_dispatcher_create(this->socket, this->cache); this->ike = ha_sync_ike_create(this->socket); this->child = ha_sync_child_create(this->socket); charon->bus->add_listener(charon->bus, &this->ike->listener);