2 * Copyright (C) 2009-2016 Tobias Brunner
3 * Copyright (C) 2006-2007 Martin Willi
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "child_delete.h"
21 #include <encoding/payloads/delete_payload.h>
22 #include <processing/jobs/delete_child_sa_job.h>
23 #include <sa/ikev2/tasks/child_create.h>
24 #include <sa/ikev2/tasks/child_rekey.h>
26 #ifndef DELETE_REKEYED_DELAY
27 #define DELETE_REKEYED_DELAY 5
30 typedef struct private_child_delete_t private_child_delete_t
;
33 * Private members of a child_delete_t task.
35 struct private_child_delete_t
{
38 * Public methods and task_t interface.
40 child_delete_t
public;
48 * Whether we are the initiator of the exchange
53 * Protocol of CHILD_SA to delete (as initiator)
55 protocol_id_t protocol
;
58 * Inbound SPI of CHILD_SA to delete (as initiator)
63 * CHILD_SA already expired (as initiator)
68 * CHILD_SAs which get deleted, entry_t*
70 linked_list_t
*child_sas
;
74 * Information about a deleted CHILD_SA
77 /** Deleted CHILD_SA */
79 /** Whether the CHILD_SA was rekeyed */
81 /** Whether to enforce any delete action policy */
82 bool check_delete_action
;
85 CALLBACK(match_child
, bool,
86 entry_t
*entry
, va_list args
)
90 VA_ARGS_VGET(args
, child_sa
);
91 return entry
->child_sa
== child_sa
;
95 * build the delete payloads from the listed child_sas
97 static void build_payloads(private_child_delete_t
*this, message_t
*message
)
99 delete_payload_t
*ah
= NULL
, *esp
= NULL
;
100 enumerator_t
*enumerator
;
102 protocol_id_t protocol
;
105 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
106 while (enumerator
->enumerate(enumerator
, (void**)&entry
))
108 protocol
= entry
->child_sa
->get_protocol(entry
->child_sa
);
109 spi
= entry
->child_sa
->get_spi(entry
->child_sa
, TRUE
);
116 esp
= delete_payload_create(PLV2_DELETE
, PROTO_ESP
);
117 message
->add_payload(message
, (payload_t
*)esp
);
119 esp
->add_spi(esp
, spi
);
120 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
121 protocol_id_names
, protocol
, ntohl(spi
));
126 ah
= delete_payload_create(PLV2_DELETE
, PROTO_AH
);
127 message
->add_payload(message
, (payload_t
*)ah
);
129 ah
->add_spi(ah
, spi
);
130 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
131 protocol_id_names
, protocol
, ntohl(spi
));
136 entry
->child_sa
->set_state(entry
->child_sa
, CHILD_DELETING
);
138 enumerator
->destroy(enumerator
);
142 * Check if the given CHILD_SA is the redundant SA created in a rekey collision.
144 static bool is_redundant(private_child_delete_t
*this, child_sa_t
*child
)
149 tasks
= this->ike_sa
->create_task_enumerator(this->ike_sa
,
151 while (tasks
->enumerate(tasks
, &task
))
153 if (task
->get_type(task
) == TASK_CHILD_REKEY
)
155 child_rekey_t
*rekey
= (child_rekey_t
*)task
;
157 if (rekey
->is_redundant(rekey
, child
))
159 tasks
->destroy(tasks
);
164 tasks
->destroy(tasks
);
169 * Install the outbound CHILD_SA with the given SPI
171 static void install_outbound(private_child_delete_t
*this,
172 protocol_id_t protocol
, uint32_t spi
)
174 child_sa_t
*child_sa
;
175 linked_list_t
*my_ts
, *other_ts
;
183 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
,
187 DBG1(DBG_IKE
, "CHILD_SA not found after rekeying");
190 if (this->initiator
&& is_redundant(this, child_sa
))
191 { /* if we won the rekey collision we don't want to install the
192 * redundant SA created by the peer */
196 status
= child_sa
->install_outbound(child_sa
);
197 if (status
!= SUCCESS
)
199 DBG1(DBG_IKE
, "unable to install outbound IPsec SA (SAD) in kernel");
200 charon
->bus
->alert(charon
->bus
, ALERT_INSTALL_CHILD_SA_FAILED
,
202 /* FIXME: delete the new child_sa? */
206 my_ts
= linked_list_create_from_enumerator(
207 child_sa
->create_ts_enumerator(child_sa
, TRUE
));
208 other_ts
= linked_list_create_from_enumerator(
209 child_sa
->create_ts_enumerator(child_sa
, FALSE
));
211 DBG0(DBG_IKE
, "outbound CHILD_SA %s{%d} established "
212 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
213 child_sa
->get_name(child_sa
),
214 child_sa
->get_unique_id(child_sa
),
215 ntohl(child_sa
->get_spi(child_sa
, TRUE
)),
216 ntohl(child_sa
->get_spi(child_sa
, FALSE
)),
219 my_ts
->destroy(my_ts
);
220 other_ts
->destroy(other_ts
);
224 * read in payloads and find the children to delete
226 static void process_payloads(private_child_delete_t
*this, message_t
*message
)
228 enumerator_t
*payloads
, *spis
;
230 delete_payload_t
*delete_payload
;
232 protocol_id_t protocol
;
233 child_sa_t
*child_sa
;
236 payloads
= message
->create_payload_enumerator(message
);
237 while (payloads
->enumerate(payloads
, &payload
))
239 if (payload
->get_type(payload
) == PLV2_DELETE
)
241 delete_payload
= (delete_payload_t
*)payload
;
242 protocol
= delete_payload
->get_protocol_id(delete_payload
);
243 if (protocol
!= PROTO_ESP
&& protocol
!= PROTO_AH
)
247 spis
= delete_payload
->create_spi_enumerator(delete_payload
);
248 while (spis
->enumerate(spis
, &spi
))
250 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
,
254 DBG1(DBG_IKE
, "received DELETE for unknown %N CHILD_SA with"
255 " SPI %.8x", protocol_id_names
, protocol
, ntohl(spi
));
258 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x",
259 protocol_id_names
, protocol
, ntohl(spi
));
261 if (this->child_sas
->find_first(this->child_sas
, match_child
,
269 switch (child_sa
->get_state(child_sa
))
272 entry
->rekeyed
= TRUE
;
275 /* already deleted but not yet destroyed, ignore */
277 /* we don't send back a delete if we already initiated
278 * a delete ourself */
279 if (!this->initiator
)
286 /* we reply as usual, rekeying will fail */
287 case CHILD_INSTALLED
:
288 if (!this->initiator
)
290 if (is_redundant(this, child_sa
))
292 entry
->rekeyed
= TRUE
;
296 entry
->check_delete_action
= TRUE
;
303 this->child_sas
->insert_last(this->child_sas
, entry
);
308 payloads
->destroy(payloads
);
312 * destroy the children listed in this->child_sas, reestablish by policy
314 static status_t
destroy_and_reestablish(private_child_delete_t
*this)
316 child_init_args_t args
= {};
317 enumerator_t
*enumerator
;
319 child_sa_t
*child_sa
;
320 child_cfg_t
*child_cfg
;
321 protocol_id_t protocol
;
324 status_t status
= SUCCESS
;
328 now
= time_monotonic(NULL
);
329 delay
= lib
->settings
->get_int(lib
->settings
, "%s.delete_rekeyed_delay",
330 DELETE_REKEYED_DELAY
, lib
->ns
);
332 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
333 while (enumerator
->enumerate(enumerator
, (void**)&entry
))
335 child_sa
= entry
->child_sa
;
336 child_sa
->set_state(child_sa
, CHILD_DELETED
);
337 /* signal child down event if we weren't rekeying */
338 protocol
= child_sa
->get_protocol(child_sa
);
341 charon
->bus
->child_updown(charon
->bus
, child_sa
, FALSE
);
345 /* the following two calls are only relevant as responder/loser of
346 * rekeyings as the initiator/winner already did this right after
347 * the rekeying was completed, either way, we delay destroying
348 * the CHILD_SA, by default, so we can process delayed packets */
349 install_outbound(this, protocol
, child_sa
->get_rekey_spi(child_sa
));
350 child_sa
->remove_outbound(child_sa
);
352 expire
= child_sa
->get_lifetime(child_sa
, TRUE
);
353 if (delay
&& (!expire
|| ((now
+ delay
) < expire
)))
355 lib
->scheduler
->schedule_job(lib
->scheduler
,
356 (job_t
*)delete_child_sa_job_create_id(
357 child_sa
->get_unique_id(child_sa
)), delay
);
360 else if (now
< expire
)
361 { /* let it expire naturally */
364 /* no delay and no lifetime, destroy it immediately */
366 spi
= child_sa
->get_spi(child_sa
, TRUE
);
367 child_cfg
= child_sa
->get_config(child_sa
);
368 child_cfg
->get_ref(child_cfg
);
369 args
.reqid
= child_sa
->get_reqid(child_sa
);
370 args
.label
= child_sa
->get_label(child_sa
);
373 args
.label
= args
.label
->clone(args
.label
);
375 action
= child_sa
->get_close_action(child_sa
);
377 this->ike_sa
->destroy_child_sa(this->ike_sa
, protocol
, spi
);
379 if (entry
->check_delete_action
)
380 { /* enforce child_cfg policy if deleted passively */
381 if (action
& ACTION_TRAP
)
383 charon
->traps
->install(charon
->traps
,
384 this->ike_sa
->get_peer_cfg(this->ike_sa
),
387 if (action
& ACTION_START
)
389 child_cfg
->get_ref(child_cfg
);
390 status
= this->ike_sa
->initiate(this->ike_sa
, child_cfg
, &args
);
393 child_cfg
->destroy(child_cfg
);
394 DESTROY_IF(args
.label
);
395 if (status
!= SUCCESS
)
400 enumerator
->destroy(enumerator
);
405 * send closing signals for all CHILD_SAs over the bus
407 static void log_children(private_child_delete_t
*this)
409 linked_list_t
*my_ts
, *other_ts
;
410 enumerator_t
*enumerator
;
412 child_sa_t
*child_sa
;
413 uint64_t bytes_in
, bytes_out
;
415 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
416 while (enumerator
->enumerate(enumerator
, (void**)&entry
))
418 child_sa
= entry
->child_sa
;
419 my_ts
= linked_list_create_from_enumerator(
420 child_sa
->create_ts_enumerator(child_sa
, TRUE
));
421 other_ts
= linked_list_create_from_enumerator(
422 child_sa
->create_ts_enumerator(child_sa
, FALSE
));
425 DBG0(DBG_IKE
, "closing expired CHILD_SA %s{%d} "
426 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
427 child_sa
->get_name(child_sa
), child_sa
->get_unique_id(child_sa
),
428 ntohl(child_sa
->get_spi(child_sa
, TRUE
)),
429 ntohl(child_sa
->get_spi(child_sa
, FALSE
)), my_ts
, other_ts
);
433 child_sa
->get_usestats(child_sa
, TRUE
, NULL
, &bytes_in
, NULL
);
434 child_sa
->get_usestats(child_sa
, FALSE
, NULL
, &bytes_out
, NULL
);
436 DBG0(DBG_IKE
, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
437 "(%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
438 child_sa
->get_name(child_sa
), child_sa
->get_unique_id(child_sa
),
439 ntohl(child_sa
->get_spi(child_sa
, TRUE
)), bytes_in
,
440 ntohl(child_sa
->get_spi(child_sa
, FALSE
)), bytes_out
,
443 my_ts
->destroy(my_ts
);
444 other_ts
->destroy(other_ts
);
446 enumerator
->destroy(enumerator
);
449 METHOD(task_t
, build_i
, status_t
,
450 private_child_delete_t
*this, message_t
*message
)
452 child_sa_t
*child_sa
;
455 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, this->protocol
,
458 { /* check if it is an outbound sa */
459 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, this->protocol
,
462 { /* child does not exist anymore */
465 /* we work only with the inbound SPI */
466 this->spi
= child_sa
->get_spi(child_sa
, TRUE
);
469 if (this->expired
&& child_sa
->get_state(child_sa
) == CHILD_REKEYED
)
470 { /* the peer was expected to delete this SA, but if we send a DELETE
471 * we might cause a collision there if the CREATE_CHILD_SA response
472 * is delayed (the peer wouldn't know if we deleted this SA due to an
473 * expire or because of a forced delete by the user and might then
474 * ignore the CREATE_CHILD_SA response once it arrives) */
475 child_sa
->set_state(child_sa
, CHILD_DELETED
);
476 install_outbound(this, this->protocol
,
477 child_sa
->get_rekey_spi(child_sa
));
480 if (child_sa
->get_state(child_sa
) == CHILD_DELETED
)
481 { /* DELETEs for this CHILD_SA were already exchanged, but it was not yet
482 * destroyed to allow delayed packets to get processed */
483 this->ike_sa
->destroy_child_sa(this->ike_sa
, this->protocol
, this->spi
);
484 message
->set_exchange_type(message
, EXCHANGE_TYPE_UNDEFINED
);
489 .child_sa
= child_sa
,
490 .rekeyed
= child_sa
->get_state(child_sa
) == CHILD_REKEYED
,
492 this->child_sas
->insert_last(this->child_sas
, entry
);
494 build_payloads(this, message
);
496 if (!entry
->rekeyed
&& this->expired
)
498 child_cfg_t
*child_cfg
;
500 DBG1(DBG_IKE
, "scheduling CHILD_SA recreate after hard expire");
501 child_cfg
= child_sa
->get_config(child_sa
);
502 this->ike_sa
->queue_task(this->ike_sa
, (task_t
*)
503 child_create_create(this->ike_sa
, child_cfg
->get_ref(child_cfg
),
509 METHOD(task_t
, process_i
, status_t
,
510 private_child_delete_t
*this, message_t
*message
)
512 process_payloads(this, message
);
513 DBG1(DBG_IKE
, "CHILD_SA closed");
514 return destroy_and_reestablish(this);
517 METHOD(task_t
, process_r
, status_t
,
518 private_child_delete_t
*this, message_t
*message
)
520 process_payloads(this, message
);
525 METHOD(task_t
, build_r
, status_t
,
526 private_child_delete_t
*this, message_t
*message
)
528 build_payloads(this, message
);
529 DBG1(DBG_IKE
, "CHILD_SA closed");
530 return destroy_and_reestablish(this);
533 METHOD(task_t
, get_type
, task_type_t
,
534 private_child_delete_t
*this)
536 return TASK_CHILD_DELETE
;
539 METHOD(child_delete_t
, get_child
, child_sa_t
*,
540 private_child_delete_t
*this)
542 child_sa_t
*child_sa
= NULL
;
545 if (this->child_sas
->get_first(this->child_sas
, (void**)&entry
) == SUCCESS
)
547 child_sa
= entry
->child_sa
;
552 METHOD(task_t
, migrate
, void,
553 private_child_delete_t
*this, ike_sa_t
*ike_sa
)
555 this->ike_sa
= ike_sa
;
557 this->child_sas
->destroy_function(this->child_sas
, free
);
558 this->child_sas
= linked_list_create();
561 METHOD(task_t
, destroy
, void,
562 private_child_delete_t
*this)
564 this->child_sas
->destroy_function(this->child_sas
, free
);
569 * Described in header.
571 child_delete_t
*child_delete_create(ike_sa_t
*ike_sa
, protocol_id_t protocol
,
572 uint32_t spi
, bool expired
)
574 private_child_delete_t
*this;
579 .get_type
= _get_type
,
583 .get_child
= _get_child
,
586 .child_sas
= linked_list_create(),
587 .protocol
= protocol
,
592 if (protocol
!= PROTO_NONE
)
594 this->public.task
.build
= _build_i
;
595 this->public.task
.process
= _process_i
;
596 this->initiator
= TRUE
;
600 this->public.task
.build
= _build_r
;
601 this->public.task
.process
= _process_r
;
602 this->initiator
= FALSE
;
604 return &this->public;