2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2007 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
20 #include "child_create.h"
23 #include <crypto/diffie_hellman.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>
32 typedef struct private_child_create_t private_child_create_t
;
35 * Private members of a child_create_t task.
37 struct private_child_create_t
{
40 * Public methods and task_t interface.
42 child_create_t
public;
50 * Are we the initiator?
60 * nonce chosen by peer
65 * config to create the CHILD_SA from
70 * list of proposal candidates
72 linked_list_t
*proposals
;
75 * selected proposal to use for CHILD_SA
80 * traffic selectors for initiators side
85 * traffic selectors for responders side
90 * optional diffie hellman exchange
95 * group used for DH exchange
97 diffie_hellman_group_t dh_group
;
100 * mode the new CHILD_SA uses (transport/tunnel/beet)
105 * IPComp transform to use
107 ipcomp_transform_t ipcomp
;
110 * IPComp transform proposed or accepted by the other peer
112 ipcomp_transform_t ipcomp_received
;
115 * Other Compression Parameter Index (CPI)
120 * reqid to use if we are rekeying
125 * CHILD_SA which gets established
127 child_sa_t
*child_sa
;
130 * successfully established the CHILD?
136 * get the nonce from a message
138 static status_t
get_nonce(message_t
*message
, chunk_t
*nonce
)
140 nonce_payload_t
*payload
;
142 payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
147 *nonce
= payload
->get_nonce(payload
);
152 * generate a new nonce to include in a CREATE_CHILD_SA message
154 static status_t
generate_nonce(chunk_t
*nonce
)
158 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
161 DBG1(DBG_IKE
, "error generating nonce value, no RNG found");
164 rng
->allocate_bytes(rng
, NONCE_SIZE
, nonce
);
170 * Check a list of traffic selectors if any selector belongs to host
172 static bool ts_list_is_host(linked_list_t
*list
, host_t
*host
)
174 traffic_selector_t
*ts
;
176 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
178 while (is_host
&& iterator
->iterate(iterator
, (void**)&ts
))
180 is_host
= is_host
&& ts
->is_host(ts
, host
);
182 iterator
->destroy(iterator
);
187 * Install a CHILD_SA for usage, return value:
188 * - FAILED: no acceptable proposal
189 * - INVALID_ARG: diffie hellman group inacceptable
190 * - NOT_FOUND: TS inacceptable
192 static status_t
select_and_install(private_child_create_t
*this, bool no_dh
)
194 prf_plus_t
*prf_plus
;
196 chunk_t nonce_i
, nonce_r
, secret
, seed
;
197 linked_list_t
*my_ts
, *other_ts
;
198 host_t
*me
, *other
, *other_vip
, *my_vip
;
200 if (this->proposals
== NULL
)
202 SIG_CHD(UP_FAILED
, this->child_sa
, "SA payload missing in message");
205 if (this->tsi
== NULL
|| this->tsr
== NULL
)
207 SIG_CHD(UP_FAILED
, this->child_sa
, "TS payloads missing in message");
213 nonce_i
= this->my_nonce
;
214 nonce_r
= this->other_nonce
;
216 other_ts
= this->tsr
;
220 nonce_r
= this->my_nonce
;
221 nonce_i
= this->other_nonce
;
223 other_ts
= this->tsi
;
226 me
= this->ike_sa
->get_my_host(this->ike_sa
);
227 other
= this->ike_sa
->get_other_host(this->ike_sa
);
228 my_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
229 other_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
231 this->proposal
= this->config
->select_proposal(this->config
, this->proposals
,
233 if (this->proposal
== NULL
)
235 SIG_CHD(UP_FAILED
, this->child_sa
, "no acceptable proposal found");
239 if (!this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
243 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
246 SIG_CHD(UP_FAILED
, this->child_sa
, "DH group %N inacceptable, "
247 "requesting %N", diffie_hellman_group_names
, this->dh_group
,
248 diffie_hellman_group_names
, group
);
249 this->dh_group
= group
;
254 SIG_CHD(UP_FAILED
, this->child_sa
, "no acceptable proposal found");
263 else if (this->initiator
)
265 /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
266 this->child_sa
->set_virtual_ip(this->child_sa
, my_vip
);
268 if (other_vip
== NULL
)
273 my_ts
= this->config
->get_traffic_selectors(this->config
, TRUE
, my_ts
,
275 other_ts
= this->config
->get_traffic_selectors(this->config
, FALSE
, other_ts
,
278 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
280 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
281 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
282 SIG_CHD(UP_FAILED
, this->child_sa
, "no acceptable traffic selectors found");
286 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
287 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
291 this->tsr
= other_ts
;
296 this->tsi
= other_ts
;
299 if (!this->initiator
)
301 /* check if requested mode is acceptable, downgrade if required */
305 if (!ts_list_is_host(this->tsi
, other
) ||
306 !ts_list_is_host(this->tsr
, me
))
308 this->mode
= MODE_TUNNEL
;
309 DBG1(DBG_IKE
, "not using tranport mode, not host-to-host");
311 else if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
313 this->mode
= MODE_TUNNEL
;
314 DBG1(DBG_IKE
, "not using tranport mode, connection NATed");
318 if (!ts_list_is_host(this->tsi
, NULL
) ||
319 !ts_list_is_host(this->tsr
, NULL
))
321 this->mode
= MODE_TUNNEL
;
322 DBG1(DBG_IKE
, "not using BEET mode, not host-to-host");
332 if (this->dh
->get_shared_secret(this->dh
, &secret
) != SUCCESS
)
334 SIG_CHD(UP_FAILED
, this->child_sa
, "DH exchange incomplete");
337 DBG3(DBG_IKE
, "DH secret %B", &secret
);
338 seed
= chunk_cata("mcc", secret
, nonce_i
, nonce_r
);
342 seed
= chunk_cata("cc", nonce_i
, nonce_r
);
345 if (this->ipcomp
!= IPCOMP_NONE
)
347 this->child_sa
->activate_ipcomp(this->child_sa
, this->ipcomp
,
351 status
= this->child_sa
->add_policies(this->child_sa
, my_ts
, other_ts
,
352 this->mode
, this->proposal
->get_protocol(this->proposal
));
353 if (status
!= SUCCESS
)
355 SIG_CHD(UP_FAILED
, this->child_sa
,
356 "unable to install IPsec policies (SPD) in kernel");
360 prf_plus
= prf_plus_create(this->ike_sa
->get_child_prf(this->ike_sa
), seed
);
363 status
= this->child_sa
->update(this->child_sa
, this->proposal
,
364 this->mode
, prf_plus
);
368 status
= this->child_sa
->add(this->child_sa
, this->proposal
,
369 this->mode
, prf_plus
);
371 prf_plus
->destroy(prf_plus
);
373 if (status
!= SUCCESS
)
375 SIG_CHD(UP_FAILED
, this->child_sa
,
376 "unable to install IPsec SA (SAD) in kernel");
379 /* add to IKE_SA, and remove from task */
380 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
381 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
382 this->established
= TRUE
;
387 * build the payloads for the message
389 static void build_payloads(private_child_create_t
*this, message_t
*message
)
391 sa_payload_t
*sa_payload
;
392 nonce_payload_t
*nonce_payload
;
393 ke_payload_t
*ke_payload
;
394 ts_payload_t
*ts_payload
;
399 sa_payload
= sa_payload_create_from_proposal_list(this->proposals
);
403 sa_payload
= sa_payload_create_from_proposal(this->proposal
);
405 message
->add_payload(message
, (payload_t
*)sa_payload
);
407 /* add nonce payload if not in IKE_AUTH */
408 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
410 nonce_payload
= nonce_payload_create();
411 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
412 message
->add_payload(message
, (payload_t
*)nonce_payload
);
415 /* diffie hellman exchange, if PFS enabled */
418 ke_payload
= ke_payload_create_from_diffie_hellman(this->dh
);
419 message
->add_payload(message
, (payload_t
*)ke_payload
);
422 /* add TSi/TSr payloads */
423 ts_payload
= ts_payload_create_from_traffic_selectors(TRUE
, this->tsi
);
424 message
->add_payload(message
, (payload_t
*)ts_payload
);
425 ts_payload
= ts_payload_create_from_traffic_selectors(FALSE
, this->tsr
);
426 message
->add_payload(message
, (payload_t
*)ts_payload
);
428 /* add a notify if we are not in tunnel mode */
432 message
->add_notify(message
, FALSE
, USE_TRANSPORT_MODE
, chunk_empty
);
435 message
->add_notify(message
, FALSE
, USE_BEET_MODE
, chunk_empty
);
443 * Adds an IPCOMP_SUPPORTED notify to the message, if possible
445 static void build_ipcomp_supported_notify(private_child_create_t
*this,
451 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
453 DBG1(DBG_IKE
, "IPComp is not supported if either peer is natted, "
455 this->ipcomp
= IPCOMP_NONE
;
459 cpi
= this->child_sa
->allocate_cpi(this->child_sa
);
463 message
->add_notify(message
, FALSE
, IPCOMP_SUPPORTED
,
464 chunk_cata("cc", chunk_from_thing(cpi
), chunk_from_thing(tid
)));
468 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, IPComp disabled");
469 this->ipcomp
= IPCOMP_NONE
;
474 * Read payloads from message
476 static void process_payloads(private_child_create_t
*this, message_t
*message
)
478 iterator_t
*iterator
;
480 sa_payload_t
*sa_payload
;
481 ke_payload_t
*ke_payload
;
482 ts_payload_t
*ts_payload
;
483 notify_payload_t
*notify_payload
;
485 /* defaults to TUNNEL mode */
486 this->mode
= MODE_TUNNEL
;
488 iterator
= message
->get_payload_iterator(message
);
489 while (iterator
->iterate(iterator
, (void**)&payload
))
491 switch (payload
->get_type(payload
))
493 case SECURITY_ASSOCIATION
:
494 sa_payload
= (sa_payload_t
*)payload
;
495 this->proposals
= sa_payload
->get_proposals(sa_payload
);
498 ke_payload
= (ke_payload_t
*)payload
;
499 if (!this->initiator
)
501 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
502 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
506 this->dh
->set_other_public_value(this->dh
,
507 ke_payload
->get_key_exchange_data(ke_payload
));
510 case TRAFFIC_SELECTOR_INITIATOR
:
511 ts_payload
= (ts_payload_t
*)payload
;
512 this->tsi
= ts_payload
->get_traffic_selectors(ts_payload
);
514 case TRAFFIC_SELECTOR_RESPONDER
:
515 ts_payload
= (ts_payload_t
*)payload
;
516 this->tsr
= ts_payload
->get_traffic_selectors(ts_payload
);
519 notify_payload
= (notify_payload_t
*)payload
;
520 switch (notify_payload
->get_notify_type(notify_payload
))
522 case USE_TRANSPORT_MODE
:
523 this->mode
= MODE_TRANSPORT
;
526 this->mode
= MODE_BEET
;
528 case IPCOMP_SUPPORTED
:
530 chunk_t data
= notify_payload
->get_notification_data(notify_payload
);
531 u_int16_t cpi
= *(u_int16_t
*)data
.ptr
;
532 ipcomp_transform_t ipcomp
= (ipcomp_transform_t
)(*(data
.ptr
+ 2));
536 this->other_cpi
= cpi
;
537 this->ipcomp_received
= ipcomp
;
542 DBG1(DBG_IKE
, "received IPCOMP_SUPPORTED notify with a transform"
543 " ID we don't support %N", ipcomp_transform_names
, ipcomp
);
555 iterator
->destroy(iterator
);
559 * Implementation of task_t.build for initiator
561 static status_t
build_i(private_child_create_t
*this, message_t
*message
)
563 host_t
*me
, *other
, *vip
;
564 bool propose_all
= FALSE
;
565 peer_cfg_t
*peer_cfg
;
567 switch (message
->get_exchange_type(message
))
570 return get_nonce(message
, &this->my_nonce
);
571 case CREATE_CHILD_SA
:
572 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
574 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
577 if (this->dh_group
== MODP_NONE
)
579 this->dh_group
= this->config
->get_dh_group(this->config
);
583 if (!message
->get_payload(message
, ID_INITIATOR
))
585 /* send only in the first request, not in subsequent EAP */
593 SIG_CHD(UP_START
, NULL
, "establishing CHILD_SA '%s'",
594 this->config
->get_name(this->config
));
596 /* reuse virtual IP if we already have one */
597 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
600 me
= this->ike_sa
->get_my_host(this->ike_sa
);
602 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
605 other
= this->ike_sa
->get_other_host(this->ike_sa
);
608 /* check if we want a virtual IP, but don't have one */
611 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
612 vip
= peer_cfg
->get_virtual_ip(peer_cfg
);
620 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
621 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
625 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
626 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
629 this->tsr
= this->config
->get_traffic_selectors(this->config
, FALSE
,
632 this->proposals
= this->config
->get_proposals(this->config
,
633 this->dh_group
== MODP_NONE
);
634 this->mode
= this->config
->get_mode(this->config
);
636 this->child_sa
= child_sa_create(
637 this->ike_sa
->get_my_host(this->ike_sa
),
638 this->ike_sa
->get_other_host(this->ike_sa
),
639 this->ike_sa
->get_my_id(this->ike_sa
),
640 this->ike_sa
->get_other_id(this->ike_sa
), this->config
, this->reqid
,
641 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
643 if (this->child_sa
->alloc(this->child_sa
, this->proposals
) != SUCCESS
)
645 SIG_CHD(UP_FAILED
, this->child_sa
,
646 "unable to allocate SPIs from kernel");
650 if (this->dh_group
!= MODP_NONE
)
652 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
655 if (this->config
->use_ipcomp(this->config
)) {
656 /* IPCOMP_DEFLATE is the only transform we support at the moment */
657 this->ipcomp
= IPCOMP_DEFLATE
;
658 build_ipcomp_supported_notify(this, message
);
661 build_payloads(this, message
);
663 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
664 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
665 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
668 this->proposals
= NULL
;
674 * Implementation of task_t.process for initiator
676 static status_t
process_r(private_child_create_t
*this, message_t
*message
)
678 peer_cfg_t
*peer_cfg
;
680 switch (message
->get_exchange_type(message
))
683 return get_nonce(message
, &this->other_nonce
);
684 case CREATE_CHILD_SA
:
685 get_nonce(message
, &this->other_nonce
);
688 if (message
->get_payload(message
, ID_INITIATOR
) == NULL
)
690 /* wait until extensible authentication completed, if used */
697 process_payloads(this, message
);
699 if (this->tsi
== NULL
|| this->tsr
== NULL
)
701 DBG1(DBG_IKE
, "TS payload missing in message");
705 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
710 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
713 me
= this->ike_sa
->get_my_host(this->ike_sa
);
715 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
718 other
= this->ike_sa
->get_other_host(this->ike_sa
);
721 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, this->tsr
,
722 this->tsi
, me
, other
);
728 * handle CHILD_SA setup failure
730 static void handle_child_sa_failure(private_child_create_t
*this,
733 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
734 lib
->settings
->get_bool(lib
->settings
,
735 "charon.close_ike_on_child_failure", FALSE
))
737 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
739 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
740 charon
->scheduler
->schedule_job(charon
->scheduler
, (job_t
*)
741 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
747 * Implementation of task_t.build for responder
749 static status_t
build_r(private_child_create_t
*this, message_t
*message
)
752 iterator_t
*iterator
;
755 switch (message
->get_exchange_type(message
))
758 return get_nonce(message
, &this->my_nonce
);
759 case CREATE_CHILD_SA
:
760 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
762 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
769 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
771 /* wait until extensible authentication completed, if used */
778 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
780 SIG_CHD(UP_FAILED
, NULL
,
781 "unable to create CHILD_SA while rekeying IKE_SA");
782 message
->add_notify(message
, TRUE
, NO_ADDITIONAL_SAS
, chunk_empty
);
786 if (this->config
== NULL
)
788 SIG_CHD(UP_FAILED
, NULL
, "traffic selectors %#R=== %#R inacceptable",
789 this->tsr
, this->tsi
);
790 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
791 handle_child_sa_failure(this, message
);
795 /* check if ike_config_t included non-critical error notifies */
796 iterator
= message
->get_payload_iterator(message
);
797 while (iterator
->iterate(iterator
, (void**)&payload
))
799 if (payload
->get_type(payload
) == NOTIFY
)
801 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
803 switch (notify
->get_notify_type(notify
))
805 case INTERNAL_ADDRESS_FAILURE
:
806 case FAILED_CP_REQUIRED
:
808 SIG_CHD(UP_FAILED
, NULL
, "configuration payload negotation "
809 "failed, no CHILD_SA built");
810 iterator
->destroy(iterator
);
811 handle_child_sa_failure(this, message
);
819 iterator
->destroy(iterator
);
821 this->child_sa
= child_sa_create(
822 this->ike_sa
->get_my_host(this->ike_sa
),
823 this->ike_sa
->get_other_host(this->ike_sa
),
824 this->ike_sa
->get_my_id(this->ike_sa
),
825 this->ike_sa
->get_other_id(this->ike_sa
), this->config
, this->reqid
,
826 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
828 if (this->config
->use_ipcomp(this->config
) &&
829 this->ipcomp_received
!= IPCOMP_NONE
)
831 this->ipcomp
= this->ipcomp_received
;
832 build_ipcomp_supported_notify(this, message
);
834 else if (this->ipcomp_received
!= IPCOMP_NONE
)
836 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
837 notify_type_names
, IPCOMP_SUPPORTED
);
840 switch (select_and_install(this, no_dh
))
845 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
846 handle_child_sa_failure(this, message
);
850 u_int16_t group
= htons(this->dh_group
);
851 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
852 chunk_from_thing(group
));
853 handle_child_sa_failure(this, message
);
858 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
859 handle_child_sa_failure(this, message
);
863 build_payloads(this, message
);
865 SIG_CHD(UP_SUCCESS
, this->child_sa
, "CHILD_SA '%s{%d}' established "
866 "with ts %#R=== %#R",
867 this->child_sa
->get_name(this->child_sa
),
868 this->child_sa
->get_reqid(this->child_sa
),
869 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
870 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
876 * Implementation of task_t.process for initiator
878 static status_t
process_i(private_child_create_t
*this, message_t
*message
)
880 iterator_t
*iterator
;
884 switch (message
->get_exchange_type(message
))
887 return get_nonce(message
, &this->other_nonce
);
888 case CREATE_CHILD_SA
:
889 get_nonce(message
, &this->other_nonce
);
893 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
895 /* wait until extensible authentication completed, if used */
902 /* check for erronous notifies */
903 iterator
= message
->get_payload_iterator(message
);
904 while (iterator
->iterate(iterator
, (void**)&payload
))
906 if (payload
->get_type(payload
) == NOTIFY
)
908 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
909 notify_type_t type
= notify
->get_notify_type(notify
);
913 /* handle notify errors related to CHILD_SA only */
914 case NO_PROPOSAL_CHOSEN
:
915 case SINGLE_PAIR_REQUIRED
:
916 case NO_ADDITIONAL_SAS
:
917 case INTERNAL_ADDRESS_FAILURE
:
918 case FAILED_CP_REQUIRED
:
919 case TS_UNACCEPTABLE
:
920 case INVALID_SELECTORS
:
922 SIG_CHD(UP_FAILED
, this->child_sa
, "received %N notify, "
923 "no CHILD_SA built", notify_type_names
, type
);
924 iterator
->destroy(iterator
);
925 handle_child_sa_failure(this, message
);
926 /* an error in CHILD_SA creation is not critical */
929 case INVALID_KE_PAYLOAD
:
932 diffie_hellman_group_t bad_group
;
934 bad_group
= this->dh_group
;
935 data
= notify
->get_notification_data(notify
);
936 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
937 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
938 "it requested %N", diffie_hellman_group_names
,
939 bad_group
, diffie_hellman_group_names
, this->dh_group
);
941 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
942 iterator
->destroy(iterator
);
950 iterator
->destroy(iterator
);
952 process_payloads(this, message
);
954 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
956 SIG_CHD(UP_FAILED
, this->child_sa
, "received an IPCOMP_SUPPORTED notify"
957 " but we did not send one previously, no CHILD_SA built");
958 handle_child_sa_failure(this, message
);
961 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
963 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
964 "IPComp is disabled");
965 this->ipcomp
= IPCOMP_NONE
;
967 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
969 SIG_CHD(UP_FAILED
, this->child_sa
, "received an IPCOMP_SUPPORTED notify"
970 " for a transform we did not propose, no CHILD_SA built");
971 handle_child_sa_failure(this, message
);
975 if (select_and_install(this, no_dh
) == SUCCESS
)
977 SIG_CHD(UP_SUCCESS
, this->child_sa
, "CHILD_SA '%s{%d}' established "
978 "with ts %#R=== %#R",
979 this->child_sa
->get_name(this->child_sa
),
980 this->child_sa
->get_reqid(this->child_sa
),
981 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
982 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
986 handle_child_sa_failure(this, message
);
992 * Implementation of task_t.get_type
994 static task_type_t
get_type(private_child_create_t
*this)
1000 * Implementation of child_create_t.use_reqid
1002 static void use_reqid(private_child_create_t
*this, u_int32_t reqid
)
1004 this->reqid
= reqid
;
1008 * Implementation of child_create_t.get_child
1010 static child_sa_t
* get_child(private_child_create_t
*this)
1012 return this->child_sa
;
1016 * Implementation of child_create_t.get_lower_nonce
1018 static chunk_t
get_lower_nonce(private_child_create_t
*this)
1020 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1021 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1023 return this->my_nonce
;
1027 return this->other_nonce
;
1032 * Implementation of task_t.migrate
1034 static void migrate(private_child_create_t
*this, ike_sa_t
*ike_sa
)
1036 chunk_free(&this->my_nonce
);
1037 chunk_free(&this->other_nonce
);
1040 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1044 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1046 DESTROY_IF(this->child_sa
);
1047 DESTROY_IF(this->proposal
);
1048 DESTROY_IF(this->dh
);
1049 if (this->proposals
)
1051 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1054 this->ike_sa
= ike_sa
;
1055 this->proposals
= NULL
;
1059 this->child_sa
= NULL
;
1060 this->mode
= MODE_TUNNEL
;
1061 this->ipcomp
= IPCOMP_NONE
;
1062 this->ipcomp_received
= IPCOMP_NONE
;
1063 this->other_cpi
= 0;
1065 this->established
= FALSE
;
1069 * Implementation of task_t.destroy
1071 static void destroy(private_child_create_t
*this)
1073 chunk_free(&this->my_nonce
);
1074 chunk_free(&this->other_nonce
);
1077 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1081 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1083 if (!this->established
)
1085 DESTROY_IF(this->child_sa
);
1087 DESTROY_IF(this->proposal
);
1088 DESTROY_IF(this->dh
);
1089 if (this->proposals
)
1091 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1094 DESTROY_IF(this->config
);
1099 * Described in header.
1101 child_create_t
*child_create_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
)
1103 private_child_create_t
*this = malloc_thing(private_child_create_t
);
1105 this->public.get_child
= (child_sa_t
*(*)(child_create_t
*))get_child
;
1106 this->public.get_lower_nonce
= (chunk_t(*)(child_create_t
*))get_lower_nonce
;
1107 this->public.use_reqid
= (void(*)(child_create_t
*,u_int32_t
))use_reqid
;
1108 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
1109 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
1110 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
1113 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
1114 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
1115 this->initiator
= TRUE
;
1116 config
->get_ref(config
);
1120 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
1121 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
1122 this->initiator
= FALSE
;
1125 this->ike_sa
= ike_sa
;
1126 this->config
= config
;
1127 this->my_nonce
= chunk_empty
;
1128 this->other_nonce
= chunk_empty
;
1129 this->proposals
= NULL
;
1130 this->proposal
= NULL
;
1134 this->dh_group
= MODP_NONE
;
1135 this->child_sa
= NULL
;
1136 this->mode
= MODE_TUNNEL
;
1137 this->ipcomp
= IPCOMP_NONE
;
1138 this->ipcomp_received
= IPCOMP_NONE
;
1139 this->other_cpi
= 0;
1141 this->established
= FALSE
;
1143 return &this->public;