]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/sa/ikev1/tasks/quick_mode.c
child-sa: Configure interface ID on SAs and policies
[thirdparty/strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
CommitLineData
2b04aa46 1/*
4de361d9 2 * Copyright (C) 2012-2015 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
MW
153 /**
154 * Reqid to use, 0 for auto-allocate
155 */
b12c53ce 156 uint32_t reqid;
14dc7941 157
85b23888
MW
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
669d8bde
MW
168 /**
169 * SPI of SA we rekey
170 */
b12c53ce 171 uint32_t rekey;
669d8bde 172
2f3c08d2
TB
173 /**
174 * Delete old child after successful rekey
175 */
176 bool delete;
177
90731f38
MW
178 /**
179 * Negotiated mode, tunnel or transport
180 */
181 ipsec_mode_t mode;
182
908fe163
MW
183 /*
184 * SA protocol (ESP|AH) negotiated
185 */
186 protocol_id_t proto;
187
7fd7ffc6
MW
188 /**
189 * Use UDP encapsulation
190 */
191 bool udp;
192
4de361d9
TB
193 /**
194 * Message ID of handled quick mode exchange
195 */
b12c53ce 196 uint32_t mid;
4de361d9 197
2b04aa46
MW
198 /** states of quick mode */
199 enum {
200 QM_INIT,
21b7db99 201 QM_NEGOTIATED,
2b04aa46
MW
202 } state;
203};
204
c60246a6
MW
205/**
206 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
207 */
208static void schedule_inactivity_timeout(private_quick_mode_t *this)
209{
b12c53ce 210 uint32_t timeout;
c60246a6
MW
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,
d223fe80 217 "%s.inactivity_close_ike", FALSE, lib->ns);
c60246a6 218 lib->scheduler->schedule_job(lib->scheduler, (job_t*)
85ace154
MW
219 inactivity_job_create(this->child_sa->get_unique_id(this->child_sa),
220 timeout, close_ike), timeout);
c60246a6
MW
221 }
222}
223
c4acf375
MW
224/**
225 * Check if we have a an address pool configured
226 */
227static 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/**
7ee37114 248 * Get hosts to use for dynamic traffic selectors
c4acf375 249 */
7ee37114 250static linked_list_t *get_dynamic_hosts(ike_sa_t *ike_sa, bool local)
c4acf375
MW
251{
252 enumerator_t *enumerator;
7ee37114 253 linked_list_t *list;
c4acf375
MW
254 host_t *host;
255
7ee37114 256 list = linked_list_create();
c4acf375 257 enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
7ee37114 258 while (enumerator->enumerate(enumerator, &host))
c4acf375 259 {
7ee37114
MW
260 list->insert_last(list, host);
261 }
262 enumerator->destroy(enumerator);
263
264 if (list->get_count(list) == 0)
265 { /* no virtual IPs assigned */
c4acf375
MW
266 if (local)
267 {
268 host = ike_sa->get_my_host(ike_sa);
7ee37114 269 list->insert_last(list, host);
c4acf375 270 }
7ee37114
MW
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);
c4acf375
MW
275 }
276 }
7ee37114 277 return list;
c4acf375
MW
278}
279
5351d63c
MW
280/**
281 * Install negotiated CHILD_SA
282 */
283static 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;
553bb787 287 linked_list_t *tsi, *tsr, *my_ts, *other_ts;
669d8bde 288 child_sa_t *old = NULL;
5351d63c
MW
289
290 this->child_sa->set_proposal(this->child_sa, this->proposal);
291 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
90731f38 292 this->child_sa->set_mode(this->child_sa, this->mode);
47b448b8
TB
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
5351d63c
MW
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;
abdb82fc
MW
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);
696fa8e0
MW
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,
f942588f 318 NARROW_RESPONDER_POST, tsr, tsi);
696fa8e0
MW
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
4989aba8
TB
328 if (this->initiator)
329 {
330 this->child_sa->set_policies(this->child_sa, tsi, tsr);
331 }
332 else
333 {
334 this->child_sa->set_policies(this->child_sa, tsr, tsi);
335 }
336 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
337 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
338
5adf855e 339 if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
a7910b1c
MW
340 this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
341 &encr_i, &integ_i, &encr_r, &integ_r))
5351d63c
MW
342 {
343 if (this->initiator)
344 {
a8c94544
MW
345 status_i = this->child_sa->install(this->child_sa,
346 encr_r, integ_r, this->spi_i, this->cpi_i,
4989aba8 347 this->initiator, TRUE, FALSE);
a8c94544
MW
348 status_o = this->child_sa->install(this->child_sa,
349 encr_i, integ_i, this->spi_r, this->cpi_r,
4989aba8 350 this->initiator, FALSE, FALSE);
5351d63c
MW
351 }
352 else
353 {
a8c94544
MW
354 status_i = this->child_sa->install(this->child_sa,
355 encr_i, integ_i, this->spi_r, this->cpi_r,
4989aba8 356 this->initiator, TRUE, FALSE);
a8c94544
MW
357 status_o = this->child_sa->install(this->child_sa,
358 encr_r, integ_r, this->spi_i, this->cpi_i,
4989aba8 359 this->initiator, FALSE, FALSE);
5351d63c
MW
360 }
361 }
5351d63c
MW
362
363 if (status_i != SUCCESS || status_o != SUCCESS)
364 {
365 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
366 (status_i != SUCCESS) ? "inbound " : "",
367 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
368 (status_o != SUCCESS) ? "outbound " : "");
c4a286c8 369 status = FAILED;
5351d63c
MW
370 }
371 else
372 {
4989aba8
TB
373 status = this->child_sa->install_policies(this->child_sa);
374
c4a286c8
TB
375 if (status != SUCCESS)
376 {
377 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
378 }
379 else
380 {
381 charon->bus->child_derived_keys(charon->bus, this->child_sa,
382 this->initiator, encr_i, encr_r,
383 integ_i, integ_r);
384 }
5351d63c 385 }
c4a286c8
TB
386 chunk_clear(&integ_i);
387 chunk_clear(&integ_r);
388 chunk_clear(&encr_i);
389 chunk_clear(&encr_r);
390
5351d63c
MW
391 if (status != SUCCESS)
392 {
5351d63c
MW
393 return FALSE;
394 }
395
396 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
5adf855e 397 this->dh, this->nonce_i, this->nonce_r);
5351d63c 398
553bb787
MW
399 my_ts = linked_list_create_from_enumerator(
400 this->child_sa->create_ts_enumerator(this->child_sa, TRUE));
401 other_ts = linked_list_create_from_enumerator(
402 this->child_sa->create_ts_enumerator(this->child_sa, FALSE));
403
5351d63c 404 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
ebeb8c87 405 "with SPIs %.8x_i %.8x_o and TS %#R === %#R",
5351d63c 406 this->child_sa->get_name(this->child_sa),
246c969d 407 this->child_sa->get_unique_id(this->child_sa),
5351d63c 408 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
553bb787
MW
409 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)), my_ts, other_ts);
410
411 my_ts->destroy(my_ts);
412 other_ts->destroy(other_ts);
5351d63c 413
a0cde769
TB
414 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
415 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
416
669d8bde
MW
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);
2f3c08d2
TB
426 /* rekeyed CHILD_SAs stay installed until they expire or are deleted
427 * by the other peer */
70728eb1 428 old->set_state(old, CHILD_REKEYED);
2f3c08d2
TB
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 }
669d8bde
MW
437 }
438 else
439 {
440 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
441 }
85ace154 442 schedule_inactivity_timeout(this);
5351d63c 443 this->child_sa = NULL;
5351d63c
MW
444 return TRUE;
445}
446
818330aa
MW
447/**
448 * Generate and add NONCE
449 */
450static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
451 message_t *message)
452{
453 nonce_payload_t *nonce_payload;
afaf1bdf 454 nonce_gen_t *nonceg;
818330aa 455
afaf1bdf
AKR
456 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
457 if (!nonceg)
818330aa 458 {
afaf1bdf 459 DBG1(DBG_IKE, "no nonce generator found to create nonce");
818330aa
MW
460 return FALSE;
461 }
605985d1
RB
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 }
afaf1bdf 468 nonceg->destroy(nonceg);
818330aa 469
3ecfc83c 470 nonce_payload = nonce_payload_create(PLV1_NONCE);
818330aa
MW
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 */
480static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
481 message_t *message)
482{
483 nonce_payload_t *nonce_payload;
484
3ecfc83c 485 nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
818330aa
MW
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
5adf855e
MW
496/**
497 * Add KE payload to message
498 */
520d58e0 499static bool add_ke(private_quick_mode_t *this, message_t *message)
5adf855e
MW
500{
501 ke_payload_t *ke_payload;
502
520d58e0
MW
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 }
5adf855e 510 message->add_payload(message, &ke_payload->payload_interface);
520d58e0 511 return TRUE;
5adf855e
MW
512}
513
514/**
515 * Get DH value from a KE payload
516 */
517static bool get_ke(private_quick_mode_t *this, message_t *message)
518{
519 ke_payload_t *ke_payload;
520
3ecfc83c 521 ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
5adf855e
MW
522 if (!ke_payload)
523 {
524 DBG1(DBG_IKE, "KE payload missing");
525 return FALSE;
526 }
66147ef6 527 if (!this->dh->set_other_public_value(this->dh,
a777155f
MW
528 ke_payload->get_key_exchange_data(ke_payload)))
529 {
530 DBG1(DBG_IKE, "unable to apply received KE value");
531 return FALSE;
532 }
5adf855e
MW
533 return TRUE;
534}
535
c4b8539f
MW
536/**
537 * Select a traffic selector from configuration
538 */
36431795
MW
539static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
540 linked_list_t *supplied)
c4b8539f
MW
541{
542 traffic_selector_t *ts;
7ee37114 543 linked_list_t *list, *hosts;
c4b8539f 544
7ee37114
MW
545 hosts = get_dynamic_hosts(this->ike_sa, local);
546 list = this->config->get_traffic_selectors(this->config,
84cdfbc9 547 local, supplied, hosts, TRUE);
7ee37114 548 hosts->destroy(hosts);
c4b8539f
MW
549 if (list->get_first(list, (void**)&ts) == SUCCESS)
550 {
c4b8539f
MW
551 ts = ts->clone(ts);
552 }
553 else
554 {
555 DBG1(DBG_IKE, "%s traffic selector missing in configuration",
cdc42256 556 local ? "local" : "remote");
c4b8539f
MW
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 */
9cc38c8e 566static void add_ts(private_quick_mode_t *this, message_t *message)
c4b8539f
MW
567{
568 id_payload_t *id_payload;
569
77ccff82
TB
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);
c4b8539f
MW
574}
575
576/**
577 * Get traffic selectors from received message
578 */
9cc38c8e 579static bool get_ts(private_quick_mode_t *this, message_t *message)
c4b8539f
MW
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 {
3ecfc83c 591 if (payload->get_type(payload) == PLV1_ID)
c4b8539f
MW
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 */
9cc38c8e 610 if (this->initiator)
c4b8539f
MW
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),
a1db77de 623 hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0, 65535);
c4b8539f
MW
624 }
625 if (!tsr)
626 {
627 tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
a1db77de 628 hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0, 65535);
c4b8539f 629 }
283898d6 630 if (this->mode == MODE_TRANSPORT && this->udp &&
a889cfe5
TB
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
9cc38c8e 639 if (this->initiator)
c4b8539f 640 {
9d9042d6
MW
641 traffic_selector_t *tsisub, *tsrsub;
642
29906717 643 /* check if peer selection is valid */
9d9042d6
MW
644 tsisub = this->tsi->get_subset(this->tsi, tsi);
645 tsrsub = this->tsr->get_subset(this->tsr, tsr);
646 if (!tsisub || !tsrsub)
c4b8539f 647 {
29906717 648 DBG1(DBG_IKE, "peer selected invalid traffic selectors: "
c4b8539f 649 "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
9d9042d6
MW
650 DESTROY_IF(tsisub);
651 DESTROY_IF(tsrsub);
c4b8539f
MW
652 tsi->destroy(tsi);
653 tsr->destroy(tsr);
654 return FALSE;
655 }
9d9042d6
MW
656 tsi->destroy(tsi);
657 tsr->destroy(tsr);
c4b8539f
MW
658 this->tsi->destroy(this->tsi);
659 this->tsr->destroy(this->tsr);
9d9042d6
MW
660 this->tsi = tsisub;
661 this->tsr = tsrsub;
c4b8539f
MW
662 }
663 else
664 {
665 this->tsi = tsi;
666 this->tsr = tsr;
667 }
668 return TRUE;
669}
670
0ff8d20a
VR
671/**
672 * Get encap
673 */
674static 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 */
690static 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 {
3ecfc83c 694 return PLV1_NAT_OA_DRAFT_00_03;
0ff8d20a 695 }
3ecfc83c 696 return PLV1_NAT_OA;
0ff8d20a
VR
697}
698
3bf0be6b
TB
699/**
700 * Add NAT-OA payloads
701 */
702static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
703{
704 identification_t *id;
705 id_payload_t *nat_oa;
d8f0d9c2 706 host_t *init, *resp;
0ff8d20a 707 payload_type_t nat_oa_payload_type;
3bf0be6b 708
d8f0d9c2
TB
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 }
3bf0be6b 719
0ff8d20a
VR
720 nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa);
721
3bf0be6b 722 /* first NAT-OA is the initiator's address */
d8f0d9c2 723 id = identification_create_from_sockaddr(init->get_sockaddr(init));
0ff8d20a 724 nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
3bf0be6b
TB
725 message->add_payload(message, (payload_t*)nat_oa);
726 id->destroy(id);
727
728 /* second NAT-OA is that of the responder */
d8f0d9c2 729 id = identification_create_from_sockaddr(resp->get_sockaddr(resp));
0ff8d20a 730 nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
3bf0be6b
TB
731 message->add_payload(message, (payload_t*)nat_oa);
732 id->destroy(id);
733}
734
cd0017d4
MW
735/**
736 * Look up lifetimes
737 */
738static void get_lifetimes(private_quick_mode_t *this)
739{
740 lifetime_cfg_t *lft;
741
b1df6312 742 lft = this->config->get_lifetime(this->config, TRUE);
cd0017d4
MW
743 if (lft->time.life)
744 {
745 this->lifetime = lft->time.life;
746 }
9e01d7ca 747 if (lft->bytes.life)
cd0017d4
MW
748 {
749 this->lifebytes = lft->bytes.life;
750 }
751 free(lft);
752}
753
754/**
755 * Check and apply lifetimes
756 */
757static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
758{
b12c53ce
AS
759 uint32_t lifetime;
760 uint64_t lifebytes;
cd0017d4
MW
761
762 lifetime = sa_payload->get_lifetime(sa_payload);
763 lifebytes = sa_payload->get_lifebytes(sa_payload);
764 if (this->lifetime != lifetime)
765 {
31bd5c8c 766 DBG1(DBG_IKE, "received %us lifetime, configured %us",
cd0017d4 767 lifetime, this->lifetime);
31bd5c8c 768 this->lifetime = lifetime;
cd0017d4
MW
769 }
770 if (this->lifebytes != lifebytes)
771 {
31bd5c8c 772 DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
cd0017d4 773 lifebytes, this->lifebytes);
31bd5c8c 774 this->lifebytes = lifebytes;
cd0017d4
MW
775 }
776}
777
e7ae90c1
MW
778/**
779 * Set the task ready to build notify error message
780 */
781static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
5c6abd28
CO
782{
783 notify_payload_t *notify;
784
3ecfc83c 785 notify = notify_payload_create_from_protocol_and_type(PLV1_NOTIFY,
908fe163 786 this->proto, type);
5c6abd28
CO
787 notify->set_spi(notify, this->spi_i);
788
e7ae90c1 789 this->ike_sa->queue_task(this->ike_sa,
2ddd45c9 790 (task_t*)informational_create(this->ike_sa, notify));
e7ae90c1 791 /* cancel all active/passive tasks in favour of informational */
7ce504e1
MW
792 this->ike_sa->flush_queue(this->ike_sa,
793 this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
e7ae90c1 794 return ALREADY_DONE;
5c6abd28
CO
795}
796
7d938be9
TE
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 */
801static 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
2b04aa46
MW
829METHOD(task_t, build_i, status_t,
830 private_quick_mode_t *this, message_t *message)
831{
21b7db99
MW
832 switch (this->state)
833 {
834 case QM_INIT:
835 {
836 sa_payload_t *sa_payload;
696fa8e0 837 linked_list_t *list, *tsi, *tsr;
908fe163 838 proposal_t *proposal;
5adf855e 839 diffie_hellman_group_t group;
0ff8d20a 840 encap_t encap;
21b7db99 841
7fd7ffc6 842 this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
47b448b8 843 this->mode = this->config->get_mode(this->config);
5351d63c
MW
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),
85b23888 847 this->config, this->reqid, this->udp,
a6014d99
TB
848 this->mark_in, this->mark_out,
849 0, 0);
5351d63c 850
00e11bce
TB
851 if (this->udp && this->mode == MODE_TRANSPORT)
852 {
853 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
854 add_nat_oa_payloads(this, message);
855 }
5351d63c 856
749ac175 857 if (this->config->has_option(this->config, OPT_IPCOMP))
47b448b8 858 {
44d9970f
MW
859 this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
860 if (!this->cpi_i)
47b448b8 861 {
44d9970f
MW
862 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
863 "IPComp disabled");
47b448b8
TB
864 }
865 }
866
908fe163
MW
867 list = this->config->get_proposals(this->config, MODP_NONE);
868 if (list->get_first(list, (void**)&proposal) == SUCCESS)
869 {
870 this->proto = proposal->get_protocol(proposal);
871 }
872 list->destroy_offset(list, offsetof(proposal_t, destroy));
873 this->spi_i = this->child_sa->alloc_spi(this->child_sa, this->proto);
5351d63c
MW
874 if (!this->spi_i)
875 {
876 DBG1(DBG_IKE, "allocating SPI from kernel failed");
877 return FAILED;
878 }
908fe163 879
f48e7272
TB
880 group = this->config->get_dh_group(this->config);
881 if (group != MODP_NONE)
882 {
7d938be9 883 proposal_t *proposal;
b12c53ce 884 uint16_t preferred_group;
7d938be9
TE
885
886 proposal = this->ike_sa->get_proposal(this->ike_sa);
887 proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
888 &preferred_group, NULL);
889 /* try the negotiated DH group from IKE_SA */
890 list = get_proposals(this, preferred_group);
891 if (list->get_count(list))
892 {
893 group = preferred_group;
894 }
895 else
896 {
897 /* fall back to the first configured DH group */
898 list->destroy(list);
899 list = get_proposals(this, group);
900 }
901
f48e7272
TB
902 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
903 group);
904 if (!this->dh)
905 {
906 DBG1(DBG_IKE, "configured DH group %N not supported",
907 diffie_hellman_group_names, group);
7d938be9 908 list->destroy_offset(list, offsetof(proposal_t, destroy));
f48e7272
TB
909 return FAILED;
910 }
911 }
7d938be9 912 else
5351d63c 913 {
7d938be9 914 list = get_proposals(this, MODP_NONE);
5351d63c 915 }
5351d63c 916
cd0017d4 917 get_lifetimes(this);
0ff8d20a 918 encap = get_encap(this->ike_sa, this->udp);
e174e0d4 919 sa_payload = sa_payload_create_from_proposals_v1(list,
cd0017d4 920 this->lifetime, this->lifebytes, AUTH_NONE,
0ff8d20a 921 this->mode, encap, this->cpi_i);
21b7db99
MW
922 list->destroy_offset(list, offsetof(proposal_t, destroy));
923 message->add_payload(message, &sa_payload->payload_interface);
924
818330aa 925 if (!add_nonce(this, &this->nonce_i, message))
21b7db99 926 {
21b7db99
MW
927 return FAILED;
928 }
5adf855e
MW
929 if (group != MODP_NONE)
930 {
520d58e0
MW
931 if (!add_ke(this, message))
932 {
933 return FAILED;
934 }
5adf855e 935 }
d61f2906
MW
936 if (!this->tsi)
937 {
938 this->tsi = select_ts(this, TRUE, NULL);
939 }
940 if (!this->tsr)
941 {
942 this->tsr = select_ts(this, FALSE, NULL);
943 }
abdb82fc
MW
944 tsi = linked_list_create_with_items(this->tsi, NULL);
945 tsr = linked_list_create_with_items(this->tsr, NULL);
696fa8e0
MW
946 this->tsi = this->tsr = NULL;
947 charon->bus->narrow(charon->bus, this->child_sa,
948 NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
949 tsi->remove_first(tsi, (void**)&this->tsi);
950 tsr->remove_first(tsr, (void**)&this->tsr);
951 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
952 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
c4b8539f 953 if (!this->tsi || !this->tsr)
21b7db99 954 {
21b7db99
MW
955 return FAILED;
956 }
9cc38c8e 957 add_ts(this, message);
21b7db99
MW
958 return NEED_MORE;
959 }
960 case QM_NEGOTIATED:
961 {
21b7db99
MW
962 return SUCCESS;
963 }
964 default:
965 return FAILED;
966 }
2b04aa46
MW
967}
968
1755ac06
MW
969/**
970 * Check for notify errors, return TRUE if error found
971 */
972static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
07abb470 973{
1755ac06
MW
974 enumerator_t *enumerator;
975 payload_t *payload;
976 bool err = FALSE;
977
978 enumerator = message->create_payload_enumerator(message);
979 while (enumerator->enumerate(enumerator, &payload))
07abb470 980 {
3ecfc83c 981 if (payload->get_type(payload) == PLV1_NOTIFY)
1755ac06
MW
982 {
983 notify_payload_t *notify;
984 notify_type_t type;
985
986 notify = (notify_payload_t*)payload;
987 type = notify->get_notify_type(notify);
988 if (type < 16384)
989 {
bf5b1d9e 990
1755ac06
MW
991 DBG1(DBG_IKE, "received %N error notify",
992 notify_type_names, type);
993 err = TRUE;
994 }
995 else
996 {
997 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
998 }
999 }
07abb470 1000 }
1755ac06
MW
1001 enumerator->destroy(enumerator);
1002
1003 return err;
07abb470
CO
1004}
1005
f56c3c53
MW
1006/**
1007 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
1008 */
e8735440 1009static void check_for_rekeyed_child(private_quick_mode_t *this, bool responder)
f56c3c53
MW
1010{
1011 enumerator_t *enumerator, *policies;
e8735440 1012 traffic_selector_t *local, *remote, *my_ts, *other_ts;
f56c3c53 1013 child_sa_t *child_sa;
bee8b5e3
MW
1014 proposal_t *proposal;
1015 char *name;
f56c3c53 1016
e8735440
AH
1017 if (responder)
1018 {
1019 my_ts = this->tsr;
1020 other_ts = this->tsi;
1021 }
1022 else
1023 {
1024 my_ts = this->tsi;
1025 other_ts = this->tsr;
1026 }
1027
bee8b5e3 1028 name = this->config->get_name(this->config);
f56c3c53
MW
1029 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
1030 while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
1031 {
bee8b5e3 1032 if (streq(child_sa->get_name(child_sa), name))
f56c3c53 1033 {
bee8b5e3
MW
1034 proposal = child_sa->get_proposal(child_sa);
1035 switch (child_sa->get_state(child_sa))
f56c3c53 1036 {
bee8b5e3
MW
1037 case CHILD_INSTALLED:
1038 case CHILD_REKEYING:
1039 policies = child_sa->create_policy_enumerator(child_sa);
1040 if (policies->enumerate(policies, &local, &remote) &&
e8735440
AH
1041 local->equals(local, my_ts) &&
1042 remote->equals(remote, other_ts) &&
bee8b5e3
MW
1043 this->proposal->equals(this->proposal, proposal))
1044 {
1045 this->reqid = child_sa->get_reqid(child_sa);
1046 this->rekey = child_sa->get_spi(child_sa, TRUE);
85b23888
MW
1047 this->mark_in = child_sa->get_mark(child_sa,
1048 TRUE).value;
1049 this->mark_out = child_sa->get_mark(child_sa,
1050 FALSE).value;
bee8b5e3
MW
1051 child_sa->set_state(child_sa, CHILD_REKEYING);
1052 DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
246c969d
MW
1053 child_sa->get_name(child_sa),
1054 child_sa->get_unique_id(child_sa));
bee8b5e3
MW
1055 }
1056 policies->destroy(policies);
bf3bed1c
TB
1057 break;
1058 case CHILD_REKEYED:
1059 default:
1060 break;
f56c3c53 1061 }
f56c3c53
MW
1062 }
1063 }
1064 enumerator->destroy(enumerator);
1065}
1066
2b04aa46
MW
1067METHOD(task_t, process_r, status_t,
1068 private_quick_mode_t *this, message_t *message)
1069{
4de361d9
TB
1070 if (this->mid && this->mid != message->get_message_id(message))
1071 { /* not responsible for this quick mode exchange */
37a22a16 1072 return INVALID_ARG;
4de361d9
TB
1073 }
1074
21b7db99
MW
1075 switch (this->state)
1076 {
1077 case QM_INIT:
1078 {
1079 sa_payload_t *sa_payload;
7ee37114 1080 linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
21b7db99 1081 peer_cfg_t *peer_cfg;
b12c53ce 1082 uint16_t group;
0a954d67 1083 bool private, prefer_configured;
21b7db99 1084
a889cfe5 1085 sa_payload = (sa_payload_t*)message->get_payload(message,
3ecfc83c 1086 PLV1_SECURITY_ASSOCIATION);
a889cfe5
TB
1087 if (!sa_payload)
1088 {
1089 DBG1(DBG_IKE, "sa payload missing");
1090 return send_notify(this, INVALID_PAYLOAD_TYPE);
1091 }
1092
1093 this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
1094
9cc38c8e 1095 if (!get_ts(this, message))
c4c59504 1096 {
c4b8539f 1097 return FAILED;
c4c59504 1098 }
21b7db99 1099 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
abdb82fc
MW
1100 tsi = linked_list_create_with_items(this->tsi, NULL);
1101 tsr = linked_list_create_with_items(this->tsr, NULL);
36431795 1102 this->tsi = this->tsr = NULL;
7ee37114
MW
1103 hostsi = get_dynamic_hosts(this->ike_sa, FALSE);
1104 hostsr = get_dynamic_hosts(this->ike_sa, TRUE);
21b7db99 1105 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
7ee37114
MW
1106 hostsr, hostsi);
1107 hostsi->destroy(hostsi);
1108 hostsr->destroy(hostsr);
28e3c659
MW
1109 if (this->config)
1110 {
1111 this->tsi = select_ts(this, FALSE, tsi);
1112 this->tsr = select_ts(this, TRUE, tsr);
1113 }
2d38a03d
TB
1114 if (!this->config || !this->tsi || !this->tsr ||
1115 this->mode != this->config->get_mode(this->config))
21b7db99 1116 {
a160f100
TE
1117 DBG1(DBG_IKE, "no matching CHILD_SA config found for "
1118 "%#R === %#R", tsi, tsr);
1119 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1120 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
5f1df0a0 1121 return send_notify(this, INVALID_ID_INFORMATION);
21b7db99 1122 }
a160f100
TE
1123 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1124 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
21b7db99 1125
749ac175 1126 if (this->config->has_option(this->config, OPT_IPCOMP))
47b448b8 1127 {
44d9970f
MW
1128 list = sa_payload->get_ipcomp_proposals(sa_payload,
1129 &this->cpi_i);
1130 if (!list->get_count(list))
47b448b8 1131 {
44d9970f
MW
1132 DBG1(DBG_IKE, "expected IPComp proposal but peer did "
1133 "not send one, IPComp disabled");
1134 this->cpi_i = 0;
47b448b8
TB
1135 }
1136 }
1137 if (!list || !list->get_count(list))
1138 {
1139 DESTROY_IF(list);
47b448b8
TB
1140 list = sa_payload->get_proposals(sa_payload);
1141 }
44bd9b48
AS
1142 private = this->ike_sa->supports_extension(this->ike_sa,
1143 EXT_STRONGSWAN);
0a954d67
TB
1144 prefer_configured = lib->settings->get_bool(lib->settings,
1145 "%s.prefer_configured_proposals", TRUE, lib->ns);
f2ea230b 1146 this->proposal = this->config->select_proposal(this->config, list,
0a954d67 1147 FALSE, private, prefer_configured);
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);
f56c3c53 1184
5351d63c
MW
1185 this->child_sa = child_sa_create(
1186 this->ike_sa->get_my_host(this->ike_sa),
1187 this->ike_sa->get_other_host(this->ike_sa),
85b23888 1188 this->config, this->reqid, this->udp,
a6014d99
TB
1189 this->mark_in, this->mark_out,
1190 0, 0);
f942588f 1191
abdb82fc
MW
1192 tsi = linked_list_create_with_items(this->tsi, NULL);
1193 tsr = linked_list_create_with_items(this->tsr, NULL);
f942588f
MW
1194 this->tsi = this->tsr = NULL;
1195 charon->bus->narrow(charon->bus, this->child_sa,
1196 NARROW_RESPONDER, tsr, tsi);
1197 if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS ||
1198 tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS)
1199 {
1200 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1201 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1202 return send_notify(this, INVALID_ID_INFORMATION);
1203 }
1204 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1205 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1206
21b7db99
MW
1207 return NEED_MORE;
1208 }
1209 case QM_NEGOTIATED:
1210 {
cd9bba50 1211 if (has_notify_errors(this, message))
07abb470 1212 {
bf5b1d9e 1213 return SUCCESS;
07abb470 1214 }
cd9bba50
MW
1215 if (message->get_exchange_type(message) == INFORMATIONAL_V1)
1216 {
1217 if (message->get_payload(message, PLV1_DELETE))
1218 {
1219 /* If the DELETE for a Quick Mode follows immediately
1220 * after rekeying, we might receive it before the
1221 * third completing Quick Mode message. Ignore it, as
1222 * it gets handled by a separately queued delete task. */
1223 return NEED_MORE;
1224 }
1225 return SUCCESS;
1226 }
5351d63c
MW
1227 if (!install(this))
1228 {
e91157a4
TB
1229 ike_sa_t *ike_sa = this->ike_sa;
1230 task_t *task;
1231
1232 task = (task_t*)quick_delete_create(this->ike_sa,
767966e7 1233 this->proposal->get_protocol(this->proposal),
e91157a4
TB
1234 this->spi_i, TRUE, TRUE);
1235 /* flush_queue() destroys the current task */
1236 ike_sa->flush_queue(ike_sa, TASK_QUEUE_PASSIVE);
1237 ike_sa->queue_task(ike_sa, task);
767966e7 1238 return ALREADY_DONE;
5351d63c 1239 }
21b7db99
MW
1240 return SUCCESS;
1241 }
1242 default:
1243 return FAILED;
1244 }
2b04aa46
MW
1245}
1246
1247METHOD(task_t, build_r, status_t,
1248 private_quick_mode_t *this, message_t *message)
1249{
4de361d9
TB
1250 if (this->mid && this->mid != message->get_message_id(message))
1251 { /* not responsible for this quick mode exchange */
37a22a16 1252 return INVALID_ARG;
4de361d9
TB
1253 }
1254
21b7db99
MW
1255 switch (this->state)
1256 {
1257 case QM_INIT:
1258 {
1259 sa_payload_t *sa_payload;
0ff8d20a 1260 encap_t encap;
21b7db99 1261
908fe163
MW
1262 this->proto = this->proposal->get_protocol(this->proposal);
1263 this->spi_r = this->child_sa->alloc_spi(this->child_sa, this->proto);
5351d63c
MW
1264 if (!this->spi_r)
1265 {
1266 DBG1(DBG_IKE, "allocating SPI from kernel failed");
bf5b1d9e 1267 return send_notify(this, NO_PROPOSAL_CHOSEN);
5351d63c
MW
1268 }
1269 this->proposal->set_spi(this->proposal, this->spi_r);
1270
47b448b8
TB
1271 if (this->cpi_i)
1272 {
1273 this->cpi_r = this->child_sa->alloc_cpi(this->child_sa);
1274 if (!this->cpi_r)
1275 {
1276 DBG1(DBG_IKE, "unable to allocate a CPI from "
1277 "kernel, IPComp disabled");
1278 return send_notify(this, NO_PROPOSAL_CHOSEN);
1279 }
1280 }
1281
7fd7ffc6 1282 if (this->udp && this->mode == MODE_TRANSPORT)
29b0cb32 1283 {
3bf0be6b 1284 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
9f80110b 1285 add_nat_oa_payloads(this, message);
29b0cb32
TB
1286 }
1287
0ff8d20a 1288 encap = get_encap(this->ike_sa, this->udp);
e174e0d4 1289 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
cd0017d4 1290 this->lifetime, this->lifebytes, AUTH_NONE,
0ff8d20a 1291 this->mode, encap, this->cpi_r);
21b7db99
MW
1292 message->add_payload(message, &sa_payload->payload_interface);
1293
818330aa 1294 if (!add_nonce(this, &this->nonce_r, message))
21b7db99 1295 {
21b7db99
MW
1296 return FAILED;
1297 }
5adf855e
MW
1298 if (this->dh)
1299 {
520d58e0
MW
1300 if (!add_ke(this, message))
1301 {
1302 return FAILED;
1303 }
5adf855e
MW
1304 }
1305
9cc38c8e 1306 add_ts(this, message);
21b7db99 1307
21b7db99 1308 this->state = QM_NEGOTIATED;
4de361d9 1309 this->mid = message->get_message_id(message);
21b7db99
MW
1310 return NEED_MORE;
1311 }
cd9bba50
MW
1312 case QM_NEGOTIATED:
1313 if (message->get_exchange_type(message) == INFORMATIONAL_V1)
1314 {
1315 /* skip INFORMATIONAL response if we received a INFORMATIONAL
1316 * delete, see process_r() */
1317 return ALREADY_DONE;
1318 }
1319 /* fall */
21b7db99
MW
1320 default:
1321 return FAILED;
1322 }
2b04aa46
MW
1323}
1324
1325METHOD(task_t, process_i, status_t,
1326 private_quick_mode_t *this, message_t *message)
1327{
21b7db99
MW
1328 switch (this->state)
1329 {
1330 case QM_INIT:
1331 {
1332 sa_payload_t *sa_payload;
47b448b8 1333 linked_list_t *list = NULL;
44bd9b48 1334 bool private;
21b7db99
MW
1335
1336 sa_payload = (sa_payload_t*)message->get_payload(message,
3ecfc83c 1337 PLV1_SECURITY_ASSOCIATION);
21b7db99
MW
1338 if (!sa_payload)
1339 {
1340 DBG1(DBG_IKE, "sa payload missing");
bf5b1d9e 1341 return send_notify(this, NO_PROPOSAL_CHOSEN);
21b7db99 1342 }
47b448b8
TB
1343 if (this->cpi_i)
1344 {
1345 list = sa_payload->get_ipcomp_proposals(sa_payload,
1346 &this->cpi_r);
3451ecd7
TB
1347 if (!list->get_count(list))
1348 {
2db6d5b8 1349 DBG1(DBG_IKE, "peer did not accept our IPComp proposal, "
3451ecd7
TB
1350 "IPComp disabled");
1351 this->cpi_i = 0;
1352 }
47b448b8
TB
1353 }
1354 if (!list || !list->get_count(list))
1355 {
1356 DESTROY_IF(list);
47b448b8
TB
1357 list = sa_payload->get_proposals(sa_payload);
1358 }
44bd9b48
AS
1359 private = this->ike_sa->supports_extension(this->ike_sa,
1360 EXT_STRONGSWAN);
f2ea230b
TB
1361 this->proposal = this->config->select_proposal(this->config, list,
1362 FALSE, private, TRUE);
21b7db99
MW
1363 list->destroy_offset(list, offsetof(proposal_t, destroy));
1364 if (!this->proposal)
1365 {
1366 DBG1(DBG_IKE, "no matching proposal found");
bf5b1d9e 1367 return send_notify(this, NO_PROPOSAL_CHOSEN);
21b7db99 1368 }
5351d63c
MW
1369 this->spi_r = this->proposal->get_spi(this->proposal);
1370
cd0017d4
MW
1371 apply_lifetimes(this, sa_payload);
1372
818330aa 1373 if (!get_nonce(this, &this->nonce_r, message))
21b7db99 1374 {
bf5b1d9e 1375 return send_notify(this, INVALID_PAYLOAD_TYPE);
21b7db99 1376 }
5adf855e
MW
1377 if (this->dh && !get_ke(this, message))
1378 {
bf5b1d9e 1379 return send_notify(this, INVALID_KEY_INFORMATION);
5adf855e 1380 }
9cc38c8e 1381 if (!get_ts(this, message))
c4b8539f 1382 {
bf5b1d9e 1383 return send_notify(this, INVALID_PAYLOAD_TYPE);
c4b8539f 1384 }
e8735440 1385 check_for_rekeyed_child(this, FALSE);
5351d63c
MW
1386 if (!install(this))
1387 {
bf5b1d9e 1388 return send_notify(this, NO_PROPOSAL_CHOSEN);
5351d63c 1389 }
21b7db99
MW
1390 this->state = QM_NEGOTIATED;
1391 return NEED_MORE;
1392 }
1393 default:
1394 return FAILED;
1395 }
2b04aa46
MW
1396}
1397
1398METHOD(task_t, get_type, task_type_t,
1399 private_quick_mode_t *this)
1400{
1401 return TASK_QUICK_MODE;
1402}
1403
b12c53ce 1404METHOD(quick_mode_t, get_mid, uint32_t,
4de361d9
TB
1405 private_quick_mode_t *this)
1406{
1407 return this->mid;
1408}
1409
14dc7941 1410METHOD(quick_mode_t, use_reqid, void,
b12c53ce 1411 private_quick_mode_t *this, uint32_t reqid)
14dc7941
MW
1412{
1413 this->reqid = reqid;
1414}
1415
85b23888
MW
1416METHOD(quick_mode_t, use_marks, void,
1417 private_quick_mode_t *this, u_int in, u_int out)
1418{
1419 this->mark_in = in;
1420 this->mark_out = out;
1421}
1422
669d8bde 1423METHOD(quick_mode_t, rekey, void,
b12c53ce 1424 private_quick_mode_t *this, uint32_t spi)
669d8bde
MW
1425{
1426 this->rekey = spi;
1427}
1428
2b04aa46
MW
1429METHOD(task_t, migrate, void,
1430 private_quick_mode_t *this, ike_sa_t *ike_sa)
1431{
bce22af2
MW
1432 chunk_free(&this->nonce_i);
1433 chunk_free(&this->nonce_r);
1434 DESTROY_IF(this->tsi);
1435 DESTROY_IF(this->tsr);
1436 DESTROY_IF(this->proposal);
1437 DESTROY_IF(this->child_sa);
1438 DESTROY_IF(this->dh);
1439
2b04aa46 1440 this->ike_sa = ike_sa;
bce22af2
MW
1441 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1442 this->state = QM_INIT;
4de361d9 1443 this->mid = 0;
bce22af2
MW
1444 this->tsi = NULL;
1445 this->tsr = NULL;
1446 this->proposal = NULL;
1447 this->child_sa = NULL;
1448 this->dh = NULL;
1449 this->spi_i = 0;
1450 this->spi_r = 0;
85b23888
MW
1451 this->mark_in = 0;
1452 this->mark_out = 0;
bce22af2
MW
1453
1454 if (!this->initiator)
1455 {
1456 DESTROY_IF(this->config);
1457 this->config = NULL;
1458 }
2b04aa46
MW
1459}
1460
1461METHOD(task_t, destroy, void,
1462 private_quick_mode_t *this)
1463{
1464 chunk_free(&this->nonce_i);
1465 chunk_free(&this->nonce_r);
1466 DESTROY_IF(this->tsi);
1467 DESTROY_IF(this->tsr);
1468 DESTROY_IF(this->proposal);
1469 DESTROY_IF(this->child_sa);
1470 DESTROY_IF(this->config);
5adf855e 1471 DESTROY_IF(this->dh);
2b04aa46
MW
1472 free(this);
1473}
1474
1475/*
1476 * Described in header.
1477 */
1478quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1479 traffic_selector_t *tsi, traffic_selector_t *tsr)
1480{
1481 private_quick_mode_t *this;
1482
1483 INIT(this,
1484 .public = {
1485 .task = {
1486 .get_type = _get_type,
1487 .migrate = _migrate,
1488 .destroy = _destroy,
1489 },
4de361d9 1490 .get_mid = _get_mid,
14dc7941 1491 .use_reqid = _use_reqid,
85b23888 1492 .use_marks = _use_marks,
669d8bde 1493 .rekey = _rekey,
2b04aa46
MW
1494 },
1495 .ike_sa = ike_sa,
5351d63c 1496 .initiator = config != NULL,
2b04aa46 1497 .config = config,
5351d63c 1498 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
2b04aa46 1499 .state = QM_INIT,
d61f2906
MW
1500 .tsi = tsi ? tsi->clone(tsi) : NULL,
1501 .tsr = tsr ? tsr->clone(tsr) : NULL,
908fe163 1502 .proto = PROTO_ESP,
2f3c08d2
TB
1503 .delete = lib->settings->get_bool(lib->settings,
1504 "%s.delete_rekeyed", FALSE, lib->ns),
2b04aa46
MW
1505 );
1506
1507 if (config)
1508 {
1509 this->public.task.build = _build_i;
1510 this->public.task.process = _process_i;
1511 }
1512 else
1513 {
1514 this->public.task.build = _build_r;
1515 this->public.task.process = _process_r;
1516 }
1517
1518 return &this->public;
1519}