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