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