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
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
;
105 * mode the new CHILD_SA uses (transport/tunnel/beet)
110 * IPComp transform to use
112 ipcomp_transform_t ipcomp
;
115 * IPComp transform proposed or accepted by the other peer
117 ipcomp_transform_t ipcomp_received
;
120 * Other Compression Parameter Index (CPI)
125 * reqid to use if we are rekeying
130 * CHILD_SA which gets established
132 child_sa_t
*child_sa
;
135 * successfully established the CHILD?
141 * get the nonce from a message
143 static status_t
get_nonce(message_t
*message
, chunk_t
*nonce
)
145 nonce_payload_t
*payload
;
147 payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
152 *nonce
= payload
->get_nonce(payload
);
157 * generate a new nonce to include in a CREATE_CHILD_SA message
159 static status_t
generate_nonce(chunk_t
*nonce
)
163 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
166 DBG1(DBG_IKE
, "error generating nonce value, no RNG found");
169 rng
->allocate_bytes(rng
, NONCE_SIZE
, nonce
);
175 * Check a list of traffic selectors if any selector belongs to host
177 static bool ts_list_is_host(linked_list_t
*list
, host_t
*host
)
179 traffic_selector_t
*ts
;
181 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
183 while (is_host
&& iterator
->iterate(iterator
, (void**)&ts
))
185 is_host
= is_host
&& ts
->is_host(ts
, host
);
187 iterator
->destroy(iterator
);
192 * Install a CHILD_SA for usage, return value:
193 * - FAILED: no acceptable proposal
194 * - INVALID_ARG: diffie hellman group inacceptable
195 * - NOT_FOUND: TS inacceptable
197 static status_t
select_and_install(private_child_create_t
*this, bool no_dh
)
200 chunk_t nonce_i
, nonce_r
, encr_i
, integ_i
, encr_r
, integ_r
;
201 linked_list_t
*my_ts
, *other_ts
;
202 host_t
*me
, *other
, *other_vip
, *my_vip
;
204 if (this->proposals
== NULL
)
206 DBG1(DBG_IKE
, "SA payload missing in message");
209 if (this->tsi
== NULL
|| this->tsr
== NULL
)
211 DBG1(DBG_IKE
, "TS payloads missing in message");
215 me
= this->ike_sa
->get_my_host(this->ike_sa
);
216 other
= this->ike_sa
->get_other_host(this->ike_sa
);
217 my_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
218 other_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
220 this->proposal
= this->config
->select_proposal(this->config
, this->proposals
,
222 if (this->proposal
== NULL
)
224 DBG1(DBG_IKE
, "no acceptable proposal found");
228 if (!this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
232 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
235 DBG1(DBG_IKE
, "DH group %N inacceptable, requesting %N",
236 diffie_hellman_group_names
, this->dh_group
,
237 diffie_hellman_group_names
, group
);
238 this->dh_group
= group
;
243 DBG1(DBG_IKE
, "no acceptable proposal found");
252 if (other_vip
== NULL
)
259 nonce_i
= this->my_nonce
;
260 nonce_r
= this->other_nonce
;
262 other_ts
= this->tsr
;
266 nonce_r
= this->my_nonce
;
267 nonce_i
= this->other_nonce
;
269 other_ts
= this->tsi
;
271 my_ts
= this->config
->get_traffic_selectors(this->config
, TRUE
, my_ts
,
273 other_ts
= this->config
->get_traffic_selectors(this->config
, FALSE
, other_ts
,
276 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
278 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
279 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
280 DBG1(DBG_IKE
, "no acceptable traffic selectors found");
284 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
285 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
289 this->tsr
= other_ts
;
294 this->tsi
= other_ts
;
297 if (!this->initiator
)
299 /* check if requested mode is acceptable, downgrade if required */
303 if (!ts_list_is_host(this->tsi
, other
) ||
304 !ts_list_is_host(this->tsr
, me
))
306 this->mode
= MODE_TUNNEL
;
307 DBG1(DBG_IKE
, "not using tranport mode, not host-to-host");
309 else if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
311 this->mode
= MODE_TUNNEL
;
312 DBG1(DBG_IKE
, "not using tranport mode, connection NATed");
316 if (!ts_list_is_host(this->tsi
, NULL
) ||
317 !ts_list_is_host(this->tsr
, NULL
))
319 this->mode
= MODE_TUNNEL
;
320 DBG1(DBG_IKE
, "not using BEET mode, not host-to-host");
328 if (this->ipcomp
!= IPCOMP_NONE
)
330 this->child_sa
->activate_ipcomp(this->child_sa
, this->ipcomp
,
334 status
= this->child_sa
->add_policies(this->child_sa
, my_ts
, other_ts
,
335 this->mode
, this->proposal
->get_protocol(this->proposal
));
336 if (status
!= SUCCESS
)
338 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
343 if (this->keymat
->derive_child_keys(this->keymat
, this->proposal
,
344 this->dh
, nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
))
348 status
= this->child_sa
->update(this->child_sa
, this->proposal
,
349 this->mode
, integ_r
, integ_i
, encr_r
, encr_i
);
353 status
= this->child_sa
->add(this->child_sa
, this->proposal
,
354 this->mode
, integ_i
, integ_r
, encr_i
, encr_r
);
357 chunk_clear(&integ_i
);
358 chunk_clear(&integ_r
);
359 chunk_clear(&encr_i
);
360 chunk_clear(&encr_r
);
362 if (status
!= SUCCESS
)
364 DBG1(DBG_IKE
, "unable to install IPsec SA (SAD) in kernel");
368 charon
->bus
->child_keys(charon
->bus
, this->child_sa
, this->dh
,
371 /* add to IKE_SA, and remove from task */
372 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
373 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
374 this->established
= TRUE
;
379 * build the payloads for the message
381 static void build_payloads(private_child_create_t
*this, message_t
*message
)
383 sa_payload_t
*sa_payload
;
384 nonce_payload_t
*nonce_payload
;
385 ke_payload_t
*ke_payload
;
386 ts_payload_t
*ts_payload
;
391 sa_payload
= sa_payload_create_from_proposal_list(this->proposals
);
395 sa_payload
= sa_payload_create_from_proposal(this->proposal
);
397 message
->add_payload(message
, (payload_t
*)sa_payload
);
399 /* add nonce payload if not in IKE_AUTH */
400 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
402 nonce_payload
= nonce_payload_create();
403 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
404 message
->add_payload(message
, (payload_t
*)nonce_payload
);
407 /* diffie hellman exchange, if PFS enabled */
410 ke_payload
= ke_payload_create_from_diffie_hellman(this->dh
);
411 message
->add_payload(message
, (payload_t
*)ke_payload
);
414 /* add TSi/TSr payloads */
415 ts_payload
= ts_payload_create_from_traffic_selectors(TRUE
, this->tsi
);
416 message
->add_payload(message
, (payload_t
*)ts_payload
);
417 ts_payload
= ts_payload_create_from_traffic_selectors(FALSE
, this->tsr
);
418 message
->add_payload(message
, (payload_t
*)ts_payload
);
420 /* add a notify if we are not in tunnel mode */
424 message
->add_notify(message
, FALSE
, USE_TRANSPORT_MODE
, chunk_empty
);
427 message
->add_notify(message
, FALSE
, USE_BEET_MODE
, chunk_empty
);
435 * Adds an IPCOMP_SUPPORTED notify to the message, if possible
437 static void build_ipcomp_supported_notify(private_child_create_t
*this,
443 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
445 DBG1(DBG_IKE
, "IPComp is not supported if either peer is natted, "
447 this->ipcomp
= IPCOMP_NONE
;
451 cpi
= this->child_sa
->allocate_cpi(this->child_sa
);
455 message
->add_notify(message
, FALSE
, IPCOMP_SUPPORTED
,
456 chunk_cata("cc", chunk_from_thing(cpi
), chunk_from_thing(tid
)));
460 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, IPComp disabled");
461 this->ipcomp
= IPCOMP_NONE
;
466 * Read payloads from message
468 static void process_payloads(private_child_create_t
*this, message_t
*message
)
470 iterator_t
*iterator
;
472 sa_payload_t
*sa_payload
;
473 ke_payload_t
*ke_payload
;
474 ts_payload_t
*ts_payload
;
475 notify_payload_t
*notify_payload
;
477 /* defaults to TUNNEL mode */
478 this->mode
= MODE_TUNNEL
;
480 iterator
= message
->get_payload_iterator(message
);
481 while (iterator
->iterate(iterator
, (void**)&payload
))
483 switch (payload
->get_type(payload
))
485 case SECURITY_ASSOCIATION
:
486 sa_payload
= (sa_payload_t
*)payload
;
487 this->proposals
= sa_payload
->get_proposals(sa_payload
);
490 ke_payload
= (ke_payload_t
*)payload
;
491 if (!this->initiator
)
493 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
494 this->dh
= this->keymat
->create_dh(this->keymat
, this->dh_group
);
498 this->dh
->set_other_public_value(this->dh
,
499 ke_payload
->get_key_exchange_data(ke_payload
));
502 case TRAFFIC_SELECTOR_INITIATOR
:
503 ts_payload
= (ts_payload_t
*)payload
;
504 this->tsi
= ts_payload
->get_traffic_selectors(ts_payload
);
506 case TRAFFIC_SELECTOR_RESPONDER
:
507 ts_payload
= (ts_payload_t
*)payload
;
508 this->tsr
= ts_payload
->get_traffic_selectors(ts_payload
);
511 notify_payload
= (notify_payload_t
*)payload
;
512 switch (notify_payload
->get_notify_type(notify_payload
))
514 case USE_TRANSPORT_MODE
:
515 this->mode
= MODE_TRANSPORT
;
518 this->mode
= MODE_BEET
;
520 case IPCOMP_SUPPORTED
:
522 chunk_t data
= notify_payload
->get_notification_data(notify_payload
);
523 u_int16_t cpi
= *(u_int16_t
*)data
.ptr
;
524 ipcomp_transform_t ipcomp
= (ipcomp_transform_t
)(*(data
.ptr
+ 2));
528 this->other_cpi
= cpi
;
529 this->ipcomp_received
= ipcomp
;
534 DBG1(DBG_IKE
, "received IPCOMP_SUPPORTED notify with a transform"
535 " ID we don't support %N", ipcomp_transform_names
, ipcomp
);
547 iterator
->destroy(iterator
);
551 * Implementation of task_t.build for initiator
553 static status_t
build_i(private_child_create_t
*this, message_t
*message
)
555 host_t
*me
, *other
, *vip
;
556 bool propose_all
= FALSE
;
557 peer_cfg_t
*peer_cfg
;
559 switch (message
->get_exchange_type(message
))
562 return get_nonce(message
, &this->my_nonce
);
563 case CREATE_CHILD_SA
:
564 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
566 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
569 if (this->dh_group
== MODP_NONE
)
571 this->dh_group
= this->config
->get_dh_group(this->config
);
575 if (!message
->get_payload(message
, ID_INITIATOR
))
577 /* send only in the first request, not in subsequent EAP */
587 DBG0(DBG_IKE
, "establishing CHILD_SA %s{%d}",
588 this->config
->get_name(this->config
), this->reqid
);
592 DBG0(DBG_IKE
, "establishing CHILD_SA %s",
593 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(this->ike_sa
->get_my_host(this->ike_sa
),
637 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
638 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
640 if (this->child_sa
->alloc(this->child_sa
, this->proposals
) != SUCCESS
)
642 DBG1(DBG_IKE
, "unable to allocate SPIs from kernel");
646 if (this->dh_group
!= MODP_NONE
)
648 this->dh
= this->keymat
->create_dh(this->keymat
, this->dh_group
);
651 if (this->config
->use_ipcomp(this->config
)) {
652 /* IPCOMP_DEFLATE is the only transform we support at the moment */
653 this->ipcomp
= IPCOMP_DEFLATE
;
654 build_ipcomp_supported_notify(this, message
);
657 build_payloads(this, message
);
659 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
660 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
661 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
664 this->proposals
= NULL
;
670 * Implementation of task_t.process for responder
672 static status_t
process_r(private_child_create_t
*this, message_t
*message
)
674 peer_cfg_t
*peer_cfg
;
676 switch (message
->get_exchange_type(message
))
679 return get_nonce(message
, &this->other_nonce
);
680 case CREATE_CHILD_SA
:
681 get_nonce(message
, &this->other_nonce
);
684 if (message
->get_payload(message
, ID_INITIATOR
) == NULL
)
686 /* wait until extensible authentication completed, if used */
693 process_payloads(this, message
);
695 if (this->tsi
== NULL
|| this->tsr
== NULL
)
697 DBG1(DBG_IKE
, "TS payload missing in message");
701 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
706 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
709 me
= this->ike_sa
->get_my_host(this->ike_sa
);
711 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
714 other
= this->ike_sa
->get_other_host(this->ike_sa
);
717 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, this->tsr
,
718 this->tsi
, me
, other
);
724 * handle CHILD_SA setup failure
726 static void handle_child_sa_failure(private_child_create_t
*this,
729 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
730 lib
->settings
->get_bool(lib
->settings
,
731 "charon.close_ike_on_child_failure", FALSE
))
733 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
735 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
736 charon
->scheduler
->schedule_job(charon
->scheduler
, (job_t
*)
737 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
743 * Implementation of task_t.build for responder
745 static status_t
build_r(private_child_create_t
*this, message_t
*message
)
748 iterator_t
*iterator
;
751 switch (message
->get_exchange_type(message
))
754 return get_nonce(message
, &this->my_nonce
);
755 case CREATE_CHILD_SA
:
756 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
758 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
765 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
767 /* wait until extensible authentication completed, if used */
774 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
776 DBG1(DBG_IKE
, "unable to create CHILD_SA while rekeying IKE_SA");
777 message
->add_notify(message
, TRUE
, NO_ADDITIONAL_SAS
, chunk_empty
);
781 if (this->config
== NULL
)
783 DBG1(DBG_IKE
, "traffic selectors %#R=== %#R inacceptable",
784 this->tsr
, this->tsi
);
785 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
786 handle_child_sa_failure(this, message
);
790 /* check if ike_config_t included non-critical error notifies */
791 iterator
= message
->get_payload_iterator(message
);
792 while (iterator
->iterate(iterator
, (void**)&payload
))
794 if (payload
->get_type(payload
) == NOTIFY
)
796 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
798 switch (notify
->get_notify_type(notify
))
800 case INTERNAL_ADDRESS_FAILURE
:
801 case FAILED_CP_REQUIRED
:
803 DBG1(DBG_IKE
,"configuration payload negotation "
804 "failed, no CHILD_SA built");
805 iterator
->destroy(iterator
);
806 handle_child_sa_failure(this, message
);
814 iterator
->destroy(iterator
);
816 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
817 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
818 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
820 if (this->config
->use_ipcomp(this->config
) &&
821 this->ipcomp_received
!= IPCOMP_NONE
)
823 this->ipcomp
= this->ipcomp_received
;
824 build_ipcomp_supported_notify(this, message
);
826 else if (this->ipcomp_received
!= IPCOMP_NONE
)
828 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
829 notify_type_names
, IPCOMP_SUPPORTED
);
832 switch (select_and_install(this, no_dh
))
837 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
838 handle_child_sa_failure(this, message
);
842 u_int16_t group
= htons(this->dh_group
);
843 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
844 chunk_from_thing(group
));
845 handle_child_sa_failure(this, message
);
850 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
851 handle_child_sa_failure(this, message
);
855 build_payloads(this, message
);
857 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
858 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
859 this->child_sa
->get_name(this->child_sa
),
860 this->child_sa
->get_reqid(this->child_sa
),
861 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
862 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
863 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
864 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
870 * Implementation of task_t.process for initiator
872 static status_t
process_i(private_child_create_t
*this, message_t
*message
)
874 iterator_t
*iterator
;
878 switch (message
->get_exchange_type(message
))
881 return get_nonce(message
, &this->other_nonce
);
882 case CREATE_CHILD_SA
:
883 get_nonce(message
, &this->other_nonce
);
887 if (message
->get_payload(message
, EXTENSIBLE_AUTHENTICATION
))
889 /* wait until extensible authentication completed, if used */
896 /* check for erronous notifies */
897 iterator
= message
->get_payload_iterator(message
);
898 while (iterator
->iterate(iterator
, (void**)&payload
))
900 if (payload
->get_type(payload
) == NOTIFY
)
902 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
903 notify_type_t type
= notify
->get_notify_type(notify
);
907 /* handle notify errors related to CHILD_SA only */
908 case NO_PROPOSAL_CHOSEN
:
909 case SINGLE_PAIR_REQUIRED
:
910 case NO_ADDITIONAL_SAS
:
911 case INTERNAL_ADDRESS_FAILURE
:
912 case FAILED_CP_REQUIRED
:
913 case TS_UNACCEPTABLE
:
914 case INVALID_SELECTORS
:
916 DBG1(DBG_IKE
, "received %N notify, no CHILD_SA built",
917 notify_type_names
, type
);
918 iterator
->destroy(iterator
);
919 handle_child_sa_failure(this, message
);
920 /* an error in CHILD_SA creation is not critical */
923 case INVALID_KE_PAYLOAD
:
926 diffie_hellman_group_t bad_group
;
928 bad_group
= this->dh_group
;
929 data
= notify
->get_notification_data(notify
);
930 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
931 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
932 "it requested %N", diffie_hellman_group_names
,
933 bad_group
, diffie_hellman_group_names
, this->dh_group
);
935 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
936 iterator
->destroy(iterator
);
944 iterator
->destroy(iterator
);
946 process_payloads(this, message
);
948 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
950 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify without requesting"
951 " one, no CHILD_SA built");
952 handle_child_sa_failure(this, message
);
955 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
957 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
958 "IPComp is disabled");
959 this->ipcomp
= IPCOMP_NONE
;
961 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
963 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify we didn't propose, "
964 "no CHILD_SA built");
965 handle_child_sa_failure(this, message
);
969 if (select_and_install(this, no_dh
) == SUCCESS
)
971 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
972 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
973 this->child_sa
->get_name(this->child_sa
),
974 this->child_sa
->get_reqid(this->child_sa
),
975 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
976 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
977 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
978 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
982 handle_child_sa_failure(this, message
);
988 * Implementation of task_t.get_type
990 static task_type_t
get_type(private_child_create_t
*this)
996 * Implementation of child_create_t.use_reqid
998 static void use_reqid(private_child_create_t
*this, u_int32_t reqid
)
1000 this->reqid
= reqid
;
1004 * Implementation of child_create_t.get_child
1006 static child_sa_t
* get_child(private_child_create_t
*this)
1008 return this->child_sa
;
1012 * Implementation of child_create_t.get_lower_nonce
1014 static chunk_t
get_lower_nonce(private_child_create_t
*this)
1016 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1017 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1019 return this->my_nonce
;
1023 return this->other_nonce
;
1028 * Implementation of task_t.migrate
1030 static void migrate(private_child_create_t
*this, ike_sa_t
*ike_sa
)
1032 chunk_free(&this->my_nonce
);
1033 chunk_free(&this->other_nonce
);
1036 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1040 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1042 DESTROY_IF(this->child_sa
);
1043 DESTROY_IF(this->proposal
);
1044 DESTROY_IF(this->dh
);
1045 if (this->proposals
)
1047 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1050 this->ike_sa
= ike_sa
;
1051 this->proposals
= NULL
;
1055 this->child_sa
= NULL
;
1056 this->mode
= MODE_TUNNEL
;
1057 this->ipcomp
= IPCOMP_NONE
;
1058 this->ipcomp_received
= IPCOMP_NONE
;
1059 this->other_cpi
= 0;
1061 this->established
= FALSE
;
1065 * Implementation of task_t.destroy
1067 static void destroy(private_child_create_t
*this)
1069 chunk_free(&this->my_nonce
);
1070 chunk_free(&this->other_nonce
);
1073 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1077 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1079 if (!this->established
)
1081 DESTROY_IF(this->child_sa
);
1083 DESTROY_IF(this->proposal
);
1084 DESTROY_IF(this->dh
);
1085 if (this->proposals
)
1087 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1090 DESTROY_IF(this->config
);
1095 * Described in header.
1097 child_create_t
*child_create_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
)
1099 private_child_create_t
*this = malloc_thing(private_child_create_t
);
1101 this->public.get_child
= (child_sa_t
*(*)(child_create_t
*))get_child
;
1102 this->public.get_lower_nonce
= (chunk_t(*)(child_create_t
*))get_lower_nonce
;
1103 this->public.use_reqid
= (void(*)(child_create_t
*,u_int32_t
))use_reqid
;
1104 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
1105 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
1106 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
1109 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
1110 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
1111 this->initiator
= TRUE
;
1112 config
->get_ref(config
);
1116 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
1117 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
1118 this->initiator
= FALSE
;
1121 this->ike_sa
= ike_sa
;
1122 this->config
= config
;
1123 this->my_nonce
= chunk_empty
;
1124 this->other_nonce
= chunk_empty
;
1125 this->proposals
= NULL
;
1126 this->proposal
= NULL
;
1130 this->dh_group
= MODP_NONE
;
1131 this->keymat
= ike_sa
->get_keymat(ike_sa
);
1132 this->child_sa
= NULL
;
1133 this->mode
= MODE_TUNNEL
;
1134 this->ipcomp
= IPCOMP_NONE
;
1135 this->ipcomp_received
= IPCOMP_NONE
;
1136 this->other_cpi
= 0;
1138 this->established
= FALSE
;
1140 return &this->public;