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