Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/tasks/ike_mid_sync.c, revision 1.1.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>