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