]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/ikev2/tasks/child_create.c
child-sa: Configure interface ID on SAs and policies
[thirdparty/strongswan.git] / src / libcharon / sa / ikev2 / tasks / child_create.c
CommitLineData
c60c7694 1/*
f8e53003 2 * Copyright (C) 2008-2018 Tobias Brunner
6a4ff35c 3 * Copyright (C) 2005-2008 Martin Willi
c60c7694 4 * Copyright (C) 2005 Jan Hutter
b92f11c3 5 * HSR Hochschule fuer Technik Rapperswil
c60c7694
MW
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18#include "child_create.h"
19
20#include <daemon.h>
15a682f4 21#include <sa/ikev2/keymat_v2.h>
c60c7694 22#include <crypto/diffie_hellman.h>
d002c623 23#include <credentials/certificates/x509.h>
c60c7694 24#include <encoding/payloads/sa_payload.h>
1fd5383e 25#include <encoding/payloads/ke_payload.h>
c60c7694
MW
26#include <encoding/payloads/ts_payload.h>
27#include <encoding/payloads/nonce_payload.h>
28#include <encoding/payloads/notify_payload.h>
e196c41b 29#include <encoding/payloads/delete_payload.h>
866ba8e0 30#include <processing/jobs/delete_ike_sa_job.h>
aa9eeb5d 31#include <processing/jobs/inactivity_job.h>
b92f11c3 32#include <processing/jobs/initiate_tasks_job.h>
c60c7694
MW
33
34typedef struct private_child_create_t private_child_create_t;
35
36/**
37 * Private members of a child_create_t task.
38 */
39struct private_child_create_t {
7daf5226 40
c60c7694
MW
41 /**
42 * Public methods and task_t interface.
43 */
44 child_create_t public;
7daf5226 45
c60c7694
MW
46 /**
47 * Assigned IKE_SA.
48 */
49 ike_sa_t *ike_sa;
7daf5226 50
c60c7694
MW
51 /**
52 * Are we the initiator?
53 */
54 bool initiator;
7daf5226 55
c60c7694
MW
56 /**
57 * nonce chosen by us
58 */
59 chunk_t my_nonce;
7daf5226 60
c60c7694
MW
61 /**
62 * nonce chosen by peer
63 */
64 chunk_t other_nonce;
7daf5226 65
72376234
RB
66 /**
67 * nonce generator
68 */
69 nonce_gen_t *nonceg;
70
c60c7694 71 /**
e0fe7651 72 * config to create the CHILD_SA from
c60c7694 73 */
e0fe7651 74 child_cfg_t *config;
7daf5226 75
c60c7694
MW
76 /**
77 * list of proposal candidates
78 */
79 linked_list_t *proposals;
7daf5226 80
c60c7694
MW
81 /**
82 * selected proposal to use for CHILD_SA
83 */
84 proposal_t *proposal;
7daf5226 85
c60c7694
MW
86 /**
87 * traffic selectors for initiators side
88 */
89 linked_list_t *tsi;
7daf5226 90
c60c7694
MW
91 /**
92 * traffic selectors for responders side
93 */
94 linked_list_t *tsr;
7daf5226 95
a13c013b
MW
96 /**
97 * source of triggering packet
98 */
99 traffic_selector_t *packet_tsi;
7daf5226 100
a13c013b
MW
101 /**
102 * destination of triggering packet
103 */
104 traffic_selector_t *packet_tsr;
7daf5226 105
1fd5383e
MW
106 /**
107 * optional diffie hellman exchange
108 */
109 diffie_hellman_t *dh;
7daf5226 110
a777155f
MW
111 /**
112 * Applying DH public value failed?
113 */
114 bool dh_failed;
115
1fd5383e
MW
116 /**
117 * group used for DH exchange
118 */
119 diffie_hellman_group_t dh_group;
7daf5226 120
80853d84
MW
121 /**
122 * IKE_SAs keymat
123 */
a0563846 124 keymat_v2_t *keymat;
7daf5226 125
c60c7694
MW
126 /**
127 * mode the new CHILD_SA uses (transport/tunnel/beet)
128 */
a341a68f 129 ipsec_mode_t mode;
7daf5226 130
55df72e6
MW
131 /**
132 * peer accepts TFC padding for this SA
133 */
134 bool tfcv3;
135
d4aad554
TB
136 /**
137 * IPComp transform to use
138 */
139 ipcomp_transform_t ipcomp;
7daf5226 140
d4aad554
TB
141 /**
142 * IPComp transform proposed or accepted by the other peer
143 */
144 ipcomp_transform_t ipcomp_received;
7daf5226 145
f91bd4b9
TB
146 /**
147 * IPsec protocol
148 */
149 protocol_id_t proto;
150
d4aad554 151 /**
3aaf7908
MW
152 * Own allocated SPI
153 */
b12c53ce 154 uint32_t my_spi;
7daf5226 155
3aaf7908
MW
156 /**
157 * SPI received in proposal
158 */
b12c53ce 159 uint32_t other_spi;
7daf5226 160
3aaf7908
MW
161 /**
162 * Own allocated Compression Parameter Index (CPI)
163 */
b12c53ce 164 uint16_t my_cpi;
7daf5226 165
3aaf7908
MW
166 /**
167 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
d4aad554 168 */
b12c53ce 169 uint16_t other_cpi;
7daf5226 170
c60c7694
MW
171 /**
172 * reqid to use if we are rekeying
173 */
b12c53ce 174 uint32_t reqid;
7daf5226 175
85b23888
MW
176 /**
177 * Explicit inbound mark value
178 */
179 u_int mark_in;
180
181 /**
182 * Explicit outbound mark value
183 */
184 u_int mark_out;
185
c60c7694
MW
186 /**
187 * CHILD_SA which gets established
188 */
189 child_sa_t *child_sa;
7daf5226 190
195ada0b
MW
191 /**
192 * successfully established the CHILD?
193 */
194 bool established;
7daf5226 195
f669f453
MW
196 /**
197 * whether the CHILD_SA rekeys an existing one
198 */
199 bool rekey;
82ad53b7
MW
200
201 /**
202 * whether we are retrying with another DH group
203 */
204 bool retry;
c60c7694
MW
205};
206
b92f11c3
TB
207/**
208 * Schedule a retry if creating the CHILD_SA temporary failed
209 */
210static void schedule_delayed_retry(private_child_create_t *this)
211{
212 child_create_t *task;
213 uint32_t retry;
214
215 retry = RETRY_INTERVAL - (random() % RETRY_JITTER);
216
217 task = child_create_create(this->ike_sa,
218 this->config->get_ref(this->config), FALSE,
219 this->packet_tsi, this->packet_tsr);
220 task->use_reqid(task, this->reqid);
221 DBG1(DBG_IKE, "creating CHILD_SA failed, trying again in %d seconds",
222 retry);
223 this->ike_sa->queue_task_delayed(this->ike_sa, (task_t*)task, retry);
224}
225
c60c7694
MW
226/**
227 * get the nonce from a message
228 */
229static status_t get_nonce(message_t *message, chunk_t *nonce)
230{
231 nonce_payload_t *payload;
7daf5226 232
3ecfc83c 233 payload = (nonce_payload_t*)message->get_payload(message, PLV2_NONCE);
c60c7694
MW
234 if (payload == NULL)
235 {
236 return FAILED;
237 }
238 *nonce = payload->get_nonce(payload);
239 return NEED_MORE;
240}
241
242/**
243 * generate a new nonce to include in a CREATE_CHILD_SA message
244 */
252f2ef8 245static bool generate_nonce(private_child_create_t *this)
c60c7694 246{
32df0d81 247 this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
252f2ef8
TB
248 if (!this->nonceg)
249 {
250 DBG1(DBG_IKE, "no nonce generator found to create nonce");
251 return FALSE;
252 }
72376234
RB
253 if (!this->nonceg->allocate_nonce(this->nonceg, NONCE_SIZE,
254 &this->my_nonce))
605985d1
RB
255 {
256 DBG1(DBG_IKE, "nonce allocation failed");
252f2ef8 257 return FALSE;
605985d1 258 }
252f2ef8 259 return TRUE;
c60c7694
MW
260}
261
262/**
263 * Check a list of traffic selectors if any selector belongs to host
264 */
265static bool ts_list_is_host(linked_list_t *list, host_t *host)
266{
267 traffic_selector_t *ts;
268 bool is_host = TRUE;
e2630434 269 enumerator_t *enumerator = list->create_enumerator(list);
7daf5226 270
e2630434 271 while (is_host && enumerator->enumerate(enumerator, (void**)&ts))
c60c7694
MW
272 {
273 is_host = is_host && ts->is_host(ts, host);
274 }
e2630434 275 enumerator->destroy(enumerator);
c60c7694
MW
276 return is_host;
277}
278
3aaf7908 279/**
7754c714 280 * Allocate local SPI
3aaf7908
MW
281 */
282static bool allocate_spi(private_child_create_t *this)
283{
3aaf7908 284 proposal_t *proposal;
7daf5226 285
cdab8630
MW
286 if (this->initiator)
287 {
f91bd4b9 288 this->proto = PROTO_ESP;
cdab8630
MW
289 /* we just get a SPI for the first protocol. TODO: If we ever support
290 * proposal lists with mixed protocols, we'd need multiple SPIs */
291 if (this->proposals->get_first(this->proposals,
292 (void**)&proposal) == SUCCESS)
293 {
f91bd4b9 294 this->proto = proposal->get_protocol(proposal);
cdab8630
MW
295 }
296 }
297 else
298 {
f91bd4b9 299 this->proto = this->proposal->get_protocol(this->proposal);
cdab8630 300 }
f91bd4b9 301 this->my_spi = this->child_sa->alloc_spi(this->child_sa, this->proto);
7754c714
TB
302 return this->my_spi != 0;
303}
304
305/**
306 * Update the proposals with the allocated SPIs as initiator and check the DH
307 * group and promote it if necessary
308 */
309static bool update_and_check_proposals(private_child_create_t *this)
310{
311 enumerator_t *enumerator;
312 proposal_t *proposal;
313 linked_list_t *other_dh_groups;
314 bool found = FALSE;
315
316 other_dh_groups = linked_list_create();
317 enumerator = this->proposals->create_enumerator(this->proposals);
318 while (enumerator->enumerate(enumerator, &proposal))
3aaf7908 319 {
7754c714
TB
320 proposal->set_spi(proposal, this->my_spi);
321
322 /* move the selected DH group to the front, if any */
323 if (this->dh_group != MODP_NONE)
324 { /* proposals that don't contain the selected group are
325 * moved to the back */
326 if (!proposal->promote_dh_group(proposal, this->dh_group))
3aaf7908 327 {
7754c714
TB
328 this->proposals->remove_at(this->proposals, enumerator);
329 other_dh_groups->insert_last(other_dh_groups, proposal);
5a259ade 330 }
7754c714
TB
331 else
332 {
333 found = TRUE;
3aaf7908 334 }
3aaf7908 335 }
3aaf7908 336 }
7754c714
TB
337 enumerator->destroy(enumerator);
338 enumerator = other_dh_groups->create_enumerator(other_dh_groups);
339 while (enumerator->enumerate(enumerator, (void**)&proposal))
340 { /* no need to remove from the list as we destroy it anyway*/
341 this->proposals->insert_last(this->proposals, proposal);
342 }
343 enumerator->destroy(enumerator);
344 other_dh_groups->destroy(other_dh_groups);
345
346 return this->dh_group == MODP_NONE || found;
3aaf7908
MW
347}
348
aa9eeb5d
MW
349/**
350 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
351 */
71da0017 352static void schedule_inactivity_timeout(private_child_create_t *this)
aa9eeb5d 353{
b12c53ce 354 uint32_t timeout, id;
aa9eeb5d
MW
355 bool close_ike;
356
71da0017 357 timeout = this->config->get_inactivity(this->config);
aa9eeb5d
MW
358 if (timeout)
359 {
360 close_ike = lib->settings->get_bool(lib->settings,
d223fe80 361 "%s.inactivity_close_ike", FALSE, lib->ns);
85ace154 362 id = this->child_sa->get_unique_id(this->child_sa);
bb381e26 363 lib->scheduler->schedule_job(lib->scheduler, (job_t*)
85ace154 364 inactivity_job_create(id, timeout, close_ike), timeout);
aa9eeb5d
MW
365 }
366}
367
7d82aaea
MW
368/**
369 * Check if we have a an address pool configured
370 */
371static bool have_pool(ike_sa_t *ike_sa)
372{
373 enumerator_t *enumerator;
374 peer_cfg_t *peer_cfg;
375 char *pool;
376 bool found = FALSE;
377
378 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
379 if (peer_cfg)
380 {
381 enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
382 if (enumerator->enumerate(enumerator, &pool))
383 {
384 found = TRUE;
385 }
386 enumerator->destroy(enumerator);
387 }
388 return found;
389}
390
101d26ba 391/**
7ee37114 392 * Get hosts to use for dynamic traffic selectors
101d26ba 393 */
7ee37114 394static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
101d26ba
MW
395{
396 enumerator_t *enumerator;
7ee37114 397 linked_list_t *list;
101d26ba
MW
398 host_t *host;
399
7ee37114 400 list = linked_list_create();
101d26ba 401 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
7ee37114 402 while (enumerator->enumerate(enumerator, &host))
101d26ba 403 {
7ee37114
MW
404 list->insert_last(list, host);
405 }
406 enumerator->destroy(enumerator);
407
408 if (list->get_count(list) == 0)
409 { /* no virtual IPs assigned */
101d26ba
MW
410 if (local)
411 {
412 host = ike_sa->get_my_host(ike_sa);
7ee37114 413 list->insert_last(list, host);
101d26ba 414 }
7ee37114
MW
415 else if (!have_pool(ike_sa))
416 { /* use host only if we don't have a pool configured */
417 host = ike_sa->get_other_host(ike_sa);
418 list->insert_last(list, host);
101d26ba
MW
419 }
420 }
7ee37114 421 return list;
101d26ba
MW
422}
423
975457c4 424/**
2db6d5b8 425 * Substitute any host address with NATed address in traffic selector
975457c4
MW
426 */
427static linked_list_t* get_transport_nat_ts(private_child_create_t *this,
428 bool local, linked_list_t *in)
429{
430 enumerator_t *enumerator;
431 linked_list_t *out;
432 traffic_selector_t *ts;
433 host_t *ike, *first = NULL;
b12c53ce 434 uint8_t mask;
975457c4
MW
435
436 if (local)
437 {
438 ike = this->ike_sa->get_my_host(this->ike_sa);
439 }
440 else
441 {
442 ike = this->ike_sa->get_other_host(this->ike_sa);
443 }
444
445 out = linked_list_create();
446
447 enumerator = in->create_enumerator(in);
448 while (enumerator->enumerate(enumerator, &ts))
449 {
450 /* require that all selectors match the first "host" selector */
451 if (ts->is_host(ts, first))
452 {
453 if (!first)
454 {
455 ts->to_subnet(ts, &first, &mask);
456 }
457 ts = ts->clone(ts);
458 ts->set_address(ts, ike);
459 out->insert_last(out, ts);
460 }
461 }
462 enumerator->destroy(enumerator);
463 DESTROY_IF(first);
464
465 return out;
466}
467
468/**
469 * Narrow received traffic selectors with configuration
470 */
471static linked_list_t* narrow_ts(private_child_create_t *this, bool local,
472 linked_list_t *in)
473{
474 linked_list_t *hosts, *nat, *ts;
475 ike_condition_t cond;
476
477 cond = local ? COND_NAT_HERE : COND_NAT_THERE;
478 hosts = get_dynamic_hosts(this->ike_sa, local);
479
480 if (this->mode == MODE_TRANSPORT &&
481 this->ike_sa->has_condition(this->ike_sa, cond))
482 {
483 nat = get_transport_nat_ts(this, local, in);
84cdfbc9
TB
484 ts = this->config->get_traffic_selectors(this->config, local, nat,
485 hosts, TRUE);
975457c4
MW
486 nat->destroy_offset(nat, offsetof(traffic_selector_t, destroy));
487 }
488 else
489 {
84cdfbc9
TB
490 ts = this->config->get_traffic_selectors(this->config, local, in,
491 hosts, TRUE);
975457c4
MW
492 }
493
494 hosts->destroy(hosts);
495
496 return ts;
497}
498
c60c7694 499/**
1fd5383e
MW
500 * Install a CHILD_SA for usage, return value:
501 * - FAILED: no acceptable proposal
2ad1df95
TB
502 * - INVALID_ARG: diffie hellman group unacceptable
503 * - NOT_FOUND: TS unacceptable
c60c7694 504 */
be715344
MW
505static status_t select_and_install(private_child_create_t *this,
506 bool no_dh, bool ike_auth)
c60c7694 507{
ecb32c75 508 status_t status, status_i, status_o;
15e745cf 509 child_sa_outbound_state_t out_state;
b59f154b
AS
510 chunk_t nonce_i, nonce_r;
511 chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
512 chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
975457c4 513 linked_list_t *my_ts, *other_ts;
101d26ba 514 host_t *me, *other;
0a954d67 515 bool private, prefer_configured;
7daf5226 516
1fd5383e 517 if (this->proposals == NULL)
c60c7694 518 {
a985db3f 519 DBG1(DBG_IKE, "SA payload missing in message");
c60c7694
MW
520 return FAILED;
521 }
1fd5383e
MW
522 if (this->tsi == NULL || this->tsr == NULL)
523 {
a985db3f 524 DBG1(DBG_IKE, "TS payloads missing in message");
1fd5383e
MW
525 return NOT_FOUND;
526 }
7daf5226 527
c60c7694
MW
528 me = this->ike_sa->get_my_host(this->ike_sa);
529 other = this->ike_sa->get_other_host(this->ike_sa);
7daf5226 530
023fd8f1 531 private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
0a954d67
TB
532 prefer_configured = lib->settings->get_bool(lib->settings,
533 "%s.prefer_configured_proposals", TRUE, lib->ns);
023fd8f1 534 this->proposal = this->config->select_proposal(this->config,
0a954d67 535 this->proposals, no_dh, private, prefer_configured);
6e1be427
MW
536 if (this->proposal == NULL)
537 {
a985db3f 538 DBG1(DBG_IKE, "no acceptable proposal found");
5dd9c308
MW
539 charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD,
540 this->proposals);
6e1be427
MW
541 return FAILED;
542 }
3aaf7908 543 this->other_spi = this->proposal->get_spi(this->proposal);
7daf5226 544
7754c714
TB
545 if (!this->initiator)
546 {
547 if (!allocate_spi(this))
548 {
549 /* responder has no SPI allocated yet */
550 DBG1(DBG_IKE, "allocating SPI failed");
551 return FAILED;
552 }
553 this->proposal->set_spi(this->proposal, this->my_spi);
3aaf7908
MW
554 }
555 this->child_sa->set_proposal(this->child_sa, this->proposal);
7daf5226 556
1fd5383e
MW
557 if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
558 {
b12c53ce 559 uint16_t group;
7daf5226 560
1fd5383e 561 if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
3c7e72f5 562 &group, NULL))
1fd5383e 563 {
2ad1df95 564 DBG1(DBG_IKE, "DH group %N unacceptable, requesting %N",
a985db3f
MW
565 diffie_hellman_group_names, this->dh_group,
566 diffie_hellman_group_names, group);
1fd5383e
MW
567 this->dh_group = group;
568 return INVALID_ARG;
569 }
1f6a707d
MW
570 /* the selected proposal does not use a DH group */
571 DBG1(DBG_IKE, "ignoring KE exchange, agreed on a non-PFS proposal");
572 DESTROY_IF(this->dh);
573 this->dh = NULL;
574 this->dh_group = MODP_NONE;
1fd5383e 575 }
7daf5226 576
80853d84
MW
577 if (this->initiator)
578 {
5dffdea1
MW
579 nonce_i = this->my_nonce;
580 nonce_r = this->other_nonce;
975457c4
MW
581 my_ts = narrow_ts(this, TRUE, this->tsi);
582 other_ts = narrow_ts(this, FALSE, this->tsr);
80853d84
MW
583 }
584 else
585 {
5dffdea1
MW
586 nonce_r = this->my_nonce;
587 nonce_i = this->other_nonce;
975457c4
MW
588 my_ts = narrow_ts(this, TRUE, this->tsr);
589 other_ts = narrow_ts(this, FALSE, this->tsi);
80853d84 590 }
7daf5226 591
be715344
MW
592 if (this->initiator)
593 {
594 if (ike_auth)
595 {
596 charon->bus->narrow(charon->bus, this->child_sa,
597 NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
598 }
599 else
600 {
601 charon->bus->narrow(charon->bus, this->child_sa,
602 NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
603 }
604 }
605 else
606 {
607 charon->bus->narrow(charon->bus, this->child_sa,
608 NARROW_RESPONDER, my_ts, other_ts);
609 }
610
e0fe7651
MW
611 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
612 {
24f30ec9 613 charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr);
16878f68
MW
614 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
615 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
a985db3f 616 DBG1(DBG_IKE, "no acceptable traffic selectors found");
1fd5383e 617 return NOT_FOUND;
c60c7694 618 }
7daf5226 619
c60c7694
MW
620 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
621 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
622 if (this->initiator)
623 {
624 this->tsi = my_ts;
625 this->tsr = other_ts;
626 }
627 else
628 {
629 this->tsr = my_ts;
630 this->tsi = other_ts;
631 }
7daf5226 632
c60c7694
MW
633 if (!this->initiator)
634 {
635 /* check if requested mode is acceptable, downgrade if required */
636 switch (this->mode)
637 {
638 case MODE_TRANSPORT:
749ac175 639 if (!this->config->has_option(this->config, OPT_PROXY_MODE) &&
d487b4b7
AS
640 (!ts_list_is_host(this->tsi, other) ||
641 !ts_list_is_host(this->tsr, me))
642 )
c60c7694
MW
643 {
644 this->mode = MODE_TUNNEL;
f41a4a4e 645 DBG1(DBG_IKE, "not using transport mode, not host-to-host");
c60c7694 646 }
ad5ad02a
MW
647 if (this->config->get_mode(this->config) != MODE_TRANSPORT)
648 {
649 this->mode = MODE_TUNNEL;
650 }
c60c7694
MW
651 break;
652 case MODE_BEET:
653 if (!ts_list_is_host(this->tsi, NULL) ||
654 !ts_list_is_host(this->tsr, NULL))
655 {
656 this->mode = MODE_TUNNEL;
657 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
658 }
ad5ad02a
MW
659 if (this->config->get_mode(this->config) != MODE_BEET)
660 {
661 this->mode = MODE_TUNNEL;
662 }
c60c7694
MW
663 break;
664 default:
665 break;
666 }
b00bcb9a
TB
667 /* use a copy of the traffic selectors, as the POST hook should not
668 * change payloads */
669 my_ts = this->tsr->clone_offset(this->tsr,
670 offsetof(traffic_selector_t, clone));
671 other_ts = this->tsi->clone_offset(this->tsi,
672 offsetof(traffic_selector_t, clone));
673 charon->bus->narrow(charon->bus, this->child_sa,
674 NARROW_RESPONDER_POST, my_ts, other_ts);
675
676 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
677 {
678 my_ts->destroy_offset(my_ts,
679 offsetof(traffic_selector_t, destroy));
680 other_ts->destroy_offset(other_ts,
681 offsetof(traffic_selector_t, destroy));
682 return NOT_FOUND;
683 }
c60c7694 684 }
7daf5226 685
4989aba8
TB
686 this->child_sa->set_policies(this->child_sa, my_ts, other_ts);
687 if (!this->initiator)
688 {
689 my_ts->destroy_offset(my_ts,
690 offsetof(traffic_selector_t, destroy));
691 other_ts->destroy_offset(other_ts,
692 offsetof(traffic_selector_t, destroy));
693 }
694
ea625fab 695 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
3aaf7908
MW
696 this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
697 this->child_sa->set_mode(this->child_sa, this->mode);
698 this->child_sa->set_protocol(this->child_sa,
699 this->proposal->get_protocol(this->proposal));
7daf5226 700
3aaf7908 701 if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
d4aad554 702 {
3aaf7908
MW
703 this->my_cpi = this->other_cpi = 0;
704 this->ipcomp = IPCOMP_NONE;
d4aad554 705 }
ecb32c75 706 status_i = status_o = FAILED;
5dffdea1 707 if (this->keymat->derive_child_keys(this->keymat, this->proposal,
6ec949e0 708 this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
c60c7694 709 {
5dffdea1 710 if (this->initiator)
80853d84 711 {
a8c94544
MW
712 status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
713 this->my_spi, this->my_cpi, this->initiator,
4989aba8 714 TRUE, this->tfcv3);
80853d84 715 }
15e745cf 716 else
80853d84 717 {
a8c94544
MW
718 status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
719 this->my_spi, this->my_cpi, this->initiator,
4989aba8 720 TRUE, this->tfcv3);
15e745cf
TB
721 }
722 if (this->rekey)
723 { /* during rekeyings we install the outbound SA and/or policies
724 * separately: as responder when we receive the delete for the old
725 * SA, as initiator pretty much immediately in the ike-rekey task,
726 * unless there was a rekey collision that we lost */
727 if (this->initiator)
728 {
729 status_o = this->child_sa->register_outbound(this->child_sa,
730 encr_i, integ_i, this->other_spi, this->other_cpi,
731 this->tfcv3);
732 }
733 else
734 {
735 status_o = this->child_sa->register_outbound(this->child_sa,
736 encr_r, integ_r, this->other_spi, this->other_cpi,
737 this->tfcv3);
738 }
739 }
740 else if (this->initiator)
741 {
742 status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
a8c94544 743 this->other_spi, this->other_cpi, this->initiator,
4989aba8 744 FALSE, this->tfcv3);
80853d84 745 }
dc3710e9 746 else
15e745cf
TB
747 {
748 status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
749 this->other_spi, this->other_cpi, this->initiator,
750 FALSE, this->tfcv3);
dc3710e9 751 }
c60c7694 752 }
7daf5226 753
ecb32c75 754 if (status_i != SUCCESS || status_o != SUCCESS)
c60c7694 755 {
ecb32c75
AS
756 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
757 (status_i != SUCCESS) ? "inbound " : "",
758 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
759 (status_o != SUCCESS) ? "outbound " : "");
bcf3147e
MW
760 charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
761 this->child_sa);
0e80f5c3 762 status = FAILED;
f942588f
MW
763 }
764 else
765 {
4989aba8 766 status = this->child_sa->install_policies(this->child_sa);
b00bcb9a 767
0e80f5c3 768 if (status != SUCCESS)
f942588f 769 {
0e80f5c3
TB
770 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
771 charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
772 this->child_sa);
773 status = NOT_FOUND;
f942588f
MW
774 }
775 else
776 {
0e80f5c3
TB
777 charon->bus->child_derived_keys(charon->bus, this->child_sa,
778 this->initiator, encr_i, encr_r,
779 integ_i, integ_r);
f942588f 780 }
f942588f 781 }
0e80f5c3
TB
782 chunk_clear(&integ_i);
783 chunk_clear(&integ_r);
784 chunk_clear(&encr_i);
785 chunk_clear(&encr_r);
786
ea625fab 787 if (status != SUCCESS)
7daf5226 788 {
0e80f5c3 789 return status;
ea625fab 790 }
7daf5226 791
b2e447e2
MW
792 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
793 this->dh, nonce_i, nonce_r);
7daf5226 794
553bb787
MW
795 my_ts = linked_list_create_from_enumerator(
796 this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
797 other_ts = linked_list_create_from_enumerator(
798 this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
15e745cf 799 out_state = this->child_sa->get_outbound_state(this->child_sa);
553bb787 800
dc3710e9 801 DBG0(DBG_IKE, "%sCHILD_SA %s{%d} established "
ebeb8c87 802 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
15e745cf 803 (out_state == CHILD_OUTBOUND_INSTALLED) ? "" : "inbound ",
553bb787 804 this->child_sa->get_name(this->child_sa),
246c969d 805 this->child_sa->get_unique_id(this->child_sa),
553bb787 806 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
dc3710e9
TB
807 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
808 my_ts, other_ts);
553bb787
MW
809
810 my_ts->destroy(my_ts);
811 other_ts->destroy(other_ts);
a0cde769
TB
812
813 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
814 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
815 this->established = TRUE;
816
817 schedule_inactivity_timeout(this);
c60c7694
MW
818 return SUCCESS;
819}
820
821/**
822 * build the payloads for the message
823 */
520d58e0 824static bool build_payloads(private_child_create_t *this, message_t *message)
c60c7694
MW
825{
826 sa_payload_t *sa_payload;
c60c7694 827 nonce_payload_t *nonce_payload;
1fd5383e
MW
828 ke_payload_t *ke_payload;
829 ts_payload_t *ts_payload;
5c55be49 830 kernel_feature_t features;
c60c7694
MW
831
832 /* add SA payload */
833 if (this->initiator)
834 {
e174e0d4 835 sa_payload = sa_payload_create_from_proposals_v2(this->proposals);
c60c7694
MW
836 }
837 else
838 {
e174e0d4 839 sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
c60c7694
MW
840 }
841 message->add_payload(message, (payload_t*)sa_payload);
7daf5226 842
c60c7694
MW
843 /* add nonce payload if not in IKE_AUTH */
844 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
845 {
3ecfc83c 846 nonce_payload = nonce_payload_create(PLV2_NONCE);
c60c7694
MW
847 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
848 message->add_payload(message, (payload_t*)nonce_payload);
849 }
7daf5226 850
1fd5383e
MW
851 /* diffie hellman exchange, if PFS enabled */
852 if (this->dh)
853 {
3ecfc83c 854 ke_payload = ke_payload_create_from_diffie_hellman(PLV2_KEY_EXCHANGE,
683d83ed 855 this->dh);
520d58e0
MW
856 if (!ke_payload)
857 {
858 DBG1(DBG_IKE, "creating KE payload failed");
859 return FALSE;
860 }
1fd5383e
MW
861 message->add_payload(message, (payload_t*)ke_payload);
862 }
7daf5226 863
c676f2e2
MW
864 /* add TSi/TSr payloads */
865 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
866 message->add_payload(message, (payload_t*)ts_payload);
867 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
868 message->add_payload(message, (payload_t*)ts_payload);
869
c60c7694
MW
870 /* add a notify if we are not in tunnel mode */
871 switch (this->mode)
872 {
873 case MODE_TRANSPORT:
874 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
875 break;
876 case MODE_BEET:
877 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
878 break;
879 default:
880 break;
881 }
5c55be49 882
8394ea2a 883 features = charon->kernel->get_features(charon->kernel);
5c55be49
MW
884 if (!(features & KERNEL_ESP_V3_TFC))
885 {
886 message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED,
887 chunk_empty);
888 }
520d58e0 889 return TRUE;
c60c7694
MW
890}
891
d4aad554 892/**
3aaf7908 893 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
d4aad554 894 */
3aaf7908 895static void add_ipcomp_notify(private_child_create_t *this,
b12c53ce 896 message_t *message, uint8_t ipcomp)
d4aad554 897{
3aaf7908
MW
898 this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
899 if (this->my_cpi)
d4aad554 900 {
3aaf7908 901 this->ipcomp = ipcomp;
7daf5226 902 message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
3aaf7908
MW
903 chunk_cata("cc", chunk_from_thing(this->my_cpi),
904 chunk_from_thing(ipcomp)));
d4aad554
TB
905 }
906 else
907 {
d510eaea 908 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
3aaf7908
MW
909 }
910}
911
912/**
913 * handle a received notify payload
914 */
915static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
916{
917 switch (notify->get_notify_type(notify))
918 {
919 case USE_TRANSPORT_MODE:
920 this->mode = MODE_TRANSPORT;
921 break;
922 case USE_BEET_MODE:
b3349c56
MW
923 if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
924 { /* handle private use notify only if we know its meaning */
925 this->mode = MODE_BEET;
926 }
927 else
928 {
929 DBG1(DBG_IKE, "received a notify strongSwan uses for BEET "
930 "mode, but peer implementation unknown, skipped");
931 }
3aaf7908
MW
932 break;
933 case IPCOMP_SUPPORTED:
934 {
935 ipcomp_transform_t ipcomp;
b12c53ce 936 uint16_t cpi;
3aaf7908 937 chunk_t data;
7daf5226 938
3aaf7908 939 data = notify->get_notification_data(notify);
b12c53ce 940 cpi = *(uint16_t*)data.ptr;
3aaf7908
MW
941 ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
942 switch (ipcomp)
943 {
944 case IPCOMP_DEFLATE:
945 this->other_cpi = cpi;
946 this->ipcomp_received = ipcomp;
947 break;
948 case IPCOMP_LZS:
949 case IPCOMP_LZJH:
950 default:
951 DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
952 "transform ID we don't support %N",
953 ipcomp_transform_names, ipcomp);
954 break;
955 }
55df72e6 956 break;
3aaf7908 957 }
55df72e6
MW
958 case ESP_TFC_PADDING_NOT_SUPPORTED:
959 DBG1(DBG_IKE, "received %N, not using ESPv3 TFC padding",
960 notify_type_names, notify->get_notify_type(notify));
961 this->tfcv3 = FALSE;
962 break;
3aaf7908
MW
963 default:
964 break;
d4aad554
TB
965 }
966}
967
c60c7694
MW
968/**
969 * Read payloads from message
970 */
971static void process_payloads(private_child_create_t *this, message_t *message)
972{
a44bb934 973 enumerator_t *enumerator;
c60c7694
MW
974 payload_t *payload;
975 sa_payload_t *sa_payload;
1fd5383e 976 ke_payload_t *ke_payload;
c60c7694 977 ts_payload_t *ts_payload;
7daf5226 978
c60c7694
MW
979 /* defaults to TUNNEL mode */
980 this->mode = MODE_TUNNEL;
981
a44bb934
MW
982 enumerator = message->create_payload_enumerator(message);
983 while (enumerator->enumerate(enumerator, &payload))
c60c7694
MW
984 {
985 switch (payload->get_type(payload))
986 {
3ecfc83c 987 case PLV2_SECURITY_ASSOCIATION:
c60c7694
MW
988 sa_payload = (sa_payload_t*)payload;
989 this->proposals = sa_payload->get_proposals(sa_payload);
990 break;
3ecfc83c 991 case PLV2_KEY_EXCHANGE:
1fd5383e
MW
992 ke_payload = (ke_payload_t*)payload;
993 if (!this->initiator)
994 {
995 this->dh_group = ke_payload->get_dh_group_number(ke_payload);
a0563846
TB
996 this->dh = this->keymat->keymat.create_dh(
997 &this->keymat->keymat, this->dh_group);
1fd5383e 998 }
ecbcfbda
TB
999 else if (this->dh)
1000 {
1001 this->dh_failed = this->dh->get_dh_group(this->dh) !=
1002 ke_payload->get_dh_group_number(ke_payload);
1003 }
1004 if (this->dh && !this->dh_failed)
1fd5383e 1005 {
a777155f 1006 this->dh_failed = !this->dh->set_other_public_value(this->dh,
1fd5383e
MW
1007 ke_payload->get_key_exchange_data(ke_payload));
1008 }
1009 break;
3ecfc83c 1010 case PLV2_TS_INITIATOR:
c60c7694
MW
1011 ts_payload = (ts_payload_t*)payload;
1012 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
7daf5226 1013 break;
3ecfc83c 1014 case PLV2_TS_RESPONDER:
c60c7694
MW
1015 ts_payload = (ts_payload_t*)payload;
1016 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
1017 break;
3ecfc83c 1018 case PLV2_NOTIFY:
3aaf7908 1019 handle_notify(this, (notify_payload_t*)payload);
c60c7694
MW
1020 break;
1021 default:
1022 break;
1023 }
1024 }
a44bb934 1025 enumerator->destroy(enumerator);
c60c7694
MW
1026}
1027
cf16a29d
AS
1028METHOD(task_t, build_i, status_t,
1029 private_child_create_t *this, message_t *message)
c60c7694 1030{
101d26ba
MW
1031 enumerator_t *enumerator;
1032 host_t *vip;
e0fe7651 1033 peer_cfg_t *peer_cfg;
7ee37114 1034 linked_list_t *list;
7daf5226 1035
c60c7694
MW
1036 switch (message->get_exchange_type(message))
1037 {
1038 case IKE_SA_INIT:
1039 return get_nonce(message, &this->my_nonce);
1040 case CREATE_CHILD_SA:
252f2ef8 1041 if (!generate_nonce(this))
c60c7694 1042 {
252f2ef8
TB
1043 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
1044 chunk_empty);
c60c7694
MW
1045 return SUCCESS;
1046 }
f8e53003
TB
1047 if (!this->retry && this->dh_group == MODP_NONE)
1048 { /* during a rekeying the group might already be set */
1fd5383e
MW
1049 this->dh_group = this->config->get_dh_group(this->config);
1050 }
9b8b3e5f 1051 break;
49e8ac05 1052 case IKE_AUTH:
a44bb934 1053 if (message->get_message_id(message) != 1)
49e8ac05 1054 {
a44bb934 1055 /* send only in the first request, not in subsequent rounds */
49e8ac05
MW
1056 return NEED_MORE;
1057 }
c60c7694
MW
1058 break;
1059 default:
1060 break;
1061 }
7daf5226 1062
419201c1 1063 /* check if we want a virtual IP, but don't have one */
7ee37114 1064 list = linked_list_create();
b81d8cd3 1065 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
4469e3d0 1066 if (!this->rekey)
419201c1 1067 {
7ee37114
MW
1068 enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
1069 while (enumerator->enumerate(enumerator, &vip))
1070 {
1071 /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
1072 vip = host_create_any(vip->get_family(vip));
1073 list->insert_last(list, vip);
1074 }
1075 enumerator->destroy(enumerator);
1076 }
1077 if (list->get_count(list))
1078 {
1079 this->tsi = this->config->get_traffic_selectors(this->config,
84cdfbc9 1080 TRUE, NULL, list, TRUE);
7ee37114 1081 list->destroy_offset(list, offsetof(host_t, destroy));
c60c7694
MW
1082 }
1083 else
7ee37114
MW
1084 { /* no virtual IPs configured */
1085 list->destroy(list);
1086 list = get_dynamic_hosts(this->ike_sa, TRUE);
1087 this->tsi = this->config->get_traffic_selectors(this->config,
84cdfbc9 1088 TRUE, NULL, list, TRUE);
7ee37114 1089 list->destroy(list);
c60c7694 1090 }
7ee37114
MW
1091 list = get_dynamic_hosts(this->ike_sa, FALSE);
1092 this->tsr = this->config->get_traffic_selectors(this->config,
84cdfbc9 1093 FALSE, NULL, list, TRUE);
7ee37114 1094 list->destroy(list);
7daf5226 1095
a13c013b
MW
1096 if (this->packet_tsi)
1097 {
1098 this->tsi->insert_first(this->tsi,
1099 this->packet_tsi->clone(this->packet_tsi));
1100 }
1101 if (this->packet_tsr)
1102 {
1103 this->tsr->insert_first(this->tsr,
1104 this->packet_tsr->clone(this->packet_tsr));
1105 }
1fd5383e
MW
1106 this->proposals = this->config->get_proposals(this->config,
1107 this->dh_group == MODP_NONE);
e0fe7651 1108 this->mode = this->config->get_mode(this->config);
7daf5226 1109
ad3af574
MW
1110 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
1111 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
85b23888 1112 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
a6014d99 1113 this->mark_in, this->mark_out, 0, 0);
7daf5226 1114
7bcd48d1
TB
1115 if (this->reqid)
1116 {
1117 DBG0(DBG_IKE, "establishing CHILD_SA %s{%d} reqid %d",
1118 this->child_sa->get_name(this->child_sa),
1119 this->child_sa->get_unique_id(this->child_sa), this->reqid);
1120 }
1121 else
1122 {
1123 DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
1124 this->child_sa->get_name(this->child_sa),
1125 this->child_sa->get_unique_id(this->child_sa));
1126 }
1127
3aaf7908 1128 if (!allocate_spi(this))
c60c7694 1129 {
a985db3f 1130 DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
c60c7694
MW
1131 return FAILED;
1132 }
7daf5226 1133
7754c714
TB
1134 if (!update_and_check_proposals(this))
1135 {
1136 DBG1(DBG_IKE, "requested DH group %N not contained in any of our "
1137 "proposals",
1138 diffie_hellman_group_names, this->dh_group);
1139 return FAILED;
1140 }
1141
1fd5383e
MW
1142 if (this->dh_group != MODP_NONE)
1143 {
a0563846
TB
1144 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
1145 this->dh_group);
1fd5383e 1146 }
7daf5226 1147
749ac175 1148 if (this->config->has_option(this->config, OPT_IPCOMP))
3aaf7908 1149 {
d4aad554 1150 /* IPCOMP_DEFLATE is the only transform we support at the moment */
3aaf7908 1151 add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
d4aad554 1152 }
7daf5226 1153
be715344
MW
1154 if (message->get_exchange_type(message) == IKE_AUTH)
1155 {
1156 charon->bus->narrow(charon->bus, this->child_sa,
1157 NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
1158 }
1159 else
1160 {
1161 charon->bus->narrow(charon->bus, this->child_sa,
1162 NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
1163 }
1164
520d58e0
MW
1165 if (!build_payloads(this, message))
1166 {
1167 return FAILED;
1168 }
7daf5226 1169
c60c7694
MW
1170 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1171 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1172 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1173 this->tsi = NULL;
1174 this->tsr = NULL;
1175 this->proposals = NULL;
7daf5226 1176
c60c7694
MW
1177 return NEED_MORE;
1178}
1179
cf16a29d
AS
1180METHOD(task_t, process_r, status_t,
1181 private_child_create_t *this, message_t *message)
c60c7694
MW
1182{
1183 switch (message->get_exchange_type(message))
1184 {
1185 case IKE_SA_INIT:
1186 return get_nonce(message, &this->other_nonce);
1187 case CREATE_CHILD_SA:
1188 get_nonce(message, &this->other_nonce);
1189 break;
49e8ac05 1190 case IKE_AUTH:
a44bb934 1191 if (message->get_message_id(message) != 1)
49e8ac05 1192 {
a44bb934 1193 /* only handle first AUTH payload, not additional rounds */
49e8ac05
MW
1194 return NEED_MORE;
1195 }
c60c7694
MW
1196 default:
1197 break;
1198 }
7daf5226 1199
c60c7694 1200 process_payloads(this, message);
7daf5226 1201
c60c7694
MW
1202 return NEED_MORE;
1203}
1204
866ba8e0
MW
1205/**
1206 * handle CHILD_SA setup failure
1207 */
1208static void handle_child_sa_failure(private_child_create_t *this,
1209 message_t *message)
1210{
8262be3c
AKR
1211 bool is_first;
1212
1213 is_first = message->get_exchange_type(message) == IKE_AUTH;
1214 if (is_first &&
866ba8e0 1215 lib->settings->get_bool(lib->settings,
d223fe80 1216 "%s.close_ike_on_child_failure", FALSE, lib->ns))
866ba8e0
MW
1217 {
1218 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
1219 * first */
1220 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
bb381e26 1221 lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
866ba8e0
MW
1222 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
1223 100);
1224 }
5d549cd4
TB
1225 else
1226 {
1227 DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA");
8262be3c
AKR
1228 charon->bus->alert(charon->bus, ALERT_KEEP_ON_CHILD_SA_FAILURE,
1229 is_first);
5d549cd4 1230 }
866ba8e0
MW
1231}
1232
975457c4
MW
1233/**
1234 * Substitute transport mode NAT selectors, if applicable
1235 */
1236static linked_list_t* get_ts_if_nat_transport(private_child_create_t *this,
1237 bool local, linked_list_t *in)
1238{
1239 linked_list_t *out = NULL;
1240 ike_condition_t cond;
1241
1242 if (this->mode == MODE_TRANSPORT)
1243 {
1244 cond = local ? COND_NAT_HERE : COND_NAT_THERE;
1245 if (this->ike_sa->has_condition(this->ike_sa, cond))
1246 {
1247 out = get_transport_nat_ts(this, local, in);
1248 if (out->get_count(out) == 0)
1249 {
1250 out->destroy(out);
1251 out = NULL;
1252 }
1253 }
1254 }
1255 return out;
1256}
1257
1258/**
1259 * Select a matching CHILD config as responder
1260 */
1261static child_cfg_t* select_child_cfg(private_child_create_t *this)
1262{
1263 peer_cfg_t *peer_cfg;
1264 child_cfg_t *child_cfg = NULL;;
1265
1266 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
1267 if (peer_cfg && this->tsi && this->tsr)
1268 {
1269 linked_list_t *listr, *listi, *tsr, *tsi;
1270
1271 tsr = get_ts_if_nat_transport(this, TRUE, this->tsr);
1272 tsi = get_ts_if_nat_transport(this, FALSE, this->tsi);
1273
1274 listr = get_dynamic_hosts(this->ike_sa, TRUE);
1275 listi = get_dynamic_hosts(this->ike_sa, FALSE);
1276 child_cfg = peer_cfg->select_child_cfg(peer_cfg,
1277 tsr ?: this->tsr, tsi ?: this->tsi,
1278 listr, listi);
1279 if ((tsi || tsr) && child_cfg &&
1280 child_cfg->get_mode(child_cfg) != MODE_TRANSPORT)
1281 {
1282 /* found a CHILD config, but it doesn't use transport mode */
1283 child_cfg->destroy(child_cfg);
1284 child_cfg = NULL;
1285 }
1286 if (!child_cfg && (tsi || tsr))
1287 {
1288 /* no match for the substituted NAT selectors, try it without */
1289 child_cfg = peer_cfg->select_child_cfg(peer_cfg,
1290 this->tsr, this->tsi, listr, listi);
1291 }
1292 listr->destroy(listr);
1293 listi->destroy(listi);
1294 DESTROY_OFFSET_IF(tsi, offsetof(traffic_selector_t, destroy));
1295 DESTROY_OFFSET_IF(tsr, offsetof(traffic_selector_t, destroy));
1296 }
1297
1298 return child_cfg;
1299}
1300
cf16a29d
AS
1301METHOD(task_t, build_r, status_t,
1302 private_child_create_t *this, message_t *message)
c60c7694 1303{
d510eaea 1304 payload_t *payload;
a44bb934 1305 enumerator_t *enumerator;
be715344 1306 bool no_dh = TRUE, ike_auth = FALSE;
7daf5226 1307
c60c7694
MW
1308 switch (message->get_exchange_type(message))
1309 {
1310 case IKE_SA_INIT:
1311 return get_nonce(message, &this->my_nonce);
1312 case CREATE_CHILD_SA:
252f2ef8 1313 if (!generate_nonce(this))
a777155f
MW
1314 {
1315 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
1316 chunk_empty);
1317 return SUCCESS;
1318 }
1319 if (this->dh_failed)
c60c7694 1320 {
a777155f 1321 DBG1(DBG_IKE, "applying DH public value failed");
866ba8e0
MW
1322 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
1323 chunk_empty);
c60c7694
MW
1324 return SUCCESS;
1325 }
1fd5383e 1326 no_dh = FALSE;
c60c7694 1327 break;
49e8ac05 1328 case IKE_AUTH:
a44bb934
MW
1329 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
1330 { /* wait until all authentication round completed */
49e8ac05
MW
1331 return NEED_MORE;
1332 }
b6fcb917
TB
1333 if (this->ike_sa->has_condition(this->ike_sa, COND_REDIRECTED))
1334 { /* no CHILD_SA is created for redirected SAs */
1335 return SUCCESS;
1336 }
be715344 1337 ike_auth = TRUE;
c60c7694
MW
1338 default:
1339 break;
1340 }
7daf5226 1341
0f33e826
MW
1342 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
1343 {
a985db3f 1344 DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
869b7075 1345 message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
0f33e826
MW
1346 return SUCCESS;
1347 }
f02cabbe
MW
1348 if (this->ike_sa->get_state(this->ike_sa) == IKE_DELETING)
1349 {
1350 DBG1(DBG_IKE, "unable to create CHILD_SA while deleting IKE_SA");
869b7075 1351 message->add_notify(message, TRUE, TEMPORARY_FAILURE, chunk_empty);
f02cabbe
MW
1352 return SUCCESS;
1353 }
7daf5226 1354
975457c4 1355 if (this->config == NULL)
a44bb934 1356 {
975457c4 1357 this->config = select_child_cfg(this);
a44bb934 1358 }
e0fe7651 1359 if (this->config == NULL)
c60c7694 1360 {
2ad1df95 1361 DBG1(DBG_IKE, "traffic selectors %#R === %#R unacceptable",
a985db3f 1362 this->tsr, this->tsi);
24f30ec9 1363 charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr);
e0fe7651 1364 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
866ba8e0 1365 handle_child_sa_failure(this, message);
c60c7694
MW
1366 return SUCCESS;
1367 }
7daf5226 1368
d510eaea 1369 /* check if ike_config_t included non-critical error notifies */
a44bb934
MW
1370 enumerator = message->create_payload_enumerator(message);
1371 while (enumerator->enumerate(enumerator, &payload))
d510eaea 1372 {
3ecfc83c 1373 if (payload->get_type(payload) == PLV2_NOTIFY)
d510eaea
MW
1374 {
1375 notify_payload_t *notify = (notify_payload_t*)payload;
7daf5226 1376
d510eaea
MW
1377 switch (notify->get_notify_type(notify))
1378 {
1379 case INTERNAL_ADDRESS_FAILURE:
1380 case FAILED_CP_REQUIRED:
1381 {
84545f6e 1382 DBG1(DBG_IKE,"configuration payload negotiation "
a985db3f 1383 "failed, no CHILD_SA built");
a44bb934 1384 enumerator->destroy(enumerator);
866ba8e0 1385 handle_child_sa_failure(this, message);
d510eaea
MW
1386 return SUCCESS;
1387 }
1388 default:
1389 break;
1390 }
1391 }
1392 }
a44bb934 1393 enumerator->destroy(enumerator);
7daf5226 1394
ad3af574
MW
1395 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
1396 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
85b23888 1397 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY),
a6014d99 1398 this->mark_in, this->mark_out, 0, 0);
7daf5226 1399
3aaf7908 1400 if (this->ipcomp_received != IPCOMP_NONE)
d4aad554 1401 {
749ac175 1402 if (this->config->has_option(this->config, OPT_IPCOMP))
3aaf7908
MW
1403 {
1404 add_ipcomp_notify(this, message, this->ipcomp_received);
1405 }
1406 else
1407 {
1408 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
1409 notify_type_names, IPCOMP_SUPPORTED);
1410 }
d4aad554 1411 }
7daf5226 1412
be715344 1413 switch (select_and_install(this, no_dh, ike_auth))
c60c7694 1414 {
1fd5383e
MW
1415 case SUCCESS:
1416 break;
1417 case NOT_FOUND:
1418 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
866ba8e0 1419 handle_child_sa_failure(this, message);
1fd5383e
MW
1420 return SUCCESS;
1421 case INVALID_ARG:
1422 {
b12c53ce 1423 uint16_t group = htons(this->dh_group);
1fd5383e
MW
1424 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
1425 chunk_from_thing(group));
1426 return SUCCESS;
1427 }
1428 case FAILED:
1429 default:
1430 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
866ba8e0 1431 handle_child_sa_failure(this, message);
1fd5383e 1432 return SUCCESS;
c60c7694 1433 }
7daf5226 1434
520d58e0
MW
1435 if (!build_payloads(this, message))
1436 {
1437 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
1438 handle_child_sa_failure(this, message);
1439 return SUCCESS;
1440 }
7daf5226 1441
f669f453
MW
1442 if (!this->rekey)
1443 { /* invoke the child_up() hook if we are not rekeying */
1444 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
1445 }
c60c7694
MW
1446 return SUCCESS;
1447}
1448
e93f386d
MW
1449/**
1450 * Raise alerts for received notify errors
1451 */
1452static void raise_alerts(private_child_create_t *this, notify_type_t type)
1453{
1454 linked_list_t *list;
1455
1456 switch (type)
1457 {
1458 case NO_PROPOSAL_CHOSEN:
1459 list = this->config->get_proposals(this->config, FALSE);
1460 charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD, list);
1461 list->destroy_offset(list, offsetof(proposal_t, destroy));
1462 break;
1463 default:
1464 break;
1465 }
1466}
1467
e196c41b
MW
1468METHOD(task_t, build_i_delete, status_t,
1469 private_child_create_t *this, message_t *message)
1470{
1471 message->set_exchange_type(message, INFORMATIONAL);
f91bd4b9 1472 if (this->my_spi && this->proto)
e196c41b 1473 {
e196c41b 1474 delete_payload_t *del;
e196c41b 1475
f91bd4b9 1476 del = delete_payload_create(PLV2_DELETE, this->proto);
ffe0889a 1477 del->add_spi(del, this->my_spi);
e196c41b
MW
1478 message->add_payload(message, (payload_t*)del);
1479
1480 DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
f91bd4b9 1481 protocol_id_names, this->proto, ntohl(this->my_spi));
e196c41b
MW
1482 }
1483 return NEED_MORE;
1484}
1485
1486/**
1487 * Change task to delete the failed CHILD_SA as initiator
1488 */
1489static status_t delete_failed_sa(private_child_create_t *this)
1490{
f91bd4b9 1491 if (this->my_spi && this->proto)
ffe0889a
TB
1492 {
1493 this->public.task.build = _build_i_delete;
1494 this->public.task.process = (void*)return_success;
1495 return NEED_MORE;
1496 }
1497 return SUCCESS;
e196c41b
MW
1498}
1499
cf16a29d
AS
1500METHOD(task_t, process_i, status_t,
1501 private_child_create_t *this, message_t *message)
c60c7694 1502{
a44bb934 1503 enumerator_t *enumerator;
c60c7694 1504 payload_t *payload;
be715344 1505 bool no_dh = TRUE, ike_auth = FALSE;
c60c7694
MW
1506
1507 switch (message->get_exchange_type(message))
1508 {
1509 case IKE_SA_INIT:
1510 return get_nonce(message, &this->other_nonce);
1511 case CREATE_CHILD_SA:
1512 get_nonce(message, &this->other_nonce);
1fd5383e 1513 no_dh = FALSE;
c60c7694 1514 break;
49e8ac05 1515 case IKE_AUTH:
a44bb934
MW
1516 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
1517 { /* wait until all authentication round completed */
49e8ac05
MW
1518 return NEED_MORE;
1519 }
be715344 1520 ike_auth = TRUE;
c60c7694
MW
1521 default:
1522 break;
1523 }
1524
ef33a4ab 1525 /* check for erroneous notifies */
a44bb934
MW
1526 enumerator = message->create_payload_enumerator(message);
1527 while (enumerator->enumerate(enumerator, &payload))
c60c7694 1528 {
3ecfc83c 1529 if (payload->get_type(payload) == PLV2_NOTIFY)
c60c7694
MW
1530 {
1531 notify_payload_t *notify = (notify_payload_t*)payload;
1532 notify_type_t type = notify->get_notify_type(notify);
7daf5226 1533
c676f2e2 1534 switch (type)
c60c7694 1535 {
c676f2e2
MW
1536 /* handle notify errors related to CHILD_SA only */
1537 case NO_PROPOSAL_CHOSEN:
1538 case SINGLE_PAIR_REQUIRED:
1539 case NO_ADDITIONAL_SAS:
1540 case INTERNAL_ADDRESS_FAILURE:
1541 case FAILED_CP_REQUIRED:
1542 case TS_UNACCEPTABLE:
1543 case INVALID_SELECTORS:
1544 {
a985db3f
MW
1545 DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
1546 notify_type_names, type);
a44bb934 1547 enumerator->destroy(enumerator);
e93f386d 1548 raise_alerts(this, type);
866ba8e0 1549 handle_child_sa_failure(this, message);
c676f2e2
MW
1550 /* an error in CHILD_SA creation is not critical */
1551 return SUCCESS;
1552 }
b92f11c3
TB
1553 case TEMPORARY_FAILURE:
1554 {
1555 DBG1(DBG_IKE, "received %N notify, will retry later",
1556 notify_type_names, type);
1557 enumerator->destroy(enumerator);
1558 if (!this->rekey)
1559 { /* the rekey task will retry itself if necessary */
1560 schedule_delayed_retry(this);
1561 }
1562 return SUCCESS;
1563 }
1fd5383e
MW
1564 case INVALID_KE_PAYLOAD:
1565 {
1566 chunk_t data;
b12c53ce 1567 uint16_t group = MODP_NONE;
7daf5226 1568
1fd5383e 1569 data = notify->get_notification_data(notify);
0d1d19b9
MW
1570 if (data.len == sizeof(group))
1571 {
1572 memcpy(&group, data.ptr, data.len);
1573 group = ntohs(group);
1574 }
4f1bf89e
TB
1575 if (this->retry)
1576 {
023d47a0
TB
1577 DBG1(DBG_IKE, "already retried with DH group %N, "
1578 "ignore requested %N", diffie_hellman_group_names,
4f1bf89e
TB
1579 this->dh_group, diffie_hellman_group_names, group);
1580 handle_child_sa_failure(this, message);
1581 /* an error in CHILD_SA creation is not critical */
1582 return SUCCESS;
1583 }
1fd5383e
MW
1584 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
1585 "it requested %N", diffie_hellman_group_names,
0d1d19b9 1586 this->dh_group, diffie_hellman_group_names, group);
82ad53b7 1587 this->retry = TRUE;
0d1d19b9 1588 this->dh_group = group;
013857ad 1589 this->child_sa->set_state(this->child_sa, CHILD_RETRYING);
1fd5383e 1590 this->public.task.migrate(&this->public.task, this->ike_sa);
a44bb934 1591 enumerator->destroy(enumerator);
1fd5383e
MW
1592 return NEED_MORE;
1593 }
c676f2e2 1594 default:
e7099aa2
MW
1595 {
1596 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
1597 { /* handle notifies if not handled in IKE_AUTH */
1598 if (type <= 16383)
1599 {
1600 DBG1(DBG_IKE, "received %N notify error",
1601 notify_type_names, type);
1602 enumerator->destroy(enumerator);
1603 return SUCCESS;
1604 }
1605 DBG2(DBG_IKE, "received %N notify",
1606 notify_type_names, type);
1607 }
c676f2e2 1608 break;
e7099aa2 1609 }
c60c7694
MW
1610 }
1611 }
1612 }
a44bb934 1613 enumerator->destroy(enumerator);
7daf5226 1614
c60c7694 1615 process_payloads(this, message);
7daf5226 1616
d4aad554
TB
1617 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
1618 {
a985db3f
MW
1619 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
1620 " one, no CHILD_SA built");
866ba8e0 1621 handle_child_sa_failure(this, message);
e196c41b 1622 return delete_failed_sa(this);
d4aad554
TB
1623 }
1624 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
1625 {
1626 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
a985db3f 1627 "IPComp is disabled");
d4aad554
TB
1628 this->ipcomp = IPCOMP_NONE;
1629 }
1630 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
1631 {
a985db3f
MW
1632 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1633 "no CHILD_SA built");
866ba8e0 1634 handle_child_sa_failure(this, message);
e196c41b 1635 return delete_failed_sa(this);
d4aad554 1636 }
7daf5226 1637
a777155f
MW
1638 if (this->dh_failed)
1639 {
1640 DBG1(DBG_IKE, "applying DH public value failed");
1641 handle_child_sa_failure(this, message);
1642 return delete_failed_sa(this);
1643 }
1644
be715344 1645 if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
195ada0b 1646 {
f669f453
MW
1647 if (!this->rekey)
1648 { /* invoke the child_up() hook if we are not rekeying */
1649 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
1650 }
195ada0b 1651 }
866ba8e0
MW
1652 else
1653 {
1654 handle_child_sa_failure(this, message);
e196c41b 1655 return delete_failed_sa(this);
866ba8e0 1656 }
c60c7694
MW
1657 return SUCCESS;
1658}
1659
cf16a29d 1660METHOD(child_create_t, use_reqid, void,
b12c53ce 1661 private_child_create_t *this, uint32_t reqid)
c60c7694
MW
1662{
1663 this->reqid = reqid;
1664}
1665
85b23888
MW
1666METHOD(child_create_t, use_marks, void,
1667 private_child_create_t *this, u_int in, u_int out)
1668{
1669 this->mark_in = in;
1670 this->mark_out = out;
1671}
1672
f8e53003
TB
1673METHOD(child_create_t, use_dh_group, void,
1674 private_child_create_t *this, diffie_hellman_group_t dh_group)
1675{
1676 this->dh_group = dh_group;
1677}
1678
cf16a29d
AS
1679METHOD(child_create_t, get_child, child_sa_t*,
1680 private_child_create_t *this)
195ada0b 1681{
92275b09 1682 return this->child_sa;
195ada0b
MW
1683}
1684
ab24a32e
MW
1685METHOD(child_create_t, set_config, void,
1686 private_child_create_t *this, child_cfg_t *cfg)
1687{
1688 DESTROY_IF(this->config);
1689 this->config = cfg;
1690}
1691
cf16a29d
AS
1692METHOD(child_create_t, get_lower_nonce, chunk_t,
1693 private_child_create_t *this)
7daf5226 1694{
eef08590
MW
1695 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1696 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1697 {
1698 return this->my_nonce;
1699 }
1700 else
1701 {
1702 return this->other_nonce;
1703 }
1704}
1705
cf16a29d
AS
1706METHOD(task_t, get_type, task_type_t,
1707 private_child_create_t *this)
1708{
a09972df 1709 return TASK_CHILD_CREATE;
cf16a29d
AS
1710}
1711
1712METHOD(task_t, migrate, void,
1713 private_child_create_t *this, ike_sa_t *ike_sa)
c60c7694
MW
1714{
1715 chunk_free(&this->my_nonce);
1716 chunk_free(&this->other_nonce);
6d61e334 1717 if (this->tsr)
c60c7694
MW
1718 {
1719 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1720 }
6d61e334 1721 if (this->tsi)
c60c7694
MW
1722 {
1723 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1724 }
1725 DESTROY_IF(this->child_sa);
1726 DESTROY_IF(this->proposal);
32df0d81 1727 DESTROY_IF(this->nonceg);
1fd5383e 1728 DESTROY_IF(this->dh);
a777155f 1729 this->dh_failed = FALSE;
c60c7694
MW
1730 if (this->proposals)
1731 {
1732 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1733 }
7daf5226 1734
c60c7694 1735 this->ike_sa = ike_sa;
12b6a68a 1736 this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
394eb35b 1737 this->proposal = NULL;
c60c7694
MW
1738 this->proposals = NULL;
1739 this->tsi = NULL;
1740 this->tsr = NULL;
1fd5383e 1741 this->dh = NULL;
1729df92 1742 this->nonceg = NULL;
c60c7694
MW
1743 this->child_sa = NULL;
1744 this->mode = MODE_TUNNEL;
d4aad554
TB
1745 this->ipcomp = IPCOMP_NONE;
1746 this->ipcomp_received = IPCOMP_NONE;
1747 this->other_cpi = 0;
c60c7694 1748 this->reqid = 0;
85b23888
MW
1749 this->mark_in = 0;
1750 this->mark_out = 0;
195ada0b 1751 this->established = FALSE;
c60c7694
MW
1752}
1753
cf16a29d
AS
1754METHOD(task_t, destroy, void,
1755 private_child_create_t *this)
c60c7694
MW
1756{
1757 chunk_free(&this->my_nonce);
1758 chunk_free(&this->other_nonce);
0a3ca290 1759 if (this->tsr)
c60c7694
MW
1760 {
1761 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1762 }
0a3ca290 1763 if (this->tsi)
c60c7694
MW
1764 {
1765 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1766 }
195ada0b
MW
1767 if (!this->established)
1768 {
1769 DESTROY_IF(this->child_sa);
1770 }
a13c013b
MW
1771 DESTROY_IF(this->packet_tsi);
1772 DESTROY_IF(this->packet_tsr);
c60c7694 1773 DESTROY_IF(this->proposal);
1fd5383e 1774 DESTROY_IF(this->dh);
c60c7694
MW
1775 if (this->proposals)
1776 {
1777 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1778 }
e0fe7651 1779 DESTROY_IF(this->config);
72376234 1780 DESTROY_IF(this->nonceg);
c60c7694
MW
1781 free(this);
1782}
1783
1784/*
1785 * Described in header.
1786 */
f669f453
MW
1787child_create_t *child_create_create(ike_sa_t *ike_sa,
1788 child_cfg_t *config, bool rekey,
a13c013b 1789 traffic_selector_t *tsi, traffic_selector_t *tsr)
c60c7694 1790{
cf16a29d
AS
1791 private_child_create_t *this;
1792
1793 INIT(this,
1794 .public = {
1795 .get_child = _get_child,
ab24a32e 1796 .set_config = _set_config,
cf16a29d
AS
1797 .get_lower_nonce = _get_lower_nonce,
1798 .use_reqid = _use_reqid,
85b23888 1799 .use_marks = _use_marks,
f8e53003 1800 .use_dh_group = _use_dh_group,
cf16a29d
AS
1801 .task = {
1802 .get_type = _get_type,
1803 .migrate = _migrate,
1804 .destroy = _destroy,
1805 },
1806 },
1807 .ike_sa = ike_sa,
1808 .config = config,
1809 .packet_tsi = tsi ? tsi->clone(tsi) : NULL,
1810 .packet_tsr = tsr ? tsr->clone(tsr) : NULL,
1811 .dh_group = MODP_NONE,
a0563846 1812 .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
cf16a29d
AS
1813 .mode = MODE_TUNNEL,
1814 .tfcv3 = TRUE,
1815 .ipcomp = IPCOMP_NONE,
1816 .ipcomp_received = IPCOMP_NONE,
1817 .rekey = rekey,
82ad53b7 1818 .retry = FALSE,
cf16a29d 1819 );
72376234 1820
e0fe7651 1821 if (config)
c60c7694 1822 {
cf16a29d
AS
1823 this->public.task.build = _build_i;
1824 this->public.task.process = _process_i;
905ab99f 1825 this->initiator = TRUE;
c60c7694
MW
1826 }
1827 else
1828 {
cf16a29d
AS
1829 this->public.task.build = _build_r;
1830 this->public.task.process = _process_r;
c60c7694
MW
1831 this->initiator = FALSE;
1832 }
c60c7694
MW
1833 return &this->public;
1834}