e7d26443b02babfd62078a8ac6487ca85a260035
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
1 /*
2 * Copyright (C) 2012-2015 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 /*
20 * Copyright (C) 2012 Volker R├╝melin
21 *
22 * Permission is hereby granted, free of charge, to any person obtaining a copy
23 * of this software and associated documentation files (the "Software"), to deal
24 * in the Software without restriction, including without limitation the rights
25 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
26 * copies of the Software, and to permit persons to whom the Software is
27 * furnished to do so, subject to the following conditions:
28 *
29 * The above copyright notice and this permission notice shall be included in
30 * all copies or substantial portions of the Software.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
38 * THE SOFTWARE.
39 */
40
41 #include "quick_mode.h"
42
43 #include <string.h>
44
45 #include <daemon.h>
46 #include <sa/ikev1/keymat_v1.h>
47 #include <encoding/payloads/sa_payload.h>
48 #include <encoding/payloads/nonce_payload.h>
49 #include <encoding/payloads/ke_payload.h>
50 #include <encoding/payloads/id_payload.h>
51 #include <encoding/payloads/payload.h>
52 #include <sa/ikev1/tasks/informational.h>
53 #include <sa/ikev1/tasks/quick_delete.h>
54 #include <processing/jobs/inactivity_job.h>
55
56 typedef struct private_quick_mode_t private_quick_mode_t;
57
58 /**
59 * Private members of a quick_mode_t task.
60 */
61 struct private_quick_mode_t {
62
63 /**
64 * Public methods and task_t interface.
65 */
66 quick_mode_t public;
67
68 /**
69 * Assigned IKE_SA.
70 */
71 ike_sa_t *ike_sa;
72
73 /**
74 * TRUE if we are initiating quick mode
75 */
76 bool initiator;
77
78 /**
79 * Traffic selector of initiator
80 */
81 traffic_selector_t *tsi;
82
83 /**
84 * Traffic selector of responder
85 */
86 traffic_selector_t *tsr;
87
88 /**
89 * Initiators nonce
90 */
91 chunk_t nonce_i;
92
93 /**
94 * Responder nonce
95 */
96 chunk_t nonce_r;
97
98 /**
99 * Initiators ESP SPI
100 */
101 u_int32_t spi_i;
102
103 /**
104 * Responder ESP SPI
105 */
106 u_int32_t spi_r;
107
108 /**
109 * Initiators IPComp CPI
110 */
111 u_int16_t cpi_i;
112
113 /**
114 * Responders IPComp CPI
115 */
116 u_int16_t cpi_r;
117
118 /**
119 * selected CHILD_SA proposal
120 */
121 proposal_t *proposal;
122
123 /**
124 * Config of CHILD_SA to establish
125 */
126 child_cfg_t *config;
127
128 /**
129 * CHILD_SA we are about to establish
130 */
131 child_sa_t *child_sa;
132
133 /**
134 * IKEv1 keymat
135 */
136 keymat_v1_t *keymat;
137
138 /**
139 * DH exchange, when PFS is in use
140 */
141 diffie_hellman_t *dh;
142
143 /**
144 * Negotiated lifetime of new SA
145 */
146 u_int32_t lifetime;
147
148 /**
149 * Negotaited lifebytes of new SA
150 */
151 u_int64_t lifebytes;
152
153 /**
154 * Reqid to use, 0 for auto-allocate
155 */
156 u_int32_t reqid;
157
158 /**
159 * Explicit inbound mark value to use, if any
160 */
161 u_int mark_in;
162
163 /**
164 * Explicit inbound mark value to use, if any
165 */
166 u_int mark_out;
167
168 /**
169 * SPI of SA we rekey
170 */
171 u_int32_t rekey;
172
173 /**
174 * Negotiated mode, tunnel or transport
175 */
176 ipsec_mode_t mode;
177
178 /*
179 * SA protocol (ESP|AH) negotiated
180 */
181 protocol_id_t proto;
182
183 /**
184 * Use UDP encapsulation
185 */
186 bool udp;
187
188 /**
189 * Message ID of handled quick mode exchange
190 */
191 u_int32_t mid;
192
193 /** states of quick mode */
194 enum {
195 QM_INIT,
196 QM_NEGOTIATED,
197 } state;
198 };
199
200 /**
201 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
202 */
203 static void schedule_inactivity_timeout(private_quick_mode_t *this)
204 {
205 u_int32_t timeout;
206 bool close_ike;
207
208 timeout = this->config->get_inactivity(this->config);
209 if (timeout)
210 {
211 close_ike = lib->settings->get_bool(lib->settings,
212 "%s.inactivity_close_ike", FALSE, lib->ns);
213 lib->scheduler->schedule_job(lib->scheduler, (job_t*)
214 inactivity_job_create(this->child_sa->get_unique_id(this->child_sa),
215 timeout, close_ike), timeout);
216 }
217 }
218
219 /**
220 * Check if we have a an address pool configured
221 */
222 static bool have_pool(ike_sa_t *ike_sa)
223 {
224 enumerator_t *enumerator;
225 peer_cfg_t *peer_cfg;
226 char *pool;
227 bool found = FALSE;
228
229 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
230 if (peer_cfg)
231 {
232 enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
233 if (enumerator->enumerate(enumerator, &pool))
234 {
235 found = TRUE;
236 }
237 enumerator->destroy(enumerator);
238 }
239 return found;
240 }
241
242 /**
243 * Get hosts to use for dynamic traffic selectors
244 */
245 static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
246 {
247 enumerator_t *enumerator;
248 linked_list_t *list;
249 host_t *host;
250
251 list = linked_list_create();
252 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
253 while (enumerator->enumerate(enumerator, &host))
254 {
255 list->insert_last(list, host);
256 }
257 enumerator->destroy(enumerator);
258
259 if (list->get_count(list) == 0)
260 { /* no virtual IPs assigned */
261 if (local)
262 {
263 host = ike_sa->get_my_host(ike_sa);
264 list->insert_last(list, host);
265 }
266 else if (!have_pool(ike_sa))
267 { /* use host only if we don't have a pool configured */
268 host = ike_sa->get_other_host(ike_sa);
269 list->insert_last(list, host);
270 }
271 }
272 return list;
273 }
274
275 /**
276 * Install negotiated CHILD_SA
277 */
278 static bool install(private_quick_mode_t *this)
279 {
280 status_t status, status_i, status_o;
281 chunk_t encr_i, encr_r, integ_i, integ_r;
282 linked_list_t *tsi, *tsr, *my_ts, *other_ts;
283 child_sa_t *old = NULL;
284
285 this->child_sa->set_proposal(this->child_sa, this->proposal);
286 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
287 this->child_sa->set_mode(this->child_sa, this->mode);
288
289 if (this->cpi_i && this->cpi_r)
290 { /* DEFLATE is the only transform we currently support */
291 this->child_sa->set_ipcomp(this->child_sa, IPCOMP_DEFLATE);
292 }
293 else
294 {
295 this->cpi_i = this->cpi_r = 0;
296 }
297
298 this->child_sa->set_protocol(this->child_sa,
299 this->proposal->get_protocol(this->proposal));
300
301 status_i = status_o = FAILED;
302 encr_i = encr_r = integ_i = integ_r = chunk_empty;
303 tsi = linked_list_create_with_items(this->tsi->clone(this->tsi), NULL);
304 tsr = linked_list_create_with_items(this->tsr->clone(this->tsr), NULL);
305 if (this->initiator)
306 {
307 charon->bus->narrow(charon->bus, this->child_sa,
308 NARROW_INITIATOR_POST_AUTH, tsi, tsr);
309 }
310 else
311 {
312 charon->bus->narrow(charon->bus, this->child_sa,
313 NARROW_RESPONDER_POST, tsr, tsi);
314 }
315 if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0)
316 {
317 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
318 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
319 DBG1(DBG_IKE, "no acceptable traffic selectors found");
320 return FALSE;
321 }
322
323 if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
324 this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
325 &encr_i, &integ_i, &encr_r, &integ_r))
326 {
327 if (this->initiator)
328 {
329 status_i = this->child_sa->install(this->child_sa,
330 encr_r, integ_r, this->spi_i, this->cpi_i,
331 this->initiator, TRUE, FALSE, tsi, tsr);
332 status_o = this->child_sa->install(this->child_sa,
333 encr_i, integ_i, this->spi_r, this->cpi_r,
334 this->initiator, FALSE, FALSE, tsi, tsr);
335 }
336 else
337 {
338 status_i = this->child_sa->install(this->child_sa,
339 encr_i, integ_i, this->spi_r, this->cpi_r,
340 this->initiator, TRUE, FALSE, tsr, tsi);
341 status_o = this->child_sa->install(this->child_sa,
342 encr_r, integ_r, this->spi_i, this->cpi_i,
343 this->initiator, FALSE, FALSE, tsr, tsi);
344 }
345 }
346 chunk_clear(&integ_i);
347 chunk_clear(&integ_r);
348 chunk_clear(&encr_i);
349 chunk_clear(&encr_r);
350
351 if (status_i != SUCCESS || status_o != SUCCESS)
352 {
353 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
354 (status_i != SUCCESS) ? "inbound " : "",
355 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
356 (status_o != SUCCESS) ? "outbound " : "");
357 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
358 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
359 return FALSE;
360 }
361
362 if (this->initiator)
363 {
364 status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
365 }
366 else
367 {
368 status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
369 }
370 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
371 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
372 if (status != SUCCESS)
373 {
374 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
375 return FALSE;
376 }
377
378 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
379 this->dh, this->nonce_i, this->nonce_r);
380
381 /* add to IKE_SA, and remove from task */
382 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
383 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
384
385 my_ts = linked_list_create_from_enumerator(
386 this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
387 other_ts = linked_list_create_from_enumerator(
388 this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
389
390 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
391 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
392 this->child_sa->get_name(this->child_sa),
393 this->child_sa->get_unique_id(this->child_sa),
394 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
395 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts);
396
397 my_ts->destroy(my_ts);
398 other_ts->destroy(other_ts);
399
400 if (this->rekey)
401 {
402 old = this->ike_sa->get_child_sa(this->ike_sa,
403 this->proposal->get_protocol(this->proposal),
404 this->rekey, TRUE);
405 }
406 if (old)
407 {
408 charon->bus->child_rekey(charon->bus, old, this->child_sa);
409 /* rekeyed CHILD_SAs stay installed until they expire */
410 old->set_state(old, CHILD_REKEYED);
411 }
412 else
413 {
414 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
415 }
416 schedule_inactivity_timeout(this);
417 this->child_sa = NULL;
418 return TRUE;
419 }
420
421 /**
422 * Generate and add NONCE
423 */
424 static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
425 message_t *message)
426 {
427 nonce_payload_t *nonce_payload;
428 nonce_gen_t *nonceg;
429
430 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
431 if (!nonceg)
432 {
433 DBG1(DBG_IKE, "no nonce generator found to create nonce");
434 return FALSE;
435 }
436 if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, nonce))
437 {
438 DBG1(DBG_IKE, "nonce allocation failed");
439 nonceg->destroy(nonceg);
440 return FALSE;
441 }
442 nonceg->destroy(nonceg);
443
444 nonce_payload = nonce_payload_create(PLV1_NONCE);
445 nonce_payload->set_nonce(nonce_payload, *nonce);
446 message->add_payload(message, &nonce_payload->payload_interface);
447
448 return TRUE;
449 }
450
451 /**
452 * Extract nonce from NONCE payload
453 */
454 static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
455 message_t *message)
456 {
457 nonce_payload_t *nonce_payload;
458
459 nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
460 if (!nonce_payload)
461 {
462 DBG1(DBG_IKE, "NONCE payload missing in message");
463 return FALSE;
464 }
465 *nonce = nonce_payload->get_nonce(nonce_payload);
466
467 return TRUE;
468 }
469
470 /**
471 * Add KE payload to message
472 */
473 static bool add_ke(private_quick_mode_t *this, message_t *message)
474 {
475 ke_payload_t *ke_payload;
476
477 ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE,
478 this->dh);
479 if (!ke_payload)
480 {
481 DBG1(DBG_IKE, "creating KE payload failed");
482 return FALSE;
483 }
484 message->add_payload(message, &ke_payload->payload_interface);
485 return TRUE;
486 }
487
488 /**
489 * Get DH value from a KE payload
490 */
491 static bool get_ke(private_quick_mode_t *this, message_t *message)
492 {
493 ke_payload_t *ke_payload;
494
495 ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
496 if (!ke_payload)
497 {
498 DBG1(DBG_IKE, "KE payload missing");
499 return FALSE;
500 }
501 if (!this->dh->set_other_public_value(this->dh,
502 ke_payload->get_key_exchange_data(ke_payload)))
503 {
504 DBG1(DBG_IKE, "unable to apply received KE value");
505 return FALSE;
506 }
507 return TRUE;
508 }
509
510 /**
511 * Select a traffic selector from configuration
512 */
513 static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
514 linked_list_t *supplied)
515 {
516 traffic_selector_t *ts;
517 linked_list_t *list, *hosts;
518
519 hosts = get_dynamic_hosts(this->ike_sa, local);
520 list = this->config->get_traffic_selectors(this->config,
521 local, supplied, hosts);
522 hosts->destroy(hosts);
523 if (list->get_first(list, (void**)&ts) == SUCCESS)
524 {
525 ts = ts->clone(ts);
526 }
527 else
528 {
529 DBG1(DBG_IKE, "%s traffic selector missing in configuration",
530 local ? "local" : "remote");
531 ts = NULL;
532 }
533 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
534 return ts;
535 }
536
537 /**
538 * Add selected traffic selectors to message
539 */
540 static void add_ts(private_quick_mode_t *this, message_t *message)
541 {
542 id_payload_t *id_payload;
543
544 id_payload = id_payload_create_from_ts(this->tsi);
545 message->add_payload(message, &id_payload->payload_interface);
546 id_payload = id_payload_create_from_ts(this->tsr);
547 message->add_payload(message, &id_payload->payload_interface);
548 }
549
550 /**
551 * Get traffic selectors from received message
552 */
553 static bool get_ts(private_quick_mode_t *this, message_t *message)
554 {
555 traffic_selector_t *tsi = NULL, *tsr = NULL;
556 enumerator_t *enumerator;
557 id_payload_t *id_payload;
558 payload_t *payload;
559 host_t *hsi, *hsr;
560 bool first = TRUE;
561
562 enumerator = message->create_payload_enumerator(message);
563 while (enumerator->enumerate(enumerator, &payload))
564 {
565 if (payload->get_type(payload) == PLV1_ID)
566 {
567 id_payload = (id_payload_t*)payload;
568
569 if (first)
570 {
571 tsi = id_payload->get_ts(id_payload);
572 first = FALSE;
573 }
574 else
575 {
576 tsr = id_payload->get_ts(id_payload);
577 break;
578 }
579 }
580 }
581 enumerator->destroy(enumerator);
582
583 /* create host2host selectors if ID payloads missing */
584 if (this->initiator)
585 {
586 hsi = this->ike_sa->get_my_host(this->ike_sa);
587 hsr = this->ike_sa->get_other_host(this->ike_sa);
588 }
589 else
590 {
591 hsr = this->ike_sa->get_my_host(this->ike_sa);
592 hsi = this->ike_sa->get_other_host(this->ike_sa);
593 }
594 if (!tsi)
595 {
596 tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
597 hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0, 65535);
598 }
599 if (!tsr)
600 {
601 tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
602 hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0, 65535);
603 }
604 if (this->mode == MODE_TRANSPORT && this->udp &&
605 (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr)))
606 { /* change TS in case of a NAT in transport mode */
607 DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT",
608 tsi, tsr);
609 tsi->set_address(tsi, hsi);
610 tsr->set_address(tsr, hsr);
611 }
612
613 if (this->initiator)
614 {
615 traffic_selector_t *tsisub, *tsrsub;
616
617 /* check if peer selection is valid */
618 tsisub = this->tsi->get_subset(this->tsi, tsi);
619 tsrsub = this->tsr->get_subset(this->tsr, tsr);
620 if (!tsisub || !tsrsub)
621 {
622 DBG1(DBG_IKE, "peer selected invalid traffic selectors: "
623 "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
624 DESTROY_IF(tsisub);
625 DESTROY_IF(tsrsub);
626 tsi->destroy(tsi);
627 tsr->destroy(tsr);
628 return FALSE;
629 }
630 tsi->destroy(tsi);
631 tsr->destroy(tsr);
632 this->tsi->destroy(this->tsi);
633 this->tsr->destroy(this->tsr);
634 this->tsi = tsisub;
635 this->tsr = tsrsub;
636 }
637 else
638 {
639 this->tsi = tsi;
640 this->tsr = tsr;
641 }
642 return TRUE;
643 }
644
645 /**
646 * Get encap
647 */
648 static encap_t get_encap(ike_sa_t* ike_sa, bool udp)
649 {
650 if (!udp)
651 {
652 return ENCAP_NONE;
653 }
654 if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
655 {
656 return ENCAP_UDP_DRAFT_00_03;
657 }
658 return ENCAP_UDP;
659 }
660
661 /**
662 * Get NAT-OA payload type (RFC 3947 or RFC 3947 drafts).
663 */
664 static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa)
665 {
666 if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
667 {
668 return PLV1_NAT_OA_DRAFT_00_03;
669 }
670 return PLV1_NAT_OA;
671 }
672
673 /**
674 * Add NAT-OA payloads
675 */
676 static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
677 {
678 identification_t *id;
679 id_payload_t *nat_oa;
680 host_t *src, *dst;
681 payload_type_t nat_oa_payload_type;
682
683 src = message->get_source(message);
684 dst = message->get_destination(message);
685
686 src = this->initiator ? src : dst;
687 dst = this->initiator ? dst : src;
688
689 nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa);
690
691 /* first NAT-OA is the initiator's address */
692 id = identification_create_from_sockaddr(src->get_sockaddr(src));
693 nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
694 message->add_payload(message, (payload_t*)nat_oa);
695 id->destroy(id);
696
697 /* second NAT-OA is that of the responder */
698 id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
699 nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
700 message->add_payload(message, (payload_t*)nat_oa);
701 id->destroy(id);
702 }
703
704 /**
705 * Look up lifetimes
706 */
707 static void get_lifetimes(private_quick_mode_t *this)
708 {
709 lifetime_cfg_t *lft;
710
711 lft = this->config->get_lifetime(this->config);
712 if (lft->time.life)
713 {
714 this->lifetime = lft->time.life;
715 }
716 else if (lft->bytes.life)
717 {
718 this->lifebytes = lft->bytes.life;
719 }
720 free(lft);
721 }
722
723 /**
724 * Check and apply lifetimes
725 */
726 static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
727 {
728 u_int32_t lifetime;
729 u_int64_t lifebytes;
730
731 lifetime = sa_payload->get_lifetime(sa_payload);
732 lifebytes = sa_payload->get_lifebytes(sa_payload);
733 if (this->lifetime != lifetime)
734 {
735 DBG1(DBG_IKE, "received %us lifetime, configured %us",
736 lifetime, this->lifetime);
737 this->lifetime = lifetime;
738 }
739 if (this->lifebytes != lifebytes)
740 {
741 DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
742 lifebytes, this->lifebytes);
743 this->lifebytes = lifebytes;
744 }
745 }
746
747 /**
748 * Set the task ready to build notify error message
749 */
750 static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
751 {
752 notify_payload_t *notify;
753
754 notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
755 this->proto, type);
756 notify->set_spi(notify, this->spi_i);
757
758 this->ike_sa->queue_task(this->ike_sa,
759 (task_t*)informational_create(this->ike_sa, notify));
760 /* cancel all active/passive tasks in favour of informational */
761 this->ike_sa->flush_queue(this->ike_sa,
762 this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
763 return ALREADY_DONE;
764 }
765
766 /**
767 * Prepare a list of proposals from child_config containing only the specified
768 * DH group, unless it is set to MODP_NONE.
769 */
770 static linked_list_t *get_proposals(private_quick_mode_t *this,
771 diffie_hellman_group_t group)
772 {
773 linked_list_t *list;
774 proposal_t *proposal;
775 enumerator_t *enumerator;
776
777 list = this->config->get_proposals(this->config, FALSE);
778 enumerator = list->create_enumerator(list);
779 while (enumerator->enumerate(enumerator, &proposal))
780 {
781 if (group != MODP_NONE)
782 {
783 if (!proposal->has_dh_group(proposal, group))
784 {
785 list->remove_at(list, enumerator);
786 proposal->destroy(proposal);
787 continue;
788 }
789 proposal->strip_dh(proposal, group);
790 }
791 proposal->set_spi(proposal, this->spi_i);
792 }
793 enumerator->destroy(enumerator);
794
795 return list;
796 }
797
798 METHOD(task_t, build_i, status_t,
799 private_quick_mode_t *this, message_t *message)
800 {
801 switch (this->state)
802 {
803 case QM_INIT:
804 {
805 sa_payload_t *sa_payload;
806 linked_list_t *list, *tsi, *tsr;
807 proposal_t *proposal;
808 diffie_hellman_group_t group;
809 encap_t encap;
810
811 this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
812 this->mode = this->config->get_mode(this->config);
813 this->child_sa = child_sa_create(
814 this->ike_sa->get_my_host(this->ike_sa),
815 this->ike_sa->get_other_host(this->ike_sa),
816 this->config, this->reqid, this->udp,
817 this->mark_in, this->mark_out);
818
819 if (this->udp && this->mode == MODE_TRANSPORT)
820 {
821 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
822 add_nat_oa_payloads(this, message);
823 }
824
825 if (this->config->use_ipcomp(this->config))
826 {
827 this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
828 if (!this->cpi_i)
829 {
830 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
831 "IPComp disabled");
832 }
833 }
834
835 list = this->config->get_proposals(this->config, MODP_NONE);
836 if (list->get_first(list, (void**)&proposal) == SUCCESS)
837 {
838 this->proto = proposal->get_protocol(proposal);
839 }
840 list->destroy_offset(list, offsetof(proposal_t, destroy));
841 this->spi_i = this->child_sa->alloc_spi(this->child_sa, this->proto);
842 if (!this->spi_i)
843 {
844 DBG1(DBG_IKE, "allocating SPI from kernel failed");
845 return FAILED;
846 }
847
848 group = this->config->get_dh_group(this->config);
849 if (group != MODP_NONE)
850 {
851 proposal_t *proposal;
852 u_int16_t preferred_group;
853
854 proposal = this->ike_sa->get_proposal(this->ike_sa);
855 proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
856 &preferred_group, NULL);
857 /* try the negotiated DH group from IKE_SA */
858 list = get_proposals(this, preferred_group);
859 if (list->get_count(list))
860 {
861 group = preferred_group;
862 }
863 else
864 {
865 /* fall back to the first configured DH group */
866 list->destroy(list);
867 list = get_proposals(this, group);
868 }
869
870 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
871 group);
872 if (!this->dh)
873 {
874 DBG1(DBG_IKE, "configured DH group %N not supported",
875 diffie_hellman_group_names, group);
876 list->destroy_offset(list, offsetof(proposal_t, destroy));
877 return FAILED;
878 }
879 }
880 else
881 {
882 list = get_proposals(this, MODP_NONE);
883 }
884
885 get_lifetimes(this);
886 encap = get_encap(this->ike_sa, this->udp);
887 sa_payload = sa_payload_create_from_proposals_v1(list,
888 this->lifetime, this->lifebytes, AUTH_NONE,
889 this->mode, encap, this->cpi_i);
890 list->destroy_offset(list, offsetof(proposal_t, destroy));
891 message->add_payload(message, &sa_payload->payload_interface);
892
893 if (!add_nonce(this, &this->nonce_i, message))
894 {
895 return FAILED;
896 }
897 if (group != MODP_NONE)
898 {
899 if (!add_ke(this, message))
900 {
901 return FAILED;
902 }
903 }
904 if (!this->tsi)
905 {
906 this->tsi = select_ts(this, TRUE, NULL);
907 }
908 if (!this->tsr)
909 {
910 this->tsr = select_ts(this, FALSE, NULL);
911 }
912 tsi = linked_list_create_with_items(this->tsi, NULL);
913 tsr = linked_list_create_with_items(this->tsr, NULL);
914 this->tsi = this->tsr = NULL;
915 charon->bus->narrow(charon->bus, this->child_sa,
916 NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
917 tsi->remove_first(tsi, (void**)&this->tsi);
918 tsr->remove_first(tsr, (void**)&this->tsr);
919 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
920 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
921 if (!this->tsi || !this->tsr)
922 {
923 return FAILED;
924 }
925 add_ts(this, message);
926 return NEED_MORE;
927 }
928 case QM_NEGOTIATED:
929 {
930 return SUCCESS;
931 }
932 default:
933 return FAILED;
934 }
935 }
936
937 /**
938 * Check for notify errors, return TRUE if error found
939 */
940 static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
941 {
942 enumerator_t *enumerator;
943 payload_t *payload;
944 bool err = FALSE;
945
946 enumerator = message->create_payload_enumerator(message);
947 while (enumerator->enumerate(enumerator, &payload))
948 {
949 if (payload->get_type(payload) == PLV1_NOTIFY)
950 {
951 notify_payload_t *notify;
952 notify_type_t type;
953
954 notify = (notify_payload_t*)payload;
955 type = notify->get_notify_type(notify);
956 if (type < 16384)
957 {
958
959 DBG1(DBG_IKE, "received %N error notify",
960 notify_type_names, type);
961 err = TRUE;
962 }
963 else
964 {
965 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
966 }
967 }
968 }
969 enumerator->destroy(enumerator);
970
971 return err;
972 }
973
974 /**
975 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
976 */
977 static void check_for_rekeyed_child(private_quick_mode_t *this)
978 {
979 enumerator_t *enumerator, *policies;
980 traffic_selector_t *local, *remote;
981 child_sa_t *child_sa;
982 proposal_t *proposal;
983 char *name;
984
985 name = this->config->get_name(this->config);
986 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
987 while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
988 {
989 if (streq(child_sa->get_name(child_sa), name))
990 {
991 proposal = child_sa->get_proposal(child_sa);
992 switch (child_sa->get_state(child_sa))
993 {
994 case CHILD_INSTALLED:
995 case CHILD_REKEYING:
996 case CHILD_REKEYED:
997 policies = child_sa->create_policy_enumerator(child_sa);
998 if (policies->enumerate(policies, &local, &remote) &&
999 local->equals(local, this->tsr) &&
1000 remote->equals(remote, this->tsi) &&
1001 this->proposal->equals(this->proposal, proposal))
1002 {
1003 this->reqid = child_sa->get_reqid(child_sa);
1004 this->rekey = child_sa->get_spi(child_sa, TRUE);
1005 this->mark_in = child_sa->get_mark(child_sa,
1006 TRUE).value;
1007 this->mark_out = child_sa->get_mark(child_sa,
1008 FALSE).value;
1009 child_sa->set_state(child_sa, CHILD_REKEYING);
1010 DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
1011 child_sa->get_name(child_sa),
1012 child_sa->get_unique_id(child_sa));
1013 }
1014 policies->destroy(policies);
1015 break;
1016 default:
1017 break;
1018 }
1019 }
1020 }
1021 enumerator->destroy(enumerator);
1022 }
1023
1024 METHOD(task_t, process_r, status_t,
1025 private_quick_mode_t *this, message_t *message)
1026 {
1027 if (this->mid && this->mid != message->get_message_id(message))
1028 { /* not responsible for this quick mode exchange */
1029 return INVALID_ARG;
1030 }
1031
1032 switch (this->state)
1033 {
1034 case QM_INIT:
1035 {
1036 sa_payload_t *sa_payload;
1037 linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
1038 peer_cfg_t *peer_cfg;
1039 u_int16_t group;
1040 bool private;
1041
1042 sa_payload = (sa_payload_t*)message->get_payload(message,
1043 PLV1_SECURITY_ASSOCIATION);
1044 if (!sa_payload)
1045 {
1046 DBG1(DBG_IKE, "sa payload missing");
1047 return send_notify(this, INVALID_PAYLOAD_TYPE);
1048 }
1049
1050 this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
1051
1052 if (!get_ts(this, message))
1053 {
1054 return FAILED;
1055 }
1056 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
1057 tsi = linked_list_create_with_items(this->tsi, NULL);
1058 tsr = linked_list_create_with_items(this->tsr, NULL);
1059 this->tsi = this->tsr = NULL;
1060 hostsi = get_dynamic_hosts(this->ike_sa, FALSE);
1061 hostsr = get_dynamic_hosts(this->ike_sa, TRUE);
1062 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
1063 hostsr, hostsi);
1064 hostsi->destroy(hostsi);
1065 hostsr->destroy(hostsr);
1066 if (this->config)
1067 {
1068 this->tsi = select_ts(this, FALSE, tsi);
1069 this->tsr = select_ts(this, TRUE, tsr);
1070 }
1071 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1072 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1073 if (!this->config || !this->tsi || !this->tsr ||
1074 this->mode != this->config->get_mode(this->config))
1075 {
1076 DBG1(DBG_IKE, "no matching CHILD_SA config found");
1077 return send_notify(this, INVALID_ID_INFORMATION);
1078 }
1079
1080 if (this->config->use_ipcomp(this->config))
1081 {
1082 list = sa_payload->get_ipcomp_proposals(sa_payload,
1083 &this->cpi_i);
1084 if (!list->get_count(list))
1085 {
1086 DBG1(DBG_IKE, "expected IPComp proposal but peer did "
1087 "not send one, IPComp disabled");
1088 this->cpi_i = 0;
1089 }
1090 }
1091 if (!list || !list->get_count(list))
1092 {
1093 DESTROY_IF(list);
1094 list = sa_payload->get_proposals(sa_payload);
1095 }
1096 private = this->ike_sa->supports_extension(this->ike_sa,
1097 EXT_STRONGSWAN);
1098 this->proposal = this->config->select_proposal(this->config,
1099 list, FALSE, private);
1100 list->destroy_offset(list, offsetof(proposal_t, destroy));
1101
1102 get_lifetimes(this);
1103 apply_lifetimes(this, sa_payload);
1104
1105 if (!this->proposal)
1106 {
1107 DBG1(DBG_IKE, "no matching proposal found, sending %N",
1108 notify_type_names, NO_PROPOSAL_CHOSEN);
1109 return send_notify(this, NO_PROPOSAL_CHOSEN);
1110 }
1111 this->spi_i = this->proposal->get_spi(this->proposal);
1112
1113 if (!get_nonce(this, &this->nonce_i, message))
1114 {
1115 return send_notify(this, INVALID_PAYLOAD_TYPE);
1116 }
1117
1118 if (this->proposal->get_algorithm(this->proposal,
1119 DIFFIE_HELLMAN_GROUP, &group, NULL))
1120 {
1121 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
1122 group);
1123 if (!this->dh)
1124 {
1125 DBG1(DBG_IKE, "negotiated DH group %N not supported",
1126 diffie_hellman_group_names, group);
1127 return send_notify(this, INVALID_KEY_INFORMATION);
1128 }
1129 if (!get_ke(this, message))
1130 {
1131 return send_notify(this, INVALID_PAYLOAD_TYPE);
1132 }
1133 }
1134
1135 check_for_rekeyed_child(this);
1136
1137 this->child_sa = child_sa_create(
1138 this->ike_sa->get_my_host(this->ike_sa),
1139 this->ike_sa->get_other_host(this->ike_sa),
1140 this->config, this->reqid, this->udp,
1141 this->mark_in, this->mark_out);
1142
1143 tsi = linked_list_create_with_items(this->tsi, NULL);
1144 tsr = linked_list_create_with_items(this->tsr, NULL);
1145 this->tsi = this->tsr = NULL;
1146 charon->bus->narrow(charon->bus, this->child_sa,
1147 NARROW_RESPONDER, tsr, tsi);
1148 if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS ||
1149 tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS)
1150 {
1151 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1152 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1153 return send_notify(this, INVALID_ID_INFORMATION);
1154 }
1155 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1156 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1157
1158 return NEED_MORE;
1159 }
1160 case QM_NEGOTIATED:
1161 {
1162 if (has_notify_errors(this, message))
1163 {
1164 return SUCCESS;
1165 }
1166 if (message->get_exchange_type(message) == INFORMATIONAL_V1)
1167 {
1168 if (message->get_payload(message, PLV1_DELETE))
1169 {
1170 /* If the DELETE for a Quick Mode follows immediately
1171 * after rekeying, we might receive it before the
1172 * third completing Quick Mode message. Ignore it, as
1173 * it gets handled by a separately queued delete task. */
1174 return NEED_MORE;
1175 }
1176 return SUCCESS;
1177 }
1178 if (!install(this))
1179 {
1180 ike_sa_t *ike_sa = this->ike_sa;
1181 task_t *task;
1182
1183 task = (task_t*)quick_delete_create(this->ike_sa,
1184 this->proposal->get_protocol(this->proposal),
1185 this->spi_i, TRUE, TRUE);
1186 /* flush_queue() destroys the current task */
1187 ike_sa->flush_queue(ike_sa, TASK_QUEUE_PASSIVE);
1188 ike_sa->queue_task(ike_sa, task);
1189 return ALREADY_DONE;
1190 }
1191 return SUCCESS;
1192 }
1193 default:
1194 return FAILED;
1195 }
1196 }
1197
1198 METHOD(task_t, build_r, status_t,
1199 private_quick_mode_t *this, message_t *message)
1200 {
1201 if (this->mid && this->mid != message->get_message_id(message))
1202 { /* not responsible for this quick mode exchange */
1203 return INVALID_ARG;
1204 }
1205
1206 switch (this->state)
1207 {
1208 case QM_INIT:
1209 {
1210 sa_payload_t *sa_payload;
1211 encap_t encap;
1212
1213 this->proto = this->proposal->get_protocol(this->proposal);
1214 this->spi_r = this->child_sa->alloc_spi(this->child_sa, this->proto);
1215 if (!this->spi_r)
1216 {
1217 DBG1(DBG_IKE, "allocating SPI from kernel failed");
1218 return send_notify(this, NO_PROPOSAL_CHOSEN);
1219 }
1220 this->proposal->set_spi(this->proposal, this->spi_r);
1221
1222 if (this->cpi_i)
1223 {
1224 this->cpi_r = this->child_sa->alloc_cpi(this->child_sa);
1225 if (!this->cpi_r)
1226 {
1227 DBG1(DBG_IKE, "unable to allocate a CPI from "
1228 "kernel, IPComp disabled");
1229 return send_notify(this, NO_PROPOSAL_CHOSEN);
1230 }
1231 }
1232
1233 if (this->udp && this->mode == MODE_TRANSPORT)
1234 {
1235 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
1236 add_nat_oa_payloads(this, message);
1237 }
1238
1239 encap = get_encap(this->ike_sa, this->udp);
1240 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
1241 this->lifetime, this->lifebytes, AUTH_NONE,
1242 this->mode, encap, this->cpi_r);
1243 message->add_payload(message, &sa_payload->payload_interface);
1244
1245 if (!add_nonce(this, &this->nonce_r, message))
1246 {
1247 return FAILED;
1248 }
1249 if (this->dh)
1250 {
1251 if (!add_ke(this, message))
1252 {
1253 return FAILED;
1254 }
1255 }
1256
1257 add_ts(this, message);
1258
1259 this->state = QM_NEGOTIATED;
1260 this->mid = message->get_message_id(message);
1261 return NEED_MORE;
1262 }
1263 case QM_NEGOTIATED:
1264 if (message->get_exchange_type(message) == INFORMATIONAL_V1)
1265 {
1266 /* skip INFORMATIONAL response if we received a INFORMATIONAL
1267 * delete, see process_r() */
1268 return ALREADY_DONE;
1269 }
1270 /* fall */
1271 default:
1272 return FAILED;
1273 }
1274 }
1275
1276 METHOD(task_t, process_i, status_t,
1277 private_quick_mode_t *this, message_t *message)
1278 {
1279 switch (this->state)
1280 {
1281 case QM_INIT:
1282 {
1283 sa_payload_t *sa_payload;
1284 linked_list_t *list = NULL;
1285 bool private;
1286
1287 sa_payload = (sa_payload_t*)message->get_payload(message,
1288 PLV1_SECURITY_ASSOCIATION);
1289 if (!sa_payload)
1290 {
1291 DBG1(DBG_IKE, "sa payload missing");
1292 return send_notify(this, NO_PROPOSAL_CHOSEN);
1293 }
1294 if (this->cpi_i)
1295 {
1296 list = sa_payload->get_ipcomp_proposals(sa_payload,
1297 &this->cpi_r);
1298 if (!list->get_count(list))
1299 {
1300 DBG1(DBG_IKE, "peer did not acccept our IPComp proposal, "
1301 "IPComp disabled");
1302 this->cpi_i = 0;
1303 }
1304 }
1305 if (!list || !list->get_count(list))
1306 {
1307 DESTROY_IF(list);
1308 list = sa_payload->get_proposals(sa_payload);
1309 }
1310 private = this->ike_sa->supports_extension(this->ike_sa,
1311 EXT_STRONGSWAN);
1312 this->proposal = this->config->select_proposal(this->config,
1313 list, FALSE, private);
1314 list->destroy_offset(list, offsetof(proposal_t, destroy));
1315 if (!this->proposal)
1316 {
1317 DBG1(DBG_IKE, "no matching proposal found");
1318 return send_notify(this, NO_PROPOSAL_CHOSEN);
1319 }
1320 this->spi_r = this->proposal->get_spi(this->proposal);
1321
1322 apply_lifetimes(this, sa_payload);
1323
1324 if (!get_nonce(this, &this->nonce_r, message))
1325 {
1326 return send_notify(this, INVALID_PAYLOAD_TYPE);
1327 }
1328 if (this->dh && !get_ke(this, message))
1329 {
1330 return send_notify(this, INVALID_KEY_INFORMATION);
1331 }
1332 if (!get_ts(this, message))
1333 {
1334 return send_notify(this, INVALID_PAYLOAD_TYPE);
1335 }
1336 if (!install(this))
1337 {
1338 return send_notify(this, NO_PROPOSAL_CHOSEN);
1339 }
1340 this->state = QM_NEGOTIATED;
1341 return NEED_MORE;
1342 }
1343 default:
1344 return FAILED;
1345 }
1346 }
1347
1348 METHOD(task_t, get_type, task_type_t,
1349 private_quick_mode_t *this)
1350 {
1351 return TASK_QUICK_MODE;
1352 }
1353
1354 METHOD(quick_mode_t, get_mid, u_int32_t,
1355 private_quick_mode_t *this)
1356 {
1357 return this->mid;
1358 }
1359
1360 METHOD(quick_mode_t, use_reqid, void,
1361 private_quick_mode_t *this, u_int32_t reqid)
1362 {
1363 this->reqid = reqid;
1364 }
1365
1366 METHOD(quick_mode_t, use_marks, void,
1367 private_quick_mode_t *this, u_int in, u_int out)
1368 {
1369 this->mark_in = in;
1370 this->mark_out = out;
1371 }
1372
1373 METHOD(quick_mode_t, rekey, void,
1374 private_quick_mode_t *this, u_int32_t spi)
1375 {
1376 this->rekey = spi;
1377 }
1378
1379 METHOD(task_t, migrate, void,
1380 private_quick_mode_t *this, ike_sa_t *ike_sa)
1381 {
1382 chunk_free(&this->nonce_i);
1383 chunk_free(&this->nonce_r);
1384 DESTROY_IF(this->tsi);
1385 DESTROY_IF(this->tsr);
1386 DESTROY_IF(this->proposal);
1387 DESTROY_IF(this->child_sa);
1388 DESTROY_IF(this->dh);
1389
1390 this->ike_sa = ike_sa;
1391 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1392 this->state = QM_INIT;
1393 this->mid = 0;
1394 this->tsi = NULL;
1395 this->tsr = NULL;
1396 this->proposal = NULL;
1397 this->child_sa = NULL;
1398 this->dh = NULL;
1399 this->spi_i = 0;
1400 this->spi_r = 0;
1401 this->mark_in = 0;
1402 this->mark_out = 0;
1403
1404 if (!this->initiator)
1405 {
1406 DESTROY_IF(this->config);
1407 this->config = NULL;
1408 }
1409 }
1410
1411 METHOD(task_t, destroy, void,
1412 private_quick_mode_t *this)
1413 {
1414 chunk_free(&this->nonce_i);
1415 chunk_free(&this->nonce_r);
1416 DESTROY_IF(this->tsi);
1417 DESTROY_IF(this->tsr);
1418 DESTROY_IF(this->proposal);
1419 DESTROY_IF(this->child_sa);
1420 DESTROY_IF(this->config);
1421 DESTROY_IF(this->dh);
1422 free(this);
1423 }
1424
1425 /*
1426 * Described in header.
1427 */
1428 quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1429 traffic_selector_t *tsi, traffic_selector_t *tsr)
1430 {
1431 private_quick_mode_t *this;
1432
1433 INIT(this,
1434 .public = {
1435 .task = {
1436 .get_type = _get_type,
1437 .migrate = _migrate,
1438 .destroy = _destroy,
1439 },
1440 .get_mid = _get_mid,
1441 .use_reqid = _use_reqid,
1442 .use_marks = _use_marks,
1443 .rekey = _rekey,
1444 },
1445 .ike_sa = ike_sa,
1446 .initiator = config != NULL,
1447 .config = config,
1448 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1449 .state = QM_INIT,
1450 .tsi = tsi ? tsi->clone(tsi) : NULL,
1451 .tsr = tsr ? tsr->clone(tsr) : NULL,
1452 .proto = PROTO_ESP,
1453 );
1454
1455 if (config)
1456 {
1457 this->public.task.build = _build_i;
1458 this->public.task.process = _process_i;
1459 }
1460 else
1461 {
1462 this->public.task.build = _build_r;
1463 this->public.task.process = _process_r;
1464 }
1465
1466 return &this->public;
1467 }