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 */
595 SIG_CHD(UP_START
, NULL
, "establishing CHILD_SA %s{%d}",
596 this->config
->get_name(this->config
), this->reqid
);
600 SIG_CHD(UP_START
, NULL
, "establishing CHILD_SA %s{?}",
601 this->config
->get_name(this->config
));
604 /* reuse virtual IP if we already have one */
605 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
608 me
= this->ike_sa
->get_my_host(this->ike_sa
);
610 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
613 other
= this->ike_sa
->get_other_host(this->ike_sa
);
616 /* check if we want a virtual IP, but don't have one */
619 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
620 vip
= peer_cfg
->get_virtual_ip(peer_cfg
);
628 { /* propose a 0.0.0.0/0 subnet when we use virtual ip */
629 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
633 { /* but shorten a 0.0.0.0/0 subnet for host2host/we already have a vip */
634 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
637 this->tsr
= this->config
->get_traffic_selectors(this->config
, FALSE
,
640 this->proposals
= this->config
->get_proposals(this->config
,
641 this->dh_group
== MODP_NONE
);
642 this->mode
= this->config
->get_mode(this->config
);
644 this->child_sa
= child_sa_create(
645 this->ike_sa
->get_my_host(this->ike_sa
),
646 this->ike_sa
->get_other_host(this->ike_sa
),
647 this->ike_sa
->get_my_id(this->ike_sa
),
648 this->ike_sa
->get_other_id(this->ike_sa
), this->config
, this->reqid
,
649 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
651 if (this->child_sa
->alloc(this->child_sa
, this->proposals
) != SUCCESS
)
653 SIG_CHD(UP_FAILED
, this->child_sa
,
654 "unable to allocate SPIs from kernel");
658 if (this->dh_group
!= MODP_NONE
)
660 this->dh
= lib
->crypto
->create_dh(lib
->crypto
, this->dh_group
);
663 if (this->config
->use_ipcomp(this->config
)) {
664 /* IPCOMP_DEFLATE is the only transform we support at the moment */
665 this->ipcomp
= IPCOMP_DEFLATE
;
666 build_ipcomp_supported_notify(this, message
);
669 build_payloads(this, message
);
671 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
672 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
673 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
676 this->proposals
= NULL
;
682 * Implementation of task_t.process for initiator
684 static status_t
process_r(private_child_create_t
*this, message_t
*message
)
686 peer_cfg_t
*peer_cfg
;
688 switch (message
->get_exchange_type(message
))
691 return get_nonce(message
, &this->other_nonce
);
692 case CREATE_CHILD_SA
:
693 get_nonce(message
, &this->other_nonce
);
696 if (message
->get_payload(message
, ID_INITIATOR
) == NULL
)
698 /* wait until extensible authentication completed, if used */
705 process_payloads(this, message
);
707 if (this->tsi
== NULL
|| this->tsr
== NULL
)
709 DBG1(DBG_IKE
, "TS payload missing in message");
713 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
718 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
721 me
= this->ike_sa
->get_my_host(this->ike_sa
);
723 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
726 other
= this->ike_sa
->get_other_host(this->ike_sa
);
729 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, this->tsr
,
730 this->tsi
, me
, other
);
736 * handle CHILD_SA setup failure
738 static void handle_child_sa_failure(private_child_create_t
*this,
741 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
742 lib
->settings
->get_bool(lib
->settings
,
743 "charon.close_ike_on_child_failure", FALSE
))
745 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
747 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
748 charon
->scheduler
->schedule_job(charon
->scheduler
, (job_t
*)
749 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
755 * Implementation of task_t.build for responder
757 static status_t
build_r(private_child_create_t
*this, message_t
*message
)
760 iterator_t
*iterator
;
763 switch (message
->get_exchange_type(message
))
766 return get_nonce(message
, &this->my_nonce
);
767 case CREATE_CHILD_SA
:
768 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
770 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
777 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
779 /* wait until extensible authentication completed, if used */
786 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
788 SIG_CHD(UP_FAILED
, NULL
,
789 "unable to create CHILD_SA while rekeying IKE_SA");
790 message
->add_notify(message
, TRUE
, NO_ADDITIONAL_SAS
, chunk_empty
);
794 if (this->config
== NULL
)
796 SIG_CHD(UP_FAILED
, NULL
, "traffic selectors %#R=== %#R inacceptable",
797 this->tsr
, this->tsi
);
798 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
799 handle_child_sa_failure(this, message
);
803 /* check if ike_config_t included non-critical error notifies */
804 iterator
= message
->get_payload_iterator(message
);
805 while (iterator
->iterate(iterator
, (void**)&payload
))
807 if (payload
->get_type(payload
) == NOTIFY
)
809 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
811 switch (notify
->get_notify_type(notify
))
813 case INTERNAL_ADDRESS_FAILURE
:
814 case FAILED_CP_REQUIRED
:
816 SIG_CHD(UP_FAILED
, NULL
, "configuration payload negotation "
817 "failed, no CHILD_SA built");
818 iterator
->destroy(iterator
);
819 handle_child_sa_failure(this, message
);
827 iterator
->destroy(iterator
);
829 this->child_sa
= child_sa_create(
830 this->ike_sa
->get_my_host(this->ike_sa
),
831 this->ike_sa
->get_other_host(this->ike_sa
),
832 this->ike_sa
->get_my_id(this->ike_sa
),
833 this->ike_sa
->get_other_id(this->ike_sa
), this->config
, this->reqid
,
834 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
836 if (this->config
->use_ipcomp(this->config
) &&
837 this->ipcomp_received
!= IPCOMP_NONE
)
839 this->ipcomp
= this->ipcomp_received
;
840 build_ipcomp_supported_notify(this, message
);
842 else if (this->ipcomp_received
!= IPCOMP_NONE
)
844 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
845 notify_type_names
, IPCOMP_SUPPORTED
);
848 switch (select_and_install(this, no_dh
))
853 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
854 handle_child_sa_failure(this, message
);
858 u_int16_t group
= htons(this->dh_group
);
859 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
860 chunk_from_thing(group
));
861 handle_child_sa_failure(this, message
);
866 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
867 handle_child_sa_failure(this, message
);
871 build_payloads(this, message
);
873 SIG_CHD(UP_SUCCESS
, this->child_sa
, "CHILD_SA %s{%d} established "
874 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
875 this->child_sa
->get_name(this->child_sa
),
876 this->child_sa
->get_reqid(this->child_sa
),
877 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
878 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
879 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
880 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
886 * Implementation of task_t.process for initiator
888 static status_t
process_i(private_child_create_t
*this, message_t
*message
)
890 iterator_t
*iterator
;
894 switch (message
->get_exchange_type(message
))
897 return get_nonce(message
, &this->other_nonce
);
898 case CREATE_CHILD_SA
:
899 get_nonce(message
, &this->other_nonce
);
903 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
905 /* wait until extensible authentication completed, if used */
912 /* check for erronous notifies */
913 iterator
= message
->get_payload_iterator(message
);
914 while (iterator
->iterate(iterator
, (void**)&payload
))
916 if (payload
->get_type(payload
) == NOTIFY
)
918 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
919 notify_type_t type
= notify
->get_notify_type(notify
);
923 /* handle notify errors related to CHILD_SA only */
924 case NO_PROPOSAL_CHOSEN
:
925 case SINGLE_PAIR_REQUIRED
:
926 case NO_ADDITIONAL_SAS
:
927 case INTERNAL_ADDRESS_FAILURE
:
928 case FAILED_CP_REQUIRED
:
929 case TS_UNACCEPTABLE
:
930 case INVALID_SELECTORS
:
932 SIG_CHD(UP_FAILED
, this->child_sa
, "received %N notify, "
933 "no CHILD_SA built", notify_type_names
, type
);
934 iterator
->destroy(iterator
);
935 handle_child_sa_failure(this, message
);
936 /* an error in CHILD_SA creation is not critical */
939 case INVALID_KE_PAYLOAD
:
942 diffie_hellman_group_t bad_group
;
944 bad_group
= this->dh_group
;
945 data
= notify
->get_notification_data(notify
);
946 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
947 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
948 "it requested %N", diffie_hellman_group_names
,
949 bad_group
, diffie_hellman_group_names
, this->dh_group
);
951 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
952 iterator
->destroy(iterator
);
960 iterator
->destroy(iterator
);
962 process_payloads(this, message
);
964 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
966 SIG_CHD(UP_FAILED
, this->child_sa
, "received an IPCOMP_SUPPORTED notify"
967 " but we did not send one previously, no CHILD_SA built");
968 handle_child_sa_failure(this, message
);
971 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
973 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
974 "IPComp is disabled");
975 this->ipcomp
= IPCOMP_NONE
;
977 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
979 SIG_CHD(UP_FAILED
, this->child_sa
, "received an IPCOMP_SUPPORTED notify"
980 " for a transform we did not propose, no CHILD_SA built");
981 handle_child_sa_failure(this, message
);
985 if (select_and_install(this, no_dh
) == SUCCESS
)
987 SIG_CHD(UP_SUCCESS
, this->child_sa
, "CHILD_SA %s{%d} established "
988 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
989 this->child_sa
->get_name(this->child_sa
),
990 this->child_sa
->get_reqid(this->child_sa
),
991 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
992 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
993 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
994 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
998 handle_child_sa_failure(this, message
);
1004 * Implementation of task_t.get_type
1006 static task_type_t
get_type(private_child_create_t
*this)
1008 return CHILD_CREATE
;
1012 * Implementation of child_create_t.use_reqid
1014 static void use_reqid(private_child_create_t
*this, u_int32_t reqid
)
1016 this->reqid
= reqid
;
1020 * Implementation of child_create_t.get_child
1022 static child_sa_t
* get_child(private_child_create_t
*this)
1024 return this->child_sa
;
1028 * Implementation of child_create_t.get_lower_nonce
1030 static chunk_t
get_lower_nonce(private_child_create_t
*this)
1032 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1033 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1035 return this->my_nonce
;
1039 return this->other_nonce
;
1044 * Implementation of task_t.migrate
1046 static void migrate(private_child_create_t
*this, ike_sa_t
*ike_sa
)
1048 chunk_free(&this->my_nonce
);
1049 chunk_free(&this->other_nonce
);
1052 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1056 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1058 DESTROY_IF(this->child_sa
);
1059 DESTROY_IF(this->proposal
);
1060 DESTROY_IF(this->dh
);
1061 if (this->proposals
)
1063 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1066 this->ike_sa
= ike_sa
;
1067 this->proposals
= NULL
;
1071 this->child_sa
= NULL
;
1072 this->mode
= MODE_TUNNEL
;
1073 this->ipcomp
= IPCOMP_NONE
;
1074 this->ipcomp_received
= IPCOMP_NONE
;
1075 this->other_cpi
= 0;
1077 this->established
= FALSE
;
1081 * Implementation of task_t.destroy
1083 static void destroy(private_child_create_t
*this)
1085 chunk_free(&this->my_nonce
);
1086 chunk_free(&this->other_nonce
);
1089 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1093 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1095 if (!this->established
)
1097 DESTROY_IF(this->child_sa
);
1099 DESTROY_IF(this->proposal
);
1100 DESTROY_IF(this->dh
);
1101 if (this->proposals
)
1103 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1106 DESTROY_IF(this->config
);
1111 * Described in header.
1113 child_create_t
*child_create_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
)
1115 private_child_create_t
*this = malloc_thing(private_child_create_t
);
1117 this->public.get_child
= (child_sa_t
*(*)(child_create_t
*))get_child
;
1118 this->public.get_lower_nonce
= (chunk_t(*)(child_create_t
*))get_lower_nonce
;
1119 this->public.use_reqid
= (void(*)(child_create_t
*,u_int32_t
))use_reqid
;
1120 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
1121 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
1122 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
1125 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
1126 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
1127 this->initiator
= TRUE
;
1128 config
->get_ref(config
);
1132 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
1133 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
1134 this->initiator
= FALSE
;
1137 this->ike_sa
= ike_sa
;
1138 this->config
= config
;
1139 this->my_nonce
= chunk_empty
;
1140 this->other_nonce
= chunk_empty
;
1141 this->proposals
= NULL
;
1142 this->proposal
= NULL
;
1146 this->dh_group
= MODP_NONE
;
1147 this->child_sa
= NULL
;
1148 this->mode
= MODE_TUNNEL
;
1149 this->ipcomp
= IPCOMP_NONE
;
1150 this->ipcomp_received
= IPCOMP_NONE
;
1151 this->other_cpi
= 0;
1153 this->established
= FALSE
;
1155 return &this->public;