Raise an ALERT_PROPOSAL_MISMATCH_CHILD also when receiving NO_PROPOSAL_CHOSEN
[strongswan.git] / src / libcharon / sa / ikev2 / tasks / child_create.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
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>
21 #include <hydra.h>
22 #include <sa/ikev2/keymat_v2.h>
23 #include <crypto/diffie_hellman.h>
24 #include <credentials/certificates/x509.h>
25 #include <encoding/payloads/sa_payload.h>
26 #include <encoding/payloads/ke_payload.h>
27 #include <encoding/payloads/ts_payload.h>
28 #include <encoding/payloads/nonce_payload.h>
29 #include <encoding/payloads/notify_payload.h>
30 #include <processing/jobs/delete_ike_sa_job.h>
31 #include <processing/jobs/inactivity_job.h>
32
33
34 typedef struct private_child_create_t private_child_create_t;
35
36 /**
37 * Private members of a child_create_t task.
38 */
39 struct private_child_create_t {
40
41 /**
42 * Public methods and task_t interface.
43 */
44 child_create_t public;
45
46 /**
47 * Assigned IKE_SA.
48 */
49 ike_sa_t *ike_sa;
50
51 /**
52 * Are we the initiator?
53 */
54 bool initiator;
55
56 /**
57 * nonce chosen by us
58 */
59 chunk_t my_nonce;
60
61 /**
62 * nonce chosen by peer
63 */
64 chunk_t other_nonce;
65
66 /**
67 * config to create the CHILD_SA from
68 */
69 child_cfg_t *config;
70
71 /**
72 * list of proposal candidates
73 */
74 linked_list_t *proposals;
75
76 /**
77 * selected proposal to use for CHILD_SA
78 */
79 proposal_t *proposal;
80
81 /**
82 * traffic selectors for initiators side
83 */
84 linked_list_t *tsi;
85
86 /**
87 * traffic selectors for responders side
88 */
89 linked_list_t *tsr;
90
91 /**
92 * source of triggering packet
93 */
94 traffic_selector_t *packet_tsi;
95
96 /**
97 * destination of triggering packet
98 */
99 traffic_selector_t *packet_tsr;
100
101 /**
102 * optional diffie hellman exchange
103 */
104 diffie_hellman_t *dh;
105
106 /**
107 * group used for DH exchange
108 */
109 diffie_hellman_group_t dh_group;
110
111 /**
112 * IKE_SAs keymat
113 */
114 keymat_v2_t *keymat;
115
116 /**
117 * mode the new CHILD_SA uses (transport/tunnel/beet)
118 */
119 ipsec_mode_t mode;
120
121 /**
122 * peer accepts TFC padding for this SA
123 */
124 bool tfcv3;
125
126 /**
127 * IPComp transform to use
128 */
129 ipcomp_transform_t ipcomp;
130
131 /**
132 * IPComp transform proposed or accepted by the other peer
133 */
134 ipcomp_transform_t ipcomp_received;
135
136 /**
137 * Own allocated SPI
138 */
139 u_int32_t my_spi;
140
141 /**
142 * SPI received in proposal
143 */
144 u_int32_t other_spi;
145
146 /**
147 * Own allocated Compression Parameter Index (CPI)
148 */
149 u_int16_t my_cpi;
150
151 /**
152 * Other Compression Parameter Index (CPI), received via IPCOMP_SUPPORTED
153 */
154 u_int16_t other_cpi;
155
156 /**
157 * reqid to use if we are rekeying
158 */
159 u_int32_t reqid;
160
161 /**
162 * CHILD_SA which gets established
163 */
164 child_sa_t *child_sa;
165
166 /**
167 * successfully established the CHILD?
168 */
169 bool established;
170
171 /**
172 * whether the CHILD_SA rekeys an existing one
173 */
174 bool rekey;
175
176 /**
177 * whether we are retrying with another DH group
178 */
179 bool retry;
180 };
181
182 /**
183 * get the nonce from a message
184 */
185 static status_t get_nonce(message_t *message, chunk_t *nonce)
186 {
187 nonce_payload_t *payload;
188
189 payload = (nonce_payload_t*)message->get_payload(message, NONCE);
190 if (payload == NULL)
191 {
192 return FAILED;
193 }
194 *nonce = payload->get_nonce(payload);
195 return NEED_MORE;
196 }
197
198 /**
199 * generate a new nonce to include in a CREATE_CHILD_SA message
200 */
201 static status_t generate_nonce(private_child_create_t *this)
202 {
203 nonce_gen_t *nonceg;
204
205 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
206 if (!nonceg)
207 {
208 DBG1(DBG_IKE, "no nonce generator found to create nonce");
209 return FAILED;
210 }
211 if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
212 {
213 DBG1(DBG_IKE, "nonce allocation failed");
214 nonceg->destroy(nonceg);
215 return FAILED;
216 }
217 nonceg->destroy(nonceg);
218
219 return SUCCESS;
220 }
221
222 /**
223 * Check a list of traffic selectors if any selector belongs to host
224 */
225 static bool ts_list_is_host(linked_list_t *list, host_t *host)
226 {
227 traffic_selector_t *ts;
228 bool is_host = TRUE;
229 enumerator_t *enumerator = list->create_enumerator(list);
230
231 while (is_host && enumerator->enumerate(enumerator, (void**)&ts))
232 {
233 is_host = is_host && ts->is_host(ts, host);
234 }
235 enumerator->destroy(enumerator);
236 return is_host;
237 }
238
239 /**
240 * Allocate SPIs and update proposals
241 */
242 static bool allocate_spi(private_child_create_t *this)
243 {
244 enumerator_t *enumerator;
245 proposal_t *proposal;
246
247 /* TODO: allocate additional SPI for AH if we have such proposals */
248 this->my_spi = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
249 if (this->my_spi)
250 {
251 if (this->initiator)
252 {
253 enumerator = this->proposals->create_enumerator(this->proposals);
254 while (enumerator->enumerate(enumerator, &proposal))
255 {
256 proposal->set_spi(proposal, this->my_spi);
257 }
258 enumerator->destroy(enumerator);
259 }
260 else
261 {
262 this->proposal->set_spi(this->proposal, this->my_spi);
263 }
264 return TRUE;
265 }
266 return FALSE;
267 }
268
269 /**
270 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
271 */
272 static void schedule_inactivity_timeout(private_child_create_t *this)
273 {
274 u_int32_t timeout;
275 bool close_ike;
276
277 timeout = this->config->get_inactivity(this->config);
278 if (timeout)
279 {
280 close_ike = lib->settings->get_bool(lib->settings,
281 "%s.inactivity_close_ike", FALSE, charon->name);
282 lib->scheduler->schedule_job(lib->scheduler, (job_t*)
283 inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
284 timeout, close_ike), timeout);
285 }
286 }
287
288 /**
289 * Check if we have a an address pool configured
290 */
291 static bool have_pool(ike_sa_t *ike_sa)
292 {
293 enumerator_t *enumerator;
294 peer_cfg_t *peer_cfg;
295 char *pool;
296 bool found = FALSE;
297
298 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
299 if (peer_cfg)
300 {
301 enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
302 if (enumerator->enumerate(enumerator, &pool))
303 {
304 found = TRUE;
305 }
306 enumerator->destroy(enumerator);
307 }
308 return found;
309 }
310
311 /**
312 * Get hosts to use for dynamic traffic selectors
313 */
314 static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
315 {
316 enumerator_t *enumerator;
317 linked_list_t *list;
318 host_t *host;
319
320 list = linked_list_create();
321 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
322 while (enumerator->enumerate(enumerator, &host))
323 {
324 list->insert_last(list, host);
325 }
326 enumerator->destroy(enumerator);
327
328 if (list->get_count(list) == 0)
329 { /* no virtual IPs assigned */
330 if (local)
331 {
332 host = ike_sa->get_my_host(ike_sa);
333 list->insert_last(list, host);
334 }
335 else if (!have_pool(ike_sa))
336 { /* use host only if we don't have a pool configured */
337 host = ike_sa->get_other_host(ike_sa);
338 list->insert_last(list, host);
339 }
340 }
341 return list;
342 }
343
344 /**
345 * Install a CHILD_SA for usage, return value:
346 * - FAILED: no acceptable proposal
347 * - INVALID_ARG: diffie hellman group inacceptable
348 * - NOT_FOUND: TS inacceptable
349 */
350 static status_t select_and_install(private_child_create_t *this,
351 bool no_dh, bool ike_auth)
352 {
353 status_t status, status_i, status_o;
354 chunk_t nonce_i, nonce_r;
355 chunk_t encr_i = chunk_empty, encr_r = chunk_empty;
356 chunk_t integ_i = chunk_empty, integ_r = chunk_empty;
357 linked_list_t *my_ts, *other_ts, *list;
358 host_t *me, *other;
359 bool private;
360
361 if (this->proposals == NULL)
362 {
363 DBG1(DBG_IKE, "SA payload missing in message");
364 return FAILED;
365 }
366 if (this->tsi == NULL || this->tsr == NULL)
367 {
368 DBG1(DBG_IKE, "TS payloads missing in message");
369 return NOT_FOUND;
370 }
371
372 me = this->ike_sa->get_my_host(this->ike_sa);
373 other = this->ike_sa->get_other_host(this->ike_sa);
374
375 private = this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN);
376 this->proposal = this->config->select_proposal(this->config,
377 this->proposals, no_dh, private);
378 if (this->proposal == NULL)
379 {
380 DBG1(DBG_IKE, "no acceptable proposal found");
381 charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD,
382 this->proposals);
383 return FAILED;
384 }
385 this->other_spi = this->proposal->get_spi(this->proposal);
386
387 if (!this->initiator && !allocate_spi(this))
388 { /* responder has no SPI allocated yet */
389 DBG1(DBG_IKE, "allocating SPI failed");
390 return FAILED;
391 }
392 this->child_sa->set_proposal(this->child_sa, this->proposal);
393
394 if (!this->proposal->has_dh_group(this->proposal, this->dh_group))
395 {
396 u_int16_t group;
397
398 if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP,
399 &group, NULL))
400 {
401 DBG1(DBG_IKE, "DH group %N inacceptable, requesting %N",
402 diffie_hellman_group_names, this->dh_group,
403 diffie_hellman_group_names, group);
404 this->dh_group = group;
405 return INVALID_ARG;
406 }
407 /* the selected proposal does not use a DH group */
408 DBG1(DBG_IKE, "ignoring KE exchange, agreed on a non-PFS proposal");
409 DESTROY_IF(this->dh);
410 this->dh = NULL;
411 this->dh_group = MODP_NONE;
412 }
413
414 if (this->initiator)
415 {
416 nonce_i = this->my_nonce;
417 nonce_r = this->other_nonce;
418 my_ts = this->tsi;
419 other_ts = this->tsr;
420 }
421 else
422 {
423 nonce_r = this->my_nonce;
424 nonce_i = this->other_nonce;
425 my_ts = this->tsr;
426 other_ts = this->tsi;
427 }
428 list = get_dynamic_hosts(this->ike_sa, TRUE);
429 my_ts = this->config->get_traffic_selectors(this->config,
430 TRUE, my_ts, list);
431 list->destroy(list);
432 list = get_dynamic_hosts(this->ike_sa, FALSE);
433 other_ts = this->config->get_traffic_selectors(this->config,
434 FALSE, other_ts, list);
435 list->destroy(list);
436
437 if (this->initiator)
438 {
439 if (ike_auth)
440 {
441 charon->bus->narrow(charon->bus, this->child_sa,
442 NARROW_INITIATOR_POST_NOAUTH, my_ts, other_ts);
443 }
444 else
445 {
446 charon->bus->narrow(charon->bus, this->child_sa,
447 NARROW_INITIATOR_POST_AUTH, my_ts, other_ts);
448 }
449 }
450 else
451 {
452 charon->bus->narrow(charon->bus, this->child_sa,
453 NARROW_RESPONDER, my_ts, other_ts);
454 }
455
456 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
457 {
458 charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr);
459 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
460 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
461 DBG1(DBG_IKE, "no acceptable traffic selectors found");
462 return NOT_FOUND;
463 }
464
465 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
466 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
467 if (this->initiator)
468 {
469 this->tsi = my_ts;
470 this->tsr = other_ts;
471 }
472 else
473 {
474 this->tsr = my_ts;
475 this->tsi = other_ts;
476 }
477
478 if (!this->initiator)
479 {
480 /* check if requested mode is acceptable, downgrade if required */
481 switch (this->mode)
482 {
483 case MODE_TRANSPORT:
484 if (!this->config->use_proxy_mode(this->config) &&
485 (!ts_list_is_host(this->tsi, other) ||
486 !ts_list_is_host(this->tsr, me))
487 )
488 {
489 this->mode = MODE_TUNNEL;
490 DBG1(DBG_IKE, "not using transport mode, not host-to-host");
491 }
492 else if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
493 {
494 this->mode = MODE_TUNNEL;
495 DBG1(DBG_IKE, "not using transport mode, connection NATed");
496 }
497 break;
498 case MODE_BEET:
499 if (!ts_list_is_host(this->tsi, NULL) ||
500 !ts_list_is_host(this->tsr, NULL))
501 {
502 this->mode = MODE_TUNNEL;
503 DBG1(DBG_IKE, "not using BEET mode, not host-to-host");
504 }
505 break;
506 default:
507 break;
508 }
509 }
510
511 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
512 this->child_sa->set_ipcomp(this->child_sa, this->ipcomp);
513 this->child_sa->set_mode(this->child_sa, this->mode);
514 this->child_sa->set_protocol(this->child_sa,
515 this->proposal->get_protocol(this->proposal));
516
517 if (this->my_cpi == 0 || this->other_cpi == 0 || this->ipcomp == IPCOMP_NONE)
518 {
519 this->my_cpi = this->other_cpi = 0;
520 this->ipcomp = IPCOMP_NONE;
521 }
522 status_i = status_o = FAILED;
523 if (this->keymat->derive_child_keys(this->keymat, this->proposal,
524 this->dh, nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r))
525 {
526 if (this->initiator)
527 {
528 status_i = this->child_sa->install(this->child_sa,
529 encr_r, integ_r, this->my_spi, this->my_cpi,
530 TRUE, this->tfcv3, my_ts, other_ts);
531 status_o = this->child_sa->install(this->child_sa,
532 encr_i, integ_i, this->other_spi, this->other_cpi,
533 FALSE, this->tfcv3, my_ts, other_ts);
534 }
535 else
536 {
537 status_i = this->child_sa->install(this->child_sa,
538 encr_i, integ_i, this->my_spi, this->my_cpi,
539 TRUE, this->tfcv3, my_ts, other_ts);
540 status_o = this->child_sa->install(this->child_sa,
541 encr_r, integ_r, this->other_spi, this->other_cpi,
542 FALSE, this->tfcv3, my_ts, other_ts);
543 }
544 }
545 chunk_clear(&integ_i);
546 chunk_clear(&integ_r);
547 chunk_clear(&encr_i);
548 chunk_clear(&encr_r);
549
550 if (status_i != SUCCESS || status_o != SUCCESS)
551 {
552 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
553 (status_i != SUCCESS) ? "inbound " : "",
554 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
555 (status_o != SUCCESS) ? "outbound " : "");
556 charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_SA_FAILED,
557 this->child_sa);
558 return FAILED;
559 }
560
561 if (this->initiator)
562 {
563 status = this->child_sa->add_policies(this->child_sa, my_ts, other_ts);
564 }
565 else
566 {
567 /* use a copy of the traffic selectors, as the POST hook should not
568 * change payloads */
569 my_ts = this->tsr->clone_offset(this->tsr,
570 offsetof(traffic_selector_t, clone));
571 other_ts = this->tsi->clone_offset(this->tsi,
572 offsetof(traffic_selector_t, clone));
573 charon->bus->narrow(charon->bus, this->child_sa,
574 NARROW_RESPONDER_POST, my_ts, other_ts);
575 if (my_ts->get_count(my_ts) == 0 || other_ts->get_count(other_ts) == 0)
576 {
577 status = FAILED;
578 }
579 else
580 {
581 status = this->child_sa->add_policies(this->child_sa,
582 my_ts, other_ts);
583 }
584 my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
585 other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
586 }
587 if (status != SUCCESS)
588 {
589 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
590 charon->bus->alert(charon->bus, ALERT_INSTALL_CHILD_POLICY_FAILED,
591 this->child_sa);
592 return NOT_FOUND;
593 }
594
595 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
596 this->dh, nonce_i, nonce_r);
597
598 /* add to IKE_SA, and remove from task */
599 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
600 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
601 this->established = TRUE;
602
603 if (!this->rekey)
604 { /* a rekeyed SA uses the same reqid, no need for a new job */
605 schedule_inactivity_timeout(this);
606 }
607 return SUCCESS;
608 }
609
610 /**
611 * build the payloads for the message
612 */
613 static void build_payloads(private_child_create_t *this, message_t *message)
614 {
615 sa_payload_t *sa_payload;
616 nonce_payload_t *nonce_payload;
617 ke_payload_t *ke_payload;
618 ts_payload_t *ts_payload;
619 kernel_feature_t features;
620
621 /* add SA payload */
622 if (this->initiator)
623 {
624 sa_payload = sa_payload_create_from_proposals_v2(this->proposals);
625 }
626 else
627 {
628 sa_payload = sa_payload_create_from_proposal_v2(this->proposal);
629 }
630 message->add_payload(message, (payload_t*)sa_payload);
631
632 /* add nonce payload if not in IKE_AUTH */
633 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
634 {
635 nonce_payload = nonce_payload_create(NONCE);
636 nonce_payload->set_nonce(nonce_payload, this->my_nonce);
637 message->add_payload(message, (payload_t*)nonce_payload);
638 }
639
640 /* diffie hellman exchange, if PFS enabled */
641 if (this->dh)
642 {
643 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE,
644 this->dh);
645 message->add_payload(message, (payload_t*)ke_payload);
646 }
647
648 /* add TSi/TSr payloads */
649 ts_payload = ts_payload_create_from_traffic_selectors(TRUE, this->tsi);
650 message->add_payload(message, (payload_t*)ts_payload);
651 ts_payload = ts_payload_create_from_traffic_selectors(FALSE, this->tsr);
652 message->add_payload(message, (payload_t*)ts_payload);
653
654 /* add a notify if we are not in tunnel mode */
655 switch (this->mode)
656 {
657 case MODE_TRANSPORT:
658 message->add_notify(message, FALSE, USE_TRANSPORT_MODE, chunk_empty);
659 break;
660 case MODE_BEET:
661 message->add_notify(message, FALSE, USE_BEET_MODE, chunk_empty);
662 break;
663 default:
664 break;
665 }
666
667 features = hydra->kernel_interface->get_features(hydra->kernel_interface);
668 if (!(features & KERNEL_ESP_V3_TFC))
669 {
670 message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED,
671 chunk_empty);
672 }
673 }
674
675 /**
676 * Adds an IPCOMP_SUPPORTED notify to the message, allocating a CPI
677 */
678 static void add_ipcomp_notify(private_child_create_t *this,
679 message_t *message, u_int8_t ipcomp)
680 {
681 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
682 {
683 DBG1(DBG_IKE, "IPComp is not supported if either peer is natted, "
684 "IPComp disabled");
685 return;
686 }
687
688 this->my_cpi = this->child_sa->alloc_cpi(this->child_sa);
689 if (this->my_cpi)
690 {
691 this->ipcomp = ipcomp;
692 message->add_notify(message, FALSE, IPCOMP_SUPPORTED,
693 chunk_cata("cc", chunk_from_thing(this->my_cpi),
694 chunk_from_thing(ipcomp)));
695 }
696 else
697 {
698 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, IPComp disabled");
699 }
700 }
701
702 /**
703 * handle a received notify payload
704 */
705 static void handle_notify(private_child_create_t *this, notify_payload_t *notify)
706 {
707 switch (notify->get_notify_type(notify))
708 {
709 case USE_TRANSPORT_MODE:
710 this->mode = MODE_TRANSPORT;
711 break;
712 case USE_BEET_MODE:
713 if (this->ike_sa->supports_extension(this->ike_sa, EXT_STRONGSWAN))
714 { /* handle private use notify only if we know its meaning */
715 this->mode = MODE_BEET;
716 }
717 else
718 {
719 DBG1(DBG_IKE, "received a notify strongSwan uses for BEET "
720 "mode, but peer implementation unknown, skipped");
721 }
722 break;
723 case IPCOMP_SUPPORTED:
724 {
725 ipcomp_transform_t ipcomp;
726 u_int16_t cpi;
727 chunk_t data;
728
729 data = notify->get_notification_data(notify);
730 cpi = *(u_int16_t*)data.ptr;
731 ipcomp = (ipcomp_transform_t)(*(data.ptr + 2));
732 switch (ipcomp)
733 {
734 case IPCOMP_DEFLATE:
735 this->other_cpi = cpi;
736 this->ipcomp_received = ipcomp;
737 break;
738 case IPCOMP_LZS:
739 case IPCOMP_LZJH:
740 default:
741 DBG1(DBG_IKE, "received IPCOMP_SUPPORTED notify with a "
742 "transform ID we don't support %N",
743 ipcomp_transform_names, ipcomp);
744 break;
745 }
746 break;
747 }
748 case ESP_TFC_PADDING_NOT_SUPPORTED:
749 DBG1(DBG_IKE, "received %N, not using ESPv3 TFC padding",
750 notify_type_names, notify->get_notify_type(notify));
751 this->tfcv3 = FALSE;
752 break;
753 default:
754 break;
755 }
756 }
757
758 /**
759 * Read payloads from message
760 */
761 static void process_payloads(private_child_create_t *this, message_t *message)
762 {
763 enumerator_t *enumerator;
764 payload_t *payload;
765 sa_payload_t *sa_payload;
766 ke_payload_t *ke_payload;
767 ts_payload_t *ts_payload;
768
769 /* defaults to TUNNEL mode */
770 this->mode = MODE_TUNNEL;
771
772 enumerator = message->create_payload_enumerator(message);
773 while (enumerator->enumerate(enumerator, &payload))
774 {
775 switch (payload->get_type(payload))
776 {
777 case SECURITY_ASSOCIATION:
778 sa_payload = (sa_payload_t*)payload;
779 this->proposals = sa_payload->get_proposals(sa_payload);
780 break;
781 case KEY_EXCHANGE:
782 ke_payload = (ke_payload_t*)payload;
783 if (!this->initiator)
784 {
785 this->dh_group = ke_payload->get_dh_group_number(ke_payload);
786 this->dh = this->keymat->keymat.create_dh(
787 &this->keymat->keymat, this->dh_group);
788 }
789 if (this->dh)
790 {
791 this->dh->set_other_public_value(this->dh,
792 ke_payload->get_key_exchange_data(ke_payload));
793 }
794 break;
795 case TRAFFIC_SELECTOR_INITIATOR:
796 ts_payload = (ts_payload_t*)payload;
797 this->tsi = ts_payload->get_traffic_selectors(ts_payload);
798 break;
799 case TRAFFIC_SELECTOR_RESPONDER:
800 ts_payload = (ts_payload_t*)payload;
801 this->tsr = ts_payload->get_traffic_selectors(ts_payload);
802 break;
803 case NOTIFY:
804 handle_notify(this, (notify_payload_t*)payload);
805 break;
806 default:
807 break;
808 }
809 }
810 enumerator->destroy(enumerator);
811 }
812
813 METHOD(task_t, build_i, status_t,
814 private_child_create_t *this, message_t *message)
815 {
816 enumerator_t *enumerator;
817 host_t *vip;
818 peer_cfg_t *peer_cfg;
819 linked_list_t *list;
820
821 switch (message->get_exchange_type(message))
822 {
823 case IKE_SA_INIT:
824 return get_nonce(message, &this->my_nonce);
825 case CREATE_CHILD_SA:
826 if (generate_nonce(this) != SUCCESS)
827 {
828 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
829 return SUCCESS;
830 }
831 if (!this->retry)
832 {
833 this->dh_group = this->config->get_dh_group(this->config);
834 }
835 break;
836 case IKE_AUTH:
837 if (message->get_message_id(message) != 1)
838 {
839 /* send only in the first request, not in subsequent rounds */
840 return NEED_MORE;
841 }
842 break;
843 default:
844 break;
845 }
846
847 if (this->reqid)
848 {
849 DBG0(DBG_IKE, "establishing CHILD_SA %s{%d}",
850 this->config->get_name(this->config), this->reqid);
851 }
852 else
853 {
854 DBG0(DBG_IKE, "establishing CHILD_SA %s",
855 this->config->get_name(this->config));
856 }
857
858 /* check if we want a virtual IP, but don't have one */
859 list = linked_list_create();
860 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
861 if (!this->reqid)
862 {
863 enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
864 while (enumerator->enumerate(enumerator, &vip))
865 {
866 /* propose a 0.0.0.0/0 or ::/0 subnet when we use virtual ip */
867 vip = host_create_any(vip->get_family(vip));
868 list->insert_last(list, vip);
869 }
870 enumerator->destroy(enumerator);
871 }
872 if (list->get_count(list))
873 {
874 this->tsi = this->config->get_traffic_selectors(this->config,
875 TRUE, NULL, list);
876 list->destroy_offset(list, offsetof(host_t, destroy));
877 }
878 else
879 { /* no virtual IPs configured */
880 list->destroy(list);
881 list = get_dynamic_hosts(this->ike_sa, TRUE);
882 this->tsi = this->config->get_traffic_selectors(this->config,
883 TRUE, NULL, list);
884 list->destroy(list);
885 }
886 list = get_dynamic_hosts(this->ike_sa, FALSE);
887 this->tsr = this->config->get_traffic_selectors(this->config,
888 FALSE, NULL, list);
889 list->destroy(list);
890
891 if (this->packet_tsi)
892 {
893 this->tsi->insert_first(this->tsi,
894 this->packet_tsi->clone(this->packet_tsi));
895 }
896 if (this->packet_tsr)
897 {
898 this->tsr->insert_first(this->tsr,
899 this->packet_tsr->clone(this->packet_tsr));
900 }
901 this->proposals = this->config->get_proposals(this->config,
902 this->dh_group == MODP_NONE);
903 this->mode = this->config->get_mode(this->config);
904 if (this->mode == MODE_TRANSPORT &&
905 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
906 {
907 this->mode = MODE_TUNNEL;
908 DBG1(DBG_IKE, "not using transport mode, connection NATed");
909 }
910
911 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
912 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
913 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
914
915 if (!allocate_spi(this))
916 {
917 DBG1(DBG_IKE, "unable to allocate SPIs from kernel");
918 return FAILED;
919 }
920
921 if (this->dh_group != MODP_NONE)
922 {
923 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
924 this->dh_group);
925 }
926
927 if (this->config->use_ipcomp(this->config))
928 {
929 /* IPCOMP_DEFLATE is the only transform we support at the moment */
930 add_ipcomp_notify(this, message, IPCOMP_DEFLATE);
931 }
932
933 if (message->get_exchange_type(message) == IKE_AUTH)
934 {
935 charon->bus->narrow(charon->bus, this->child_sa,
936 NARROW_INITIATOR_PRE_NOAUTH, this->tsi, this->tsr);
937 }
938 else
939 {
940 charon->bus->narrow(charon->bus, this->child_sa,
941 NARROW_INITIATOR_PRE_AUTH, this->tsi, this->tsr);
942 }
943
944 build_payloads(this, message);
945
946 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
947 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
948 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
949 this->tsi = NULL;
950 this->tsr = NULL;
951 this->proposals = NULL;
952
953 return NEED_MORE;
954 }
955
956 METHOD(task_t, process_r, status_t,
957 private_child_create_t *this, message_t *message)
958 {
959 switch (message->get_exchange_type(message))
960 {
961 case IKE_SA_INIT:
962 return get_nonce(message, &this->other_nonce);
963 case CREATE_CHILD_SA:
964 get_nonce(message, &this->other_nonce);
965 break;
966 case IKE_AUTH:
967 if (message->get_message_id(message) != 1)
968 {
969 /* only handle first AUTH payload, not additional rounds */
970 return NEED_MORE;
971 }
972 default:
973 break;
974 }
975
976 process_payloads(this, message);
977
978 return NEED_MORE;
979 }
980
981 /**
982 * handle CHILD_SA setup failure
983 */
984 static void handle_child_sa_failure(private_child_create_t *this,
985 message_t *message)
986 {
987 if (message->get_exchange_type(message) == IKE_AUTH &&
988 lib->settings->get_bool(lib->settings,
989 "%s.close_ike_on_child_failure", FALSE, charon->name))
990 {
991 /* we delay the delete for 100ms, as the IKE_AUTH response must arrive
992 * first */
993 DBG1(DBG_IKE, "closing IKE_SA due CHILD_SA setup failure");
994 lib->scheduler->schedule_job_ms(lib->scheduler, (job_t*)
995 delete_ike_sa_job_create(this->ike_sa->get_id(this->ike_sa), TRUE),
996 100);
997 }
998 else
999 {
1000 DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA");
1001 charon->bus->alert(charon->bus, ALERT_KEEP_ON_CHILD_SA_FAILURE);
1002 }
1003 }
1004
1005 METHOD(task_t, build_r, status_t,
1006 private_child_create_t *this, message_t *message)
1007 {
1008 peer_cfg_t *peer_cfg;
1009 payload_t *payload;
1010 enumerator_t *enumerator;
1011 bool no_dh = TRUE, ike_auth = FALSE;
1012
1013 switch (message->get_exchange_type(message))
1014 {
1015 case IKE_SA_INIT:
1016 return get_nonce(message, &this->my_nonce);
1017 case CREATE_CHILD_SA:
1018 if (generate_nonce(this) != SUCCESS)
1019 {
1020 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
1021 chunk_empty);
1022 return SUCCESS;
1023 }
1024 no_dh = FALSE;
1025 break;
1026 case IKE_AUTH:
1027 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
1028 { /* wait until all authentication round completed */
1029 return NEED_MORE;
1030 }
1031 ike_auth = TRUE;
1032 default:
1033 break;
1034 }
1035
1036 if (this->ike_sa->get_state(this->ike_sa) == IKE_REKEYING)
1037 {
1038 DBG1(DBG_IKE, "unable to create CHILD_SA while rekeying IKE_SA");
1039 message->add_notify(message, TRUE, NO_ADDITIONAL_SAS, chunk_empty);
1040 return SUCCESS;
1041 }
1042
1043 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
1044 if (!this->config && peer_cfg && this->tsi && this->tsr)
1045 {
1046 linked_list_t *listr, *listi;
1047
1048 listr = get_dynamic_hosts(this->ike_sa, TRUE);
1049 listi = get_dynamic_hosts(this->ike_sa, FALSE);
1050 this->config = peer_cfg->select_child_cfg(peer_cfg,
1051 this->tsr, this->tsi, listr, listi);
1052 listr->destroy(listr);
1053 listi->destroy(listi);
1054 }
1055
1056 if (this->config == NULL)
1057 {
1058 DBG1(DBG_IKE, "traffic selectors %#R=== %#R inacceptable",
1059 this->tsr, this->tsi);
1060 charon->bus->alert(charon->bus, ALERT_TS_MISMATCH, this->tsi, this->tsr);
1061 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
1062 handle_child_sa_failure(this, message);
1063 return SUCCESS;
1064 }
1065
1066 /* check if ike_config_t included non-critical error notifies */
1067 enumerator = message->create_payload_enumerator(message);
1068 while (enumerator->enumerate(enumerator, &payload))
1069 {
1070 if (payload->get_type(payload) == NOTIFY)
1071 {
1072 notify_payload_t *notify = (notify_payload_t*)payload;
1073
1074 switch (notify->get_notify_type(notify))
1075 {
1076 case INTERNAL_ADDRESS_FAILURE:
1077 case FAILED_CP_REQUIRED:
1078 {
1079 DBG1(DBG_IKE,"configuration payload negotiation "
1080 "failed, no CHILD_SA built");
1081 enumerator->destroy(enumerator);
1082 handle_child_sa_failure(this, message);
1083 return SUCCESS;
1084 }
1085 default:
1086 break;
1087 }
1088 }
1089 }
1090 enumerator->destroy(enumerator);
1091
1092 this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
1093 this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
1094 this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
1095
1096 if (this->ipcomp_received != IPCOMP_NONE)
1097 {
1098 if (this->config->use_ipcomp(this->config))
1099 {
1100 add_ipcomp_notify(this, message, this->ipcomp_received);
1101 }
1102 else
1103 {
1104 DBG1(DBG_IKE, "received %N notify but IPComp is disabled, ignoring",
1105 notify_type_names, IPCOMP_SUPPORTED);
1106 }
1107 }
1108
1109 switch (select_and_install(this, no_dh, ike_auth))
1110 {
1111 case SUCCESS:
1112 break;
1113 case NOT_FOUND:
1114 message->add_notify(message, FALSE, TS_UNACCEPTABLE, chunk_empty);
1115 handle_child_sa_failure(this, message);
1116 return SUCCESS;
1117 case INVALID_ARG:
1118 {
1119 u_int16_t group = htons(this->dh_group);
1120 message->add_notify(message, FALSE, INVALID_KE_PAYLOAD,
1121 chunk_from_thing(group));
1122 handle_child_sa_failure(this, message);
1123 return SUCCESS;
1124 }
1125 case FAILED:
1126 default:
1127 message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
1128 handle_child_sa_failure(this, message);
1129 return SUCCESS;
1130 }
1131
1132 build_payloads(this, message);
1133
1134 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
1135 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1136 this->child_sa->get_name(this->child_sa),
1137 this->child_sa->get_reqid(this->child_sa),
1138 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
1139 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
1140 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
1141 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
1142
1143 if (!this->rekey)
1144 { /* invoke the child_up() hook if we are not rekeying */
1145 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
1146 }
1147 return SUCCESS;
1148 }
1149
1150 /**
1151 * Raise alerts for received notify errors
1152 */
1153 static void raise_alerts(private_child_create_t *this, notify_type_t type)
1154 {
1155 linked_list_t *list;
1156
1157 switch (type)
1158 {
1159 case NO_PROPOSAL_CHOSEN:
1160 list = this->config->get_proposals(this->config, FALSE);
1161 charon->bus->alert(charon->bus, ALERT_PROPOSAL_MISMATCH_CHILD, list);
1162 list->destroy_offset(list, offsetof(proposal_t, destroy));
1163 break;
1164 default:
1165 break;
1166 }
1167 }
1168
1169 METHOD(task_t, process_i, status_t,
1170 private_child_create_t *this, message_t *message)
1171 {
1172 enumerator_t *enumerator;
1173 payload_t *payload;
1174 bool no_dh = TRUE, ike_auth = FALSE;
1175
1176 switch (message->get_exchange_type(message))
1177 {
1178 case IKE_SA_INIT:
1179 return get_nonce(message, &this->other_nonce);
1180 case CREATE_CHILD_SA:
1181 get_nonce(message, &this->other_nonce);
1182 no_dh = FALSE;
1183 break;
1184 case IKE_AUTH:
1185 if (this->ike_sa->get_state(this->ike_sa) != IKE_ESTABLISHED)
1186 { /* wait until all authentication round completed */
1187 return NEED_MORE;
1188 }
1189 ike_auth = TRUE;
1190 default:
1191 break;
1192 }
1193
1194 /* check for erroneous notifies */
1195 enumerator = message->create_payload_enumerator(message);
1196 while (enumerator->enumerate(enumerator, &payload))
1197 {
1198 if (payload->get_type(payload) == NOTIFY)
1199 {
1200 notify_payload_t *notify = (notify_payload_t*)payload;
1201 notify_type_t type = notify->get_notify_type(notify);
1202
1203 switch (type)
1204 {
1205 /* handle notify errors related to CHILD_SA only */
1206 case NO_PROPOSAL_CHOSEN:
1207 case SINGLE_PAIR_REQUIRED:
1208 case NO_ADDITIONAL_SAS:
1209 case INTERNAL_ADDRESS_FAILURE:
1210 case FAILED_CP_REQUIRED:
1211 case TS_UNACCEPTABLE:
1212 case INVALID_SELECTORS:
1213 {
1214 DBG1(DBG_IKE, "received %N notify, no CHILD_SA built",
1215 notify_type_names, type);
1216 enumerator->destroy(enumerator);
1217 raise_alerts(this, type);
1218 handle_child_sa_failure(this, message);
1219 /* an error in CHILD_SA creation is not critical */
1220 return SUCCESS;
1221 }
1222 case INVALID_KE_PAYLOAD:
1223 {
1224 chunk_t data;
1225 u_int16_t group = MODP_NONE;
1226
1227 data = notify->get_notification_data(notify);
1228 if (data.len == sizeof(group))
1229 {
1230 memcpy(&group, data.ptr, data.len);
1231 group = ntohs(group);
1232 }
1233 DBG1(DBG_IKE, "peer didn't accept DH group %N, "
1234 "it requested %N", diffie_hellman_group_names,
1235 this->dh_group, diffie_hellman_group_names, group);
1236 this->retry = TRUE;
1237 this->dh_group = group;
1238 this->public.task.migrate(&this->public.task, this->ike_sa);
1239 enumerator->destroy(enumerator);
1240 return NEED_MORE;
1241 }
1242 default:
1243 {
1244 if (message->get_exchange_type(message) == CREATE_CHILD_SA)
1245 { /* handle notifies if not handled in IKE_AUTH */
1246 if (type <= 16383)
1247 {
1248 DBG1(DBG_IKE, "received %N notify error",
1249 notify_type_names, type);
1250 enumerator->destroy(enumerator);
1251 return SUCCESS;
1252 }
1253 DBG2(DBG_IKE, "received %N notify",
1254 notify_type_names, type);
1255 }
1256 break;
1257 }
1258 }
1259 }
1260 }
1261 enumerator->destroy(enumerator);
1262
1263 process_payloads(this, message);
1264
1265 if (this->ipcomp == IPCOMP_NONE && this->ipcomp_received != IPCOMP_NONE)
1266 {
1267 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify without requesting"
1268 " one, no CHILD_SA built");
1269 handle_child_sa_failure(this, message);
1270 return SUCCESS;
1271 }
1272 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp_received == IPCOMP_NONE)
1273 {
1274 DBG1(DBG_IKE, "peer didn't accept our proposed IPComp transforms, "
1275 "IPComp is disabled");
1276 this->ipcomp = IPCOMP_NONE;
1277 }
1278 else if (this->ipcomp != IPCOMP_NONE && this->ipcomp != this->ipcomp_received)
1279 {
1280 DBG1(DBG_IKE, "received an IPCOMP_SUPPORTED notify we didn't propose, "
1281 "no CHILD_SA built");
1282 handle_child_sa_failure(this, message);
1283 return SUCCESS;
1284 }
1285
1286 if (select_and_install(this, no_dh, ike_auth) == SUCCESS)
1287 {
1288 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
1289 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
1290 this->child_sa->get_name(this->child_sa),
1291 this->child_sa->get_reqid(this->child_sa),
1292 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
1293 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
1294 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
1295 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
1296
1297 if (!this->rekey)
1298 { /* invoke the child_up() hook if we are not rekeying */
1299 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
1300 }
1301 }
1302 else
1303 {
1304 handle_child_sa_failure(this, message);
1305 }
1306 return SUCCESS;
1307 }
1308
1309 METHOD(child_create_t, use_reqid, void,
1310 private_child_create_t *this, u_int32_t reqid)
1311 {
1312 this->reqid = reqid;
1313 }
1314
1315 METHOD(child_create_t, get_child, child_sa_t*,
1316 private_child_create_t *this)
1317 {
1318 return this->child_sa;
1319 }
1320
1321 METHOD(child_create_t, set_config, void,
1322 private_child_create_t *this, child_cfg_t *cfg)
1323 {
1324 DESTROY_IF(this->config);
1325 this->config = cfg;
1326 }
1327
1328 METHOD(child_create_t, get_lower_nonce, chunk_t,
1329 private_child_create_t *this)
1330 {
1331 if (memcmp(this->my_nonce.ptr, this->other_nonce.ptr,
1332 min(this->my_nonce.len, this->other_nonce.len)) < 0)
1333 {
1334 return this->my_nonce;
1335 }
1336 else
1337 {
1338 return this->other_nonce;
1339 }
1340 }
1341
1342 METHOD(task_t, get_type, task_type_t,
1343 private_child_create_t *this)
1344 {
1345 return TASK_CHILD_CREATE;
1346 }
1347
1348 METHOD(task_t, migrate, void,
1349 private_child_create_t *this, ike_sa_t *ike_sa)
1350 {
1351 chunk_free(&this->my_nonce);
1352 chunk_free(&this->other_nonce);
1353 if (this->tsr)
1354 {
1355 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1356 }
1357 if (this->tsi)
1358 {
1359 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1360 }
1361 DESTROY_IF(this->child_sa);
1362 DESTROY_IF(this->proposal);
1363 DESTROY_IF(this->dh);
1364 if (this->proposals)
1365 {
1366 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1367 }
1368
1369 this->ike_sa = ike_sa;
1370 this->keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
1371 this->proposal = NULL;
1372 this->proposals = NULL;
1373 this->tsi = NULL;
1374 this->tsr = NULL;
1375 this->dh = NULL;
1376 this->child_sa = NULL;
1377 this->mode = MODE_TUNNEL;
1378 this->ipcomp = IPCOMP_NONE;
1379 this->ipcomp_received = IPCOMP_NONE;
1380 this->other_cpi = 0;
1381 this->reqid = 0;
1382 this->established = FALSE;
1383 }
1384
1385 METHOD(task_t, destroy, void,
1386 private_child_create_t *this)
1387 {
1388 chunk_free(&this->my_nonce);
1389 chunk_free(&this->other_nonce);
1390 if (this->tsr)
1391 {
1392 this->tsr->destroy_offset(this->tsr, offsetof(traffic_selector_t, destroy));
1393 }
1394 if (this->tsi)
1395 {
1396 this->tsi->destroy_offset(this->tsi, offsetof(traffic_selector_t, destroy));
1397 }
1398 if (!this->established)
1399 {
1400 DESTROY_IF(this->child_sa);
1401 }
1402 DESTROY_IF(this->packet_tsi);
1403 DESTROY_IF(this->packet_tsr);
1404 DESTROY_IF(this->proposal);
1405 DESTROY_IF(this->dh);
1406 if (this->proposals)
1407 {
1408 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
1409 }
1410
1411 DESTROY_IF(this->config);
1412 free(this);
1413 }
1414
1415 /*
1416 * Described in header.
1417 */
1418 child_create_t *child_create_create(ike_sa_t *ike_sa,
1419 child_cfg_t *config, bool rekey,
1420 traffic_selector_t *tsi, traffic_selector_t *tsr)
1421 {
1422 private_child_create_t *this;
1423
1424 INIT(this,
1425 .public = {
1426 .get_child = _get_child,
1427 .set_config = _set_config,
1428 .get_lower_nonce = _get_lower_nonce,
1429 .use_reqid = _use_reqid,
1430 .task = {
1431 .get_type = _get_type,
1432 .migrate = _migrate,
1433 .destroy = _destroy,
1434 },
1435 },
1436 .ike_sa = ike_sa,
1437 .config = config,
1438 .packet_tsi = tsi ? tsi->clone(tsi) : NULL,
1439 .packet_tsr = tsr ? tsr->clone(tsr) : NULL,
1440 .dh_group = MODP_NONE,
1441 .keymat = (keymat_v2_t*)ike_sa->get_keymat(ike_sa),
1442 .mode = MODE_TUNNEL,
1443 .tfcv3 = TRUE,
1444 .ipcomp = IPCOMP_NONE,
1445 .ipcomp_received = IPCOMP_NONE,
1446 .rekey = rekey,
1447 .retry = FALSE,
1448 );
1449
1450 if (config)
1451 {
1452 this->public.task.build = _build_i;
1453 this->public.task.process = _process_i;
1454 this->initiator = TRUE;
1455 }
1456 else
1457 {
1458 this->public.task.build = _build_r;
1459 this->public.task.process = _process_r;
1460 this->initiator = FALSE;
1461 }
1462
1463 return &this->public;
1464 }