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