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