diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/plugins/ha_sync/Makefile.am | 1 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_child.c | 13 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_child.h | 5 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_ike.c | 15 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_ike.h | 5 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_plugin.c | 54 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_plugin.h | 5 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_socket.c | 314 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_socket.h | 15 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_tunnel.c | 293 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_tunnel.h | 57 |
11 files changed, 461 insertions, 316 deletions
diff --git a/src/charon/plugins/ha_sync/Makefile.am b/src/charon/plugins/ha_sync/Makefile.am index aadf7dd65..da634c96d 100644 --- a/src/charon/plugins/ha_sync/Makefile.am +++ b/src/charon/plugins/ha_sync/Makefile.am @@ -8,6 +8,7 @@ libstrongswan_ha_sync_la_SOURCES = \ ha_sync_plugin.h ha_sync_plugin.c \ ha_sync_message.h ha_sync_message.c \ ha_sync_socket.h ha_sync_socket.c \ + ha_sync_tunnel.h ha_sync_tunnel.c \ ha_sync_dispatcher.h ha_sync_dispatcher.c \ ha_sync_segments.h ha_sync_segments.c \ ha_sync_ctl.h ha_sync_ctl.c \ diff --git a/src/charon/plugins/ha_sync/ha_sync_child.c b/src/charon/plugins/ha_sync/ha_sync_child.c index 91b8573ca..9f200eccb 100644 --- a/src/charon/plugins/ha_sync/ha_sync_child.c +++ b/src/charon/plugins/ha_sync/ha_sync_child.c @@ -31,6 +31,11 @@ struct private_ha_sync_child_t { * socket we use for syncing */ ha_sync_socket_t *socket; + + /** + * tunnel securing sync messages + */ + ha_sync_tunnel_t *tunnel; }; /** @@ -48,7 +53,7 @@ static bool child_keys(private_ha_sync_child_t *this, ike_sa_t *ike_sa, enumerator_t *enumerator; traffic_selector_t *ts; - if (this->socket->is_sync_sa(this->socket, ike_sa)) + if (this->tunnel && this->tunnel->is_sync_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } @@ -115,7 +120,7 @@ static bool child_state_change(private_ha_sync_child_t *this, ike_sa_t *ike_sa, { /* only sync active IKE_SAs */ return TRUE; } - if (this->socket->is_sync_sa(this->socket, ike_sa)) + if (this->tunnel && this->tunnel->is_sync_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } @@ -145,7 +150,8 @@ static void destroy(private_ha_sync_child_t *this) /** * See header */ -ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket) +ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket, + ha_sync_tunnel_t *tunnel) { private_ha_sync_child_t *this = malloc_thing(private_ha_sync_child_t); @@ -155,6 +161,7 @@ ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket) this->public.destroy = (void(*)(ha_sync_child_t*))destroy; this->socket = socket; + this->tunnel = tunnel; return &this->public; } diff --git a/src/charon/plugins/ha_sync/ha_sync_child.h b/src/charon/plugins/ha_sync/ha_sync_child.h index 4a6402abc..10d0bc7d9 100644 --- a/src/charon/plugins/ha_sync/ha_sync_child.h +++ b/src/charon/plugins/ha_sync/ha_sync_child.h @@ -22,6 +22,7 @@ #define HA_SYNC_CHILD_H_ #include "ha_sync_socket.h" +#include "ha_sync_tunnel.h" #include "ha_sync_segments.h" #include <daemon.h> @@ -48,8 +49,10 @@ struct ha_sync_child_t { * Create a ha_sync_child instance. * * @param socket socket to use for sending synchronization messages + * @param tunnel tunnel securing sync messages, if any * @return CHILD listener */ -ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket); +ha_sync_child_t *ha_sync_child_create(ha_sync_socket_t *socket, + ha_sync_tunnel_t *tunnel); #endif /* HA_SYNC_CHILD_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.c b/src/charon/plugins/ha_sync/ha_sync_ike.c index 18033c824..dba3d0da2 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.c +++ b/src/charon/plugins/ha_sync/ha_sync_ike.c @@ -31,6 +31,11 @@ struct private_ha_sync_ike_t { * socket we use for syncing */ ha_sync_socket_t *socket; + + /** + * tunnel securing sync messages + */ + ha_sync_tunnel_t *tunnel; }; /** @@ -69,7 +74,7 @@ static bool ike_keys(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, proposal_t *proposal; u_int16_t alg, len; - if (this->socket->is_sync_sa(this->socket, ike_sa)) + if (this->tunnel && this->tunnel->is_sync_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } @@ -131,7 +136,7 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, { /* only sync active IKE_SAs */ return TRUE; } - if (this->socket->is_sync_sa(this->socket, ike_sa)) + if (this->tunnel && this->tunnel->is_sync_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } @@ -204,7 +209,7 @@ static bool ike_state_change(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, static bool message_hook(private_ha_sync_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming) { - if (this->socket->is_sync_sa(this->socket, ike_sa)) + if (this->tunnel && this->tunnel->is_sync_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } @@ -260,7 +265,8 @@ static void destroy(private_ha_sync_ike_t *this) /** * See header */ -ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket) +ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket, + ha_sync_tunnel_t *tunnel) { private_ha_sync_ike_t *this = malloc_thing(private_ha_sync_ike_t); @@ -271,6 +277,7 @@ ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket) this->public.destroy = (void(*)(ha_sync_ike_t*))destroy; this->socket = socket; + this->tunnel = tunnel; return &this->public; } diff --git a/src/charon/plugins/ha_sync/ha_sync_ike.h b/src/charon/plugins/ha_sync/ha_sync_ike.h index 4b27c0f33..94128e194 100644 --- a/src/charon/plugins/ha_sync/ha_sync_ike.h +++ b/src/charon/plugins/ha_sync/ha_sync_ike.h @@ -22,6 +22,7 @@ #define HA_SYNC_IKE_H_ #include "ha_sync_socket.h" +#include "ha_sync_tunnel.h" #include "ha_sync_segments.h" #include <daemon.h> @@ -48,8 +49,10 @@ struct ha_sync_ike_t { * Create a ha_sync_ike instance. * * @param socket socket to use for sending synchronization messages + * @param tunnel tunnel securing sync messages, if any * @return IKE listener */ -ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket); +ha_sync_ike_t *ha_sync_ike_create(ha_sync_socket_t *socket, + ha_sync_tunnel_t *tunnel); #endif /* HA_SYNC_IKE_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_plugin.c b/src/charon/plugins/ha_sync/ha_sync_plugin.c index 027bc10dc..af474af12 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.c +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.c @@ -17,6 +17,7 @@ #include "ha_sync_ike.h" #include "ha_sync_child.h" #include "ha_sync_socket.h" +#include "ha_sync_tunnel.h" #include "ha_sync_dispatcher.h" #include "ha_sync_segments.h" #include "ha_sync_ctl.h" @@ -42,6 +43,11 @@ struct private_ha_sync_plugin_t { ha_sync_socket_t *socket; /** + * Tunnel securing sync messages. + */ + ha_sync_tunnel_t *tunnel; + + /** * IKE_SA synchronization */ ha_sync_ike_t *ike; @@ -72,10 +78,7 @@ struct private_ha_sync_plugin_t { */ static void destroy(private_ha_sync_plugin_t *this) { - if (this->ctl) - { - this->ctl->destroy(this->ctl); - } + DESTROY_IF(this->ctl); charon->bus->remove_listener(charon->bus, &this->ike->listener); charon->bus->remove_listener(charon->bus, &this->child->listener); this->ike->destroy(this->ike); @@ -83,6 +86,7 @@ static void destroy(private_ha_sync_plugin_t *this) this->dispatcher->destroy(this->dispatcher); this->segments->destroy(this->segments); this->socket->destroy(this->socket); + DESTROY_IF(this->tunnel); free(this); } @@ -91,28 +95,50 @@ static void destroy(private_ha_sync_plugin_t *this) */ plugin_t *plugin_create() { - private_ha_sync_plugin_t *this = malloc_thing(private_ha_sync_plugin_t); + private_ha_sync_plugin_t *this; + char *local, *remote, *secret; + bool fifo; + + local = lib->settings->get_str(lib->settings, + "charon.plugins.ha_sync.local", NULL); + remote = lib->settings->get_str(lib->settings, + "charon.plugins.ha_sync.remote", NULL); + secret = lib->settings->get_str(lib->settings, + "charon.plugins.ha_sync.secret", NULL); + fifo = lib->settings->get_bool(lib->settings, + "charon.plugins.ha_sync.fifo_interface", FALSE); + if (!local || !remote) + { + DBG1(DBG_CFG, "HA sync config misses local/remote address"); + return NULL; + } + + this = malloc_thing(private_ha_sync_plugin_t); this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + this->tunnel = NULL; + this->ctl = NULL; - this->socket = ha_sync_socket_create(); + this->socket = ha_sync_socket_create(local, remote); if (!this->socket) { free(this); return NULL; } this->segments = ha_sync_segments_create(); - this->dispatcher = ha_sync_dispatcher_create(this->socket); - 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); - charon->bus->add_listener(charon->bus, &this->child->listener); - this->ctl = NULL; - if (lib->settings->get_bool(lib->settings, - "charon.plugins.ha_sync.fifo_interface", FALSE)) + if (secret) + { + this->tunnel = ha_sync_tunnel_create(secret, local, remote); + } + if (fifo) { this->ctl = ha_sync_ctl_create(this->segments); } + this->dispatcher = ha_sync_dispatcher_create(this->socket); + this->ike = ha_sync_ike_create(this->socket, this->tunnel); + this->child = ha_sync_child_create(this->socket, this->tunnel); + charon->bus->add_listener(charon->bus, &this->ike->listener); + charon->bus->add_listener(charon->bus, &this->child->listener); return &this->public.plugin; } diff --git a/src/charon/plugins/ha_sync/ha_sync_plugin.h b/src/charon/plugins/ha_sync/ha_sync_plugin.h index 5ecd8ca4f..1337c0c8d 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.h +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.h @@ -26,6 +26,11 @@ #include <plugins/plugin.h> +/** + * UDP port we use for communication + */ +#define HA_SYNC_PORT 4510 + typedef struct ha_sync_plugin_t ha_sync_plugin_t; /** diff --git a/src/charon/plugins/ha_sync/ha_sync_socket.c b/src/charon/plugins/ha_sync/ha_sync_socket.c index 3432d7b8e..41e818528 100644 --- a/src/charon/plugins/ha_sync/ha_sync_socket.c +++ b/src/charon/plugins/ha_sync/ha_sync_socket.c @@ -14,6 +14,7 @@ */ #include "ha_sync_socket.h" +#include "ha_sync_plugin.h" #include <sys/types.h> #include <sys/socket.h> @@ -87,24 +88,14 @@ struct private_ha_sync_socket_t { int fd; /** - * remote host to receive/send to + * local host to receive/send from */ - host_t *remote; - - /** - * Reqid of installed trap - */ - u_int32_t trap; - - /** - * backend for sync SA - */ - ha_backend_t backend; + host_t *local; /** - * credential set for sync SA + * remote host to receive/send to */ - ha_creds_t creds; + host_t *remote; }; /** @@ -148,31 +139,19 @@ static job_requeue_t send_message(job_data_t *data) */ static void push(private_ha_sync_socket_t *this, ha_sync_message_t *message) { - if (this->trap) - { - callback_job_t *job; - job_data_t *data; - - data = malloc_thing(job_data_t); - data->message = message; - data->this = this; - - /* we send sync message asynchronously. This is required, as sendto() - * is a blocking call if it acquires a policy. Otherwise we could - * end up in a deadlock, as we own an IKE_SA. */ - job = callback_job_create((callback_job_cb_t)send_message, - data, (void*)job_data_destroy, NULL); - charon->processor->queue_job(charon->processor, (job_t*)job); - } - else - { - job_data_t data; - - data.message = message; - data.this = this; - send_message(&data); - message->destroy(message); - } + callback_job_t *job; + job_data_t *data; + + data = malloc_thing(job_data_t); + data->message = message; + data->this = this; + + /* we send sync message asynchronously. This is required, as sendto() + * is a blocking call if it acquires a policy. Otherwise we could + * end up in a deadlock, as we own an IKE_SA. */ + job = callback_job_create((callback_job_cb_t)send_message, + data, (void*)job_data_destroy, NULL); + charon->processor->queue_job(charon->processor, (job_t*)job); } /** @@ -211,230 +190,25 @@ static ha_sync_message_t *pull(private_ha_sync_socket_t *this) } /** - * Implementation of ha_sync_socket_t.is_sync_sa - */ -static bool is_sync_sa(private_ha_sync_socket_t *this, ike_sa_t *ike_sa) -{ - peer_cfg_t *cfg = this->backend.cfg; - - return cfg && ike_sa->get_ike_cfg(ike_sa) == cfg->get_ike_cfg(cfg); -} - -/** - * Enumerator over HA shared_key - */ -typedef struct { - /** Implements enumerator_t */ - enumerator_t public; - /** a single secret we serve */ - shared_key_t *key; -} shared_enum_t; - -/** - * Implementation of shared_enum_t.enumerate - */ -static bool shared_enumerate(shared_enum_t *this, shared_key_t **key, - id_match_t *me, id_match_t *other) -{ - if (this->key) - { - if (me) - { - *me = ID_MATCH_PERFECT; - } - if (other) - { - *other = ID_MATCH_PERFECT; - } - *key = this->key; - this->key = NULL; - return TRUE; - } - return FALSE; -} - -/** - * Implements ha_creds_t.create_shared_enumerator - */ -static enumerator_t* create_shared_enumerator(ha_creds_t *this, - shared_key_type_t type, identification_t *me, - identification_t *other) -{ - shared_enum_t *enumerator; - - if (type != SHARED_IKE && type != SHARED_ANY) - { - return NULL; - } - if (me && !me->equals(me, this->local)) - { - return NULL; - } - if (other && !other->equals(other, this->remote)) - { - return NULL; - } - - enumerator = malloc_thing(shared_enum_t); - enumerator->public.enumerate = (void*)shared_enumerate; - enumerator->public.destroy = (void*)free; - enumerator->key = this->key; - - return &enumerator->public; -} - -/** - * Implementation of backend_t.create_peer_cfg_enumerator. - */ -static enumerator_t* create_peer_cfg_enumerator(ha_backend_t *this, - identification_t *me, identification_t *other) -{ - return enumerator_create_single(this->cfg, NULL); -} - -/** - * Implementation of backend_t.create_ike_cfg_enumerator. - */ -static enumerator_t* create_ike_cfg_enumerator(ha_backend_t *this, - host_t *me, host_t *other) -{ - return enumerator_create_single(this->cfg->get_ike_cfg(this->cfg), NULL); -} - -/** - * Install configs and a a trap for secured sync - */ -static void setup_sync_tunnel(private_ha_sync_socket_t *this) -{ - char *local, *remote, *secret; - peer_cfg_t *peer_cfg; - ike_cfg_t *ike_cfg; - auth_cfg_t *auth_cfg; - child_cfg_t *child_cfg; - traffic_selector_t *ts; - lifetime_cfg_t lifetime = { - .time = { - .life = 21600, .rekey = 20400, .jitter = 400, - }, - }; - - secret = lib->settings->get_str(lib->settings, - "charon.plugins.ha_sync.secret", NULL); - if (!secret) - { - DBG1(DBG_CFG, "no HA sync secret defined, using unencrypted sync"); - return; - } - local = lib->settings->get_str(lib->settings, - "charon.plugins.ha_sync.local", NULL); - remote = lib->settings->get_str(lib->settings, - "charon.plugins.ha_sync.remote", NULL); - - /* setup credentials */ - this->creds.key = shared_key_create(SHARED_IKE, - chunk_clone(chunk_create(secret, strlen(secret)))); - this->creds.local = identification_create_from_string(local); - this->creds.remote = identification_create_from_string(remote); - this->creds.public.create_private_enumerator = (void*)return_null; - this->creds.public.create_cert_enumerator = (void*)return_null; - this->creds.public.create_shared_enumerator = (void*)create_shared_enumerator; - this->creds.public.create_cdp_enumerator = (void*)return_null; - this->creds.public.cache_cert = (void*)nop; - - charon->credentials->add_set(charon->credentials, &this->creds.public); - - /* create config and backend */ - ike_cfg = ike_cfg_create(FALSE, FALSE, local, remote); - ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); - peer_cfg = peer_cfg_create("ha-sync", 2, ike_cfg, CERT_NEVER_SEND, - UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30, - NULL, NULL, FALSE, NULL, NULL); - - auth_cfg = auth_cfg_create(); - auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); - auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY, - identification_create_from_string(local)); - peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE); - - auth_cfg = auth_cfg_create(); - auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); - auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY, - identification_create_from_string(remote)); - peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE); - - child_cfg = child_cfg_create("ha-sync", &lifetime, NULL, TRUE, - MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE); - ts = traffic_selector_create_dynamic(0, HA_SYNC_PORT, HA_SYNC_PORT); - child_cfg->add_traffic_selector(child_cfg, TRUE, ts); - ts = traffic_selector_create_dynamic(0, HA_SYNC_PORT, HA_SYNC_PORT); - child_cfg->add_traffic_selector(child_cfg, FALSE, ts); - child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); - peer_cfg->add_child_cfg(peer_cfg, child_cfg); - - this->backend.cfg = peer_cfg; - this->backend.public.create_peer_cfg_enumerator = (void*)create_peer_cfg_enumerator; - this->backend.public.create_ike_cfg_enumerator = (void*)create_ike_cfg_enumerator; - this->backend.public.get_peer_cfg_by_name = (void*)return_null; - - charon->backends->add_backend(charon->backends, &this->backend.public); - - /* install an acquiring trap */ - this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg); -} - -/** - * read local/remote node address from config - */ -static host_t *get_host_config(char *key) -{ - char *value; - host_t *host; - - value = lib->settings->get_str(lib->settings, - "charon.plugins.ha_sync.%s", NULL, key); - if (!value) - { - DBG1(DBG_CFG, "no %s node specified for HA sync", key); - return NULL; - } - host = host_create_from_dns(value, 0, HA_SYNC_PORT); - if (!host) - { - DBG1(DBG_CFG, "%s node '%s' is invalid", key, value); - } - return host; -} - -/** * Open and connect the HA sync socket */ static bool open_socket(private_ha_sync_socket_t *this) { - host_t *local; - - local = get_host_config("local"); - if (!local) - { - return FALSE; - } - - this->fd = socket(local->get_family(local), SOCK_DGRAM, 0); - if (!this->fd) + this->fd = socket(this->local->get_family(this->local), SOCK_DGRAM, 0); + if (this->fd == -1) { - local->destroy(local); DBG1(DBG_CFG, "opening HA sync socket failed: %s", strerror(errno)); return FALSE; } - if (bind(this->fd, local->get_sockaddr(local), - *local->get_sockaddr_len(local)) == -1) + if (bind(this->fd, this->local->get_sockaddr(this->local), + *this->local->get_sockaddr_len(this->local)) == -1) { DBG1(DBG_CFG, "binding HA sync socket failed: %s", strerror(errno)); close(this->fd); - local->destroy(local); + this->fd = -1; return FALSE; } - local->destroy(local); return TRUE; } @@ -443,59 +217,41 @@ static bool open_socket(private_ha_sync_socket_t *this) */ static void destroy(private_ha_sync_socket_t *this) { - close(this->fd); - if (this->backend.cfg) + if (this->fd != -1) { - charon->backends->remove_backend(charon->backends, &this->backend.public); - this->backend.cfg->destroy(this->backend.cfg); - } - if (this->creds.key) - { - charon->credentials->remove_set(charon->credentials, &this->creds.public); - this->creds.key->destroy(this->creds.key); + close(this->fd); } - DESTROY_IF(this->creds.local); - DESTROY_IF(this->creds.remote); + DESTROY_IF(this->local); DESTROY_IF(this->remote); - if (this->trap) - { - charon->traps->uninstall(charon->traps, this->trap); - } free(this); } /** * See header */ -ha_sync_socket_t *ha_sync_socket_create() +ha_sync_socket_t *ha_sync_socket_create(char *local, char *remote) { private_ha_sync_socket_t *this = malloc_thing(private_ha_sync_socket_t); this->public.push = (void(*)(ha_sync_socket_t*, ha_sync_message_t*))push; this->public.pull = (ha_sync_message_t*(*)(ha_sync_socket_t*))pull; - this->public.is_sync_sa = (bool(*)(ha_sync_socket_t*, ike_sa_t *ike_sa))is_sync_sa; this->public.destroy = (void(*)(ha_sync_socket_t*))destroy; - this->remote = get_host_config("remote"); - if (!this->remote) + this->local = host_create_from_dns(local, 0, HA_SYNC_PORT); + this->remote = host_create_from_dns(remote, 0, HA_SYNC_PORT); + this->fd = -1; + + if (!this->local || !this->remote) { - free(this); + DBG1(DBG_CFG, "invalid local/remote HA sync address"); + destroy(this); return NULL; } - this->trap = 0; - this->creds.key = NULL; - this->creds.local = NULL; - this->creds.remote = NULL; - this->backend.cfg = NULL; - - setup_sync_tunnel(this); - if (!open_socket(this)) { - free(this); + destroy(this); return NULL; } - return &this->public; } diff --git a/src/charon/plugins/ha_sync/ha_sync_socket.h b/src/charon/plugins/ha_sync/ha_sync_socket.h index 2bd5fdc33..20c2812f9 100644 --- a/src/charon/plugins/ha_sync/ha_sync_socket.h +++ b/src/charon/plugins/ha_sync/ha_sync_socket.h @@ -25,11 +25,6 @@ #include <sa/ike_sa.h> -/** - * UDP port we use for communication - */ -#define HA_SYNC_PORT 4510 - typedef struct ha_sync_socket_t ha_sync_socket_t; /** @@ -52,14 +47,6 @@ struct ha_sync_socket_t { ha_sync_message_t *(*pull)(ha_sync_socket_t *this); /** - * Check if an IKE_SA is used for exchanging sync messages. - * - * @param ike_Sa ike_sa to check - * @return TRUE if IKE_SA is used to secure sync messages - */ - bool (*is_sync_sa)(ha_sync_socket_t *this, ike_sa_t *ike_sa); - - /** * Destroy a ha_sync_socket_t. */ void (*destroy)(ha_sync_socket_t *this); @@ -68,6 +55,6 @@ struct ha_sync_socket_t { /** * Create a ha_sync_socket instance. */ -ha_sync_socket_t *ha_sync_socket_create(); +ha_sync_socket_t *ha_sync_socket_create(char *local, char *remote); #endif /* HA_SYNC_SOCKET_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_tunnel.c b/src/charon/plugins/ha_sync/ha_sync_tunnel.c new file mode 100644 index 000000000..e9848257a --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_tunnel.c @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2009 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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. + */ + +#include "ha_sync_tunnel.h" +#include "ha_sync_plugin.h" + +#include <daemon.h> +#include <utils/identification.h> +#include <processing/jobs/callback_job.h> + +typedef struct private_ha_sync_tunnel_t private_ha_sync_tunnel_t; +typedef struct ha_backend_t ha_backend_t; +typedef struct ha_creds_t ha_creds_t; + +/** + * Serves credentials for the HA sync SA + */ +struct ha_creds_t { + + /** + * Implements credential_set_t + */ + credential_set_t public; + + /** + * own identity + */ + identification_t *local; + + /** + * peer identity + */ + identification_t *remote; + + /** + * Shared key to serve + */ + shared_key_t *key; +}; + +/** + * Serves configurations for the HA sync SA + */ +struct ha_backend_t { + + /** + * Implements backend_t + */ + backend_t public; + + /** + * peer config we serve + */ + peer_cfg_t *cfg; +}; + +/** + * Private data of an ha_sync_tunnel_t object. + */ +struct private_ha_sync_tunnel_t { + + /** + * Public ha_sync_tunnel_t interface. + */ + ha_sync_tunnel_t public; + + /** + * Reqid of installed trap + */ + u_int32_t trap; + + /** + * backend for sync SA + */ + ha_backend_t backend; + + /** + * credential set for sync SA + */ + ha_creds_t creds; +}; + +/** + * Implementation of ha_sync_tunnel_t.is_sync_sa + */ +static bool is_sync_sa(private_ha_sync_tunnel_t *this, ike_sa_t *ike_sa) +{ + peer_cfg_t *cfg = this->backend.cfg; + + return cfg && ike_sa->get_ike_cfg(ike_sa) == cfg->get_ike_cfg(cfg); +} + +/** + * Enumerator over HA shared_key + */ +typedef struct { + /** Implements enumerator_t */ + enumerator_t public; + /** a single secret we serve */ + shared_key_t *key; +} shared_enum_t; + +/** + * Implementation of shared_enum_t.enumerate + */ +static bool shared_enumerate(shared_enum_t *this, shared_key_t **key, + id_match_t *me, id_match_t *other) +{ + if (this->key) + { + if (me) + { + *me = ID_MATCH_PERFECT; + } + if (other) + { + *other = ID_MATCH_PERFECT; + } + *key = this->key; + this->key = NULL; + return TRUE; + } + return FALSE; +} + +/** + * Implements ha_creds_t.create_shared_enumerator + */ +static enumerator_t* create_shared_enumerator(ha_creds_t *this, + shared_key_type_t type, identification_t *me, + identification_t *other) +{ + shared_enum_t *enumerator; + + if (type != SHARED_IKE && type != SHARED_ANY) + { + return NULL; + } + if (me && !me->equals(me, this->local)) + { + return NULL; + } + if (other && !other->equals(other, this->remote)) + { + return NULL; + } + + enumerator = malloc_thing(shared_enum_t); + enumerator->public.enumerate = (void*)shared_enumerate; + enumerator->public.destroy = (void*)free; + enumerator->key = this->key; + + return &enumerator->public; +} + +/** + * Implementation of backend_t.create_peer_cfg_enumerator. + */ +static enumerator_t* create_peer_cfg_enumerator(ha_backend_t *this, + identification_t *me, identification_t *other) +{ + return enumerator_create_single(this->cfg, NULL); +} + +/** + * Implementation of backend_t.create_ike_cfg_enumerator. + */ +static enumerator_t* create_ike_cfg_enumerator(ha_backend_t *this, + host_t *me, host_t *other) +{ + return enumerator_create_single(this->cfg->get_ike_cfg(this->cfg), NULL); +} + +/** + * Install configs and a a trap for secured sync + */ +static void setup_sync_tunnel(private_ha_sync_tunnel_t *this, + char *local, char *remote, char *secret) +{ + peer_cfg_t *peer_cfg; + ike_cfg_t *ike_cfg; + auth_cfg_t *auth_cfg; + child_cfg_t *child_cfg; + traffic_selector_t *ts; + lifetime_cfg_t lifetime = { + .time = { + .life = 21600, .rekey = 20400, .jitter = 400, + }, + }; + + /* setup credentials */ + this->creds.local = identification_create_from_string(local); + this->creds.remote = identification_create_from_string(remote); + this->creds.key = shared_key_create(SHARED_IKE, + chunk_clone(chunk_create(secret, strlen(secret)))); + this->creds.public.create_private_enumerator = (void*)return_null; + this->creds.public.create_cert_enumerator = (void*)return_null; + this->creds.public.create_shared_enumerator = (void*)create_shared_enumerator; + this->creds.public.create_cdp_enumerator = (void*)return_null; + this->creds.public.cache_cert = (void*)nop; + + charon->credentials->add_set(charon->credentials, &this->creds.public); + + /* create config and backend */ + ike_cfg = ike_cfg_create(FALSE, FALSE, local, remote); + ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); + peer_cfg = peer_cfg_create("ha-sync", 2, ike_cfg, CERT_NEVER_SEND, + UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30, + NULL, NULL, FALSE, NULL, NULL); + + auth_cfg = auth_cfg_create(); + auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); + auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY, + identification_create_from_string(local)); + peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, TRUE); + + auth_cfg = auth_cfg_create(); + auth_cfg->add(auth_cfg, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK); + auth_cfg->add(auth_cfg, AUTH_RULE_IDENTITY, + identification_create_from_string(remote)); + peer_cfg->add_auth_cfg(peer_cfg, auth_cfg, FALSE); + + child_cfg = child_cfg_create("ha-sync", &lifetime, NULL, TRUE, + MODE_TRANSPORT, ACTION_NONE, ACTION_NONE, FALSE); + ts = traffic_selector_create_dynamic(0, HA_SYNC_PORT, HA_SYNC_PORT); + child_cfg->add_traffic_selector(child_cfg, TRUE, ts); + ts = traffic_selector_create_dynamic(0, HA_SYNC_PORT, HA_SYNC_PORT); + child_cfg->add_traffic_selector(child_cfg, FALSE, ts); + child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); + peer_cfg->add_child_cfg(peer_cfg, child_cfg); + + this->backend.cfg = peer_cfg; + this->backend.public.create_peer_cfg_enumerator = (void*)create_peer_cfg_enumerator; + this->backend.public.create_ike_cfg_enumerator = (void*)create_ike_cfg_enumerator; + this->backend.public.get_peer_cfg_by_name = (void*)return_null; + + charon->backends->add_backend(charon->backends, &this->backend.public); + + /* install an acquiring trap */ + this->trap = charon->traps->install(charon->traps, peer_cfg, child_cfg); +} + +/** + * Implementation of ha_sync_tunnel_t.destroy. + */ +static void destroy(private_ha_sync_tunnel_t *this) +{ + if (this->backend.cfg) + { + charon->backends->remove_backend(charon->backends, &this->backend.public); + this->backend.cfg->destroy(this->backend.cfg); + } + if (this->creds.key) + { + charon->credentials->remove_set(charon->credentials, &this->creds.public); + this->creds.key->destroy(this->creds.key); + } + this->creds.local->destroy(this->creds.local); + this->creds.remote->destroy(this->creds.remote); + if (this->trap) + { + charon->traps->uninstall(charon->traps, this->trap); + } + free(this); +} + +/** + * See header + */ +ha_sync_tunnel_t *ha_sync_tunnel_create(char *local, char *remote, char *secret) +{ + private_ha_sync_tunnel_t *this = malloc_thing(private_ha_sync_tunnel_t); + + this->public.is_sync_sa = (bool(*)(ha_sync_tunnel_t*, ike_sa_t *ike_sa))is_sync_sa; + this->public.destroy = (void(*)(ha_sync_tunnel_t*))destroy; + + setup_sync_tunnel(this, local, remote, secret); + + return &this->public; +} + diff --git a/src/charon/plugins/ha_sync/ha_sync_tunnel.h b/src/charon/plugins/ha_sync/ha_sync_tunnel.h new file mode 100644 index 000000000..c37dfad9b --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_tunnel.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2009 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 <http://www.fsf.org/copyleft/gpl.txt>. + * + * 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. + */ + +/** + * @defgroup ha_sync_ ha_sync_tunnel + * @{ @ingroup ha_sync + */ + +#ifndef HA_SYNC_TUNNEL_H_ +#define HA_SYNC_TUNNEL_H_ + +#include <sa/ike_sa.h> + +typedef struct ha_sync_tunnel_t ha_sync_tunnel_t; + +/** + * Socket to send/received SA synchronization data + */ +struct ha_sync_tunnel_t { + + /** + * Check if an IKE_SA is used for exchanging sync messages. + * + * @param ike_Sa ike_sa to check + * @return TRUE if IKE_SA is used to secure sync messages + */ + bool (*is_sync_sa)(ha_sync_tunnel_t *this, ike_sa_t *ike_sa); + + /** + * Destroy a ha_sync_tunnel_t. + */ + void (*destroy)(ha_sync_tunnel_t *this); +}; + +/** + * Create a ha_sync_tunnel instance. + * + * @param local local address of sync tunnel + * @param remote remote address of sync tunnel + * @param secret PSK tunnel authentication secret + * @return sync tunnel instance + */ +ha_sync_tunnel_t *ha_sync_tunnel_create(char *local, char *remote, char *secret); + +#endif /* HA_SYNC_TUNNEL_H_ @}*/ |