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 <crypto/diffie_hellman.h>
22 #include <encoding/payloads/sa_payload.h>
23 #include <encoding/payloads/ke_payload.h>
24 #include <encoding/payloads/ts_payload.h>
25 #include <encoding/payloads/nonce_payload.h>
26 #include <encoding/payloads/notify_payload.h>
27 #include <processing/jobs/delete_ike_sa_job.h>
30 typedef struct private_child_create_t private_child_create_t
;
33 * Private members of a child_create_t task.
35 struct private_child_create_t
{
38 * Public methods and task_t interface.
40 child_create_t
public;
48 * Are we the initiator?
58 * nonce chosen by peer
63 * config to create the CHILD_SA from
68 * list of proposal candidates
70 linked_list_t
*proposals
;
73 * selected proposal to use for CHILD_SA
78 * traffic selectors for initiators side
83 * traffic selectors for responders side
88 * optional diffie hellman exchange
93 * group used for DH exchange
95 diffie_hellman_group_t dh_group
;
103 * mode the new CHILD_SA uses (transport/tunnel/beet)
108 * IPComp transform to use
110 ipcomp_transform_t ipcomp
;
113 * IPComp transform proposed or accepted by the other peer
115 ipcomp_transform_t ipcomp_received
;
123 * SPI received in proposal
128 * Own allocated Compression Parameter Index (CPI)
133 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
138 * reqid to use if we are rekeying
143 * CHILD_SA which gets established
145 child_sa_t
*child_sa
;
148 * successfully established the CHILD?
154 * get the nonce from a message
156 static status_t
get_nonce(message_t
*message
, chunk_t
*nonce
)
158 nonce_payload_t
*payload
;
160 payload
= (nonce_payload_t
*)message
->get_payload(message
, NONCE
);
165 *nonce
= payload
->get_nonce(payload
);
170 * generate a new nonce to include in a CREATE_CHILD_SA message
172 static status_t
generate_nonce(chunk_t
*nonce
)
176 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
179 DBG1(DBG_IKE
, "error generating nonce value, no RNG found");
182 rng
->allocate_bytes(rng
, NONCE_SIZE
, nonce
);
188 * Check a list of traffic selectors if any selector belongs to host
190 static bool ts_list_is_host(linked_list_t
*list
, host_t
*host
)
192 traffic_selector_t
*ts
;
194 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
196 while (is_host
&& iterator
->iterate(iterator
, (void**)&ts
))
198 is_host
= is_host
&& ts
->is_host(ts
, host
);
200 iterator
->destroy(iterator
);
205 * Allocate SPIs and update proposals
207 static bool allocate_spi(private_child_create_t
*this)
209 enumerator_t
*enumerator
;
210 proposal_t
*proposal
;
212 /* TODO: allocate additional SPI for AH if we have such proposals */
213 this->my_spi
= this->child_sa
->alloc_spi(this->child_sa
, PROTO_ESP
);
218 enumerator
= this->proposals
->create_enumerator(this->proposals
);
219 while (enumerator
->enumerate(enumerator
, &proposal
))
221 proposal
->set_spi(proposal
, this->my_spi
);
223 enumerator
->destroy(enumerator
);
227 this->proposal
->set_spi(this->proposal
, this->my_spi
);
235 * Install a CHILD_SA for usage, return value:
236 * - FAILED: no acceptable proposal
237 * - INVALID_ARG: diffie hellman group inacceptable
238 * - NOT_FOUND: TS inacceptable
240 static status_t
select_and_install(private_child_create_t
*this, bool no_dh
)
243 chunk_t nonce_i
, nonce_r
;
244 chunk_t encr_i
= chunk_empty
, encr_r
= chunk_empty
;
245 chunk_t integ_i
= chunk_empty
, integ_r
= chunk_empty
;
246 linked_list_t
*my_ts
, *other_ts
;
247 host_t
*me
, *other
, *other_vip
, *my_vip
;
249 if (this->proposals
== NULL
)
251 DBG1(DBG_IKE
, "SA payload missing in message");
254 if (this->tsi
== NULL
|| this->tsr
== NULL
)
256 DBG1(DBG_IKE
, "TS payloads missing in message");
260 me
= this->ike_sa
->get_my_host(this->ike_sa
);
261 other
= this->ike_sa
->get_other_host(this->ike_sa
);
262 my_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
263 other_vip
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
265 this->proposal
= this->config
->select_proposal(this->config
, this->proposals
,
267 if (this->proposal
== NULL
)
269 DBG1(DBG_IKE
, "no acceptable proposal found");
272 this->other_spi
= this->proposal
->get_spi(this->proposal
);
274 if (!this->initiator
&& !allocate_spi(this))
275 { /* responder has no SPI allocated yet */
276 DBG1(DBG_IKE
, "allocating SPI failed");
279 this->child_sa
->set_proposal(this->child_sa
, this->proposal
);
281 if (!this->proposal
->has_dh_group(this->proposal
, this->dh_group
))
285 if (this->proposal
->get_algorithm(this->proposal
, DIFFIE_HELLMAN_GROUP
,
288 DBG1(DBG_IKE
, "DH group %N inacceptable, requesting %N",
289 diffie_hellman_group_names
, this->dh_group
,
290 diffie_hellman_group_names
, group
);
291 this->dh_group
= group
;
296 DBG1(DBG_IKE
, "no acceptable proposal found");
305 if (other_vip
== NULL
)
312 nonce_i
= this->my_nonce
;
313 nonce_r
= this->other_nonce
;
315 other_ts
= this->tsr
;
319 nonce_r
= this->my_nonce
;
320 nonce_i
= this->other_nonce
;
322 other_ts
= this->tsi
;
324 my_ts
= this->config
->get_traffic_selectors(this->config
, TRUE
, my_ts
,
326 other_ts
= this->config
->get_traffic_selectors(this->config
, FALSE
, other_ts
,
329 if (my_ts
->get_count(my_ts
) == 0 || other_ts
->get_count(other_ts
) == 0)
331 my_ts
->destroy_offset(my_ts
, offsetof(traffic_selector_t
, destroy
));
332 other_ts
->destroy_offset(other_ts
, offsetof(traffic_selector_t
, destroy
));
333 DBG1(DBG_IKE
, "no acceptable traffic selectors found");
337 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
338 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
342 this->tsr
= other_ts
;
347 this->tsi
= other_ts
;
350 if (!this->initiator
)
352 /* check if requested mode is acceptable, downgrade if required */
356 if (!this->config
->use_proxy_mode(this->config
) &&
357 (!ts_list_is_host(this->tsi
, other
) ||
358 !ts_list_is_host(this->tsr
, me
))
361 this->mode
= MODE_TUNNEL
;
362 DBG1(DBG_IKE
, "not using transport mode, not host-to-host");
364 else if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
366 this->mode
= MODE_TUNNEL
;
367 DBG1(DBG_IKE
, "not using transport mode, connection NATed");
371 if (!ts_list_is_host(this->tsi
, NULL
) ||
372 !ts_list_is_host(this->tsr
, NULL
))
374 this->mode
= MODE_TUNNEL
;
375 DBG1(DBG_IKE
, "not using BEET mode, not host-to-host");
383 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLING
);
384 this->child_sa
->set_ipcomp(this->child_sa
, this->ipcomp
);
385 this->child_sa
->set_mode(this->child_sa
, this->mode
);
386 this->child_sa
->set_protocol(this->child_sa
,
387 this->proposal
->get_protocol(this->proposal
));
389 if (this->my_cpi
== 0 || this->other_cpi
== 0 || this->ipcomp
== IPCOMP_NONE
)
391 this->my_cpi
= this->other_cpi
= 0;
392 this->ipcomp
= IPCOMP_NONE
;
395 if (this->keymat
->derive_child_keys(this->keymat
, this->proposal
,
396 this->dh
, nonce_i
, nonce_r
, &encr_i
, &integ_i
, &encr_r
, &integ_r
))
400 status
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
401 this->my_spi
, this->my_cpi
, TRUE
);
402 status
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
403 this->other_spi
, this->other_cpi
, FALSE
);
407 status
= this->child_sa
->install(this->child_sa
, encr_i
, integ_i
,
408 this->my_spi
, this->my_cpi
, TRUE
);
409 status
= this->child_sa
->install(this->child_sa
, encr_r
, integ_r
,
410 this->other_spi
, this->other_cpi
, FALSE
);
413 chunk_clear(&integ_i
);
414 chunk_clear(&integ_r
);
415 chunk_clear(&encr_i
);
416 chunk_clear(&encr_r
);
418 if (status
!= SUCCESS
)
420 DBG1(DBG_IKE
, "unable to install IPsec SA (SAD) in kernel");
424 status
= this->child_sa
->add_policies(this->child_sa
, my_ts
, other_ts
);
425 if (status
!= SUCCESS
)
427 DBG1(DBG_IKE
, "unable to install IPsec policies (SPD) in kernel");
431 charon
->bus
->child_keys(charon
->bus
, this->child_sa
, this->dh
,
434 /* add to IKE_SA, and remove from task */
435 this->child_sa
->set_state(this->child_sa
, CHILD_INSTALLED
);
436 this->ike_sa
->add_child_sa(this->ike_sa
, this->child_sa
);
437 this->established
= TRUE
;
442 * build the payloads for the message
444 static void build_payloads(private_child_create_t
*this, message_t
*message
)
446 sa_payload_t
*sa_payload
;
447 nonce_payload_t
*nonce_payload
;
448 ke_payload_t
*ke_payload
;
449 ts_payload_t
*ts_payload
;
454 sa_payload
= sa_payload_create_from_proposal_list(this->proposals
);
458 sa_payload
= sa_payload_create_from_proposal(this->proposal
);
460 message
->add_payload(message
, (payload_t
*)sa_payload
);
462 /* add nonce payload if not in IKE_AUTH */
463 if (message
->get_exchange_type(message
) == CREATE_CHILD_SA
)
465 nonce_payload
= nonce_payload_create();
466 nonce_payload
->set_nonce(nonce_payload
, this->my_nonce
);
467 message
->add_payload(message
, (payload_t
*)nonce_payload
);
470 /* diffie hellman exchange, if PFS enabled */
473 ke_payload
= ke_payload_create_from_diffie_hellman(this->dh
);
474 message
->add_payload(message
, (payload_t
*)ke_payload
);
477 /* add TSi/TSr payloads */
478 ts_payload
= ts_payload_create_from_traffic_selectors(TRUE
, this->tsi
);
479 message
->add_payload(message
, (payload_t
*)ts_payload
);
480 ts_payload
= ts_payload_create_from_traffic_selectors(FALSE
, this->tsr
);
481 message
->add_payload(message
, (payload_t
*)ts_payload
);
483 /* add a notify if we are not in tunnel mode */
487 message
->add_notify(message
, FALSE
, USE_TRANSPORT_MODE
, chunk_empty
);
490 message
->add_notify(message
, FALSE
, USE_BEET_MODE
, chunk_empty
);
498 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
500 static void add_ipcomp_notify(private_child_create_t
*this,
501 message_t
*message
, u_int8_t ipcomp
)
503 if (this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
))
505 DBG1(DBG_IKE
, "IPComp is not supported if either peer is natted, "
510 this->my_cpi
= this->child_sa
->alloc_cpi(this->child_sa
);
513 this->ipcomp
= ipcomp
;
514 message
->add_notify(message
, FALSE
, IPCOMP_SUPPORTED
,
515 chunk_cata("cc", chunk_from_thing(this->my_cpi
),
516 chunk_from_thing(ipcomp
)));
520 DBG1(DBG_IKE
, "unable to allocate a CPI from kernel, IPComp disabled");
525 * handle a received notify payload
527 static void handle_notify(private_child_create_t
*this, notify_payload_t
*notify
)
529 switch (notify
->get_notify_type(notify
))
531 case USE_TRANSPORT_MODE
:
532 this->mode
= MODE_TRANSPORT
;
535 this->mode
= MODE_BEET
;
537 case IPCOMP_SUPPORTED
:
539 ipcomp_transform_t ipcomp
;
543 data
= notify
->get_notification_data(notify
);
544 cpi
= *(u_int16_t
*)data
.ptr
;
545 ipcomp
= (ipcomp_transform_t
)(*(data
.ptr
+ 2));
549 this->other_cpi
= cpi
;
550 this->ipcomp_received
= ipcomp
;
555 DBG1(DBG_IKE
, "received IPCOMP_SUPPORTED notify with a "
556 "transform ID we don't support %N",
557 ipcomp_transform_names
, ipcomp
);
567 * Read payloads from message
569 static void process_payloads(private_child_create_t
*this, message_t
*message
)
571 enumerator_t
*enumerator
;
573 sa_payload_t
*sa_payload
;
574 ke_payload_t
*ke_payload
;
575 ts_payload_t
*ts_payload
;
577 /* defaults to TUNNEL mode */
578 this->mode
= MODE_TUNNEL
;
580 enumerator
= message
->create_payload_enumerator(message
);
581 while (enumerator
->enumerate(enumerator
, &payload
))
583 switch (payload
->get_type(payload
))
585 case SECURITY_ASSOCIATION
:
586 sa_payload
= (sa_payload_t
*)payload
;
587 this->proposals
= sa_payload
->get_proposals(sa_payload
);
590 ke_payload
= (ke_payload_t
*)payload
;
591 if (!this->initiator
)
593 this->dh_group
= ke_payload
->get_dh_group_number(ke_payload
);
594 this->dh
= this->keymat
->create_dh(this->keymat
, this->dh_group
);
598 this->dh
->set_other_public_value(this->dh
,
599 ke_payload
->get_key_exchange_data(ke_payload
));
602 case TRAFFIC_SELECTOR_INITIATOR
:
603 ts_payload
= (ts_payload_t
*)payload
;
604 this->tsi
= ts_payload
->get_traffic_selectors(ts_payload
);
606 case TRAFFIC_SELECTOR_RESPONDER
:
607 ts_payload
= (ts_payload_t
*)payload
;
608 this->tsr
= ts_payload
->get_traffic_selectors(ts_payload
);
611 handle_notify(this, (notify_payload_t
*)payload
);
617 enumerator
->destroy(enumerator
);
621 * Implementation of task_t.build for initiator
623 static status_t
build_i(private_child_create_t
*this, message_t
*message
)
625 host_t
*me
, *other
, *vip
;
626 peer_cfg_t
*peer_cfg
;
628 switch (message
->get_exchange_type(message
))
631 return get_nonce(message
, &this->my_nonce
);
632 case CREATE_CHILD_SA
:
633 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
635 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
638 if (this->dh_group
== MODP_NONE
)
640 this->dh_group
= this->config
->get_dh_group(this->config
);
644 if (message
->get_message_id(message
) != 1)
646 /* send only in the first request, not in subsequent rounds */
656 DBG0(DBG_IKE
, "establishing CHILD_SA %s{%d}",
657 this->config
->get_name(this->config
), this->reqid
);
661 DBG0(DBG_IKE
, "establishing CHILD_SA %s",
662 this->config
->get_name(this->config
));
665 /* reuse virtual IP if we already have one */
666 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
669 me
= this->ike_sa
->get_my_host(this->ike_sa
);
671 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
674 other
= this->ike_sa
->get_other_host(this->ike_sa
);
677 /* check if we want a virtual IP, but don't have one */
678 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
679 vip
= peer_cfg
->get_virtual_ip(peer_cfg
);
680 if (!this->reqid
&& vip
)
682 /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
683 vip
= host_create_any(vip
->get_family(vip
));
684 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
689 { /* but narrow it for host2host / if we already have a vip */
690 this->tsi
= this->config
->get_traffic_selectors(this->config
, TRUE
,
693 this->tsr
= this->config
->get_traffic_selectors(this->config
, FALSE
,
696 this->proposals
= this->config
->get_proposals(this->config
,
697 this->dh_group
== MODP_NONE
);
698 this->mode
= this->config
->get_mode(this->config
);
700 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
701 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
702 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
704 if (!allocate_spi(this))
706 DBG1(DBG_IKE
, "unable to allocate SPIs from kernel");
710 if (this->dh_group
!= MODP_NONE
)
712 this->dh
= this->keymat
->create_dh(this->keymat
, this->dh_group
);
715 if (this->config
->use_ipcomp(this->config
))
717 /* IPCOMP_DEFLATE is the only transform we support at the moment */
718 add_ipcomp_notify(this, message
, IPCOMP_DEFLATE
);
721 build_payloads(this, message
);
723 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
724 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
725 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
728 this->proposals
= NULL
;
734 * Implementation of task_t.process for responder
736 static status_t
process_r(private_child_create_t
*this, message_t
*message
)
738 switch (message
->get_exchange_type(message
))
741 return get_nonce(message
, &this->other_nonce
);
742 case CREATE_CHILD_SA
:
743 get_nonce(message
, &this->other_nonce
);
746 if (message
->get_message_id(message
) != 1)
748 /* only handle first AUTH payload, not additional rounds */
755 process_payloads(this, message
);
761 * handle CHILD_SA setup failure
763 static void handle_child_sa_failure(private_child_create_t
*this,
766 if (message
->get_exchange_type(message
) == IKE_AUTH
&&
767 lib
->settings
->get_bool(lib
->settings
,
768 "charon.close_ike_on_child_failure", FALSE
))
770 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
772 DBG1(DBG_IKE
, "closing IKE_SA due CHILD_SA setup failure");
773 charon
->scheduler
->schedule_job_ms(charon
->scheduler
, (job_t
*)
774 delete_ike_sa_job_create(this->ike_sa
->get_id(this->ike_sa
), TRUE
),
780 * Implementation of task_t.build for responder
782 static status_t
build_r(private_child_create_t
*this, message_t
*message
)
784 peer_cfg_t
*peer_cfg
;
786 enumerator_t
*enumerator
;
789 switch (message
->get_exchange_type(message
))
792 return get_nonce(message
, &this->my_nonce
);
793 case CREATE_CHILD_SA
:
794 if (generate_nonce(&this->my_nonce
) != SUCCESS
)
796 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
,
803 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
804 { /* wait until all authentication round completed */
811 if (this->ike_sa
->get_state(this->ike_sa
) == IKE_REKEYING
)
813 DBG1(DBG_IKE
, "unable to create CHILD_SA while rekeying IKE_SA");
814 message
->add_notify(message
, TRUE
, NO_ADDITIONAL_SAS
, chunk_empty
);
818 peer_cfg
= this->ike_sa
->get_peer_cfg(this->ike_sa
);
819 if (peer_cfg
&& this->tsi
&& this->tsr
)
823 me
= this->ike_sa
->get_virtual_ip(this->ike_sa
, TRUE
);
826 me
= this->ike_sa
->get_my_host(this->ike_sa
);
828 other
= this->ike_sa
->get_virtual_ip(this->ike_sa
, FALSE
);
831 other
= this->ike_sa
->get_other_host(this->ike_sa
);
833 this->config
= peer_cfg
->select_child_cfg(peer_cfg
, this->tsr
,
834 this->tsi
, me
, other
);
837 if (this->config
== NULL
)
839 DBG1(DBG_IKE
, "traffic selectors %#R=== %#R inacceptable",
840 this->tsr
, this->tsi
);
841 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
842 handle_child_sa_failure(this, message
);
846 /* check if ike_config_t included non-critical error notifies */
847 enumerator
= message
->create_payload_enumerator(message
);
848 while (enumerator
->enumerate(enumerator
, &payload
))
850 if (payload
->get_type(payload
) == NOTIFY
)
852 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
854 switch (notify
->get_notify_type(notify
))
856 case INTERNAL_ADDRESS_FAILURE
:
857 case FAILED_CP_REQUIRED
:
859 DBG1(DBG_IKE
,"configuration payload negotation "
860 "failed, no CHILD_SA built");
861 enumerator
->destroy(enumerator
);
862 handle_child_sa_failure(this, message
);
870 enumerator
->destroy(enumerator
);
872 this->child_sa
= child_sa_create(this->ike_sa
->get_my_host(this->ike_sa
),
873 this->ike_sa
->get_other_host(this->ike_sa
), this->config
, this->reqid
,
874 this->ike_sa
->has_condition(this->ike_sa
, COND_NAT_ANY
));
876 if (this->ipcomp_received
!= IPCOMP_NONE
)
878 if (this->config
->use_ipcomp(this->config
))
880 add_ipcomp_notify(this, message
, this->ipcomp_received
);
884 DBG1(DBG_IKE
, "received %N notify but IPComp is disabled, ignoring",
885 notify_type_names
, IPCOMP_SUPPORTED
);
889 switch (select_and_install(this, no_dh
))
894 message
->add_notify(message
, FALSE
, TS_UNACCEPTABLE
, chunk_empty
);
895 handle_child_sa_failure(this, message
);
899 u_int16_t group
= htons(this->dh_group
);
900 message
->add_notify(message
, FALSE
, INVALID_KE_PAYLOAD
,
901 chunk_from_thing(group
));
902 handle_child_sa_failure(this, message
);
907 message
->add_notify(message
, FALSE
, NO_PROPOSAL_CHOSEN
, chunk_empty
);
908 handle_child_sa_failure(this, message
);
912 build_payloads(this, message
);
914 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
915 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
916 this->child_sa
->get_name(this->child_sa
),
917 this->child_sa
->get_reqid(this->child_sa
),
918 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
919 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
920 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
921 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
927 * Implementation of task_t.process for initiator
929 static status_t
process_i(private_child_create_t
*this, message_t
*message
)
931 enumerator_t
*enumerator
;
935 switch (message
->get_exchange_type(message
))
938 return get_nonce(message
, &this->other_nonce
);
939 case CREATE_CHILD_SA
:
940 get_nonce(message
, &this->other_nonce
);
944 if (this->ike_sa
->get_state(this->ike_sa
) != IKE_ESTABLISHED
)
945 { /* wait until all authentication round completed */
952 /* check for erronous notifies */
953 enumerator
= message
->create_payload_enumerator(message
);
954 while (enumerator
->enumerate(enumerator
, &payload
))
956 if (payload
->get_type(payload
) == NOTIFY
)
958 notify_payload_t
*notify
= (notify_payload_t
*)payload
;
959 notify_type_t type
= notify
->get_notify_type(notify
);
963 /* handle notify errors related to CHILD_SA only */
964 case NO_PROPOSAL_CHOSEN
:
965 case SINGLE_PAIR_REQUIRED
:
966 case NO_ADDITIONAL_SAS
:
967 case INTERNAL_ADDRESS_FAILURE
:
968 case FAILED_CP_REQUIRED
:
969 case TS_UNACCEPTABLE
:
970 case INVALID_SELECTORS
:
972 DBG1(DBG_IKE
, "received %N notify, no CHILD_SA built",
973 notify_type_names
, type
);
974 enumerator
->destroy(enumerator
);
975 handle_child_sa_failure(this, message
);
976 /* an error in CHILD_SA creation is not critical */
979 case INVALID_KE_PAYLOAD
:
982 diffie_hellman_group_t bad_group
;
984 bad_group
= this->dh_group
;
985 data
= notify
->get_notification_data(notify
);
986 this->dh_group
= ntohs(*((u_int16_t
*)data
.ptr
));
987 DBG1(DBG_IKE
, "peer didn't accept DH group %N, "
988 "it requested %N", diffie_hellman_group_names
,
989 bad_group
, diffie_hellman_group_names
, this->dh_group
);
991 this->public.task
.migrate(&this->public.task
, this->ike_sa
);
992 enumerator
->destroy(enumerator
);
1000 enumerator
->destroy(enumerator
);
1002 process_payloads(this, message
);
1004 if (this->ipcomp
== IPCOMP_NONE
&& this->ipcomp_received
!= IPCOMP_NONE
)
1006 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify without requesting"
1007 " one, no CHILD_SA built");
1008 handle_child_sa_failure(this, message
);
1011 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp_received
== IPCOMP_NONE
)
1013 DBG1(DBG_IKE
, "peer didn't accept our proposed IPComp transforms, "
1014 "IPComp is disabled");
1015 this->ipcomp
= IPCOMP_NONE
;
1017 else if (this->ipcomp
!= IPCOMP_NONE
&& this->ipcomp
!= this->ipcomp_received
)
1019 DBG1(DBG_IKE
, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1020 "no CHILD_SA built");
1021 handle_child_sa_failure(this, message
);
1025 if (select_and_install(this, no_dh
) == SUCCESS
)
1027 DBG0(DBG_IKE
, "CHILD_SA %s{%d} established "
1028 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1029 this->child_sa
->get_name(this->child_sa
),
1030 this->child_sa
->get_reqid(this->child_sa
),
1031 ntohl(this->child_sa
->get_spi(this->child_sa
, TRUE
)),
1032 ntohl(this->child_sa
->get_spi(this->child_sa
, FALSE
)),
1033 this->child_sa
->get_traffic_selectors(this->child_sa
, TRUE
),
1034 this->child_sa
->get_traffic_selectors(this->child_sa
, FALSE
));
1038 handle_child_sa_failure(this, message
);
1044 * Implementation of task_t.get_type
1046 static task_type_t
get_type(private_child_create_t
*this)
1048 return CHILD_CREATE
;
1052 * Implementation of child_create_t.use_reqid
1054 static void use_reqid(private_child_create_t
*this, u_int32_t reqid
)
1056 this->reqid
= reqid
;
1060 * Implementation of child_create_t.get_child
1062 static child_sa_t
* get_child(private_child_create_t
*this)
1064 return this->child_sa
;
1068 * Implementation of child_create_t.get_lower_nonce
1070 static chunk_t
get_lower_nonce(private_child_create_t
*this)
1072 if (memcmp(this->my_nonce
.ptr
, this->other_nonce
.ptr
,
1073 min(this->my_nonce
.len
, this->other_nonce
.len
)) < 0)
1075 return this->my_nonce
;
1079 return this->other_nonce
;
1084 * Implementation of task_t.migrate
1086 static void migrate(private_child_create_t
*this, ike_sa_t
*ike_sa
)
1088 chunk_free(&this->my_nonce
);
1089 chunk_free(&this->other_nonce
);
1092 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1096 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1098 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 this->ike_sa
= ike_sa
;
1107 this->keymat
= ike_sa
->get_keymat(ike_sa
);
1108 this->proposal
= NULL
;
1109 this->proposals
= NULL
;
1113 this->child_sa
= NULL
;
1114 this->mode
= MODE_TUNNEL
;
1115 this->ipcomp
= IPCOMP_NONE
;
1116 this->ipcomp_received
= IPCOMP_NONE
;
1117 this->other_cpi
= 0;
1119 this->established
= FALSE
;
1123 * Implementation of task_t.destroy
1125 static void destroy(private_child_create_t
*this)
1127 chunk_free(&this->my_nonce
);
1128 chunk_free(&this->other_nonce
);
1131 this->tsr
->destroy_offset(this->tsr
, offsetof(traffic_selector_t
, destroy
));
1135 this->tsi
->destroy_offset(this->tsi
, offsetof(traffic_selector_t
, destroy
));
1137 if (!this->established
)
1139 DESTROY_IF(this->child_sa
);
1141 DESTROY_IF(this->proposal
);
1142 DESTROY_IF(this->dh
);
1143 if (this->proposals
)
1145 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
1148 DESTROY_IF(this->config
);
1153 * Described in header.
1155 child_create_t
*child_create_create(ike_sa_t
*ike_sa
, child_cfg_t
*config
)
1157 private_child_create_t
*this = malloc_thing(private_child_create_t
);
1159 this->public.get_child
= (child_sa_t
*(*)(child_create_t
*))get_child
;
1160 this->public.get_lower_nonce
= (chunk_t(*)(child_create_t
*))get_lower_nonce
;
1161 this->public.use_reqid
= (void(*)(child_create_t
*,u_int32_t
))use_reqid
;
1162 this->public.task
.get_type
= (task_type_t(*)(task_t
*))get_type
;
1163 this->public.task
.migrate
= (void(*)(task_t
*,ike_sa_t
*))migrate
;
1164 this->public.task
.destroy
= (void(*)(task_t
*))destroy
;
1167 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_i
;
1168 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_i
;
1169 this->initiator
= TRUE
;
1170 config
->get_ref(config
);
1174 this->public.task
.build
= (status_t(*)(task_t
*,message_t
*))build_r
;
1175 this->public.task
.process
= (status_t(*)(task_t
*,message_t
*))process_r
;
1176 this->initiator
= FALSE
;
1179 this->ike_sa
= ike_sa
;
1180 this->config
= config
;
1181 this->my_nonce
= chunk_empty
;
1182 this->other_nonce
= chunk_empty
;
1183 this->proposals
= NULL
;
1184 this->proposal
= NULL
;
1188 this->dh_group
= MODP_NONE
;
1189 this->keymat
= ike_sa
->get_keymat(ike_sa
);
1190 this->child_sa
= NULL
;
1191 this->mode
= MODE_TUNNEL
;
1192 this->ipcomp
= IPCOMP_NONE
;
1193 this->ipcomp_received
= IPCOMP_NONE
;
1195 this->other_spi
= 0;
1197 this->other_cpi
= 0;
1199 this->established
= FALSE
;
1201 return &this->public;