diff options
Diffstat (limited to 'src/libcharon/plugins/ha')
-rw-r--r-- | src/libcharon/plugins/ha/ha_cache.c | 20 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_dispatcher.c | 213 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_ike.c | 151 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_message.c | 20 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_message.h | 16 | ||||
-rw-r--r-- | src/libcharon/plugins/ha/ha_tunnel.c | 4 |
6 files changed, 365 insertions, 59 deletions
diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c index 970a8a2b9..e21b461a7 100644 --- a/src/libcharon/plugins/ha/ha_cache.c +++ b/src/libcharon/plugins/ha/ha_cache.c @@ -88,6 +88,8 @@ typedef struct { ha_message_t *midi; /* last responder mid */ ha_message_t *midr; + /* last IV update */ + ha_message_t *iv; } entry_t; /** @@ -114,6 +116,7 @@ static void entry_destroy(entry_t *entry) entry->add->destroy(entry->add); DESTROY_IF(entry->midi); DESTROY_IF(entry->midr); + DESTROY_IF(entry->iv); free(entry); } @@ -164,6 +167,16 @@ METHOD(ha_cache_t, cache, void, } message->destroy(message); break; + case HA_IKE_IV: + entry = this->cache->get(this->cache, ike_sa); + if (entry) + { + DESTROY_IF(entry->iv); + entry->iv = message; + break; + } + message->destroy(message); + break; case HA_IKE_DELETE: entry = this->cache->remove(this->cache, ike_sa); if (entry) @@ -212,7 +225,8 @@ static status_t rekey_children(ike_sa_t *ike_sa) DBG1(DBG_CFG, "resyncing CHILD_SA using a delete"); status = ike_sa->delete_child_sa(ike_sa, child_sa->get_protocol(child_sa), - child_sa->get_spi(child_sa, TRUE)); + child_sa->get_spi(child_sa, TRUE), + FALSE); } else { @@ -308,6 +322,10 @@ METHOD(ha_cache_t, resync, void, { this->socket->push(this->socket, entry->midr); } + if (entry->iv) + { + this->socket->push(this->socket, entry->iv); + } } } enumerator->destroy(enumerator); diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c index 994f91d20..de5253b37 100644 --- a/src/libcharon/plugins/ha/ha_dispatcher.c +++ b/src/libcharon/plugins/ha/ha_dispatcher.c @@ -16,9 +16,13 @@ #include "ha_dispatcher.h" #include <daemon.h> +#include <sa/ikev2/keymat_v2.h> +#include <sa/ikev1/keymat_v1.h> #include <processing/jobs/callback_job.h> +#include <processing/jobs/adopt_children_job.h> typedef struct private_ha_dispatcher_t private_ha_dispatcher_t; +typedef struct ha_diffie_hellman_t ha_diffie_hellman_t; /** * Private data of an ha_dispatcher_t object. @@ -62,14 +66,65 @@ struct private_ha_dispatcher_t { }; /** - * Quick and dirty hack implementation of diffie_hellman_t.get_shared_secret + * DH implementation for HA synced DH values */ -static status_t get_shared_secret(diffie_hellman_t *this, chunk_t *secret) +struct ha_diffie_hellman_t { + + /** + * Implements diffie_hellman_t + */ + diffie_hellman_t dh; + + /** + * Shared secret + */ + chunk_t secret; + + /** + * Own public value + */ + chunk_t pub; +}; + +METHOD(diffie_hellman_t, dh_get_shared_secret, status_t, + ha_diffie_hellman_t *this, chunk_t *secret) { - *secret = chunk_clone((*(chunk_t*)this->destroy)); + *secret = chunk_clone(this->secret); return SUCCESS; } +METHOD(diffie_hellman_t, dh_get_my_public_value, void, + ha_diffie_hellman_t *this, chunk_t *value) +{ + *value = chunk_clone(this->pub); +} + +METHOD(diffie_hellman_t, dh_destroy, void, + ha_diffie_hellman_t *this) +{ + free(this); +} + +/** + * Create a HA synced DH implementation + */ +static diffie_hellman_t *ha_diffie_hellman_create(chunk_t secret, chunk_t pub) +{ + ha_diffie_hellman_t *this; + + INIT(this, + .dh = { + .get_shared_secret = _dh_get_shared_secret, + .get_my_public_value = _dh_get_my_public_value, + .destroy = _dh_destroy, + }, + .secret = secret, + .pub = pub, + ); + + return &this->dh; +} + /** * Process messages of type IKE_ADD */ @@ -79,9 +134,12 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message ha_message_value_t value; enumerator_t *enumerator; ike_sa_t *ike_sa = NULL, *old_sa = NULL; + ike_version_t version = IKEV2; u_int16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED; chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty; chunk_t secret = chunk_empty, old_skd = chunk_empty; + chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty; + bool ok = FALSE; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -89,12 +147,16 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message switch (attribute) { case HA_IKE_ID: - ike_sa = ike_sa_create(value.ike_sa_id); + ike_sa = ike_sa_create(value.ike_sa_id, + value.ike_sa_id->is_initiator(value.ike_sa_id), version); break; case HA_IKE_REKEY_ID: old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, value.ike_sa_id); break; + case HA_IKE_VERSION: + version = value.u8; + break; case HA_NONCE_I: nonce_i = value.chunk; break; @@ -104,6 +166,15 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message case HA_SECRET: secret = value.chunk; break; + case HA_LOCAL_DH: + dh_local = value.chunk; + break; + case HA_REMOTE_DH: + dh_remote = value.chunk; + break; + case HA_PSK: + psk = value.chunk; + break; case HA_OLD_SKD: old_skd = value.chunk; break; @@ -131,13 +202,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message 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 }; + diffie_hellman_t *dh; proposal = proposal_create(PROTO_IKE, 0); - keymat = ike_sa->get_keymat(ike_sa); if (integ) { proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0); @@ -151,8 +218,35 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0); } charon->bus->set_sa(charon->bus, ike_sa); - if (keymat->derive_ike_keys(keymat, proposal, &dh, nonce_i, nonce_r, - ike_sa->get_id(ike_sa), old_prf, old_skd)) + dh = ha_diffie_hellman_create(secret, dh_local); + if (ike_sa->get_version(ike_sa) == IKEV2) + { + keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); + + ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, dh, nonce_i, + nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd); + } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + shared_key_t *shared = NULL; + auth_method_t method = AUTH_RSA; + + if (psk.len) + { + method = AUTH_PSK; + shared = shared_key_create(SHARED_IKE, chunk_clone(psk)); + } + if (keymat_v1->create_hasher(keymat_v1, proposal)) + { + ok = keymat_v1->derive_ike_keys(keymat_v1, proposal, + dh, dh_remote, nonce_i, nonce_r, + ike_sa->get_id(ike_sa), method, shared); + } + DESTROY_IF(shared); + } + dh->destroy(dh); + if (ok) { if (old_sa) { @@ -168,6 +262,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message old_sa = NULL; } ike_sa->set_state(ike_sa, IKE_CONNECTING); + ike_sa->set_proposal(ike_sa, proposal); this->cache->cache(this->cache, ike_sa, message); message = NULL; charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); @@ -289,6 +384,8 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_extension(ike_sa, value.u32, EXT_STRONGSWAN); set_extension(ike_sa, value.u32, EXT_EAP_ONLY_AUTHENTICATION); set_extension(ike_sa, value.u32, EXT_MS_WINDOWS); + set_extension(ike_sa, value.u32, EXT_XAUTH); + set_extension(ike_sa, value.u32, EXT_DPD); break; case HA_CONDITIONS: set_condition(ike_sa, value.u32, COND_NAT_ANY); @@ -299,6 +396,8 @@ static void process_ike_update(private_ha_dispatcher_t *this, set_condition(ike_sa, value.u32, COND_CERTREQ_SEEN); set_condition(ike_sa, value.u32, COND_ORIGINAL_INITIATOR); set_condition(ike_sa, value.u32, COND_STALE); + set_condition(ike_sa, value.u32, COND_INIT_CONTACT_SEEN); + set_condition(ike_sa, value.u32, COND_XAUTH_AUTHENTICATED); break; default: break; @@ -333,6 +432,11 @@ static void process_ike_update(private_ha_dispatcher_t *this, } } } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + lib->processor->queue_job(lib->processor, (job_t*) + adopt_children_job_create(ike_sa->get_id(ike_sa))); + } this->cache->cache(this->cache, ike_sa, message); charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); } @@ -389,6 +493,57 @@ static void process_ike_mid(private_ha_dispatcher_t *this, } /** + * Process messages of type IKE_IV + */ +static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message) +{ + ha_message_attribute_t attribute; + ha_message_value_t value; + enumerator_t *enumerator; + ike_sa_t *ike_sa = NULL; + chunk_t iv = chunk_empty; + + enumerator = message->create_attribute_enumerator(message); + while (enumerator->enumerate(enumerator, &attribute, &value)) + { + switch (attribute) + { + case HA_IKE_ID: + ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, + value.ike_sa_id); + break; + case HA_IV: + iv = value.chunk; + break; + default: + break; + } + } + enumerator->destroy(enumerator); + + if (ike_sa) + { + if (ike_sa->get_version(ike_sa) == IKEV1) + { + if (iv.len) + { + keymat_v1_t *keymat; + + keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + keymat->update_iv(keymat, 0, iv); + keymat->confirm_iv(keymat, 0); + } + } + this->cache->cache(this->cache, ike_sa, message); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + } + else + { + message->destroy(message); + } +} + +/** * Process messages of type IKE_DELETE */ static void process_ike_delete(private_ha_dispatcher_t *this, @@ -465,8 +620,7 @@ static void process_child_add(private_ha_dispatcher_t *this, child_cfg_t *config = NULL; child_sa_t *child_sa; proposal_t *proposal; - keymat_t *keymat; - bool initiator = FALSE, failed = FALSE; + bool initiator = FALSE, failed = FALSE, ok = FALSE; u_int32_t inbound_spi = 0, outbound_spi = 0; u_int16_t inbound_cpi = 0, outbound_cpi = 0; u_int8_t mode = MODE_TUNNEL, ipcomp = 0; @@ -476,9 +630,7 @@ static void process_child_add(private_ha_dispatcher_t *this, chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty; chunk_t encr_i, integ_i, encr_r, integ_r; linked_list_t *local_ts, *remote_ts; - /* quick and dirty hack of a DH implementation */ - diffie_hellman_t dh = { .get_shared_secret = get_shared_secret, - .destroy = (void*)&secret }; + diffie_hellman_t *dh = NULL; enumerator = message->create_attribute_enumerator(message); while (enumerator->enumerate(enumerator, &attribute, &value)) @@ -572,10 +724,30 @@ static void process_child_add(private_ha_dispatcher_t *this, proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len); } proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0); - keymat = ike_sa->get_keymat(ike_sa); + if (secret.len) + { + dh = ha_diffie_hellman_create(secret, chunk_empty); + } + if (ike_sa->get_version(ike_sa) == IKEV2) + { + keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa); - if (!keymat->derive_child_keys(keymat, proposal, secret.ptr ? &dh : NULL, - nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r)) + ok = keymat_v2->derive_child_keys(keymat_v2, proposal, dh, + nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); + } + if (ike_sa->get_version(ike_sa) == IKEV1) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + u_int32_t spi_i, spi_r; + + spi_i = initiator ? inbound_spi : outbound_spi; + spi_r = initiator ? outbound_spi : inbound_spi; + + ok = keymat_v1->derive_child_keys(keymat_v1, proposal, dh, spi_i, spi_r, + nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r); + } + DESTROY_IF(dh); + if (!ok) { DBG1(DBG_CHD, "HA CHILD_SA key derivation failed"); child_sa->destroy(child_sa); @@ -825,6 +997,9 @@ static job_requeue_t dispatch(private_ha_dispatcher_t *this) case HA_IKE_MID_RESPONDER: process_ike_mid(this, message, FALSE); break; + case HA_IKE_IV: + process_ike_iv(this, message); + break; case HA_IKE_DELETE: process_ike_delete(this, message); break; diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c index e818aec9c..2819b9dd5 100644 --- a/src/libcharon/plugins/ha/ha_ike.c +++ b/src/libcharon/plugins/ha/ha_ike.c @@ -15,6 +15,9 @@ #include "ha_ike.h" +#include <sa/ikev2/keymat_v2.h> +#include <sa/ikev1/keymat_v1.h> + typedef struct private_ha_ike_t private_ha_ike_t; /** @@ -69,7 +72,8 @@ static ike_extension_t copy_extension(ike_sa_t *ike_sa, ike_extension_t ext) METHOD(listener_t, ike_keys, bool, private_ha_ike_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh, - chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey) + chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r, ike_sa_t *rekey, + shared_key_t *shared) { ha_message_t *m; chunk_t secret; @@ -86,14 +90,15 @@ METHOD(listener_t, ike_keys, bool, } m = ha_message_create(HA_IKE_ADD); + m->add_attribute(m, HA_IKE_VERSION, ike_sa->get_version(ike_sa)); m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - if (rekey) + if (rekey && rekey->get_version(rekey) == IKEV2) { chunk_t skd; - keymat_t *keymat; + keymat_v2_t *keymat; - keymat = rekey->get_keymat(rekey); + keymat = (keymat_v2_t*)rekey->get_keymat(rekey); m->add_attribute(m, HA_IKE_REKEY_ID, rekey->get_id(rekey)); m->add_attribute(m, HA_ALG_OLD_PRF, keymat->get_skd(keymat, &skd)); m->add_attribute(m, HA_OLD_SKD, skd); @@ -120,6 +125,17 @@ METHOD(listener_t, ike_keys, bool, m->add_attribute(m, HA_NONCE_R, nonce_r); m->add_attribute(m, HA_SECRET, secret); chunk_clear(&secret); + if (ike_sa->get_version(ike_sa) == IKEV1) + { + dh->get_my_public_value(dh, &secret); + m->add_attribute(m, HA_LOCAL_DH, secret); + chunk_free(&secret); + m->add_attribute(m, HA_REMOTE_DH, dh_other); + if (shared) + { + m->add_attribute(m, HA_PSK, shared->get_key(shared)); + } + } this->socket->push(this->socket, m); this->cache->cache(this->cache, ike_sa, m); @@ -159,7 +175,9 @@ METHOD(listener_t, ike_updown, bool, | copy_condition(ike_sa, COND_EAP_AUTHENTICATED) | copy_condition(ike_sa, COND_CERTREQ_SEEN) | copy_condition(ike_sa, COND_ORIGINAL_INITIATOR) - | copy_condition(ike_sa, COND_STALE); + | copy_condition(ike_sa, COND_STALE) + | copy_condition(ike_sa, COND_INIT_CONTACT_SEEN) + | copy_condition(ike_sa, COND_XAUTH_AUTHENTICATED); extension = copy_extension(ike_sa, EXT_NATT) | copy_extension(ike_sa, EXT_MOBIKE) @@ -167,7 +185,9 @@ METHOD(listener_t, ike_updown, bool, | copy_extension(ike_sa, EXT_MULTIPLE_AUTH) | copy_extension(ike_sa, EXT_STRONGSWAN) | copy_extension(ike_sa, EXT_EAP_ONLY_AUTHENTICATION) - | copy_extension(ike_sa, EXT_MS_WINDOWS); + | copy_extension(ike_sa, EXT_MS_WINDOWS) + | copy_extension(ike_sa, EXT_XAUTH) + | copy_extension(ike_sa, EXT_DPD); id = ike_sa->get_id(ike_sa); @@ -222,49 +242,116 @@ METHOD(listener_t, ike_state_change, bool, } METHOD(listener_t, message_hook, bool, - private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, bool incoming) + private_ha_ike_t *this, ike_sa_t *ike_sa, message_t *message, + bool incoming, bool plain) { if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa)) { /* do not sync SA between nodes */ return TRUE; } - if (message->get_exchange_type(message) != IKE_SA_INIT && - message->get_request(message)) - { /* we sync on requests, but skip it on IKE_SA_INIT */ - ha_message_t *m; - - if (incoming) - { - m = ha_message_create(HA_IKE_MID_RESPONDER); + if (plain && ike_sa->get_version(ike_sa) == IKEV2) + { + if (message->get_exchange_type(message) != IKE_SA_INIT && + message->get_request(message)) + { /* we sync on requests, but skip it on IKE_SA_INIT */ + ha_message_t *m; + + if (incoming) + { + m = ha_message_create(HA_IKE_MID_RESPONDER); + } + else + { + m = ha_message_create(HA_IKE_MID_INITIATOR); + } + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_MID, message->get_message_id(message) + 1); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); } - else - { - m = ha_message_create(HA_IKE_MID_INITIATOR); + if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && + message->get_exchange_type(message) == IKE_AUTH && + !message->get_request(message)) + { /* After IKE_SA has been established, sync peers virtual IP. + * We cannot sync it in the state_change hook, it is installed later. + * TODO: where to sync local VIP? */ + ha_message_t *m; + host_t *vip; + + vip = ike_sa->get_virtual_ip(ike_sa, FALSE); + if (vip) + { + m = ha_message_create(HA_IKE_UPDATE); + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_REMOTE_VIP, vip); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } } - m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - m->add_attribute(m, HA_MID, message->get_message_id(message) + 1); - this->socket->push(this->socket, m); - this->cache->cache(this->cache, ike_sa, m); } - if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && - message->get_exchange_type(message) == IKE_AUTH && - !message->get_request(message)) - { /* After IKE_SA has been established, sync peers virtual IP. - * We cannot sync it in the state_change hook, it is installed later. - * TODO: where to sync local VIP? */ + if (!plain && ike_sa->get_version(ike_sa) == IKEV1) + { ha_message_t *m; + keymat_v1_t *keymat; + u_int32_t mid; + chunk_t iv; host_t *vip; - vip = ike_sa->get_virtual_ip(ike_sa, FALSE); - if (vip) + mid = message->get_message_id(message); + if (mid == 0) { - m = ha_message_create(HA_IKE_UPDATE); + keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa); + iv = keymat->get_iv(keymat, mid); + m = ha_message_create(HA_IKE_IV); m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); - m->add_attribute(m, HA_REMOTE_VIP, vip); + m->add_attribute(m, HA_IV, iv); + free(iv.ptr); this->socket->push(this->socket, m); this->cache->cache(this->cache, ike_sa, m); } + if (!incoming && message->get_exchange_type(message) == TRANSACTION) + { + vip = ike_sa->get_virtual_ip(ike_sa, FALSE); + if (vip) + { + m = ha_message_create(HA_IKE_UPDATE); + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_REMOTE_VIP, vip); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } + } + } + if (plain && ike_sa->get_version(ike_sa) == IKEV1 && + message->get_exchange_type(message) == INFORMATIONAL_V1) + { + ha_message_t *m; + notify_payload_t *notify; + chunk_t data; + u_int32_t seq; + + notify = message->get_notify(message, DPD_R_U_THERE); + if (notify) + { + data = notify->get_notification_data(notify); + if (data.len == 4) + { + seq = untoh32(data.ptr); + if (incoming) + { + m = ha_message_create(HA_IKE_MID_RESPONDER); + } + else + { + m = ha_message_create(HA_IKE_MID_INITIATOR); + } + m->add_attribute(m, HA_IKE_ID, ike_sa->get_id(ike_sa)); + m->add_attribute(m, HA_MID, seq + 1); + this->socket->push(this->socket, m); + this->cache->cache(this->cache, ike_sa, m); + } + } } return TRUE; } diff --git a/src/libcharon/plugins/ha/ha_message.c b/src/libcharon/plugins/ha/ha_message.c index 810109a5d..6b00ed83f 100644 --- a/src/libcharon/plugins/ha/ha_message.c +++ b/src/libcharon/plugins/ha/ha_message.c @@ -46,7 +46,7 @@ struct private_ha_message_t { chunk_t buf; }; -ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC, +ENUM(ha_message_type_names, HA_IKE_ADD, HA_IKE_IV, "IKE_ADD", "IKE_UPDATE", "IKE_MID_INITIATOR", @@ -58,6 +58,7 @@ ENUM(ha_message_type_names, HA_IKE_ADD, HA_RESYNC, "SEGMENT_TAKE", "STATUS", "RESYNC", + "IKE_IV", ); typedef struct ike_sa_id_encoding_t ike_sa_id_encoding_t; @@ -66,6 +67,7 @@ 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_int8_t ike_version; u_int64_t initiator_spi; u_int64_t responder_spi; u_int8_t initiator; @@ -156,6 +158,7 @@ METHOD(ha_message_t, add_attribute, void, 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->ike_version = id->get_ike_version(id); enc->initiator_spi = id->get_initiator_spi(id); enc->responder_spi = id->get_responder_spi(id); break; @@ -213,6 +216,7 @@ METHOD(ha_message_t, add_attribute, void, break; } /* u_int8_t */ + case HA_IKE_VERSION: case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: @@ -263,6 +267,10 @@ METHOD(ha_message_t, add_attribute, void, case HA_NONCE_I: case HA_NONCE_R: case HA_SECRET: + case HA_LOCAL_DH: + case HA_REMOTE_DH: + case HA_PSK: + case HA_IV: case HA_OLD_SKD: { chunk_t chunk; @@ -351,8 +359,9 @@ METHOD(enumerator_t, attribute_enumerate, bool, return FALSE; } enc = (ike_sa_id_encoding_t*)(this->buf.ptr); - value->ike_sa_id = ike_sa_id_create(enc->initiator_spi, - enc->responder_spi, enc->initiator); + value->ike_sa_id = ike_sa_id_create(enc->ike_version, + enc->initiator_spi, enc->responder_spi, + enc->initiator); *attr_out = attr; this->cleanup = (void*)value->ike_sa_id->destroy; this->cleanup_data = value->ike_sa_id; @@ -426,6 +435,7 @@ METHOD(enumerator_t, attribute_enumerate, bool, return TRUE; } /* u_int8_t */ + case HA_IKE_VERSION: case HA_INITIATOR: case HA_IPSEC_MODE: case HA_IPCOMP: @@ -479,6 +489,10 @@ METHOD(enumerator_t, attribute_enumerate, bool, case HA_NONCE_I: case HA_NONCE_R: case HA_SECRET: + case HA_LOCAL_DH: + case HA_REMOTE_DH: + case HA_PSK: + case HA_IV: case HA_OLD_SKD: { size_t len; diff --git a/src/libcharon/plugins/ha/ha_message.h b/src/libcharon/plugins/ha/ha_message.h index d0323d7a0..8cd30f711 100644 --- a/src/libcharon/plugins/ha/ha_message.h +++ b/src/libcharon/plugins/ha/ha_message.h @@ -30,7 +30,7 @@ /** * Protocol version of this implementation */ -#define HA_MESSAGE_VERSION 2 +#define HA_MESSAGE_VERSION 3 typedef struct ha_message_t ha_message_t; typedef enum ha_message_type_t ha_message_type_t; @@ -63,6 +63,8 @@ enum ha_message_type_t { HA_STATUS, /** segments the receiving node is requested to resync */ HA_RESYNC, + /** IV synchronization for IKEv1 Main/Aggressive mode */ + HA_IKE_IV, }; /** @@ -76,7 +78,7 @@ extern enum_name_t *ha_message_type_names; enum ha_message_attribute_t { /** ike_sa_id_t*, to identify IKE_SA */ HA_IKE_ID = 1, - /** ike_Sa_id_t*, identifies IKE_SA which gets rekeyed */ + /** ike_sa_id_t*, identifies IKE_SA which gets rekeyed */ HA_IKE_REKEY_ID, /** identification_t*, local identity */ HA_LOCAL_ID, @@ -142,6 +144,16 @@ enum ha_message_attribute_t { HA_SEGMENT, /** u_int16_t, Extended Sequence numbers */ HA_ESN, + /** u_int8_t, IKE version */ + HA_IKE_VERSION, + /** chunk_t, own DH public value */ + HA_LOCAL_DH, + /** chunk_t, remote DH public value */ + HA_REMOTE_DH, + /** chunk_t, shared secret for IKEv1 key derivation */ + HA_PSK, + /** chunk_t, IV for next IKEv1 message */ + HA_IV, }; /** diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index 299053ec1..6f20620f2 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -206,8 +206,8 @@ static void setup_tunnel(private_ha_tunnel_t *this, ike_cfg = ike_cfg_create(FALSE, FALSE, local, IKEV2_UDP_PORT, remote, IKEV2_UDP_PORT); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); - peer_cfg = peer_cfg_create("ha", 2, ike_cfg, CERT_NEVER_SEND, - UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, 30, + peer_cfg = peer_cfg_create("ha", IKEV2, ike_cfg, CERT_NEVER_SEND, + UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30, NULL, NULL, FALSE, NULL, NULL); auth_cfg = auth_cfg_create(); |