2 * Copyright (C) 2009-2016 Tobias Brunner
3 * Copyright (C) 2006-2007 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
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>.
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
17 #include "child_delete.h"
20 #include <encoding/payloads/delete_payload.h>
21 #include <processing/jobs/delete_child_sa_job.h>
22 #include <sa/ikev2/tasks/child_create.h>
23 #include <sa/ikev2/tasks/child_rekey.h>
25 #ifndef DELETE_REKEYED_DELAY
26 #define DELETE_REKEYED_DELAY 5
29 typedef struct private_child_delete_t private_child_delete_t
;
32 * Private members of a child_delete_t task.
34 struct private_child_delete_t
{
37 * Public methods and task_t interface.
39 child_delete_t
public;
47 * Whether we are the initiator of the exchange
52 * Protocol of CHILD_SA to delete (as initiator)
54 protocol_id_t protocol
;
57 * Inbound SPI of CHILD_SA to delete (as initiator)
62 * CHILD_SA already expired (as initiator)
67 * CHILD_SAs which get deleted, entry_t*
69 linked_list_t
*child_sas
;
73 * Information about a deleted CHILD_SA
76 /** Deleted CHILD_SA */
78 /** Whether the CHILD_SA was rekeyed */
80 /** Whether to enforce any delete action policy */
81 bool check_delete_action
;
84 CALLBACK(match_child
, bool,
85 entry_t
*entry
, va_list args
)
89 VA_ARGS_VGET(args
, child_sa
);
90 return entry
->child_sa
== child_sa
;
94 * build the delete payloads from the listed child_sas
96 static void build_payloads(private_child_delete_t
*this, message_t
*message
)
98 delete_payload_t
*ah
= NULL
, *esp
= NULL
;
99 enumerator_t
*enumerator
;
101 protocol_id_t protocol
;
104 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
105 while (enumerator
->enumerate(enumerator
, (void**)&entry
))
107 protocol
= entry
->child_sa
->get_protocol(entry
->child_sa
);
108 spi
= entry
->child_sa
->get_spi(entry
->child_sa
, TRUE
);
115 esp
= delete_payload_create(PLV2_DELETE
, PROTO_ESP
);
116 message
->add_payload(message
, (payload_t
*)esp
);
118 esp
->add_spi(esp
, spi
);
119 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
120 protocol_id_names
, protocol
, ntohl(spi
));
125 ah
= delete_payload_create(PLV2_DELETE
, PROTO_AH
);
126 message
->add_payload(message
, (payload_t
*)ah
);
128 ah
->add_spi(ah
, spi
);
129 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
130 protocol_id_names
, protocol
, ntohl(spi
));
135 entry
->child_sa
->set_state(entry
->child_sa
, CHILD_DELETING
);
137 enumerator
->destroy(enumerator
);
141 * Check if the given CHILD_SA is the redundant SA created in a rekey collision.
143 static bool is_redundant(private_child_delete_t
*this, child_sa_t
*child
)
148 tasks
= this->ike_sa
->create_task_enumerator(this->ike_sa
,
150 while (tasks
->enumerate(tasks
, &task
))
152 if (task
->get_type(task
) == TASK_CHILD_REKEY
)
154 child_rekey_t
*rekey
= (child_rekey_t
*)task
;
156 if (rekey
->is_redundant(rekey
, child
))
158 tasks
->destroy(tasks
);
163 tasks
->destroy(tasks
);
168 * Install the outbound CHILD_SA with the given SPI
170 static void install_outbound(private_child_delete_t
*this,
171 protocol_id_t protocol
, uint32_t spi
)
173 child_sa_t
*child_sa
;
174 linked_list_t
*my_ts
, *other_ts
;
177 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
,
181 DBG1(DBG_IKE
, "CHILD_SA not found after rekeying");
184 if (this->initiator
&& is_redundant(this, child_sa
))
185 { /* if we won the rekey collision we don't want to install the
186 * redundant SA created by the peer */
190 status
= child_sa
->install_outbound(child_sa
);
191 if (status
!= SUCCESS
)
193 DBG1(DBG_IKE
, "unable to install outbound IPsec SA (SAD) in kernel");
194 charon
->bus
->alert(charon
->bus
, ALERT_INSTALL_CHILD_SA_FAILED
,
196 /* FIXME: delete the new child_sa? */
200 my_ts
= linked_list_create_from_enumerator(
201 child_sa
->create_ts_enumerator(child_sa
, TRUE
));
202 other_ts
= linked_list_create_from_enumerator(
203 child_sa
->create_ts_enumerator(child_sa
, FALSE
));
205 DBG0(DBG_IKE
, "outbound CHILD_SA %s{%d} established "
206 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
207 child_sa
->get_name(child_sa
),
208 child_sa
->get_unique_id(child_sa
),
209 ntohl(child_sa
->get_spi(child_sa
, TRUE
)),
210 ntohl(child_sa
->get_spi(child_sa
, FALSE
)),
213 my_ts
->destroy(my_ts
);
214 other_ts
->destroy(other_ts
);
218 * read in payloads and find the children to delete
220 static void process_payloads(private_child_delete_t
*this, message_t
*message
)
222 enumerator_t
*payloads
, *spis
;
224 delete_payload_t
*delete_payload
;
226 protocol_id_t protocol
;
227 child_sa_t
*child_sa
;
230 payloads
= message
->create_payload_enumerator(message
);
231 while (payloads
->enumerate(payloads
, &payload
))
233 if (payload
->get_type(payload
) == PLV2_DELETE
)
235 delete_payload
= (delete_payload_t
*)payload
;
236 protocol
= delete_payload
->get_protocol_id(delete_payload
);
237 if (protocol
!= PROTO_ESP
&& protocol
!= PROTO_AH
)
241 spis
= delete_payload
->create_spi_enumerator(delete_payload
);
242 while (spis
->enumerate(spis
, &spi
))
244 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, protocol
,
248 DBG1(DBG_IKE
, "received DELETE for unknown %N CHILD_SA with"
249 " SPI %.8x", protocol_id_names
, protocol
, ntohl(spi
));
252 DBG1(DBG_IKE
, "received DELETE for %N CHILD_SA with SPI %.8x",
253 protocol_id_names
, protocol
, ntohl(spi
));
255 if (this->child_sas
->find_first(this->child_sas
, match_child
,
263 switch (child_sa
->get_state(child_sa
))
266 entry
->rekeyed
= TRUE
;
269 /* already deleted but not yet destroyed, ignore */
271 /* we don't send back a delete if we already initiated
272 * a delete ourself */
273 if (!this->initiator
)
280 /* we reply as usual, rekeying will fail */
281 case CHILD_INSTALLED
:
282 if (!this->initiator
)
284 if (is_redundant(this, child_sa
))
286 entry
->rekeyed
= TRUE
;
290 entry
->check_delete_action
= TRUE
;
297 this->child_sas
->insert_last(this->child_sas
, entry
);
302 payloads
->destroy(payloads
);
306 * destroy the children listed in this->child_sas, reestablish by policy
308 static status_t
destroy_and_reestablish(private_child_delete_t
*this)
310 enumerator_t
*enumerator
;
312 child_sa_t
*child_sa
;
313 child_cfg_t
*child_cfg
;
314 protocol_id_t protocol
;
315 uint32_t spi
, reqid
, rekey_spi
;
317 status_t status
= SUCCESS
;
321 now
= time_monotonic(NULL
);
322 delay
= lib
->settings
->get_int(lib
->settings
, "%s.delete_rekeyed_delay",
323 DELETE_REKEYED_DELAY
, lib
->ns
);
325 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
326 while (enumerator
->enumerate(enumerator
, (void**)&entry
))
328 child_sa
= entry
->child_sa
;
329 child_sa
->set_state(child_sa
, CHILD_DELETED
);
330 /* signal child down event if we weren't rekeying */
331 protocol
= child_sa
->get_protocol(child_sa
);
334 charon
->bus
->child_updown(charon
->bus
, child_sa
, FALSE
);
338 rekey_spi
= child_sa
->get_rekey_spi(child_sa
);
341 install_outbound(this, protocol
, rekey_spi
);
343 /* for rekeyed CHILD_SAs we uninstall the outbound SA but don't
344 * immediately destroy it, by default, so we can process delayed
346 child_sa
->remove_outbound(child_sa
);
347 expire
= child_sa
->get_lifetime(child_sa
, TRUE
);
348 if (delay
&& (!expire
|| ((now
+ delay
) < expire
)))
350 lib
->scheduler
->schedule_job(lib
->scheduler
,
351 (job_t
*)delete_child_sa_job_create_id(
352 child_sa
->get_unique_id(child_sa
)), delay
);
355 else if (now
< expire
)
356 { /* let it expire naturally */
359 /* no delay and no lifetime, destroy it immediately */
361 spi
= child_sa
->get_spi(child_sa
, TRUE
);
362 reqid
= child_sa
->get_reqid(child_sa
);
363 child_cfg
= child_sa
->get_config(child_sa
);
364 child_cfg
->get_ref(child_cfg
);
365 action
= child_sa
->get_close_action(child_sa
);
367 this->ike_sa
->destroy_child_sa(this->ike_sa
, protocol
, spi
);
369 if (entry
->check_delete_action
)
370 { /* enforce child_cfg policy if deleted passively */
374 child_cfg
->get_ref(child_cfg
);
375 status
= this->ike_sa
->initiate(this->ike_sa
, child_cfg
,
379 charon
->traps
->install(charon
->traps
,
380 this->ike_sa
->get_peer_cfg(this->ike_sa
),
387 child_cfg
->destroy(child_cfg
);
388 if (status
!= SUCCESS
)
393 enumerator
->destroy(enumerator
);
398 * send closing signals for all CHILD_SAs over the bus
400 static void log_children(private_child_delete_t
*this)
402 linked_list_t
*my_ts
, *other_ts
;
403 enumerator_t
*enumerator
;
405 child_sa_t
*child_sa
;
406 uint64_t bytes_in
, bytes_out
;
408 enumerator
= this->child_sas
->create_enumerator(this->child_sas
);
409 while (enumerator
->enumerate(enumerator
, (void**)&entry
))
411 child_sa
= entry
->child_sa
;
412 my_ts
= linked_list_create_from_enumerator(
413 child_sa
->create_ts_enumerator(child_sa
, TRUE
));
414 other_ts
= linked_list_create_from_enumerator(
415 child_sa
->create_ts_enumerator(child_sa
, FALSE
));
418 DBG0(DBG_IKE
, "closing expired CHILD_SA %s{%d} "
419 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
420 child_sa
->get_name(child_sa
), child_sa
->get_unique_id(child_sa
),
421 ntohl(child_sa
->get_spi(child_sa
, TRUE
)),
422 ntohl(child_sa
->get_spi(child_sa
, FALSE
)), my_ts
, other_ts
);
426 child_sa
->get_usestats(child_sa
, TRUE
, NULL
, &bytes_in
, NULL
);
427 child_sa
->get_usestats(child_sa
, FALSE
, NULL
, &bytes_out
, NULL
);
429 DBG0(DBG_IKE
, "closing CHILD_SA %s{%d} with SPIs %.8x_i "
430 "(%llu bytes) %.8x_o (%llu bytes) and TS %#R === %#R",
431 child_sa
->get_name(child_sa
), child_sa
->get_unique_id(child_sa
),
432 ntohl(child_sa
->get_spi(child_sa
, TRUE
)), bytes_in
,
433 ntohl(child_sa
->get_spi(child_sa
, FALSE
)), bytes_out
,
436 my_ts
->destroy(my_ts
);
437 other_ts
->destroy(other_ts
);
439 enumerator
->destroy(enumerator
);
442 METHOD(task_t
, build_i
, status_t
,
443 private_child_delete_t
*this, message_t
*message
)
445 child_sa_t
*child_sa
;
448 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, this->protocol
,
451 { /* check if it is an outbound sa */
452 child_sa
= this->ike_sa
->get_child_sa(this->ike_sa
, this->protocol
,
455 { /* child does not exist anymore */
458 /* we work only with the inbound SPI */
459 this->spi
= child_sa
->get_spi(child_sa
, TRUE
);
462 if (child_sa
->get_state(child_sa
) == CHILD_DELETED
)
463 { /* DELETEs for this CHILD_SA were already exchanged, but it was not yet
464 * destroyed to allow delayed packets to get processed */
465 this->ike_sa
->destroy_child_sa(this->ike_sa
, this->protocol
, this->spi
);
466 message
->set_exchange_type(message
, EXCHANGE_TYPE_UNDEFINED
);
471 .child_sa
= child_sa
,
472 .rekeyed
= child_sa
->get_state(child_sa
) == CHILD_REKEYED
,
474 this->child_sas
->insert_last(this->child_sas
, entry
);
476 build_payloads(this, message
);
478 if (!entry
->rekeyed
&& this->expired
)
480 child_cfg_t
*child_cfg
;
482 DBG1(DBG_IKE
, "scheduling CHILD_SA recreate after hard expire");
483 child_cfg
= child_sa
->get_config(child_sa
);
484 this->ike_sa
->queue_task(this->ike_sa
, (task_t
*)
485 child_create_create(this->ike_sa
, child_cfg
->get_ref(child_cfg
),
491 METHOD(task_t
, process_i
, status_t
,
492 private_child_delete_t
*this, message_t
*message
)
494 process_payloads(this, message
);
495 DBG1(DBG_IKE
, "CHILD_SA closed");
496 return destroy_and_reestablish(this);
499 METHOD(task_t
, process_r
, status_t
,
500 private_child_delete_t
*this, message_t
*message
)
502 process_payloads(this, message
);
507 METHOD(task_t
, build_r
, status_t
,
508 private_child_delete_t
*this, message_t
*message
)
510 build_payloads(this, message
);
511 DBG1(DBG_IKE
, "CHILD_SA closed");
512 return destroy_and_reestablish(this);
515 METHOD(task_t
, get_type
, task_type_t
,
516 private_child_delete_t
*this)
518 return TASK_CHILD_DELETE
;
521 METHOD(child_delete_t
, get_child
, child_sa_t
*,
522 private_child_delete_t
*this)
524 child_sa_t
*child_sa
= NULL
;
527 if (this->child_sas
->get_first(this->child_sas
, (void**)&entry
) == SUCCESS
)
529 child_sa
= entry
->child_sa
;
534 METHOD(task_t
, migrate
, void,
535 private_child_delete_t
*this, ike_sa_t
*ike_sa
)
537 this->ike_sa
= ike_sa
;
539 this->child_sas
->destroy_function(this->child_sas
, free
);
540 this->child_sas
= linked_list_create();
543 METHOD(task_t
, destroy
, void,
544 private_child_delete_t
*this)
546 this->child_sas
->destroy_function(this->child_sas
, free
);
551 * Described in header.
553 child_delete_t
*child_delete_create(ike_sa_t
*ike_sa
, protocol_id_t protocol
,
554 uint32_t spi
, bool expired
)
556 private_child_delete_t
*this;
561 .get_type
= _get_type
,
565 .get_child
= _get_child
,
568 .child_sas
= linked_list_create(),
569 .protocol
= protocol
,
574 if (protocol
!= PROTO_NONE
)
576 this->public.task
.build
= _build_i
;
577 this->public.task
.process
= _process_i
;
578 this->initiator
= TRUE
;
582 this->public.task
.build
= _build_r
;
583 this->public.task
.process
= _process_r
;
584 this->initiator
= FALSE
;
586 return &this->public;