diff options
author | Tobias Brunner <tobias@strongswan.org> | 2016-09-16 17:26:41 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2017-02-08 15:03:25 +0100 |
commit | 5ab59221d2b365428e99e63c26a08114350ef2d1 (patch) | |
tree | 4f3fc15970e30961ef6c91aff6fc1c54e79a0e76 /src/libcharon | |
parent | 347c403cf61a131067fa240af074fd1a80de2c7d (diff) | |
download | strongswan-5ab59221d2b365428e99e63c26a08114350ef2d1.tar.bz2 strongswan-5ab59221d2b365428e99e63c26a08114350ef2d1.tar.xz |
ikev2: Add task to handle IKEV2_MESSAGE_ID_SYNC notifies as responder
Diffstat (limited to 'src/libcharon')
-rw-r--r-- | src/libcharon/Android.mk | 1 | ||||
-rw-r--r-- | src/libcharon/Makefile.am | 1 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/task_manager_v2.c | 5 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_mid_sync.c | 259 | ||||
-rw-r--r-- | src/libcharon/sa/ikev2/tasks/ike_mid_sync.h | 74 | ||||
-rw-r--r-- | src/libcharon/sa/task.c | 1 | ||||
-rw-r--r-- | src/libcharon/sa/task.h | 2 |
7 files changed, 343 insertions, 0 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index cb7e4b103..1a8e068d1 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -106,6 +106,7 @@ sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \ sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \ sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \ sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \ +sa/ikev2/tasks/ike_mid_sync.c sa/ikev2/tasks/ike_mid_sync.h \ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 18f2dee10..8461d6230 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -105,6 +105,7 @@ sa/ikev2/tasks/ike_delete.c sa/ikev2/tasks/ike_delete.h \ sa/ikev2/tasks/ike_dpd.c sa/ikev2/tasks/ike_dpd.h \ sa/ikev2/tasks/ike_init.c sa/ikev2/tasks/ike_init.h \ sa/ikev2/tasks/ike_natd.c sa/ikev2/tasks/ike_natd.h \ +sa/ikev2/tasks/ike_mid_sync.c sa/ikev2/tasks/ike_mid_sync.h \ sa/ikev2/tasks/ike_mobike.c sa/ikev2/tasks/ike_mobike.h \ sa/ikev2/tasks/ike_rekey.c sa/ikev2/tasks/ike_rekey.h \ sa/ikev2/tasks/ike_reauth.c sa/ikev2/tasks/ike_reauth.h \ diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index c101ebf2b..d3b371f10 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> @@ -1069,6 +1070,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; } diff --git a/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c new file mode 100644 index 000000000..9967697dd --- /dev/null +++ b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2016 Tobias Brunner + * HSR 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. + */ +/* + * Copyright (C) 2016 Stephen J. Bevan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "ike_mid_sync.h" + +#include <daemon.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> +#include <encoding/payloads/notify_payload.h> + +typedef struct private_ike_mid_sync_t private_ike_mid_sync_t; + +/** + * Private members + */ +struct private_ike_mid_sync_t { + + /** + * Public methods and task_t interface. + */ + ike_mid_sync_t public; + + /** + * Assigned IKE_SA. + */ + ike_sa_t *ike_sa; + + /** + * Nonce sent by the peer and expected to be returned + */ + chunk_t nonce; + + /** + * Expected next sender message ID + */ + uint32_t send; + + /** + * Expected received message ID + */ + uint32_t recv; +}; + +/* + * Encoding of IKEV2_MESSAGE_SYNC_ID notify, RFC 6311 + * + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Next Payload |C| RESERVED | Payload Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Protocol ID(=0)| SPI Size (=0) | Notify Message Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Nonce Data | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | EXPECTED_SEND_REQ_MESSAGE_ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | EXPECTED_RECV_REQ_MESSAGE_ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/* + * RFC 6311 section 5.1 + * + * o The peer MUST silently drop any received synchronization message + * if M1 is lower than or equal to the highest value it has seen from + * the cluster. This includes any previous received synchronization + * messages. + */ +METHOD(task_t, pre_process, status_t, + private_ike_mid_sync_t *this, message_t *message) +{ + notify_payload_t *notify; + bio_reader_t *reader; + chunk_t nonce; + uint32_t resp; + + if (message->get_message_id(message) != 0) + { /* ignore the notify if it was contained in an INFORMATIONAL with + * unexpected message ID */ + return SUCCESS; + } + notify = message->get_notify(message, IKEV2_MESSAGE_ID_SYNC); + + reader = bio_reader_create(notify->get_notification_data(notify)); + if (!reader->read_data(reader, 4, &nonce) || + !reader->read_uint32(reader, &this->send) || + !reader->read_uint32(reader, &this->recv)) + { + reader->destroy(reader); + DBG1(DBG_ENC, "received invalid %N notify", + notify_type_names, IKEV2_MESSAGE_ID_SYNC); + return FAILED; + } + reader->destroy(reader); + resp = this->ike_sa->get_message_id(this->ike_sa, FALSE); + if (this->send < resp) + { + DBG1(DBG_ENC, "ignore %N notify with lower (%d) than expected (%d) " + "sender MID", notify_type_names, IKEV2_MESSAGE_ID_SYNC, this->send, + resp); + return FAILED; + } + this->nonce = chunk_clone(nonce); + return SUCCESS; +} + +/** + * Check if there are any active tasks, indicating that we already + * used the currents message ID and are waiting for a response. + */ +static bool has_active_tasks(private_ike_mid_sync_t *this) +{ + enumerator_t *enumerator; + task_t *task; + bool active; + + enumerator = this->ike_sa->create_task_enumerator(this->ike_sa, + TASK_QUEUE_ACTIVE); + active = enumerator->enumerate(enumerator, &task); + enumerator->destroy(enumerator); + return active; +} + +/* + * RFC 6311 section 5.1 + * + * o M2 MUST be at least the higher of the received M1, and one more + * than the highest sender value received from the cluster. This + * includes any previous received synchronization messages. + * + * o P2 MUST be the higher of the received P1 value, and one more than + * the highest sender value used by the peer. + * + * M1 is this->send, P1 is this->recv + */ +METHOD(task_t, process, status_t, + private_ike_mid_sync_t *this, message_t *message) +{ + uint32_t resp, init, m2, p2; + + if (message->get_message_id(message) != 0) + { /* ignore the notify if it was contained in an INFORMATIONAL with + * unexpected message id */ + return SUCCESS; + } + resp = this->ike_sa->get_message_id(this->ike_sa, FALSE); + m2 = max(this->send, resp); + if (resp != m2) + { + /* after responding to this message the expected message ID is increased + * by one so we reduce it here */ + this->ike_sa->set_message_id(this->ike_sa, FALSE, m2 - 1); + } + init = this->ike_sa->get_message_id(this->ike_sa, TRUE); + p2 = max(this->recv, has_active_tasks(this) ? init + 1 : init); + if (init != p2) + { + this->ike_sa->set_message_id(this->ike_sa, TRUE, p2); + } + DBG1(DBG_IKE, "responder requested MID sync: initiating %d[%d], " + "responding %d[%d]", p2, init, m2, resp); + this->send = p2; + this->recv = m2; + return NEED_MORE; +} + +METHOD(task_t, build, status_t, + private_ike_mid_sync_t *this, message_t *message) +{ + bio_writer_t *writer; + + writer = bio_writer_create(12); + writer->write_data(writer, this->nonce); + writer->write_uint32(writer, this->send); + writer->write_uint32(writer, this->recv); + + message->set_message_id(message, 0); + message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC, + writer->get_buf(writer)); + + writer->destroy(writer); + return SUCCESS; +} + +METHOD(task_t, get_type, task_type_t, + private_ike_mid_sync_t *this) +{ + return TASK_IKE_MID_SYNC; +} + +METHOD(task_t, migrate, void, + private_ike_mid_sync_t *this, ike_sa_t *ike_sa) +{ + this->ike_sa = ike_sa; + chunk_free(&this->nonce); +} + +METHOD(task_t, destroy, void, + private_ike_mid_sync_t *this) +{ + chunk_free(&this->nonce); + free(this); +} + +/* + * Described in header. + */ +ike_mid_sync_t *ike_mid_sync_create(ike_sa_t *ike_sa) +{ + private_ike_mid_sync_t *this; + + INIT(this, + .public = { + .task = { + .get_type = _get_type, + .build = _build, + .pre_process = _pre_process, + .process = _process, + .migrate = _migrate, + .destroy = _destroy, + }, + }, + .ike_sa = ike_sa, + ); + return &this->public; +} diff --git a/src/libcharon/sa/ikev2/tasks/ike_mid_sync.h b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.h new file mode 100644 index 000000000..9dd46f925 --- /dev/null +++ b/src/libcharon/sa/ikev2/tasks/ike_mid_sync.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 Tobias Brunner + * HSR 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. + */ +/* + * Copyright (C) 2016 Stephen J. Bevan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup ike_mid_sync ike_mid_sync + * @{ @ingroup tasks_v2 + */ + +#ifndef IKE_MID_SYNC_H_ +#define IKE_MID_SYNC_H_ + +typedef struct ike_mid_sync_t ike_mid_sync_t; + +#include <library.h> +#include <sa/ike_sa.h> +#include <sa/task.h> + +/** + * Task of type TASK_IKE_MID_SYNC, implements RFC 6311 responder. + * + * This task handles an IKEV2_MESSAGE_ID_SYNC notify sent by a peer + * and if acceptable updates the SA MIDs and replies with the updated + * MID values. + */ +struct ike_mid_sync_t { + + /** + * Implements the task_t interface + */ + task_t task; +}; + +/** + * Create a new TASK_IKE_MID_SYNC task. + * + * @param ike_sa IKE_SA this task works for + * @return task to handle by the task_manager + */ +ike_mid_sync_t *ike_mid_sync_create(ike_sa_t *ike_sa); + +#endif /** IKE_MID_SYNC_H_ @}*/ diff --git a/src/libcharon/sa/task.c b/src/libcharon/sa/task.c index 405eda66b..30de08c9b 100644 --- a/src/libcharon/sa/task.c +++ b/src/libcharon/sa/task.c @@ -30,6 +30,7 @@ ENUM(task_type_names, TASK_IKE_INIT, TASK_ISAKMP_CERT_POST, "IKE_REAUTH_COMPLETE", "IKE_REDIRECT", "IKE_VERIFY_PEER_CERT", + "IKE_MID_SYNC", "IKE_DELETE", "IKE_DPD", "IKE_VENDOR", diff --git a/src/libcharon/sa/task.h b/src/libcharon/sa/task.h index 31d70fb3b..5f77149ba 100644 --- a/src/libcharon/sa/task.h +++ b/src/libcharon/sa/task.h @@ -61,6 +61,8 @@ enum task_type_t { TASK_IKE_REDIRECT, /** verify a peer's certificate */ TASK_IKE_VERIFY_PEER_CERT, + /** synchronize message IDs, RFC6311 */ + TASK_IKE_MID_SYNC, /** delete an IKE_SA */ TASK_IKE_DELETE, /** liveness check */ |