diff options
author | Yves-Alexis Perez <corsac@corsac.net> | 2017-04-01 16:26:44 +0200 |
---|---|---|
committer | Yves-Alexis Perez <corsac@corsac.net> | 2017-04-01 16:26:44 +0200 |
commit | dc9380af81fbce8e1a9532b07bc671b9d346101b (patch) | |
tree | 219f7df0b01243ac1c41c7f679d1b4c6aef36b27 /src/libcharon/sa/ikev2/task_manager_v2.c | |
parent | 212c0ba74c0e453497b840f9cd131ec99f73754a (diff) | |
parent | 05ddd767992d68bb38c7f16ece142e8c2e9ae016 (diff) | |
download | vyos-strongswan-dc9380af81fbce8e1a9532b07bc671b9d346101b.tar.gz vyos-strongswan-dc9380af81fbce8e1a9532b07bc671b9d346101b.zip |
Merge tag 'upstream/5.5.2'
Upstream version 5.5.2
Diffstat (limited to 'src/libcharon/sa/ikev2/task_manager_v2.c')
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 94 |
1 files changed, 89 insertions, 5 deletions
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index 60a262ffc..e4a16faf0 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -34,6 +34,7 @@ #include <sa/ikev2/tasks/ike_delete.h> #include <sa/ikev2/tasks/ike_config.h> #include <sa/ikev2/tasks/ike_dpd.h> +#include <sa/ikev2/tasks/ike_mid_sync.h> #include <sa/ikev2/tasks/ike_vendor.h> #include <sa/ikev2/tasks/ike_verify_peer_cert.h> #include <sa/ikev2/tasks/child_create.h> @@ -817,7 +818,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request) task_t *task; message_t *message; host_t *me, *other; - bool delete = FALSE, hook = FALSE; + bool delete = FALSE, hook = FALSE, mid_sync = FALSE; ike_sa_id_t *id = NULL; uint64_t responder_spi = 0; bool result; @@ -836,6 +837,10 @@ static status_t build_response(private_task_manager_t *this, message_t *request) enumerator = array_create_enumerator(this->passive_tasks); while (enumerator->enumerate(enumerator, (void*)&task)) { + if (task->get_type(task) == TASK_IKE_MID_SYNC) + { + mid_sync = TRUE; + } switch (task->build(task, message)) { case SUCCESS: @@ -908,6 +913,15 @@ static status_t build_response(private_task_manager_t *this, message_t *request) } return DESTROY_ME; } + else if (mid_sync) + { + /* we don't want to resend messages to sync MIDs if requests with the + * previous MID arrive */ + clear_packets(this->responding.packets); + /* avoid increasing the expected message ID after handling a message + * to sync MIDs with MID 0 */ + return NEED_MORE; + } array_compress(this->passive_tasks); @@ -1069,6 +1083,10 @@ static status_t process_request(private_task_manager_t *this, task = (task_t*)ike_redirect_create( this->ike_sa, NULL); break; + case IKEV2_MESSAGE_ID_SYNC: + task = (task_t*)ike_mid_sync_create( + this->ike_sa); + break; default: break; } @@ -1200,6 +1218,12 @@ METHOD(task_manager_t, incr_mid, void, } } +METHOD(task_manager_t, get_mid, uint32_t, + private_task_manager_t *this, bool initiate) +{ + return initiate ? this->initiating.mid : this->responding.mid; +} + /** * Handle the given IKE fragment, if it is one. * @@ -1373,6 +1397,64 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg) return status; } +/** + * Check if a message with message ID 0 looks like it is used to synchronize + * the message IDs. + */ +static bool looks_like_mid_sync(private_task_manager_t *this, message_t *msg, + bool strict) +{ + enumerator_t *enumerator; + notify_payload_t *notify; + payload_t *payload; + bool found = FALSE, other = FALSE; + + if (msg->get_exchange_type(msg) == INFORMATIONAL) + { + enumerator = msg->create_payload_enumerator(msg); + while (enumerator->enumerate(enumerator, &payload)) + { + if (payload->get_type(payload) == PLV2_NOTIFY) + { + notify = (notify_payload_t*)payload; + switch (notify->get_notify_type(notify)) + { + case IKEV2_MESSAGE_ID_SYNC: + case IPSEC_REPLAY_COUNTER_SYNC: + found = TRUE; + continue; + default: + break; + } + } + if (strict) + { + other = TRUE; + break; + } + } + enumerator->destroy(enumerator); + } + return found && !other; +} + +/** + * Check if a message with message ID 0 looks like it is used to synchronize + * the message IDs and we are prepared to process it. + * + * Note: This is not called if the responder never sent a message before (i.e. + * we expect MID 0). + */ +static bool is_mid_sync(private_task_manager_t *this, message_t *msg) +{ + if (this->ike_sa->get_state(this->ike_sa) == IKE_ESTABLISHED && + this->ike_sa->supports_extension(this->ike_sa, + EXT_IKE_MESSAGE_ID_SYNC)) + { + return looks_like_mid_sync(this, msg, TRUE); + } + return FALSE; +} METHOD(task_manager_t, process_message, status_t, private_task_manager_t *this, message_t *msg) @@ -1421,7 +1503,7 @@ METHOD(task_manager_t, process_message, status_t, mid = msg->get_message_id(msg); if (msg->get_request(msg)) { - if (mid == this->responding.mid) + if (mid == this->responding.mid || (mid == 0 && is_mid_sync(this, msg))) { /* reject initial messages if not received in specific states, * after rekeying we only expect a DELETE in an INFORMATIONAL */ @@ -1462,7 +1544,8 @@ METHOD(task_manager_t, process_message, status_t, } } else if ((mid == this->responding.mid - 1) && - array_count(this->responding.packets)) + array_count(this->responding.packets) && + !(mid == 0 && looks_like_mid_sync(this, msg, FALSE))) { status = handle_fragment(this, &this->responding.defrag, msg); if (status != SUCCESS) @@ -1477,7 +1560,7 @@ METHOD(task_manager_t, process_message, status_t, } else { - DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", + DBG1(DBG_IKE, "received message ID %d, expected %d, ignored", mid, this->responding.mid); } } @@ -1515,7 +1598,7 @@ METHOD(task_manager_t, process_message, status_t, } else { - DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", + DBG1(DBG_IKE, "received message ID %d, expected %d, ignored", mid, this->initiating.mid); return SUCCESS; } @@ -2046,6 +2129,7 @@ task_manager_v2_t *task_manager_v2_create(ike_sa_t *ike_sa) .initiate = _initiate, .retransmit = _retransmit, .incr_mid = _incr_mid, + .get_mid = _get_mid, .reset = _reset, .adopt_tasks = _adopt_tasks, .adopt_child_tasks = _adopt_child_tasks, |