ikev2: Delay installation of outbound SAs during rekeying on the responder
[strongswan.git] / src / libcharon / sa / ikev2 / tasks / child_delete.c
1 /*
2 * Copyright (C) 2009-2016 Tobias Brunner
3 * Copyright (C) 2006-2007 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "child_delete.h"
18
19 #include <daemon.h>
20 #include <encoding/payloads/delete_payload.h>
21 #include <sa/ikev2/tasks/child_create.h>
22 #include <sa/ikev2/tasks/child_rekey.h>
23
24 typedef struct private_child_delete_t private_child_delete_t;
25
26 /**
27 * Private members of a child_delete_t task.
28 */
29 struct private_child_delete_t {
30
31 /**
32 * Public methods and task_t interface.
33 */
34 child_delete_t public;
35
36 /**
37 * Assigned IKE_SA.
38 */
39 ike_sa_t *ike_sa;
40
41 /**
42 * Are we the initiator?
43 */
44 bool initiator;
45
46 /**
47 * Protocol of CHILD_SA to delete
48 */
49 protocol_id_t protocol;
50
51 /**
52 * Inbound SPI of CHILD_SA to delete
53 */
54 uint32_t spi;
55
56 /**
57 * whether to enforce delete action policy
58 */
59 bool check_delete_action;
60
61 /**
62 * is this delete exchange following a rekey?
63 */
64 bool rekeyed;
65
66 /**
67 * CHILD_SA already expired?
68 */
69 bool expired;
70
71 /**
72 * CHILD_SAs which get deleted
73 */
74 linked_list_t *child_sas;
75 };
76
77 /**
78 * build the delete payloads from the listed child_sas
79 */
80 static void build_payloads(private_child_delete_t *this, message_t *message)
81 {
82 delete_payload_t *ah = NULL, *esp = NULL;
83 enumerator_t *enumerator;
84 child_sa_t *child_sa;
85
86 enumerator = this->child_sas->create_enumerator(this->child_sas);
87 while (enumerator->enumerate(enumerator, (void**)&child_sa))
88 {
89 protocol_id_t protocol = child_sa->get_protocol(child_sa);
90 uint32_t spi = child_sa->get_spi(child_sa, TRUE);
91
92 switch (protocol)
93 {
94 case PROTO_ESP:
95 if (esp == NULL)
96 {
97 esp = delete_payload_create(PLV2_DELETE, PROTO_ESP);
98 message->add_payload(message, (payload_t*)esp);
99 }
100 esp->add_spi(esp, spi);
101 DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
102 protocol_id_names, protocol, ntohl(spi));
103 break;
104 case PROTO_AH:
105 if (ah == NULL)
106 {
107 ah = delete_payload_create(PLV2_DELETE, PROTO_AH);
108 message->add_payload(message, (payload_t*)ah);
109 }
110 ah->add_spi(ah, spi);
111 DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
112 protocol_id_names, protocol, ntohl(spi));
113 break;
114 default:
115 break;
116 }
117 child_sa->set_state(child_sa, CHILD_DELETING);
118 }
119 enumerator->destroy(enumerator);
120 }
121
122 /**
123 * Check if the given CHILD_SA is the redundant SA created in a rekey collision.
124 */
125 static bool is_redundant(private_child_delete_t *this, child_sa_t *child)
126 {
127 enumerator_t *tasks;
128 task_t *task;
129
130 tasks = this->ike_sa->create_task_enumerator(this->ike_sa,
131 TASK_QUEUE_ACTIVE);
132 while (tasks->enumerate(tasks, &task))
133 {
134 if (task->get_type(task) == TASK_CHILD_REKEY)
135 {
136 child_rekey_t *rekey = (child_rekey_t*)task;
137
138 if (rekey->is_redundant(rekey, child))
139 {
140 tasks->destroy(tasks);
141 return TRUE;
142 }
143 }
144 }
145 tasks->destroy(tasks);
146 return FALSE;
147 }
148
149 /**
150 * Install the outbound CHILD_SA with the given SPI
151 */
152 static void install_outbound(private_child_delete_t *this,
153 protocol_id_t protocol, uint32_t spi)
154 {
155 child_sa_t *child_sa;
156 linked_list_t *my_ts, *other_ts;
157 status_t status;
158
159 child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
160 spi, FALSE);
161 if (!child_sa)
162 {
163 DBG1(DBG_IKE, "CHILD_SA not found after rekeying");
164 return;
165 }
166 if (this->initiator && is_redundant(this, child_sa))
167 { /* if we won the rekey collision we don't want to install the
168 * redundant SA created by the peer */
169 return;
170 }
171
172 status = child_sa->install_outbound(child_sa);
173 if (status != SUCCESS)
174 {
175 DBG1(DBG_IKE, "unable to install outbound IPsec SA (SAD) in kernel");
176 charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
177 child_sa);
178 /* FIXME: delete the new child_sa? */
179 return;
180 }
181 child_sa->set_state(child_sa, CHILD_INSTALLED);
182
183 my_ts = linked_list_create_from_enumerator(
184 child_sa->create_ts_enumerator(child_sa, TRUE));
185 other_ts = linked_list_create_from_enumerator(
186 child_sa->create_ts_enumerator(child_sa, FALSE));
187
188 DBG0(DBG_IKE, "outbound CHILD_SA %s{%d} established "
189 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
190 child_sa->get_name(child_sa),
191 child_sa->get_unique_id(child_sa),
192 ntohl(child_sa->get_spi(child_sa, TRUE)),
193 ntohl(child_sa->get_spi(child_sa, FALSE)),
194 my_ts, other_ts);
195
196 my_ts->destroy(my_ts);
197 other_ts->destroy(other_ts);
198 }
199
200 /**
201 * read in payloads and find the children to delete
202 */
203 static void process_payloads(private_child_delete_t *this, message_t *message)
204 {
205 enumerator_t *payloads, *spis;
206 payload_t *payload;
207 delete_payload_t *delete_payload;
208 uint32_t spi;
209 protocol_id_t protocol;
210 child_sa_t *child_sa;
211
212 payloads = message->create_payload_enumerator(message);
213 while (payloads->enumerate(payloads, &payload))
214 {
215 if (payload->get_type(payload) == PLV2_DELETE)
216 {
217 delete_payload = (delete_payload_t*)payload;
218 protocol = delete_payload->get_protocol_id(delete_payload);
219 if (protocol != PROTO_ESP && protocol != PROTO_AH)
220 {
221 continue;
222 }
223 spis = delete_payload->create_spi_enumerator(delete_payload);
224 while (spis->enumerate(spis, &spi))
225 {
226 child_sa = this->ike_sa->get_child_sa(this->ike_sa, protocol,
227 spi, FALSE);
228 if (child_sa == NULL)
229 {
230 DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x, "
231 "but no such SA", protocol_id_names, protocol, ntohl(spi));
232 continue;
233 }
234 DBG1(DBG_IKE, "received DELETE for %N CHILD_SA with SPI %.8x",
235 protocol_id_names, protocol, ntohl(spi));
236
237 switch (child_sa->get_state(child_sa))
238 {
239 case CHILD_REKEYED:
240 this->rekeyed = TRUE;
241 break;
242 case CHILD_DELETING:
243 /* we don't send back a delete if we initiated ourself */
244 if (!this->initiator)
245 {
246 continue;
247 }
248 /* fall through */
249 case CHILD_REKEYING:
250 /* we reply as usual, rekeying will fail */
251 case CHILD_INSTALLED_INBOUND:
252 case CHILD_INSTALLED:
253 if (!this->initiator)
254 {
255 if (is_redundant(this, child_sa))
256 {
257 this->rekeyed = TRUE;
258 }
259 else
260 {
261 this->check_delete_action = TRUE;
262 }
263 }
264 break;
265 default:
266 break;
267 }
268 if (this->child_sas->find_first(this->child_sas, NULL,
269 (void**)&child_sa) != SUCCESS)
270 {
271 this->child_sas->insert_last(this->child_sas, child_sa);
272 }
273 }
274 spis->destroy(spis);
275 }
276 }
277 payloads->destroy(payloads);
278 }
279
280 /**
281 * destroy the children listed in this->child_sas, reestablish by policy
282 */
283 static status_t destroy_and_reestablish(private_child_delete_t *this)
284 {
285 enumerator_t *enumerator;
286 child_sa_t *child_sa;
287 child_cfg_t *child_cfg;
288 protocol_id_t protocol;
289 uint32_t spi, reqid, rekey_spi;
290 action_t action;
291 status_t status = SUCCESS;
292
293 enumerator = this->child_sas->create_enumerator(this->child_sas);
294 while (enumerator->enumerate(enumerator, (void**)&child_sa))
295 {
296 /* signal child down event if we weren't rekeying */
297 protocol = child_sa->get_protocol(child_sa);
298 if (!this->rekeyed)
299 {
300 charon->bus->child_updown(charon->bus, child_sa, FALSE);
301 }
302 else
303 {
304 rekey_spi = child_sa->get_rekey_spi(child_sa);
305 if (rekey_spi)
306 {
307 install_outbound(this, protocol, rekey_spi);
308 }
309 }
310 spi = child_sa->get_spi(child_sa, TRUE);
311 reqid = child_sa->get_reqid(child_sa);
312 child_cfg = child_sa->get_config(child_sa);
313 child_cfg->get_ref(child_cfg);
314 action = child_sa->get_close_action(child_sa);
315 this->ike_sa->destroy_child_sa(this->ike_sa, protocol, spi);
316 if (this->check_delete_action)
317 { /* enforce child_cfg policy if deleted passively */
318 switch (action)
319 {
320 case ACTION_RESTART:
321 child_cfg->get_ref(child_cfg);
322 status = this->ike_sa->initiate(this->ike_sa, child_cfg,
323 reqid, NULL, NULL);
324 break;
325 case ACTION_ROUTE:
326 charon->traps->install(charon->traps,
327 this->ike_sa->get_peer_cfg(this->ike_sa), child_cfg,
328 reqid);
329 break;
330 default:
331 break;
332 }
333 }
334 child_cfg->destroy(child_cfg);
335 if (status != SUCCESS)
336 {
337 break;
338 }
339 }
340 enumerator->destroy(enumerator);
341 return status;
342 }
343
344 /**
345 * send closing signals for all CHILD_SAs over the bus
346 */
347 static void log_children(private_child_delete_t *this)
348 {
349 linked_list_t *my_ts, *other_ts;
350 enumerator_t *enumerator;
351 child_sa_t *child_sa;
352 uint64_t bytes_in, bytes_out;
353
354 enumerator = this->child_sas->create_enumerator(this->child_sas);
355 while (enumerator->enumerate(enumerator, (void**)&child_sa))
356 {
357 my_ts = linked_list_create_from_enumerator(
358 child_sa->create_ts_enumerator(child_sa, TRUE));
359 other_ts = linked_list_create_from_enumerator(
360 child_sa->create_ts_enumerator(child_sa, FALSE));
361 if (this->expired)
362 {
363 DBG0(DBG_IKE, "closing expired CHILD_SA %s{%d} "
364 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
365 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
366 ntohl(child_sa->get_spi(child_sa, TRUE)),
367 ntohl(child_sa->get_spi(child_sa, FALSE)), my_ts, other_ts);
368 }
369 else
370 {
371 child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, NULL);
372 child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, NULL);
373
374 DBG0(DBG_IKE, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
375 "(%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
376 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
377 ntohl(child_sa->get_spi(child_sa, TRUE)), bytes_in,
378 ntohl(child_sa->get_spi(child_sa, FALSE)), bytes_out,
379 my_ts, other_ts);
380 }
381 my_ts->destroy(my_ts);
382 other_ts->destroy(other_ts);
383 }
384 enumerator->destroy(enumerator);
385 }
386
387 METHOD(task_t, build_i, status_t,
388 private_child_delete_t *this, message_t *message)
389 {
390 child_sa_t *child_sa;
391
392 child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
393 this->spi, TRUE);
394 if (!child_sa)
395 { /* check if it is an outbound sa */
396 child_sa = this->ike_sa->get_child_sa(this->ike_sa, this->protocol,
397 this->spi, FALSE);
398 if (!child_sa)
399 { /* child does not exist anymore */
400 return SUCCESS;
401 }
402 /* we work only with the inbound SPI */
403 this->spi = child_sa->get_spi(child_sa, TRUE);
404 }
405 this->child_sas->insert_last(this->child_sas, child_sa);
406 if (child_sa->get_state(child_sa) == CHILD_REKEYED)
407 {
408 this->rekeyed = TRUE;
409 }
410 log_children(this);
411 build_payloads(this, message);
412
413 if (!this->rekeyed && this->expired)
414 {
415 child_cfg_t *child_cfg;
416
417 DBG1(DBG_IKE, "scheduling CHILD_SA recreate after hard expire");
418 child_cfg = child_sa->get_config(child_sa);
419 this->ike_sa->queue_task(this->ike_sa, (task_t*)
420 child_create_create(this->ike_sa, child_cfg->get_ref(child_cfg),
421 FALSE, NULL, NULL));
422 }
423 return NEED_MORE;
424 }
425
426 METHOD(task_t, process_i, status_t,
427 private_child_delete_t *this, message_t *message)
428 {
429 process_payloads(this, message);
430 DBG1(DBG_IKE, "CHILD_SA closed");
431 return destroy_and_reestablish(this);
432 }
433
434 METHOD(task_t, process_r, status_t,
435 private_child_delete_t *this, message_t *message)
436 {
437 process_payloads(this, message);
438 log_children(this);
439 return NEED_MORE;
440 }
441
442 METHOD(task_t, build_r, status_t,
443 private_child_delete_t *this, message_t *message)
444 {
445 build_payloads(this, message);
446 DBG1(DBG_IKE, "CHILD_SA closed");
447 return destroy_and_reestablish(this);
448 }
449
450 METHOD(task_t, get_type, task_type_t,
451 private_child_delete_t *this)
452 {
453 return TASK_CHILD_DELETE;
454 }
455
456 METHOD(child_delete_t , get_child, child_sa_t*,
457 private_child_delete_t *this)
458 {
459 child_sa_t *child_sa = NULL;
460 this->child_sas->get_first(this->child_sas, (void**)&child_sa);
461 return child_sa;
462 }
463
464 METHOD(task_t, migrate, void,
465 private_child_delete_t *this, ike_sa_t *ike_sa)
466 {
467 this->check_delete_action = FALSE;
468 this->ike_sa = ike_sa;
469
470 this->child_sas->destroy(this->child_sas);
471 this->child_sas = linked_list_create();
472 }
473
474 METHOD(task_t, destroy, void,
475 private_child_delete_t *this)
476 {
477 this->child_sas->destroy(this->child_sas);
478 free(this);
479 }
480
481 /*
482 * Described in header.
483 */
484 child_delete_t *child_delete_create(ike_sa_t *ike_sa, protocol_id_t protocol,
485 uint32_t spi, bool expired)
486 {
487 private_child_delete_t *this;
488
489 INIT(this,
490 .public = {
491 .task = {
492 .get_type = _get_type,
493 .migrate = _migrate,
494 .destroy = _destroy,
495 },
496 .get_child = _get_child,
497 },
498 .ike_sa = ike_sa,
499 .child_sas = linked_list_create(),
500 .protocol = protocol,
501 .spi = spi,
502 .expired = expired,
503 );
504
505 if (protocol != PROTO_NONE)
506 {
507 this->public.task.build = _build_i;
508 this->public.task.process = _process_i;
509 this->initiator = TRUE;
510 }
511 else
512 {
513 this->public.task.build = _build_r;
514 this->public.task.process = _process_r;
515 this->initiator = FALSE;
516 }
517 return &this->public;
518 }