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