2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * 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 <processing/jobs/delete_ike_sa_job.h>
30 #include <processing/jobs/inactivity_job.h>
33 typedef struct private_child_create_t private_child_create_t
;
36 * Private members of a child_create_t task.
38 struct private_child_create_t
{
41 * Public methods and task_t interface.
43 child_create_t
public;
51 * Are we the initiator?
61 * nonce chosen by peer
66 * config to create the CHILD_SA from
71 * list of proposal candidates
73 linked_list_t
*proposals
;
76 * selected proposal to use for CHILD_SA
81 * traffic selectors for initiators side
86 * traffic selectors for responders side
91 * source of triggering packet
93 traffic_selector_t
*packet_tsi
;
96 * destination of triggering packet
98 traffic_selector_t
*packet_tsr
;
101 * optional diffie hellman exchange
103 diffie_hellman_t
*dh
;
106 * group used for DH exchange
108 diffie_hellman_group_t dh_group
;
116 * mode the new CHILD_SA uses (transport/tunnel/beet)
121 * peer accepts TFC padding for this SA
126 * IPComp transform to use
128 ipcomp_transform_t ipcomp
;
131 * IPComp transform proposed or accepted by the other peer
133 ipcomp_transform_t ipcomp_received
;
141 * SPI received in proposal
146 * Own allocated Compression Parameter Index (CPI)
151 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
156 * reqid to use if we are rekeying
161 * CHILD_SA which gets established
163 child_sa_t
*child_sa
;
166 * successfully established the CHILD?
171 * whether the CHILD_SA rekeys an existing one
176 * whether we are retrying with another DH group
182 * get the nonce from a message
184 static status_t
get_nonce(message_t
*message
, chunk_t
*nonce
)
186 nonce_payload_t
*payload
;
188 payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
193 *nonce
= payload
->get_nonce(payload
);
198 * generate a new nonce to include in a CREATE_CHILD_SA message
200 static status_t
generate_nonce(private_child_create_t
*this)
204 nonceg
= this->keymat
->keymat
.create_nonce_gen(&this->keymat
->keymat
);
207 DBG1(DBG_IKE
, "no nonce generator found to create nonce");
210 if (!nonceg
->allocate_nonce(nonceg
, NONCE_SIZE
, &this->my_nonce
))
212 DBG1(DBG_IKE
, "nonce allocation failed");
213 nonceg
->destroy(nonceg
);
216 nonceg
->destroy(nonceg
);
222 * Check a list of traffic selectors if any selector belongs to host
224 static bool ts_list_is_host(linked_list_t
*list
, host_t
*host
)
226 traffic_selector_t
*ts
;
228 enumerator_t
*enumerator
= list
->create_enumerator(list
);
230 while (is_host
&& enumerator
->enumerate(enumerator
, (void**)&ts
))
232 is_host
= is_host
&& ts
->is_host(ts
, host
);
234 enumerator
->destroy(enumerator
);
239 * Allocate SPIs and update proposals
241 static bool allocate_spi(private_child_create_t
*this)
243 enumerator_t
*enumerator
;
244 proposal_t
*proposal
;
246 /* TODO: allocate additional SPI for AH if we have such proposals */
247 this->my_spi
= this->child_sa
->alloc_spi(this->child_sa
, PROTO_ESP
);
252 enumerator
= this->proposals
->create_enumerator(this->proposals
);
253 while (enumerator
->enumerate(enumerator
, &proposal
))
255 proposal
->set_spi(proposal
, this->my_spi
);
257 enumerator
->destroy(enumerator
);
261 this->proposal
->set_spi(this->proposal
, this->my_spi
);
269 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
271 static void schedule_inactivity_timeout(private_child_create_t
*this)
276 timeout
= this->config
->get_inactivity(this->config
);
279 close_ike
= lib
->settings
->get_bool(lib
->settings
,
280 "%s.inactivity_close_ike", FALSE
, charon
->name
);
281 lib
->scheduler
->schedule_job(lib
->scheduler
, (job_t
*)
282 inactivity_job_create(this->child_sa
->get_reqid(this->child_sa
),
283 timeout
, close_ike
), timeout
);
288 * Get host to use for dynamic traffic selectors
290 static host_t
*get_dynamic_host(ike_sa_t
*ike_sa
, bool local
)
292 enumerator_t
*enumerator
;
295 enumerator
= ike_sa
->create_virtual_ip_enumerator(ike_sa
, local
);
296 if (!enumerator
->enumerate(enumerator
, &host
))
300 host
= ike_sa
->get_my_host(ike_sa
);
304 host
= ike_sa
->get_other_host(ike_sa
);
307 enumerator
->destroy(enumerator
);
312 * Install a CHILD_SA for usage, return value:
313 * - FAILED: no acceptable proposal
314 * - INVALID_ARG: diffie hellman group inacceptable
315 * - NOT_FOUND: TS inacceptable
317 static status_t
select_and_install(private_child_create_t
*this,
318 bool no_dh
, bool ike_auth
)
320 status_t status
, status_i
, status_o
;
321 chunk_t nonce_i
, nonce_r
;
322 chunk_t encr_i
= chunk_empty
, encr_r
= chunk_empty
;
323 chunk_t integ_i
= chunk_empty
, integ_r
= chunk_empty
;
324 linked_list_t
*my_ts
, *other_ts
;
328 if (this->proposals
== NULL
)
330 DBG1(DBG_IKE
, "SA payload missing in message");
333 if (this->tsi
== NULL
|| this->tsr
== NULL
)
335 DBG1(DBG_IKE
, "TS payloads missing in message");
339 me
= this->ike_sa
->get_my_host(this->ike_sa
);
340 other
= this->ike_sa
->get_other_host(this->ike_sa
);
342 private = this->ike_sa
->supports_extension(this->ike_sa
, EXT_STRONGSWAN
);
343 this->proposal
= this->config
->select_proposal(this->config
,
344 this->proposals
, no_dh
, private);
345 if (this->proposal
== NULL
)
347 DBG1(DBG_IKE
, "no acceptable proposal found");
350 this->other_spi
= this->proposal
->get_spi(this->proposal
);
352 if (!this->initiator
&& !allocate_spi(this))
353 { /* responder has no SPI allocated yet */
354 DBG1(DBG_IKE
, "allocating SPI failed");
357 this->child_sa
->set_proposal(this->child_sa
, this->proposal
);
359 if (!this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
363 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
366 DBG1(DBG_IKE
, "DH group %N inacceptable, requesting %N",
367 diffie_hellman_group_names
, this->dh_group
,
368 diffie_hellman_group_names
, group
);
369 this->dh_group
= group
;
372 /* the selected proposal does not use a DH group */
373 DBG1(DBG_IKE
, "ignoring KE exchange, agreed on a non-PFS proposal");
374 DESTROY_IF(this->dh
);
376 this->dh_group
= MODP_NONE
;
381 nonce_i
= this->my_nonce
;
382 nonce_r
= this->other_nonce
;
384 other_ts
= this->tsr
;
388 nonce_r
= this->my_nonce
;
389 nonce_i
= this->other_nonce
;
391 other_ts
= this->tsi
;
393 my_ts
= this->config
->get_traffic_selectors(this->config
, TRUE
, my_ts
,
394 get_dynamic_host(this->ike_sa
, TRUE
));
395 other_ts
= this->config
->get_traffic_selectors(this->config
, FALSE
, other_ts
,
396 get_dynamic_host(this->ike_sa
, FALSE
));
402 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
403 NARROW_INITIATOR_POST_NOAUTH
, my_ts
, other_ts
);
407 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
408 NARROW_INITIATOR_POST_AUTH
, my_ts
, other_ts
);
413 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
414 NARROW_RESPONDER
, my_ts
, other_ts
);
417 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
419 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
420 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
421 DBG1(DBG_IKE
, "no acceptable traffic selectors found");
425 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
426 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
430 this->tsr
= other_ts
;
435 this->tsi
= other_ts
;
438 if (!this->initiator
)
440 /* check if requested mode is acceptable, downgrade if required */
444 if (!this->config
->use_proxy_mode(this->config
) &&
445 (!ts_list_is_host(this->tsi
, other
) ||
446 !ts_list_is_host(this->tsr
, me
))
449 this->mode
= MODE_TUNNEL
;
450 DBG1(DBG_IKE
, "not using transport mode, not host-to-host");
452 else if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
454 this->mode
= MODE_TUNNEL
;
455 DBG1(DBG_IKE
, "not using transport mode, connection NATed");
459 if (!ts_list_is_host(this->tsi
, NULL
) ||
460 !ts_list_is_host(this->tsr
, NULL
))
462 this->mode
= MODE_TUNNEL
;
463 DBG1(DBG_IKE
, "not using BEET mode, not host-to-host");
471 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLING
);
472 this->child_sa
->set_ipcomp(this->child_sa
, this->ipcomp
);
473 this->child_sa
->set_mode(this->child_sa
, this->mode
);
474 this->child_sa
->set_protocol(this->child_sa
,
475 this->proposal
->get_protocol(this->proposal
));
477 if (this->my_cpi
== 0 || this->other_cpi
== 0 || this->ipcomp
== IPCOMP_NONE
)
479 this->my_cpi
= this->other_cpi
= 0;
480 this->ipcomp
= IPCOMP_NONE
;
482 status_i
= status_o
= FAILED
;
483 if (this->keymat
->derive_child_keys(this->keymat
, this->proposal
,
484 this->dh
, nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
))
488 status_i
= this->child_sa
->install(this->child_sa
,
489 encr_r
, integ_r
, this->my_spi
, this->my_cpi
,
490 TRUE
, this->tfcv3
, my_ts
, other_ts
);
491 status_o
= this->child_sa
->install(this->child_sa
,
492 encr_i
, integ_i
, this->other_spi
, this->other_cpi
,
493 FALSE
, this->tfcv3
, my_ts
, other_ts
);
497 status_i
= this->child_sa
->install(this->child_sa
,
498 encr_i
, integ_i
, this->my_spi
, this->my_cpi
,
499 TRUE
, this->tfcv3
, my_ts
, other_ts
);
500 status_o
= this->child_sa
->install(this->child_sa
,
501 encr_r
, integ_r
, this->other_spi
, this->other_cpi
,
502 FALSE
, this->tfcv3
, my_ts
, other_ts
);
505 chunk_clear(&integ_i
);
506 chunk_clear(&integ_r
);
507 chunk_clear(&encr_i
);
508 chunk_clear(&encr_r
);
510 if (status_i
!= SUCCESS
|| status_o
!= SUCCESS
)
512 DBG1(DBG_IKE
, "unable to install %s%s%sIPsec SA (SAD) in kernel",
513 (status_i
!= SUCCESS
) ?
"inbound " : "",
514 (status_i
!= SUCCESS
&& status_o
!= SUCCESS
) ?
"and ": "",
515 (status_o
!= SUCCESS
) ?
"outbound " : "");
521 status
= this->child_sa
->add_policies(this->child_sa
, my_ts
, other_ts
);
525 /* use a copy of the traffic selectors, as the POST hook should not
527 my_ts
= this->tsr
->clone_offset(this->tsr
,
528 offsetof(traffic_selector_t
, clone
));
529 other_ts
= this->tsi
->clone_offset(this->tsi
,
530 offsetof(traffic_selector_t
, clone
));
531 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
532 NARROW_RESPONDER_POST
, my_ts
, other_ts
);
533 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
539 status
= this->child_sa
->add_policies(this->child_sa
,
542 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
543 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
545 if (status
!= SUCCESS
)
547 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
551 charon
->bus
->child_keys(charon
->bus
, this->child_sa
, this->initiator
,
552 this->dh
, nonce_i
, nonce_r
);
554 /* add to IKE_SA, and remove from task */
555 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
556 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
557 this->established
= TRUE
;
560 { /* a rekeyed SA uses the same reqid, no need for a new job */
561 schedule_inactivity_timeout(this);
567 * build the payloads for the message
569 static void build_payloads(private_child_create_t
*this, message_t
*message
)
571 sa_payload_t
*sa_payload
;
572 nonce_payload_t
*nonce_payload
;
573 ke_payload_t
*ke_payload
;
574 ts_payload_t
*ts_payload
;
579 sa_payload
= sa_payload_create_from_proposals_v2(this->proposals
);
583 sa_payload
= sa_payload_create_from_proposal_v2(this->proposal
);
585 message
->add_payload(message
, (payload_t
*)sa_payload
);
587 /* add nonce payload if not in IKE_AUTH */
588 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
590 nonce_payload
= nonce_payload_create(NONCE
);
591 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
592 message
->add_payload(message
, (payload_t
*)nonce_payload
);
595 /* diffie hellman exchange, if PFS enabled */
598 ke_payload
= ke_payload_create_from_diffie_hellman(KEY_EXCHANGE
,
600 message
->add_payload(message
, (payload_t
*)ke_payload
);
603 /* add TSi/TSr payloads */
604 ts_payload
= ts_payload_create_from_traffic_selectors(TRUE
, this->tsi
);
605 message
->add_payload(message
, (payload_t
*)ts_payload
);
606 ts_payload
= ts_payload_create_from_traffic_selectors(FALSE
, this->tsr
);
607 message
->add_payload(message
, (payload_t
*)ts_payload
);
609 /* add a notify if we are not in tunnel mode */
613 message
->add_notify(message
, FALSE
, USE_TRANSPORT_MODE
, chunk_empty
);
616 message
->add_notify(message
, FALSE
, USE_BEET_MODE
, chunk_empty
);
624 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
626 static void add_ipcomp_notify(private_child_create_t
*this,
627 message_t
*message
, u_int8_t ipcomp
)
629 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
631 DBG1(DBG_IKE
, "IPComp is not supported if either peer is natted, "
636 this->my_cpi
= this->child_sa
->alloc_cpi(this->child_sa
);
639 this->ipcomp
= ipcomp
;
640 message
->add_notify(message
, FALSE
, IPCOMP_SUPPORTED
,
641 chunk_cata("cc", chunk_from_thing(this->my_cpi
),
642 chunk_from_thing(ipcomp
)));
646 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, IPComp disabled");
651 * handle a received notify payload
653 static void handle_notify(private_child_create_t
*this, notify_payload_t
*notify
)
655 switch (notify
->get_notify_type(notify
))
657 case USE_TRANSPORT_MODE
:
658 this->mode
= MODE_TRANSPORT
;
661 if (this->ike_sa
->supports_extension(this->ike_sa
, EXT_STRONGSWAN
))
662 { /* handle private use notify only if we know its meaning */
663 this->mode
= MODE_BEET
;
667 DBG1(DBG_IKE
, "received a notify strongSwan uses for BEET "
668 "mode, but peer implementation unknown, skipped");
671 case IPCOMP_SUPPORTED
:
673 ipcomp_transform_t ipcomp
;
677 data
= notify
->get_notification_data(notify
);
678 cpi
= *(u_int16_t
*)data
.ptr
;
679 ipcomp
= (ipcomp_transform_t
)(*(data
.ptr
+ 2));
683 this->other_cpi
= cpi
;
684 this->ipcomp_received
= ipcomp
;
689 DBG1(DBG_IKE
, "received IPCOMP_SUPPORTED notify with a "
690 "transform ID we don't support %N",
691 ipcomp_transform_names
, ipcomp
);
696 case ESP_TFC_PADDING_NOT_SUPPORTED
:
697 DBG1(DBG_IKE
, "received %N, not using ESPv3 TFC padding",
698 notify_type_names
, notify
->get_notify_type(notify
));
707 * Read payloads from message
709 static void process_payloads(private_child_create_t
*this, message_t
*message
)
711 enumerator_t
*enumerator
;
713 sa_payload_t
*sa_payload
;
714 ke_payload_t
*ke_payload
;
715 ts_payload_t
*ts_payload
;
717 /* defaults to TUNNEL mode */
718 this->mode
= MODE_TUNNEL
;
720 enumerator
= message
->create_payload_enumerator(message
);
721 while (enumerator
->enumerate(enumerator
, &payload
))
723 switch (payload
->get_type(payload
))
725 case SECURITY_ASSOCIATION
:
726 sa_payload
= (sa_payload_t
*)payload
;
727 this->proposals
= sa_payload
->get_proposals(sa_payload
);
730 ke_payload
= (ke_payload_t
*)payload
;
731 if (!this->initiator
)
733 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
734 this->dh
= this->keymat
->keymat
.create_dh(
735 &this->keymat
->keymat
, this->dh_group
);
739 this->dh
->set_other_public_value(this->dh
,
740 ke_payload
->get_key_exchange_data(ke_payload
));
743 case TRAFFIC_SELECTOR_INITIATOR
:
744 ts_payload
= (ts_payload_t
*)payload
;
745 this->tsi
= ts_payload
->get_traffic_selectors(ts_payload
);
747 case TRAFFIC_SELECTOR_RESPONDER
:
748 ts_payload
= (ts_payload_t
*)payload
;
749 this->tsr
= ts_payload
->get_traffic_selectors(ts_payload
);
752 handle_notify(this, (notify_payload_t
*)payload
);
758 enumerator
->destroy(enumerator
);
761 METHOD(task_t
, build_i
, status_t
,
762 private_child_create_t
*this, message_t
*message
)
764 enumerator_t
*enumerator
;
766 peer_cfg_t
*peer_cfg
;
768 switch (message
->get_exchange_type(message
))
771 return get_nonce(message
, &this->my_nonce
);
772 case CREATE_CHILD_SA
:
773 if (generate_nonce(this) != SUCCESS
)
775 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
780 this->dh_group
= this->config
->get_dh_group(this->config
);
784 if (message
->get_message_id(message
) != 1)
786 /* send only in the first request, not in subsequent rounds */
796 DBG0(DBG_IKE
, "establishing CHILD_SA %s{%d}",
797 this->config
->get_name(this->config
), this->reqid
);
801 DBG0(DBG_IKE
, "establishing CHILD_SA %s",
802 this->config
->get_name(this->config
));
805 /* check if we want a virtual IP, but don't have one */
806 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
807 enumerator
= peer_cfg
->create_virtual_ip_enumerator(peer_cfg
);
808 if (!this->reqid
&& enumerator
->enumerate(enumerator
, &vip
))
810 /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
811 vip
= host_create_any(vip
->get_family(vip
));
812 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
817 { /* but narrow it for host2host / if we already have a vip */
818 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
, NULL
,
819 get_dynamic_host(this->ike_sa
, TRUE
));
821 enumerator
->destroy(enumerator
);
822 this->tsr
= this->config
->get_traffic_selectors(this->config
, FALSE
, NULL
,
823 get_dynamic_host(this->ike_sa
, FALSE
));
825 if (this->packet_tsi
)
827 this->tsi
->insert_first(this->tsi
,
828 this->packet_tsi
->clone(this->packet_tsi
));
830 if (this->packet_tsr
)
832 this->tsr
->insert_first(this->tsr
,
833 this->packet_tsr
->clone(this->packet_tsr
));
835 this->proposals
= this->config
->get_proposals(this->config
,
836 this->dh_group
== MODP_NONE
);
837 this->mode
= this->config
->get_mode(this->config
);
838 if (this->mode
== MODE_TRANSPORT
&&
839 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
841 this->mode
= MODE_TUNNEL
;
842 DBG1(DBG_IKE
, "not using transport mode, connection NATed");
845 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
846 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
847 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
849 if (!allocate_spi(this))
851 DBG1(DBG_IKE
, "unable to allocate SPIs from kernel");
855 if (this->dh_group
!= MODP_NONE
)
857 this->dh
= this->keymat
->keymat
.create_dh(&this->keymat
->keymat
,
861 if (this->config
->use_ipcomp(this->config
))
863 /* IPCOMP_DEFLATE is the only transform we support at the moment */
864 add_ipcomp_notify(this, message
, IPCOMP_DEFLATE
);
867 if (message
->get_exchange_type(message
) == IKE_AUTH
)
869 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
870 NARROW_INITIATOR_PRE_NOAUTH
, this->tsi
, this->tsr
);
874 charon
->bus
->narrow(charon
->bus
, this->child_sa
,
875 NARROW_INITIATOR_PRE_AUTH
, this->tsi
, this->tsr
);
878 build_payloads(this, message
);
880 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
881 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
882 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
885 this->proposals
= NULL
;
890 METHOD(task_t
, process_r
, status_t
,
891 private_child_create_t
*this, message_t
*message
)
893 switch (message
->get_exchange_type(message
))
896 return get_nonce(message
, &this->other_nonce
);
897 case CREATE_CHILD_SA
:
898 get_nonce(message
, &this->other_nonce
);
901 if (message
->get_message_id(message
) != 1)
903 /* only handle first AUTH payload, not additional rounds */
910 process_payloads(this, message
);
916 * handle CHILD_SA setup failure
918 static void handle_child_sa_failure(private_child_create_t
*this,
921 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
922 lib
->settings
->get_bool(lib
->settings
,
923 "%s.close_ike_on_child_failure", FALSE
, charon
->name
))
925 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
927 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
928 lib
->scheduler
->schedule_job_ms(lib
->scheduler
, (job_t
*)
929 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
934 DBG1(DBG_IKE
, "failed to establish CHILD_SA, keeping IKE_SA");
938 METHOD(task_t
, build_r
, status_t
,
939 private_child_create_t
*this, message_t
*message
)
941 peer_cfg_t
*peer_cfg
;
943 enumerator_t
*enumerator
;
944 bool no_dh
= TRUE
, ike_auth
= FALSE
;
946 switch (message
->get_exchange_type(message
))
949 return get_nonce(message
, &this->my_nonce
);
950 case CREATE_CHILD_SA
:
951 if (generate_nonce(this) != SUCCESS
)
953 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
960 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
961 { /* wait until all authentication round completed */
969 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
971 DBG1(DBG_IKE
, "unable to create CHILD_SA while rekeying IKE_SA");
972 message
->add_notify(message
, TRUE
, NO_ADDITIONAL_SAS
, chunk_empty
);
976 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
977 if (!this->config
&& peer_cfg
&& this->tsi
&& this->tsr
)
979 this->config
= peer_cfg
->select_child_cfg(peer_cfg
,
980 this->tsr
, this->tsi
,
981 get_dynamic_host(this->ike_sa
, TRUE
),
982 get_dynamic_host(this->ike_sa
, FALSE
));
985 if (this->config
== NULL
)
987 DBG1(DBG_IKE
, "traffic selectors %#R=== %#R inacceptable",
988 this->tsr
, this->tsi
);
989 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
990 handle_child_sa_failure(this, message
);
994 /* check if ike_config_t included non-critical error notifies */
995 enumerator
= message
->create_payload_enumerator(message
);
996 while (enumerator
->enumerate(enumerator
, &payload
))
998 if (payload
->get_type(payload
) == NOTIFY
)
1000 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
1002 switch (notify
->get_notify_type(notify
))
1004 case INTERNAL_ADDRESS_FAILURE
:
1005 case FAILED_CP_REQUIRED
:
1007 DBG1(DBG_IKE
,"configuration payload negotiation "
1008 "failed, no CHILD_SA built");
1009 enumerator
->destroy(enumerator
);
1010 handle_child_sa_failure(this, message
);
1018 enumerator
->destroy(enumerator
);
1020 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
1021 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
1022 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
1024 if (this->ipcomp_received
!= IPCOMP_NONE
)
1026 if (this->config
->use_ipcomp(this->config
))
1028 add_ipcomp_notify(this, message
, this->ipcomp_received
);
1032 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
1033 notify_type_names
, IPCOMP_SUPPORTED
);
1037 switch (select_and_install(this, no_dh
, ike_auth
))
1042 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
1043 handle_child_sa_failure(this, message
);
1047 u_int16_t group
= htons(this->dh_group
);
1048 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
1049 chunk_from_thing(group
));
1050 handle_child_sa_failure(this, message
);
1055 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
1056 handle_child_sa_failure(this, message
);
1060 build_payloads(this, message
);
1062 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
1063 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1064 this->child_sa
->get_name(this->child_sa
),
1065 this->child_sa
->get_reqid(this->child_sa
),
1066 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
1067 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
1068 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
1069 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
1072 { /* invoke the child_up() hook if we are not rekeying */
1073 charon
->bus
->child_updown(charon
->bus
, this->child_sa
, TRUE
);
1078 METHOD(task_t
, process_i
, status_t
,
1079 private_child_create_t
*this, message_t
*message
)
1081 enumerator_t
*enumerator
;
1083 bool no_dh
= TRUE
, ike_auth
= FALSE
;
1085 switch (message
->get_exchange_type(message
))
1088 return get_nonce(message
, &this->other_nonce
);
1089 case CREATE_CHILD_SA
:
1090 get_nonce(message
, &this->other_nonce
);
1094 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
1095 { /* wait until all authentication round completed */
1103 /* check for erronous notifies */
1104 enumerator
= message
->create_payload_enumerator(message
);
1105 while (enumerator
->enumerate(enumerator
, &payload
))
1107 if (payload
->get_type(payload
) == NOTIFY
)
1109 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
1110 notify_type_t type
= notify
->get_notify_type(notify
);
1114 /* handle notify errors related to CHILD_SA only */
1115 case NO_PROPOSAL_CHOSEN
:
1116 case SINGLE_PAIR_REQUIRED
:
1117 case NO_ADDITIONAL_SAS
:
1118 case INTERNAL_ADDRESS_FAILURE
:
1119 case FAILED_CP_REQUIRED
:
1120 case TS_UNACCEPTABLE
:
1121 case INVALID_SELECTORS
:
1123 DBG1(DBG_IKE
, "received %N notify, no CHILD_SA built",
1124 notify_type_names
, type
);
1125 enumerator
->destroy(enumerator
);
1126 handle_child_sa_failure(this, message
);
1127 /* an error in CHILD_SA creation is not critical */
1130 case INVALID_KE_PAYLOAD
:
1133 u_int16_t group
= MODP_NONE
;
1135 data
= notify
->get_notification_data(notify
);
1136 if (data
.len
== sizeof(group
))
1138 memcpy(&group
, data
.ptr
, data
.len
);
1139 group
= ntohs(group
);
1141 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
1142 "it requested %N", diffie_hellman_group_names
,
1143 this->dh_group
, diffie_hellman_group_names
, group
);
1145 this->dh_group
= group
;
1146 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
1147 enumerator
->destroy(enumerator
);
1152 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
1153 { /* handle notifies if not handled in IKE_AUTH */
1156 DBG1(DBG_IKE
, "received %N notify error",
1157 notify_type_names
, type
);
1158 enumerator
->destroy(enumerator
);
1161 DBG2(DBG_IKE
, "received %N notify",
1162 notify_type_names
, type
);
1169 enumerator
->destroy(enumerator
);
1171 process_payloads(this, message
);
1173 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
1175 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify without requesting"
1176 " one, no CHILD_SA built");
1177 handle_child_sa_failure(this, message
);
1180 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
1182 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
1183 "IPComp is disabled");
1184 this->ipcomp
= IPCOMP_NONE
;
1186 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
1188 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1189 "no CHILD_SA built");
1190 handle_child_sa_failure(this, message
);
1194 if (select_and_install(this, no_dh
, ike_auth
) == SUCCESS
)
1196 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
1197 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1198 this->child_sa
->get_name(this->child_sa
),
1199 this->child_sa
->get_reqid(this->child_sa
),
1200 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
1201 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
1202 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
1203 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
1206 { /* invoke the child_up() hook if we are not rekeying */
1207 charon
->bus
->child_updown(charon
->bus
, this->child_sa
, TRUE
);
1212 handle_child_sa_failure(this, message
);
1217 METHOD(child_create_t
, use_reqid
, void,
1218 private_child_create_t
*this, u_int32_t reqid
)
1220 this->reqid
= reqid
;
1223 METHOD(child_create_t
, get_child
, child_sa_t
*,
1224 private_child_create_t
*this)
1226 return this->child_sa
;
1229 METHOD(child_create_t
, set_config
, void,
1230 private_child_create_t
*this, child_cfg_t
*cfg
)
1232 DESTROY_IF(this->config
);
1236 METHOD(child_create_t
, get_lower_nonce
, chunk_t
,
1237 private_child_create_t
*this)
1239 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1240 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1242 return this->my_nonce
;
1246 return this->other_nonce
;
1250 METHOD(task_t
, get_type
, task_type_t
,
1251 private_child_create_t
*this)
1253 return TASK_CHILD_CREATE
;
1256 METHOD(task_t
, migrate
, void,
1257 private_child_create_t
*this, ike_sa_t
*ike_sa
)
1259 chunk_free(&this->my_nonce
);
1260 chunk_free(&this->other_nonce
);
1263 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1267 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1269 DESTROY_IF(this->child_sa
);
1270 DESTROY_IF(this->proposal
);
1271 DESTROY_IF(this->dh
);
1272 if (this->proposals
)
1274 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1277 this->ike_sa
= ike_sa
;
1278 this->keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
);
1279 this->proposal
= NULL
;
1280 this->proposals
= NULL
;
1284 this->child_sa
= NULL
;
1285 this->mode
= MODE_TUNNEL
;
1286 this->ipcomp
= IPCOMP_NONE
;
1287 this->ipcomp_received
= IPCOMP_NONE
;
1288 this->other_cpi
= 0;
1290 this->established
= FALSE
;
1293 METHOD(task_t
, destroy
, void,
1294 private_child_create_t
*this)
1296 chunk_free(&this->my_nonce
);
1297 chunk_free(&this->other_nonce
);
1300 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1304 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1306 if (!this->established
)
1308 DESTROY_IF(this->child_sa
);
1310 DESTROY_IF(this->packet_tsi
);
1311 DESTROY_IF(this->packet_tsr
);
1312 DESTROY_IF(this->proposal
);
1313 DESTROY_IF(this->dh
);
1314 if (this->proposals
)
1316 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1319 DESTROY_IF(this->config
);
1324 * Described in header.
1326 child_create_t
*child_create_create(ike_sa_t
*ike_sa
,
1327 child_cfg_t
*config
, bool rekey
,
1328 traffic_selector_t
*tsi
, traffic_selector_t
*tsr
)
1330 private_child_create_t
*this;
1334 .get_child
= _get_child
,
1335 .set_config
= _set_config
,
1336 .get_lower_nonce
= _get_lower_nonce
,
1337 .use_reqid
= _use_reqid
,
1339 .get_type
= _get_type
,
1340 .migrate
= _migrate
,
1341 .destroy
= _destroy
,
1346 .packet_tsi
= tsi ? tsi
->clone(tsi
) : NULL
,
1347 .packet_tsr
= tsr ? tsr
->clone(tsr
) : NULL
,
1348 .dh_group
= MODP_NONE
,
1349 .keymat
= (keymat_v2_t
*)ike_sa
->get_keymat(ike_sa
),
1350 .mode
= MODE_TUNNEL
,
1352 .ipcomp
= IPCOMP_NONE
,
1353 .ipcomp_received
= IPCOMP_NONE
,
1360 this->public.task
.build
= _build_i
;
1361 this->public.task
.process
= _process_i
;
1362 this->initiator
= TRUE
;
1366 this->public.task
.build
= _build_r
;
1367 this->public.task
.process
= _process_r
;
1368 this->initiator
= FALSE
;
1371 return &this->public;