2 * Copyright (C) 2008-2019 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * HSR Hochschule fuer Technik Rapperswil
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_create.h"
21 #include <sa/ikev2/keymat_v2.h>
22 #include <crypto/diffie_hellman.h>
23 #include <credentials/certificates/x509.h>
24 #include <encoding/payloads/sa_payload.h>
25 #include <encoding/payloads/ke_payload.h>
26 #include <encoding/payloads/ts_payload.h>
27 #include <encoding/payloads/nonce_payload.h>
28 #include <encoding/payloads/notify_payload.h>
29 #include <encoding/payloads/delete_payload.h>
30 #include <processing/jobs/delete_ike_sa_job.h>
31 #include <processing/jobs/inactivity_job.h>
32 #include <processing/jobs/initiate_tasks_job.h>
34 typedef struct private_child_create_t private_child_create_t
;
37 * Private members of a child_create_t task.
39 struct private_child_create_t
{
42 * Public methods and task_t interface.
44 child_create_t
public;
52 * Are we the initiator?
62 * nonce chosen by peer
72 * config to create the CHILD_SA from
77 * list of proposal candidates
79 linked_list_t
*proposals
;
82 * selected proposal to use for CHILD_SA
87 * traffic selectors for initiators side
92 * traffic selectors for responders side
97 * source of triggering packet
99 traffic_selector_t
*packet_tsi
;
102 * destination of triggering packet
104 traffic_selector_t
*packet_tsr
;
107 * optional diffie hellman exchange
109 diffie_hellman_t
*dh
;
112 * Applying DH public value failed?
117 * group used for DH exchange
119 diffie_hellman_group_t dh_group
;
127 * mode the new CHILD_SA uses (transport/tunnel/beet)
132 * peer accepts TFC padding for this SA
137 * IPComp transform to use
139 ipcomp_transform_t ipcomp
;
142 * IPComp transform proposed or accepted by the other peer
144 ipcomp_transform_t ipcomp_received
;
157 * SPI received in proposal
162 * Own allocated Compression Parameter Index (CPI)
167 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
172 * reqid to use if we are rekeying
177 * Explicit inbound mark value
182 * Explicit outbound mark value
187 * Explicit inbound interface ID to use, if any
192 * Explicit outbound interface ID to use, if any
197 * CHILD_SA which gets established
199 child_sa_t
*child_sa
;
202 * successfully established the CHILD?
207 * whether the CHILD_SA rekeys an existing one
212 * whether we are retrying with another DH group
218 * Schedule a retry if creating the CHILD_SA temporary failed
220 static void schedule_delayed_retry(private_child_create_t
*this)
222 child_create_t
*task
;
225 retry
= RETRY_INTERVAL
- (random() % RETRY_JITTER
);
227 task
= child_create_create(this->ike_sa
,
228 this->config
->get_ref(this->config
), FALSE
,
229 this->packet_tsi
, this->packet_tsr
);
230 task
->use_reqid(task
, this->reqid
);
231 DBG1(DBG_IKE
, "creating CHILD_SA failed, trying again in %d seconds",
233 this->ike_sa
->queue_task_delayed(this->ike_sa
, (task_t
*)task
, retry
);
237 * get the nonce from a message
239 static status_t
get_nonce(message_t
*message
, chunk_t
*nonce
)
241 nonce_payload_t
*payload
;
243 payload
= (nonce_payload_t
*)message
->get_payload(message
, PLV2_NONCE
);
248 *nonce
= payload
->get_nonce(payload
);
253 * generate a new nonce to include in a CREATE_CHILD_SA message
255 static bool generate_nonce(private_child_create_t
*this)
257 this->nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
260 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
263 if (!this->nonceg
->allocate_nonce(this->nonceg
, NONCE_SIZE
,
266 DBG1(DBG_IKE
, "nonce allocation failed");
273 * Check a list of traffic selectors if any selector belongs to host
275 static bool ts_list_is_host(linked_list_t
*list
, host_t
*host
)
277 traffic_selector_t
*ts
;
279 enumerator_t
*enumerator
= list
->create_enumerator(list
);
281 while (is_host
&& enumerator
->enumerate(enumerator
, (void**)&ts
))
283 is_host
= is_host
&& ts
->is_host(ts
, host
);
285 enumerator
->destroy(enumerator
);
292 static bool allocate_spi(private_child_create_t
*this)
294 proposal_t
*proposal
;
298 this->proto
= PROTO_ESP
;
299 /* we just get a SPI for the first protocol. TODO: If we ever support
300 * proposal lists with mixed protocols, we'd need multiple SPIs */
301 if (this->proposals
->get_first(this->proposals
,
302 (void**)&proposal
) == SUCCESS
)
304 this->proto
= proposal
->get_protocol(proposal
);
309 this->proto
= this->proposal
->get_protocol(this->proposal
);
311 this->my_spi
= this->child_sa
->alloc_spi(this->child_sa
, this->proto
);
312 return this->my_spi
!= 0;
316 * Update the proposals with the allocated SPIs as initiator and check the DH
317 * group and promote it if necessary
319 static bool update_and_check_proposals(private_child_create_t
*this)
321 enumerator_t
*enumerator
;
322 proposal_t
*proposal
;
323 linked_list_t
*other_dh_groups
;
326 other_dh_groups
= linked_list_create();
327 enumerator
= this->proposals
->create_enumerator(this->proposals
);
328 while (enumerator
->enumerate(enumerator
, &proposal
))
330 proposal
->set_spi(proposal
, this->my_spi
);
332 /* move the selected DH group to the front, if any */
333 if (this->dh_group
!= MODP_NONE
)
334 { /* proposals that don't contain the selected group are
335 * moved to the back */
336 if (!proposal
->promote_dh_group(proposal
, this->dh_group
))
338 this->proposals
->remove_at(this->proposals
, enumerator
);
339 other_dh_groups
->insert_last(other_dh_groups
, proposal
);
347 enumerator
->destroy(enumerator
);
348 enumerator
= other_dh_groups
->create_enumerator(other_dh_groups
);
349 while (enumerator
->enumerate(enumerator
, (void**)&proposal
))
350 { /* no need to remove from the list as we destroy it anyway*/
351 this->proposals
->insert_last(this->proposals
, proposal
);
353 enumerator
->destroy(enumerator
);
354 other_dh_groups
->destroy(other_dh_groups
);
356 return this->dh_group
== MODP_NONE
|| found
;
360 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
362 static void schedule_inactivity_timeout(private_child_create_t
*this)
364 uint32_t timeout
, id
;
367 timeout
= this->config
->get_inactivity(this->config
);
370 close_ike
= lib
->settings
->get_bool(lib
->settings
,
371 "%s.inactivity_close_ike", FALSE
, lib
->ns
);
372 id
= this->child_sa
->get_unique_id(this->child_sa
);
373 lib
->scheduler
->schedule_job(lib
->scheduler
, (job_t
*)
374 inactivity_job_create(id
, timeout
, close_ike
), timeout
);
379 * Check if we have a an address pool configured
381 static bool have_pool(ike_sa_t
*ike_sa
)
383 enumerator_t
*enumerator
;
384 peer_cfg_t
*peer_cfg
;
388 peer_cfg
= ike_sa
->get_peer_cfg(ike_sa
);
391 enumerator
= peer_cfg
->create_pool_enumerator(peer_cfg
);
392 if (enumerator
->enumerate(enumerator
, &pool
))
396 enumerator
->destroy(enumerator
);
402 * Get hosts to use for dynamic traffic selectors
404 static linked_list_t
*get_dynamic_hosts(ike_sa_t
*ike_sa
, bool local
)
406 enumerator_t
*enumerator
;
410 list
= linked_list_create();
411 enumerator
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, local
);
412 while (enumerator
->enumerate(enumerator
, &host
))
414 list
->insert_last(list
, host
);
416 enumerator
->destroy(enumerator
);
418 if (list
->get_count(list
) == 0)
419 { /* no virtual IPs assigned */
422 host
= ike_sa
->get_my_host(ike_sa
);
423 list
->insert_last(list
, host
);
425 else if (!have_pool(ike_sa
))
426 { /* use host only if we don't have a pool configured */
427 host
= ike_sa
->get_other_host(ike_sa
);
428 list
->insert_last(list
, host
);
435 * Substitute any host address with NATed address in traffic selector
437 static linked_list_t
* get_transport_nat_ts(private_child_create_t
*this,
438 bool local
, linked_list_t
*in
)
440 enumerator_t
*enumerator
;
442 traffic_selector_t
*ts
;
443 host_t
*ike
, *first
= NULL
;
448 ike
= this->ike_sa
->get_my_host(this->ike_sa
);
452 ike
= this->ike_sa
->get_other_host(this->ike_sa
);
455 out
= linked_list_create();
457 enumerator
= in
->create_enumerator(in
);
458 while (enumerator
->enumerate(enumerator
, &ts
))
460 /* require that all selectors match the first "host" selector */
461 if (ts
->is_host(ts
, first
))
465 ts
->to_subnet(ts
, &first
, &mask
);
468 ts
->set_address(ts
, ike
);
469 out
->insert_last(out
, ts
);
472 enumerator
->destroy(enumerator
);
479 * Narrow received traffic selectors with configuration
481 static linked_list_t
* narrow_ts(private_child_create_t
*this, bool local
,
484 linked_list_t
*hosts
, *nat
, *ts
;
485 ike_condition_t cond
;
487 cond
= local
? COND_NAT_HERE
: COND_NAT_THERE
;
488 hosts
= get_dynamic_hosts(this->ike_sa
, local
);
490 if (this->mode
== MODE_TRANSPORT
&&
491 this->ike_sa
->has_condition(this->ike_sa
, cond
))
493 nat
= get_transport_nat_ts(this, local
, in
);
494 ts
= this->config
->get_traffic_selectors(this->config
, local
, nat
,
496 nat
->destroy_offset(nat
, offsetof(traffic_selector_t
, destroy
));
500 ts
= this->config
->get_traffic_selectors(this->config
, local
, in
,
504 hosts
->destroy(hosts
);
510 * Install a CHILD_SA for usage, return value:
511 * - FAILED: no acceptable proposal
512 * - INVALID_ARG: diffie hellman group unacceptable
513 * - NOT_FOUND: TS unacceptable
515 static status_t
select_and_install(private_child_create_t
*this,
516 bool no_dh
, bool ike_auth
)
518 status_t status
, status_i
, status_o
;
519 child_sa_outbound_state_t out_state
;
520 chunk_t nonce_i
, nonce_r
;
521 chunk_t encr_i
= chunk_empty
, encr_r
= chunk_empty
;
522 chunk_t integ_i
= chunk_empty
, integ_r
= chunk_empty
;
523 linked_list_t
*my_ts
, *other_ts
;
525 bool private, prefer_configured
;
527 if (this->proposals
== NULL
)
529 DBG1(DBG_IKE
, "SA payload missing in message");
532 if (this->tsi
== NULL
|| this->tsr
== NULL
)
534 DBG1(DBG_IKE
, "TS payloads missing in message");
538 me
= this->ike_sa
->get_my_host(this->ike_sa
);
539 other
= this->ike_sa
->get_other_host(this->ike_sa
);
541 private = this->ike_sa
->supports_extension(this->ike_sa
, EXT_STRONGSWAN
);
542 prefer_configured
= lib
->settings
->get_bool(lib
->settings
,
543 "%s.prefer_configured_proposals", TRUE
, lib
->ns
);
544 this->proposal
= this->config
->select_proposal(this->config
,
545 this->proposals
, no_dh
, private, prefer_configured
);
546 if (this->proposal
== NULL
)
548 DBG1(DBG_IKE
, "no acceptable proposal found");
549 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_CHILD
,
553 this->other_spi
= this->proposal
->get_spi(this->proposal
);
555 if (!this->initiator
)
557 if (!allocate_spi(this))
559 /* responder has no SPI allocated yet */
560 DBG1(DBG_IKE
, "allocating SPI failed");
563 this->proposal
->set_spi(this->proposal
, this->my_spi
);
565 this->child_sa
->set_proposal(this->child_sa
, this->proposal
);
567 if (!this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
571 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
574 DBG1(DBG_IKE
, "DH group %N unacceptable, requesting %N",
575 diffie_hellman_group_names
, this->dh_group
,
576 diffie_hellman_group_names
, group
);
577 this->dh_group
= group
;
580 /* the selected proposal does not use a DH group */
581 DBG1(DBG_IKE
, "ignoring KE exchange, agreed on a non-PFS proposal");
582 DESTROY_IF(this->dh
);
584 this->dh_group
= MODP_NONE
;
589 nonce_i
= this->my_nonce
;
590 nonce_r
= this->other_nonce
;
591 my_ts
= narrow_ts(this, TRUE
, this->tsi
);
592 other_ts
= narrow_ts(this, FALSE
, this->tsr
);
596 nonce_r
= this->my_nonce
;
597 nonce_i
= this->other_nonce
;
598 my_ts
= narrow_ts(this, TRUE
, this->tsr
);
599 other_ts
= narrow_ts(this, FALSE
, this->tsi
);
606 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
607 NARROW_INITIATOR_POST_NOAUTH
, my_ts
, other_ts
);
611 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
612 NARROW_INITIATOR_POST_AUTH
, my_ts
, other_ts
);
617 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
618 NARROW_RESPONDER
, my_ts
, other_ts
);
621 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
623 charon
->bus
->alert(charon
->bus
, ALERT_TS_MISMATCH
, this->tsi
, this->tsr
);
624 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
625 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
626 DBG1(DBG_IKE
, "no acceptable traffic selectors found");
630 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
631 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
635 this->tsr
= other_ts
;
640 this->tsi
= other_ts
;
643 if (!this->initiator
)
645 /* check if requested mode is acceptable, downgrade if required */
649 if (!this->config
->has_option(this->config
, OPT_PROXY_MODE
) &&
650 (!ts_list_is_host(this->tsi
, other
) ||
651 !ts_list_is_host(this->tsr
, me
))
654 this->mode
= MODE_TUNNEL
;
655 DBG1(DBG_IKE
, "not using transport mode, not host-to-host");
657 if (this->config
->get_mode(this->config
) != MODE_TRANSPORT
)
659 this->mode
= MODE_TUNNEL
;
663 if (!ts_list_is_host(this->tsi
, NULL
) ||
664 !ts_list_is_host(this->tsr
, NULL
))
666 this->mode
= MODE_TUNNEL
;
667 DBG1(DBG_IKE
, "not using BEET mode, not host-to-host");
669 if (this->config
->get_mode(this->config
) != MODE_BEET
)
671 this->mode
= MODE_TUNNEL
;
677 /* use a copy of the traffic selectors, as the POST hook should not
679 my_ts
= this->tsr
->clone_offset(this->tsr
,
680 offsetof(traffic_selector_t
, clone
));
681 other_ts
= this->tsi
->clone_offset(this->tsi
,
682 offsetof(traffic_selector_t
, clone
));
683 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
684 NARROW_RESPONDER_POST
, my_ts
, other_ts
);
686 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
688 my_ts
->destroy_offset(my_ts
,
689 offsetof(traffic_selector_t
, destroy
));
690 other_ts
->destroy_offset(other_ts
,
691 offsetof(traffic_selector_t
, destroy
));
696 this->child_sa
->set_policies(this->child_sa
, my_ts
, other_ts
);
697 if (!this->initiator
)
699 my_ts
->destroy_offset(my_ts
,
700 offsetof(traffic_selector_t
, destroy
));
701 other_ts
->destroy_offset(other_ts
,
702 offsetof(traffic_selector_t
, destroy
));
705 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLING
);
706 this->child_sa
->set_ipcomp(this->child_sa
, this->ipcomp
);
707 this->child_sa
->set_mode(this->child_sa
, this->mode
);
708 this->child_sa
->set_protocol(this->child_sa
,
709 this->proposal
->get_protocol(this->proposal
));
711 if (this->my_cpi
== 0 || this->other_cpi
== 0 || this->ipcomp
== IPCOMP_NONE
)
713 this->my_cpi
= this->other_cpi
= 0;
714 this->ipcomp
= IPCOMP_NONE
;
716 status_i
= status_o
= FAILED
;
717 if (this->keymat
->derive_child_keys(this->keymat
, this->proposal
,
718 this->dh
, nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
))
722 status_i
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
723 this->my_spi
, this->my_cpi
, this->initiator
,
728 status_i
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
729 this->my_spi
, this->my_cpi
, this->initiator
,
733 { /* during rekeyings we install the outbound SA and/or policies
734 * separately: as responder when we receive the delete for the old
735 * SA, as initiator pretty much immediately in the ike-rekey task,
736 * unless there was a rekey collision that we lost */
739 status_o
= this->child_sa
->register_outbound(this->child_sa
,
740 encr_i
, integ_i
, this->other_spi
, this->other_cpi
,
745 status_o
= this->child_sa
->register_outbound(this->child_sa
,
746 encr_r
, integ_r
, this->other_spi
, this->other_cpi
,
750 else if (this->initiator
)
752 status_o
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
753 this->other_spi
, this->other_cpi
, this->initiator
,
758 status_o
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
759 this->other_spi
, this->other_cpi
, this->initiator
,
764 if (status_i
!= SUCCESS
|| status_o
!= SUCCESS
)
766 DBG1(DBG_IKE
, "unable to install %s%s%sIPsec SA (SAD) in kernel",
767 (status_i
!= SUCCESS
) ? "inbound " : "",
768 (status_i
!= SUCCESS
&& status_o
!= SUCCESS
) ? "and ": "",
769 (status_o
!= SUCCESS
) ? "outbound " : "");
770 charon
->bus
->alert(charon
->bus
, ALERT_INSTALL_CHILD_SA_FAILED
,
776 status
= this->child_sa
->install_policies(this->child_sa
);
778 if (status
!= SUCCESS
)
780 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
781 charon
->bus
->alert(charon
->bus
, ALERT_INSTALL_CHILD_POLICY_FAILED
,
787 charon
->bus
->child_derived_keys(charon
->bus
, this->child_sa
,
788 this->initiator
, encr_i
, encr_r
,
792 chunk_clear(&integ_i
);
793 chunk_clear(&integ_r
);
794 chunk_clear(&encr_i
);
795 chunk_clear(&encr_r
);
797 if (status
!= SUCCESS
)
802 charon
->bus
->child_keys(charon
->bus
, this->child_sa
, this->initiator
,
803 this->dh
, nonce_i
, nonce_r
);
805 my_ts
= linked_list_create_from_enumerator(
806 this->child_sa
->create_ts_enumerator(this->child_sa
, TRUE
));
807 other_ts
= linked_list_create_from_enumerator(
808 this->child_sa
->create_ts_enumerator(this->child_sa
, FALSE
));
809 out_state
= this->child_sa
->get_outbound_state(this->child_sa
);
811 DBG0(DBG_IKE
, "%sCHILD_SA %s{%d} established "
812 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
813 (out_state
== CHILD_OUTBOUND_INSTALLED
) ? "" : "inbound ",
814 this->child_sa
->get_name(this->child_sa
),
815 this->child_sa
->get_unique_id(this->child_sa
),
816 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
817 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
820 my_ts
->destroy(my_ts
);
821 other_ts
->destroy(other_ts
);
823 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
824 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
825 this->established
= TRUE
;
827 schedule_inactivity_timeout(this);
832 * build the payloads for the message
834 static bool build_payloads(private_child_create_t
*this, message_t
*message
)
836 sa_payload_t
*sa_payload
;
837 nonce_payload_t
*nonce_payload
;
838 ke_payload_t
*ke_payload
;
839 ts_payload_t
*ts_payload
;
840 kernel_feature_t features
;
845 sa_payload
= sa_payload_create_from_proposals_v2(this->proposals
);
849 sa_payload
= sa_payload_create_from_proposal_v2(this->proposal
);
851 message
->add_payload(message
, (payload_t
*)sa_payload
);
853 /* add nonce payload if not in IKE_AUTH */
854 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
856 nonce_payload
= nonce_payload_create(PLV2_NONCE
);
857 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
858 message
->add_payload(message
, (payload_t
*)nonce_payload
);
861 /* diffie hellman exchange, if PFS enabled */
864 ke_payload
= ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE
,
868 DBG1(DBG_IKE
, "creating KE payload failed");
871 message
->add_payload(message
, (payload_t
*)ke_payload
);
874 /* add TSi/TSr payloads */
875 ts_payload
= ts_payload_create_from_traffic_selectors(TRUE
, this->tsi
);
876 message
->add_payload(message
, (payload_t
*)ts_payload
);
877 ts_payload
= ts_payload_create_from_traffic_selectors(FALSE
, this->tsr
);
878 message
->add_payload(message
, (payload_t
*)ts_payload
);
880 /* add a notify if we are not in tunnel mode */
884 message
->add_notify(message
, FALSE
, USE_TRANSPORT_MODE
, chunk_empty
);
887 message
->add_notify(message
, FALSE
, USE_BEET_MODE
, chunk_empty
);
893 features
= charon
->kernel
->get_features(charon
->kernel
);
894 if (!(features
& KERNEL_ESP_V3_TFC
))
896 message
->add_notify(message
, FALSE
, ESP_TFC_PADDING_NOT_SUPPORTED
,
903 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
905 static void add_ipcomp_notify(private_child_create_t
*this,
906 message_t
*message
, uint8_t ipcomp
)
908 this->my_cpi
= this->child_sa
->alloc_cpi(this->child_sa
);
911 this->ipcomp
= ipcomp
;
912 message
->add_notify(message
, FALSE
, IPCOMP_SUPPORTED
,
913 chunk_cata("cc", chunk_from_thing(this->my_cpi
),
914 chunk_from_thing(ipcomp
)));
918 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, IPComp disabled");
923 * handle a received notify payload
925 static void handle_notify(private_child_create_t
*this, notify_payload_t
*notify
)
927 switch (notify
->get_notify_type(notify
))
929 case USE_TRANSPORT_MODE
:
930 this->mode
= MODE_TRANSPORT
;
933 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_STRONGSWAN
))
934 { /* handle private use notify only if we know its meaning */
935 this->mode
= MODE_BEET
;
939 DBG1(DBG_IKE
, "received a notify strongSwan uses for BEET "
940 "mode, but peer implementation unknown, skipped");
943 case IPCOMP_SUPPORTED
:
945 ipcomp_transform_t ipcomp
;
949 data
= notify
->get_notification_data(notify
);
950 cpi
= *(uint16_t*)data
.ptr
;
951 ipcomp
= (ipcomp_transform_t
)(*(data
.ptr
+ 2));
955 this->other_cpi
= cpi
;
956 this->ipcomp_received
= ipcomp
;
961 DBG1(DBG_IKE
, "received IPCOMP_SUPPORTED notify with a "
962 "transform ID we don't support %N",
963 ipcomp_transform_names
, ipcomp
);
968 case ESP_TFC_PADDING_NOT_SUPPORTED
:
969 DBG1(DBG_IKE
, "received %N, not using ESPv3 TFC padding",
970 notify_type_names
, notify
->get_notify_type(notify
));
979 * Read payloads from message
981 static void process_payloads(private_child_create_t
*this, message_t
*message
)
983 enumerator_t
*enumerator
;
985 sa_payload_t
*sa_payload
;
986 ke_payload_t
*ke_payload
;
987 ts_payload_t
*ts_payload
;
989 /* defaults to TUNNEL mode */
990 this->mode
= MODE_TUNNEL
;
992 enumerator
= message
->create_payload_enumerator(message
);
993 while (enumerator
->enumerate(enumerator
, &payload
))
995 switch (payload
->get_type(payload
))
997 case PLV2_SECURITY_ASSOCIATION
:
998 sa_payload
= (sa_payload_t
*)payload
;
999 this->proposals
= sa_payload
->get_proposals(sa_payload
);
1001 case PLV2_KEY_EXCHANGE
:
1002 ke_payload
= (ke_payload_t
*)payload
;
1003 if (!this->initiator
)
1005 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
1006 this->dh
= this->keymat
->keymat
.create_dh(
1007 &this->keymat
->keymat
, this->dh_group
);
1011 this->dh_failed
= this->dh
->get_dh_group(this->dh
) !=
1012 ke_payload
->get_dh_group_number(ke_payload
);
1014 if (this->dh
&& !this->dh_failed
)
1016 this->dh_failed
= !this->dh
->set_other_public_value(this->dh
,
1017 ke_payload
->get_key_exchange_data(ke_payload
));
1020 case PLV2_TS_INITIATOR
:
1021 ts_payload
= (ts_payload_t
*)payload
;
1022 this->tsi
= ts_payload
->get_traffic_selectors(ts_payload
);
1024 case PLV2_TS_RESPONDER
:
1025 ts_payload
= (ts_payload_t
*)payload
;
1026 this->tsr
= ts_payload
->get_traffic_selectors(ts_payload
);
1029 handle_notify(this, (notify_payload_t
*)payload
);
1035 enumerator
->destroy(enumerator
);
1038 METHOD(task_t
, build_i
, status_t
,
1039 private_child_create_t
*this, message_t
*message
)
1041 enumerator_t
*enumerator
;
1043 peer_cfg_t
*peer_cfg
;
1044 linked_list_t
*list
;
1046 switch (message
->get_exchange_type(message
))
1049 return get_nonce(message
, &this->my_nonce
);
1050 case CREATE_CHILD_SA
:
1051 if (!generate_nonce(this))
1053 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
1057 if (!this->retry
&& this->dh_group
== MODP_NONE
)
1058 { /* during a rekeying the group might already be set */
1059 this->dh_group
= this->config
->get_dh_group(this->config
);
1063 if (message
->get_message_id(message
) != 1)
1065 /* send only in the first request, not in subsequent rounds */
1073 /* check if we want a virtual IP, but don't have one */
1074 list
= linked_list_create();
1075 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
1078 enumerator
= peer_cfg
->create_virtual_ip_enumerator(peer_cfg
);
1079 while (enumerator
->enumerate(enumerator
, &vip
))
1081 /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
1082 vip
= host_create_any(vip
->get_family(vip
));
1083 list
->insert_last(list
, vip
);
1085 enumerator
->destroy(enumerator
);
1087 if (list
->get_count(list
))
1089 this->tsi
= this->config
->get_traffic_selectors(this->config
,
1090 TRUE
, NULL
, list
, TRUE
);
1091 list
->destroy_offset(list
, offsetof(host_t
, destroy
));
1094 { /* no virtual IPs configured */
1095 list
->destroy(list
);
1096 list
= get_dynamic_hosts(this->ike_sa
, TRUE
);
1097 this->tsi
= this->config
->get_traffic_selectors(this->config
,
1098 TRUE
, NULL
, list
, TRUE
);
1099 list
->destroy(list
);
1101 list
= get_dynamic_hosts(this->ike_sa
, FALSE
);
1102 this->tsr
= this->config
->get_traffic_selectors(this->config
,
1103 FALSE
, NULL
, list
, TRUE
);
1104 list
->destroy(list
);
1106 if (this->packet_tsi
)
1108 this->tsi
->insert_first(this->tsi
,
1109 this->packet_tsi
->clone(this->packet_tsi
));
1111 if (this->packet_tsr
)
1113 this->tsr
->insert_first(this->tsr
,
1114 this->packet_tsr
->clone(this->packet_tsr
));
1116 this->proposals
= this->config
->get_proposals(this->config
,
1117 this->dh_group
== MODP_NONE
);
1118 this->mode
= this->config
->get_mode(this->config
);
1120 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
1121 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
1122 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
),
1123 this->mark_in
, this->mark_out
, this->if_id_in
, this->if_id_out
);
1127 DBG0(DBG_IKE
, "establishing CHILD_SA %s{%d} reqid %d",
1128 this->child_sa
->get_name(this->child_sa
),
1129 this->child_sa
->get_unique_id(this->child_sa
), this->reqid
);
1133 DBG0(DBG_IKE
, "establishing CHILD_SA %s{%d}",
1134 this->child_sa
->get_name(this->child_sa
),
1135 this->child_sa
->get_unique_id(this->child_sa
));
1138 if (!allocate_spi(this))
1140 DBG1(DBG_IKE
, "unable to allocate SPIs from kernel");
1144 if (!update_and_check_proposals(this))
1146 DBG1(DBG_IKE
, "requested DH group %N not contained in any of our "
1148 diffie_hellman_group_names
, this->dh_group
);
1152 if (this->dh_group
!= MODP_NONE
)
1154 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
1158 if (this->config
->has_option(this->config
, OPT_IPCOMP
))
1160 /* IPCOMP_DEFLATE is the only transform we support at the moment */
1161 add_ipcomp_notify(this, message
, IPCOMP_DEFLATE
);
1164 if (message
->get_exchange_type(message
) == IKE_AUTH
)
1166 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
1167 NARROW_INITIATOR_PRE_NOAUTH
, this->tsi
, this->tsr
);
1171 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
1172 NARROW_INITIATOR_PRE_AUTH
, this->tsi
, this->tsr
);
1175 if (!build_payloads(this, message
))
1180 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1181 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1182 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1185 this->proposals
= NULL
;
1190 METHOD(task_t
, process_r
, status_t
,
1191 private_child_create_t
*this, message_t
*message
)
1193 switch (message
->get_exchange_type(message
))
1196 return get_nonce(message
, &this->other_nonce
);
1197 case CREATE_CHILD_SA
:
1198 get_nonce(message
, &this->other_nonce
);
1201 if (message
->get_message_id(message
) != 1)
1203 /* only handle first AUTH payload, not additional rounds */
1210 process_payloads(this, message
);
1216 * handle CHILD_SA setup failure
1218 static void handle_child_sa_failure(private_child_create_t
*this,
1223 is_first
= message
->get_exchange_type(message
) == IKE_AUTH
;
1225 lib
->settings
->get_bool(lib
->settings
,
1226 "%s.close_ike_on_child_failure", FALSE
, lib
->ns
))
1228 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
1230 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
1231 lib
->scheduler
->schedule_job_ms(lib
->scheduler
, (job_t
*)
1232 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
1237 DBG1(DBG_IKE
, "failed to establish CHILD_SA, keeping IKE_SA");
1238 charon
->bus
->alert(charon
->bus
, ALERT_KEEP_ON_CHILD_SA_FAILURE
,
1244 * Substitute transport mode NAT selectors, if applicable
1246 static linked_list_t
* get_ts_if_nat_transport(private_child_create_t
*this,
1247 bool local
, linked_list_t
*in
)
1249 linked_list_t
*out
= NULL
;
1250 ike_condition_t cond
;
1252 if (this->mode
== MODE_TRANSPORT
)
1254 cond
= local
? COND_NAT_HERE
: COND_NAT_THERE
;
1255 if (this->ike_sa
->has_condition(this->ike_sa
, cond
))
1257 out
= get_transport_nat_ts(this, local
, in
);
1258 if (out
->get_count(out
) == 0)
1269 * Select a matching CHILD config as responder
1271 static child_cfg_t
* select_child_cfg(private_child_create_t
*this)
1273 peer_cfg_t
*peer_cfg
;
1274 child_cfg_t
*child_cfg
= NULL
;;
1276 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
1277 if (peer_cfg
&& this->tsi
&& this->tsr
)
1279 linked_list_t
*listr
, *listi
, *tsr
, *tsi
;
1281 tsr
= get_ts_if_nat_transport(this, TRUE
, this->tsr
);
1282 tsi
= get_ts_if_nat_transport(this, FALSE
, this->tsi
);
1284 listr
= get_dynamic_hosts(this->ike_sa
, TRUE
);
1285 listi
= get_dynamic_hosts(this->ike_sa
, FALSE
);
1286 child_cfg
= peer_cfg
->select_child_cfg(peer_cfg
,
1287 tsr
?: this->tsr
, tsi
?: this->tsi
,
1289 if ((tsi
|| tsr
) && child_cfg
&&
1290 child_cfg
->get_mode(child_cfg
) != MODE_TRANSPORT
)
1292 /* found a CHILD config, but it doesn't use transport mode */
1293 child_cfg
->destroy(child_cfg
);
1296 if (!child_cfg
&& (tsi
|| tsr
))
1298 /* no match for the substituted NAT selectors, try it without */
1299 child_cfg
= peer_cfg
->select_child_cfg(peer_cfg
,
1300 this->tsr
, this->tsi
, listr
, listi
);
1302 listr
->destroy(listr
);
1303 listi
->destroy(listi
);
1304 DESTROY_OFFSET_IF(tsi
, offsetof(traffic_selector_t
, destroy
));
1305 DESTROY_OFFSET_IF(tsr
, offsetof(traffic_selector_t
, destroy
));
1311 METHOD(task_t
, build_r
, status_t
,
1312 private_child_create_t
*this, message_t
*message
)
1315 enumerator_t
*enumerator
;
1316 bool no_dh
= TRUE
, ike_auth
= FALSE
;
1318 switch (message
->get_exchange_type(message
))
1321 return get_nonce(message
, &this->my_nonce
);
1322 case CREATE_CHILD_SA
:
1323 if (!generate_nonce(this))
1325 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
1329 if (this->dh_failed
)
1331 DBG1(DBG_IKE
, "applying DH public value failed");
1332 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
1339 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
1340 { /* wait until all authentication round completed */
1343 if (this->ike_sa
->has_condition(this->ike_sa
, COND_REDIRECTED
))
1344 { /* no CHILD_SA is created for redirected SAs */
1352 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
1354 DBG1(DBG_IKE
, "unable to create CHILD_SA while rekeying IKE_SA");
1355 message
->add_notify(message
, TRUE
, TEMPORARY_FAILURE
, chunk_empty
);
1358 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_DELETING
)
1360 DBG1(DBG_IKE
, "unable to create CHILD_SA while deleting IKE_SA");
1361 message
->add_notify(message
, TRUE
, TEMPORARY_FAILURE
, chunk_empty
);
1365 if (this->config
== NULL
)
1367 this->config
= select_child_cfg(this);
1369 if (this->config
== NULL
)
1371 DBG1(DBG_IKE
, "traffic selectors %#R === %#R unacceptable",
1372 this->tsr
, this->tsi
);
1373 charon
->bus
->alert(charon
->bus
, ALERT_TS_MISMATCH
, this->tsi
, this->tsr
);
1374 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
1375 handle_child_sa_failure(this, message
);
1379 /* check if ike_config_t included non-critical error notifies */
1380 enumerator
= message
->create_payload_enumerator(message
);
1381 while (enumerator
->enumerate(enumerator
, &payload
))
1383 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
1385 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
1387 switch (notify
->get_notify_type(notify
))
1389 case INTERNAL_ADDRESS_FAILURE
:
1390 case FAILED_CP_REQUIRED
:
1392 DBG1(DBG_IKE
,"configuration payload negotiation "
1393 "failed, no CHILD_SA built");
1394 enumerator
->destroy(enumerator
);
1395 handle_child_sa_failure(this, message
);
1403 enumerator
->destroy(enumerator
);
1405 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
1406 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
1407 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
),
1408 this->mark_in
, this->mark_out
, this->if_id_in
, this->if_id_out
);
1410 if (this->ipcomp_received
!= IPCOMP_NONE
)
1412 if (this->config
->has_option(this->config
, OPT_IPCOMP
))
1414 add_ipcomp_notify(this, message
, this->ipcomp_received
);
1418 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
1419 notify_type_names
, IPCOMP_SUPPORTED
);
1423 switch (select_and_install(this, no_dh
, ike_auth
))
1428 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
1429 handle_child_sa_failure(this, message
);
1433 uint16_t group
= htons(this->dh_group
);
1434 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
1435 chunk_from_thing(group
));
1440 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1441 handle_child_sa_failure(this, message
);
1445 if (!build_payloads(this, message
))
1447 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1448 handle_child_sa_failure(this, message
);
1453 { /* invoke the child_up() hook if we are not rekeying */
1454 charon
->bus
->child_updown(charon
->bus
, this->child_sa
, TRUE
);
1460 * Raise alerts for received notify errors
1462 static void raise_alerts(private_child_create_t
*this, notify_type_t type
)
1464 linked_list_t
*list
;
1468 case NO_PROPOSAL_CHOSEN
:
1469 list
= this->config
->get_proposals(this->config
, FALSE
);
1470 charon
->bus
->alert(charon
->bus
, ALERT_PROPOSAL_MISMATCH_CHILD
, list
);
1471 list
->destroy_offset(list
, offsetof(proposal_t
, destroy
));
1478 METHOD(task_t
, build_i_delete
, status_t
,
1479 private_child_create_t
*this, message_t
*message
)
1481 message
->set_exchange_type(message
, INFORMATIONAL
);
1482 if (this->my_spi
&& this->proto
)
1484 delete_payload_t
*del
;
1486 del
= delete_payload_create(PLV2_DELETE
, this->proto
);
1487 del
->add_spi(del
, this->my_spi
);
1488 message
->add_payload(message
, (payload_t
*)del
);
1490 DBG1(DBG_IKE
, "sending DELETE for %N CHILD_SA with SPI %.8x",
1491 protocol_id_names
, this->proto
, ntohl(this->my_spi
));
1497 * Change task to delete the failed CHILD_SA as initiator
1499 static status_t
delete_failed_sa(private_child_create_t
*this)
1501 if (this->my_spi
&& this->proto
)
1503 this->public.task
.build
= _build_i_delete
;
1504 this->public.task
.process
= (void*)return_success
;
1510 METHOD(task_t
, process_i
, status_t
,
1511 private_child_create_t
*this, message_t
*message
)
1513 enumerator_t
*enumerator
;
1515 bool no_dh
= TRUE
, ike_auth
= FALSE
;
1517 switch (message
->get_exchange_type(message
))
1520 return get_nonce(message
, &this->other_nonce
);
1521 case CREATE_CHILD_SA
:
1522 get_nonce(message
, &this->other_nonce
);
1526 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
1527 { /* wait until all authentication round completed */
1535 /* check for erroneous notifies */
1536 enumerator
= message
->create_payload_enumerator(message
);
1537 while (enumerator
->enumerate(enumerator
, &payload
))
1539 if (payload
->get_type(payload
) == PLV2_NOTIFY
)
1541 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
1542 notify_type_t type
= notify
->get_notify_type(notify
);
1546 /* handle notify errors related to CHILD_SA only */
1547 case NO_PROPOSAL_CHOSEN
:
1548 case SINGLE_PAIR_REQUIRED
:
1549 case NO_ADDITIONAL_SAS
:
1550 case INTERNAL_ADDRESS_FAILURE
:
1551 case FAILED_CP_REQUIRED
:
1552 case TS_UNACCEPTABLE
:
1553 case INVALID_SELECTORS
:
1555 DBG1(DBG_IKE
, "received %N notify, no CHILD_SA built",
1556 notify_type_names
, type
);
1557 enumerator
->destroy(enumerator
);
1558 raise_alerts(this, type
);
1559 handle_child_sa_failure(this, message
);
1560 /* an error in CHILD_SA creation is not critical */
1563 case TEMPORARY_FAILURE
:
1565 DBG1(DBG_IKE
, "received %N notify, will retry later",
1566 notify_type_names
, type
);
1567 enumerator
->destroy(enumerator
);
1569 { /* the rekey task will retry itself if necessary */
1570 schedule_delayed_retry(this);
1574 case INVALID_KE_PAYLOAD
:
1577 uint16_t group
= MODP_NONE
;
1579 data
= notify
->get_notification_data(notify
);
1580 if (data
.len
== sizeof(group
))
1582 memcpy(&group
, data
.ptr
, data
.len
);
1583 group
= ntohs(group
);
1587 DBG1(DBG_IKE
, "already retried with DH group %N, "
1588 "ignore requested %N", diffie_hellman_group_names
,
1589 this->dh_group
, diffie_hellman_group_names
, group
);
1590 handle_child_sa_failure(this, message
);
1591 /* an error in CHILD_SA creation is not critical */
1594 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
1595 "it requested %N", diffie_hellman_group_names
,
1596 this->dh_group
, diffie_hellman_group_names
, group
);
1598 this->dh_group
= group
;
1599 this->child_sa
->set_state(this->child_sa
, CHILD_RETRYING
);
1600 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
1601 enumerator
->destroy(enumerator
);
1606 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
1607 { /* handle notifies if not handled in IKE_AUTH */
1610 DBG1(DBG_IKE
, "received %N notify error",
1611 notify_type_names
, type
);
1612 enumerator
->destroy(enumerator
);
1615 DBG2(DBG_IKE
, "received %N notify",
1616 notify_type_names
, type
);
1623 enumerator
->destroy(enumerator
);
1625 process_payloads(this, message
);
1627 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
1629 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify without requesting"
1630 " one, no CHILD_SA built");
1631 handle_child_sa_failure(this, message
);
1632 return delete_failed_sa(this);
1634 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
1636 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
1637 "IPComp is disabled");
1638 this->ipcomp
= IPCOMP_NONE
;
1640 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
1642 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1643 "no CHILD_SA built");
1644 handle_child_sa_failure(this, message
);
1645 return delete_failed_sa(this);
1648 if (this->dh_failed
)
1650 DBG1(DBG_IKE
, "applying DH public value failed");
1651 handle_child_sa_failure(this, message
);
1652 return delete_failed_sa(this);
1655 if (select_and_install(this, no_dh
, ike_auth
) == SUCCESS
)
1658 { /* invoke the child_up() hook if we are not rekeying */
1659 charon
->bus
->child_updown(charon
->bus
, this->child_sa
, TRUE
);
1664 handle_child_sa_failure(this, message
);
1665 return delete_failed_sa(this);
1670 METHOD(child_create_t
, use_reqid
, void,
1671 private_child_create_t
*this, uint32_t reqid
)
1673 this->reqid
= reqid
;
1676 METHOD(child_create_t
, use_marks
, void,
1677 private_child_create_t
*this, uint32_t in
, uint32_t out
)
1680 this->mark_out
= out
;
1683 METHOD(child_create_t
, use_if_ids
, void,
1684 private_child_create_t
*this, uint32_t in
, uint32_t out
)
1686 this->if_id_in
= in
;
1687 this->if_id_out
= out
;
1690 METHOD(child_create_t
, use_dh_group
, void,
1691 private_child_create_t
*this, diffie_hellman_group_t dh_group
)
1693 this->dh_group
= dh_group
;
1696 METHOD(child_create_t
, get_child
, child_sa_t
*,
1697 private_child_create_t
*this)
1699 return this->child_sa
;
1702 METHOD(child_create_t
, set_config
, void,
1703 private_child_create_t
*this, child_cfg_t
*cfg
)
1705 DESTROY_IF(this->config
);
1709 METHOD(child_create_t
, get_lower_nonce
, chunk_t
,
1710 private_child_create_t
*this)
1712 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1713 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1715 return this->my_nonce
;
1719 return this->other_nonce
;
1723 METHOD(task_t
, get_type
, task_type_t
,
1724 private_child_create_t
*this)
1726 return TASK_CHILD_CREATE
;
1729 METHOD(task_t
, migrate
, void,
1730 private_child_create_t
*this, ike_sa_t
*ike_sa
)
1732 chunk_free(&this->my_nonce
);
1733 chunk_free(&this->other_nonce
);
1736 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1740 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1742 DESTROY_IF(this->child_sa
);
1743 DESTROY_IF(this->proposal
);
1744 DESTROY_IF(this->nonceg
);
1745 DESTROY_IF(this->dh
);
1746 this->dh_failed
= FALSE
;
1747 if (this->proposals
)
1749 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1752 this->ike_sa
= ike_sa
;
1753 this->keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
1754 this->proposal
= NULL
;
1755 this->proposals
= NULL
;
1759 this->nonceg
= NULL
;
1760 this->child_sa
= NULL
;
1761 this->mode
= MODE_TUNNEL
;
1762 this->ipcomp
= IPCOMP_NONE
;
1763 this->ipcomp_received
= IPCOMP_NONE
;
1764 this->other_cpi
= 0;
1769 this->if_id_out
= 0;
1770 this->established
= FALSE
;
1773 METHOD(task_t
, destroy
, void,
1774 private_child_create_t
*this)
1776 chunk_free(&this->my_nonce
);
1777 chunk_free(&this->other_nonce
);
1780 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1784 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1786 if (!this->established
)
1788 DESTROY_IF(this->child_sa
);
1790 DESTROY_IF(this->packet_tsi
);
1791 DESTROY_IF(this->packet_tsr
);
1792 DESTROY_IF(this->proposal
);
1793 DESTROY_IF(this->dh
);
1794 if (this->proposals
)
1796 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1798 DESTROY_IF(this->config
);
1799 DESTROY_IF(this->nonceg
);
1804 * Described in header.
1806 child_create_t
*child_create_create(ike_sa_t
*ike_sa
,
1807 child_cfg_t
*config
, bool rekey
,
1808 traffic_selector_t
*tsi
, traffic_selector_t
*tsr
)
1810 private_child_create_t
*this;
1814 .get_child
= _get_child
,
1815 .set_config
= _set_config
,
1816 .get_lower_nonce
= _get_lower_nonce
,
1817 .use_reqid
= _use_reqid
,
1818 .use_marks
= _use_marks
,
1819 .use_if_ids
= _use_if_ids
,
1820 .use_dh_group
= _use_dh_group
,
1822 .get_type
= _get_type
,
1823 .migrate
= _migrate
,
1824 .destroy
= _destroy
,
1829 .packet_tsi
= tsi
? tsi
->clone(tsi
) : NULL
,
1830 .packet_tsr
= tsr
? tsr
->clone(tsr
) : NULL
,
1831 .dh_group
= MODP_NONE
,
1832 .keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
),
1833 .mode
= MODE_TUNNEL
,
1835 .ipcomp
= IPCOMP_NONE
,
1836 .ipcomp_received
= IPCOMP_NONE
,
1843 this->public.task
.build
= _build_i
;
1844 this->public.task
.process
= _process_i
;
1845 this->initiator
= TRUE
;
1849 this->public.task
.build
= _build_r
;
1850 this->public.task
.process
= _process_r
;
1851 this->initiator
= FALSE
;
1853 return &this->public;