Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2016 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * This program is free software; you can redistribute it and/or modify it
! 6: * under the terms of the GNU General Public License as published by the
! 7: * Free Software Foundation; either version 2 of the License, or (at your
! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 9: *
! 10: * This program is distributed in the hope that it will be useful, but
! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 13: * for more details.
! 14: */
! 15: /*
! 16: * Copyright (C) 2016 Stephen J. Bevan
! 17: *
! 18: * Permission is hereby granted, free of charge, to any person obtaining a copy
! 19: * of this software and associated documentation files (the "Software"), to deal
! 20: * in the Software without restriction, including without limitation the rights
! 21: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
! 22: * copies of the Software, and to permit persons to whom the Software is
! 23: * furnished to do so, subject to the following conditions:
! 24: *
! 25: * The above copyright notice and this permission notice shall be included in
! 26: * all copies or substantial portions of the Software.
! 27: *
! 28: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
! 29: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
! 30: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
! 31: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
! 32: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
! 33: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
! 34: * THE SOFTWARE.
! 35: */
! 36:
! 37: #include "ike_mid_sync.h"
! 38:
! 39: #include <daemon.h>
! 40: #include <bio/bio_reader.h>
! 41: #include <bio/bio_writer.h>
! 42: #include <encoding/payloads/notify_payload.h>
! 43:
! 44: typedef struct private_ike_mid_sync_t private_ike_mid_sync_t;
! 45:
! 46: /**
! 47: * Private members
! 48: */
! 49: struct private_ike_mid_sync_t {
! 50:
! 51: /**
! 52: * Public methods and task_t interface.
! 53: */
! 54: ike_mid_sync_t public;
! 55:
! 56: /**
! 57: * Assigned IKE_SA.
! 58: */
! 59: ike_sa_t *ike_sa;
! 60:
! 61: /**
! 62: * Nonce sent by the peer and expected to be returned
! 63: */
! 64: chunk_t nonce;
! 65:
! 66: /**
! 67: * Expected next sender message ID
! 68: */
! 69: uint32_t send;
! 70:
! 71: /**
! 72: * Expected received message ID
! 73: */
! 74: uint32_t recv;
! 75: };
! 76:
! 77: /*
! 78: * Encoding of IKEV2_MESSAGE_SYNC_ID notify, RFC 6311
! 79: *
! 80: * 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
! 81: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 82: * | Next Payload |C| RESERVED | Payload Length |
! 83: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 84: * |Protocol ID(=0)| SPI Size (=0) | Notify Message Type |
! 85: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 86: * | Nonce Data |
! 87: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 88: * | EXPECTED_SEND_REQ_MESSAGE_ID |
! 89: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 90: * | EXPECTED_RECV_REQ_MESSAGE_ID |
! 91: * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! 92: */
! 93:
! 94: /*
! 95: * RFC 6311 section 5.1
! 96: *
! 97: * o The peer MUST silently drop any received synchronization message
! 98: * if M1 is lower than or equal to the highest value it has seen from
! 99: * the cluster. This includes any previous received synchronization
! 100: * messages.
! 101: */
! 102: METHOD(task_t, pre_process, status_t,
! 103: private_ike_mid_sync_t *this, message_t *message)
! 104: {
! 105: notify_payload_t *notify;
! 106: bio_reader_t *reader;
! 107: chunk_t nonce;
! 108: uint32_t resp;
! 109:
! 110: if (message->get_message_id(message) != 0)
! 111: { /* ignore the notify if it was contained in an INFORMATIONAL with
! 112: * unexpected message ID */
! 113: return SUCCESS;
! 114: }
! 115: if (!this->ike_sa->supports_extension(this->ike_sa,
! 116: EXT_IKE_MESSAGE_ID_SYNC))
! 117: {
! 118: DBG1(DBG_ENC, "unexpected %N notify, ignored", notify_type_names,
! 119: IKEV2_MESSAGE_ID_SYNC);
! 120: return FAILED;
! 121: }
! 122: notify = message->get_notify(message, IKEV2_MESSAGE_ID_SYNC);
! 123:
! 124: reader = bio_reader_create(notify->get_notification_data(notify));
! 125: if (!reader->read_data(reader, 4, &nonce) ||
! 126: !reader->read_uint32(reader, &this->send) ||
! 127: !reader->read_uint32(reader, &this->recv))
! 128: {
! 129: reader->destroy(reader);
! 130: DBG1(DBG_ENC, "received invalid %N notify",
! 131: notify_type_names, IKEV2_MESSAGE_ID_SYNC);
! 132: return FAILED;
! 133: }
! 134: reader->destroy(reader);
! 135: resp = this->ike_sa->get_message_id(this->ike_sa, FALSE);
! 136: if (this->send < resp)
! 137: {
! 138: DBG1(DBG_ENC, "ignore %N notify with lower (%d) than expected (%d) "
! 139: "sender MID", notify_type_names, IKEV2_MESSAGE_ID_SYNC, this->send,
! 140: resp);
! 141: return FAILED;
! 142: }
! 143: this->nonce = chunk_clone(nonce);
! 144: return SUCCESS;
! 145: }
! 146:
! 147: /**
! 148: * Check if there are any active tasks, indicating that we already
! 149: * used the currents message ID and are waiting for a response.
! 150: */
! 151: static bool has_active_tasks(private_ike_mid_sync_t *this)
! 152: {
! 153: enumerator_t *enumerator;
! 154: task_t *task;
! 155: bool active;
! 156:
! 157: enumerator = this->ike_sa->create_task_enumerator(this->ike_sa,
! 158: TASK_QUEUE_ACTIVE);
! 159: active = enumerator->enumerate(enumerator, &task);
! 160: enumerator->destroy(enumerator);
! 161: return active;
! 162: }
! 163:
! 164: /*
! 165: * RFC 6311 section 5.1
! 166: *
! 167: * o M2 MUST be at least the higher of the received M1, and one more
! 168: * than the highest sender value received from the cluster. This
! 169: * includes any previous received synchronization messages.
! 170: *
! 171: * o P2 MUST be the higher of the received P1 value, and one more than
! 172: * the highest sender value used by the peer.
! 173: *
! 174: * M1 is this->send, P1 is this->recv
! 175: */
! 176: METHOD(task_t, process, status_t,
! 177: private_ike_mid_sync_t *this, message_t *message)
! 178: {
! 179: uint32_t resp, init, m2, p2;
! 180:
! 181: if (message->get_message_id(message) != 0)
! 182: { /* ignore the notify if it was contained in an INFORMATIONAL with
! 183: * unexpected message id */
! 184: return SUCCESS;
! 185: }
! 186: resp = this->ike_sa->get_message_id(this->ike_sa, FALSE);
! 187: m2 = max(this->send, resp);
! 188: if (resp != m2)
! 189: {
! 190: this->ike_sa->set_message_id(this->ike_sa, FALSE, m2);
! 191: }
! 192: init = this->ike_sa->get_message_id(this->ike_sa, TRUE);
! 193: p2 = max(this->recv, has_active_tasks(this) ? init + 1 : init);
! 194: if (init != p2)
! 195: {
! 196: this->ike_sa->set_message_id(this->ike_sa, TRUE, p2);
! 197: }
! 198: DBG1(DBG_IKE, "responder requested MID sync: initiating %d[%d], "
! 199: "responding %d[%d]", p2, init, m2, resp);
! 200: this->send = p2;
! 201: this->recv = m2;
! 202: return NEED_MORE;
! 203: }
! 204:
! 205: METHOD(task_t, build, status_t,
! 206: private_ike_mid_sync_t *this, message_t *message)
! 207: {
! 208: bio_writer_t *writer;
! 209:
! 210: writer = bio_writer_create(12);
! 211: writer->write_data(writer, this->nonce);
! 212: writer->write_uint32(writer, this->send);
! 213: writer->write_uint32(writer, this->recv);
! 214:
! 215: message->set_message_id(message, 0);
! 216: message->add_notify(message, FALSE, IKEV2_MESSAGE_ID_SYNC,
! 217: writer->get_buf(writer));
! 218:
! 219: writer->destroy(writer);
! 220: return SUCCESS;
! 221: }
! 222:
! 223: METHOD(task_t, get_type, task_type_t,
! 224: private_ike_mid_sync_t *this)
! 225: {
! 226: return TASK_IKE_MID_SYNC;
! 227: }
! 228:
! 229: METHOD(task_t, migrate, void,
! 230: private_ike_mid_sync_t *this, ike_sa_t *ike_sa)
! 231: {
! 232: this->ike_sa = ike_sa;
! 233: chunk_free(&this->nonce);
! 234: }
! 235:
! 236: METHOD(task_t, destroy, void,
! 237: private_ike_mid_sync_t *this)
! 238: {
! 239: chunk_free(&this->nonce);
! 240: free(this);
! 241: }
! 242:
! 243: /*
! 244: * Described in header.
! 245: */
! 246: ike_mid_sync_t *ike_mid_sync_create(ike_sa_t *ike_sa)
! 247: {
! 248: private_ike_mid_sync_t *this;
! 249:
! 250: INIT(this,
! 251: .public = {
! 252: .task = {
! 253: .get_type = _get_type,
! 254: .build = _build,
! 255: .pre_process = _pre_process,
! 256: .process = _process,
! 257: .migrate = _migrate,
! 258: .destroy = _destroy,
! 259: },
! 260: },
! 261: .ike_sa = ike_sa,
! 262: );
! 263: return &this->public;
! 264: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>