As Quick Mode initiator, select a subset of the proposed and the returned TS
[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;
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, encr_r, integ_r,
310 this->spi_i, this->cpi_i, TRUE, FALSE, tsi, tsr);
311 status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
312 this->spi_r, this->cpi_r, FALSE, FALSE, tsi, tsr);
313 }
314 else
315 {
316 status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
317 this->spi_r, this->cpi_r, TRUE, FALSE, tsr, tsi);
318 status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
319 this->spi_i, this->cpi_i, FALSE, FALSE, tsr, tsi);
320 }
321 }
322 chunk_clear(&integ_i);
323 chunk_clear(&integ_r);
324 chunk_clear(&encr_i);
325 chunk_clear(&encr_r);
326
327 if (status_i != SUCCESS || status_o != SUCCESS)
328 {
329 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
330 (status_i != SUCCESS) ? "inbound " : "",
331 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
332 (status_o != SUCCESS) ? "outbound " : "");
333 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
334 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
335 return FALSE;
336 }
337
338 if (this->initiator)
339 {
340 status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
341 }
342 else
343 {
344 status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
345 }
346 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
347 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
348 if (status != SUCCESS)
349 {
350 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
351 return FALSE;
352 }
353
354 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
355 this->dh, this->nonce_i, this->nonce_r);
356
357 /* add to IKE_SA, and remove from task */
358 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
359 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
360
361 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
362 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
363 this->child_sa->get_name(this->child_sa),
364 this->child_sa->get_reqid(this->child_sa),
365 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
366 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
367 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
368 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
369
370 if (this->rekey)
371 {
372 old = this->ike_sa->get_child_sa(this->ike_sa,
373 this->proposal->get_protocol(this->proposal),
374 this->rekey, TRUE);
375 }
376 if (old)
377 {
378 charon->bus->child_rekey(charon->bus, old, this->child_sa);
379 }
380 else
381 {
382 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
383 }
384 if (!this->rekey)
385 {
386 schedule_inactivity_timeout(this);
387 }
388 this->child_sa = NULL;
389 return TRUE;
390 }
391
392 /**
393 * Generate and add NONCE
394 */
395 static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
396 message_t *message)
397 {
398 nonce_payload_t *nonce_payload;
399 nonce_gen_t *nonceg;
400
401 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
402 if (!nonceg)
403 {
404 DBG1(DBG_IKE, "no nonce generator found to create nonce");
405 return FALSE;
406 }
407 if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, nonce))
408 {
409 DBG1(DBG_IKE, "nonce allocation failed");
410 nonceg->destroy(nonceg);
411 return FALSE;
412 }
413 nonceg->destroy(nonceg);
414
415 nonce_payload = nonce_payload_create(NONCE_V1);
416 nonce_payload->set_nonce(nonce_payload, *nonce);
417 message->add_payload(message, &nonce_payload->payload_interface);
418
419 return TRUE;
420 }
421
422 /**
423 * Extract nonce from NONCE payload
424 */
425 static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
426 message_t *message)
427 {
428 nonce_payload_t *nonce_payload;
429
430 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
431 if (!nonce_payload)
432 {
433 DBG1(DBG_IKE, "NONCE payload missing in message");
434 return FALSE;
435 }
436 *nonce = nonce_payload->get_nonce(nonce_payload);
437
438 return TRUE;
439 }
440
441 /**
442 * Add KE payload to message
443 */
444 static void add_ke(private_quick_mode_t *this, message_t *message)
445 {
446 ke_payload_t *ke_payload;
447
448 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
449 message->add_payload(message, &ke_payload->payload_interface);
450 }
451
452 /**
453 * Get DH value from a KE payload
454 */
455 static bool get_ke(private_quick_mode_t *this, message_t *message)
456 {
457 ke_payload_t *ke_payload;
458
459 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
460 if (!ke_payload)
461 {
462 DBG1(DBG_IKE, "KE payload missing");
463 return FALSE;
464 }
465 this->dh->set_other_public_value(this->dh,
466 ke_payload->get_key_exchange_data(ke_payload));
467 return TRUE;
468 }
469
470 /**
471 * Select a traffic selector from configuration
472 */
473 static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
474 linked_list_t *supplied)
475 {
476 traffic_selector_t *ts;
477 linked_list_t *list, *hosts;
478
479 hosts = get_dynamic_hosts(this->ike_sa, local);
480 list = this->config->get_traffic_selectors(this->config,
481 local, supplied, hosts);
482 hosts->destroy(hosts);
483 if (list->get_first(list, (void**)&ts) == SUCCESS)
484 {
485 ts = ts->clone(ts);
486 }
487 else
488 {
489 DBG1(DBG_IKE, "%s traffic selector missing in configuration",
490 local ? "local" : "local");
491 ts = NULL;
492 }
493 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
494 return ts;
495 }
496
497 /**
498 * Add selected traffic selectors to message
499 */
500 static void add_ts(private_quick_mode_t *this, message_t *message)
501 {
502 id_payload_t *id_payload;
503 host_t *hsi, *hsr;
504
505 if (this->initiator)
506 {
507 hsi = this->ike_sa->get_my_host(this->ike_sa);
508 hsr = this->ike_sa->get_other_host(this->ike_sa);
509 }
510 else
511 {
512 hsr = this->ike_sa->get_my_host(this->ike_sa);
513 hsi = this->ike_sa->get_other_host(this->ike_sa);
514 }
515 /* add ID payload only if negotiating non host2host tunnels */
516 if (!this->tsi->is_host(this->tsi, hsi) ||
517 !this->tsr->is_host(this->tsr, hsr) ||
518 this->tsi->get_protocol(this->tsi) ||
519 this->tsr->get_protocol(this->tsr) ||
520 this->tsi->get_from_port(this->tsi) ||
521 this->tsr->get_from_port(this->tsr) ||
522 this->tsi->get_to_port(this->tsi) != 65535 ||
523 this->tsr->get_to_port(this->tsr) != 65535)
524 {
525 id_payload = id_payload_create_from_ts(this->tsi);
526 message->add_payload(message, &id_payload->payload_interface);
527 id_payload = id_payload_create_from_ts(this->tsr);
528 message->add_payload(message, &id_payload->payload_interface);
529 }
530 }
531
532 /**
533 * Get traffic selectors from received message
534 */
535 static bool get_ts(private_quick_mode_t *this, message_t *message)
536 {
537 traffic_selector_t *tsi = NULL, *tsr = NULL;
538 enumerator_t *enumerator;
539 id_payload_t *id_payload;
540 payload_t *payload;
541 host_t *hsi, *hsr;
542 bool first = TRUE;
543
544 enumerator = message->create_payload_enumerator(message);
545 while (enumerator->enumerate(enumerator, &payload))
546 {
547 if (payload->get_type(payload) == ID_V1)
548 {
549 id_payload = (id_payload_t*)payload;
550
551 if (first)
552 {
553 tsi = id_payload->get_ts(id_payload);
554 first = FALSE;
555 }
556 else
557 {
558 tsr = id_payload->get_ts(id_payload);
559 break;
560 }
561 }
562 }
563 enumerator->destroy(enumerator);
564
565 /* create host2host selectors if ID payloads missing */
566 if (this->initiator)
567 {
568 hsi = this->ike_sa->get_my_host(this->ike_sa);
569 hsr = this->ike_sa->get_other_host(this->ike_sa);
570 }
571 else
572 {
573 hsr = this->ike_sa->get_my_host(this->ike_sa);
574 hsi = this->ike_sa->get_other_host(this->ike_sa);
575 }
576 if (!tsi)
577 {
578 tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
579 hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0, 65535);
580 }
581 if (!tsr)
582 {
583 tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
584 hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0, 65535);
585 }
586 if (this->mode == MODE_TRANSPORT && this->udp &&
587 (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr)))
588 { /* change TS in case of a NAT in transport mode */
589 DBG2(DBG_IKE, "changing received traffic selectors %R=== %R due to NAT",
590 tsi, tsr);
591 tsi->set_address(tsi, hsi);
592 tsr->set_address(tsr, hsr);
593 }
594
595 if (this->initiator)
596 {
597 traffic_selector_t *tsisub, *tsrsub;
598
599 /* check if peer selection is valid */
600 tsisub = this->tsi->get_subset(this->tsi, tsi);
601 tsrsub = this->tsr->get_subset(this->tsr, tsr);
602 if (!tsisub || !tsrsub)
603 {
604 DBG1(DBG_IKE, "peer selected invalid traffic selectors: "
605 "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
606 DESTROY_IF(tsisub);
607 DESTROY_IF(tsrsub);
608 tsi->destroy(tsi);
609 tsr->destroy(tsr);
610 return FALSE;
611 }
612 tsi->destroy(tsi);
613 tsr->destroy(tsr);
614 this->tsi->destroy(this->tsi);
615 this->tsr->destroy(this->tsr);
616 this->tsi = tsisub;
617 this->tsr = tsrsub;
618 }
619 else
620 {
621 this->tsi = tsi;
622 this->tsr = tsr;
623 }
624 return TRUE;
625 }
626
627 /**
628 * Get encap
629 */
630 static encap_t get_encap(ike_sa_t* ike_sa, bool udp)
631 {
632 if (!udp)
633 {
634 return ENCAP_NONE;
635 }
636 if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
637 {
638 return ENCAP_UDP_DRAFT_00_03;
639 }
640 return ENCAP_UDP;
641 }
642
643 /**
644 * Get NAT-OA payload type (RFC 3947 or RFC 3947 drafts).
645 */
646 static payload_type_t get_nat_oa_payload_type(ike_sa_t *ike_sa)
647 {
648 if (ike_sa->supports_extension(ike_sa, EXT_NATT_DRAFT_02_03))
649 {
650 return NAT_OA_DRAFT_00_03_V1;
651 }
652 return NAT_OA_V1;
653 }
654
655 /**
656 * Add NAT-OA payloads
657 */
658 static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
659 {
660 identification_t *id;
661 id_payload_t *nat_oa;
662 host_t *src, *dst;
663 payload_type_t nat_oa_payload_type;
664
665 src = message->get_source(message);
666 dst = message->get_destination(message);
667
668 src = this->initiator ? src : dst;
669 dst = this->initiator ? dst : src;
670
671 nat_oa_payload_type = get_nat_oa_payload_type(this->ike_sa);
672
673 /* first NAT-OA is the initiator's address */
674 id = identification_create_from_sockaddr(src->get_sockaddr(src));
675 nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
676 message->add_payload(message, (payload_t*)nat_oa);
677 id->destroy(id);
678
679 /* second NAT-OA is that of the responder */
680 id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
681 nat_oa = id_payload_create_from_identification(nat_oa_payload_type, id);
682 message->add_payload(message, (payload_t*)nat_oa);
683 id->destroy(id);
684 }
685
686 /**
687 * Look up lifetimes
688 */
689 static void get_lifetimes(private_quick_mode_t *this)
690 {
691 lifetime_cfg_t *lft;
692
693 lft = this->config->get_lifetime(this->config);
694 if (lft->time.life)
695 {
696 this->lifetime = lft->time.life;
697 }
698 else if (lft->bytes.life)
699 {
700 this->lifebytes = lft->bytes.life;
701 }
702 free(lft);
703 }
704
705 /**
706 * Check and apply lifetimes
707 */
708 static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
709 {
710 u_int32_t lifetime;
711 u_int64_t lifebytes;
712
713 lifetime = sa_payload->get_lifetime(sa_payload);
714 lifebytes = sa_payload->get_lifebytes(sa_payload);
715 if (this->lifetime != lifetime)
716 {
717 DBG1(DBG_IKE, "received %us lifetime, configured %us",
718 lifetime, this->lifetime);
719 this->lifetime = lifetime;
720 }
721 if (this->lifebytes != lifebytes)
722 {
723 DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
724 lifebytes, this->lifebytes);
725 this->lifebytes = lifebytes;
726 }
727 }
728
729 /**
730 * Set the task ready to build notify error message
731 */
732 static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
733 {
734 notify_payload_t *notify;
735
736 notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
737 PROTO_ESP, type);
738 notify->set_spi(notify, this->spi_i);
739
740 this->ike_sa->queue_task(this->ike_sa,
741 (task_t*)informational_create(this->ike_sa, notify));
742 /* cancel all active/passive tasks in favour of informational */
743 this->ike_sa->flush_queue(this->ike_sa,
744 this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
745 return ALREADY_DONE;
746 }
747
748 METHOD(task_t, build_i, status_t,
749 private_quick_mode_t *this, message_t *message)
750 {
751 switch (this->state)
752 {
753 case QM_INIT:
754 {
755 enumerator_t *enumerator;
756 sa_payload_t *sa_payload;
757 linked_list_t *list, *tsi, *tsr;
758 proposal_t *proposal;
759 diffie_hellman_group_t group;
760 encap_t encap;
761
762 this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
763 this->mode = this->config->get_mode(this->config);
764 this->child_sa = child_sa_create(
765 this->ike_sa->get_my_host(this->ike_sa),
766 this->ike_sa->get_other_host(this->ike_sa),
767 this->config, this->reqid, this->udp);
768
769 if (this->udp && this->mode == MODE_TRANSPORT)
770 {
771 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
772 add_nat_oa_payloads(this, message);
773 }
774
775 if (this->config->use_ipcomp(this->config))
776 {
777 if (this->udp)
778 {
779 DBG1(DBG_IKE, "IPComp is not supported if either peer is "
780 "natted, IPComp disabled");
781 }
782 else
783 {
784 this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
785 if (!this->cpi_i)
786 {
787 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
788 "IPComp disabled");
789 }
790 }
791 }
792
793 this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
794 if (!this->spi_i)
795 {
796 DBG1(DBG_IKE, "allocating SPI from kernel failed");
797 return FAILED;
798 }
799 group = this->config->get_dh_group(this->config);
800 if (group != MODP_NONE)
801 {
802 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
803 group);
804 if (!this->dh)
805 {
806 DBG1(DBG_IKE, "configured DH group %N not supported",
807 diffie_hellman_group_names, group);
808 return FAILED;
809 }
810 }
811
812 list = this->config->get_proposals(this->config, FALSE);
813 enumerator = list->create_enumerator(list);
814 while (enumerator->enumerate(enumerator, &proposal))
815 {
816 if (group != MODP_NONE)
817 {
818 if (!proposal->has_dh_group(proposal, group))
819 {
820 list->remove_at(list, enumerator);
821 proposal->destroy(proposal);
822 continue;
823 }
824 proposal->strip_dh(proposal, group);
825 }
826 proposal->set_spi(proposal, this->spi_i);
827 }
828 enumerator->destroy(enumerator);
829
830 get_lifetimes(this);
831 encap = get_encap(this->ike_sa, this->udp);
832 sa_payload = sa_payload_create_from_proposals_v1(list,
833 this->lifetime, this->lifebytes, AUTH_NONE,
834 this->mode, encap, this->cpi_i);
835 list->destroy_offset(list, offsetof(proposal_t, destroy));
836 message->add_payload(message, &sa_payload->payload_interface);
837
838 if (!add_nonce(this, &this->nonce_i, message))
839 {
840 return FAILED;
841 }
842 if (group != MODP_NONE)
843 {
844 add_ke(this, message);
845 }
846 if (!this->tsi)
847 {
848 this->tsi = select_ts(this, TRUE, NULL);
849 }
850 if (!this->tsr)
851 {
852 this->tsr = select_ts(this, FALSE, NULL);
853 }
854 tsi = linked_list_create_with_items(this->tsi, NULL);
855 tsr = linked_list_create_with_items(this->tsr, NULL);
856 this->tsi = this->tsr = NULL;
857 charon->bus->narrow(charon->bus, this->child_sa,
858 NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
859 tsi->remove_first(tsi, (void**)&this->tsi);
860 tsr->remove_first(tsr, (void**)&this->tsr);
861 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
862 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
863 if (!this->tsi || !this->tsr)
864 {
865 return FAILED;
866 }
867 add_ts(this, message);
868 return NEED_MORE;
869 }
870 case QM_NEGOTIATED:
871 {
872 return SUCCESS;
873 }
874 default:
875 return FAILED;
876 }
877 }
878
879 /**
880 * Check for notify errors, return TRUE if error found
881 */
882 static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
883 {
884 enumerator_t *enumerator;
885 payload_t *payload;
886 bool err = FALSE;
887
888 enumerator = message->create_payload_enumerator(message);
889 while (enumerator->enumerate(enumerator, &payload))
890 {
891 if (payload->get_type(payload) == NOTIFY_V1)
892 {
893 notify_payload_t *notify;
894 notify_type_t type;
895
896 notify = (notify_payload_t*)payload;
897 type = notify->get_notify_type(notify);
898 if (type < 16384)
899 {
900
901 DBG1(DBG_IKE, "received %N error notify",
902 notify_type_names, type);
903 err = TRUE;
904 }
905 else
906 {
907 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
908 }
909 }
910 }
911 enumerator->destroy(enumerator);
912
913 return err;
914 }
915
916 /**
917 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
918 */
919 static void check_for_rekeyed_child(private_quick_mode_t *this)
920 {
921 enumerator_t *enumerator, *policies;
922 traffic_selector_t *local, *remote;
923 child_sa_t *child_sa;
924
925 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
926 while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
927 {
928 if (child_sa->get_state(child_sa) == CHILD_INSTALLED &&
929 streq(child_sa->get_name(child_sa),
930 this->config->get_name(this->config)))
931 {
932 policies = child_sa->create_policy_enumerator(child_sa);
933 if (policies->enumerate(policies, &local, &remote))
934 {
935 if (local->equals(local, this->tsr) &&
936 remote->equals(remote, this->tsi) &&
937 this->proposal->equals(this->proposal,
938 child_sa->get_proposal(child_sa)))
939 {
940 this->reqid = child_sa->get_reqid(child_sa);
941 this->rekey = child_sa->get_spi(child_sa, TRUE);
942 child_sa->set_state(child_sa, CHILD_REKEYING);
943 DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
944 child_sa->get_name(child_sa), this->reqid);
945 }
946 }
947 policies->destroy(policies);
948 }
949 }
950 enumerator->destroy(enumerator);
951 }
952
953 METHOD(task_t, process_r, status_t,
954 private_quick_mode_t *this, message_t *message)
955 {
956 switch (this->state)
957 {
958 case QM_INIT:
959 {
960 sa_payload_t *sa_payload;
961 linked_list_t *tsi, *tsr, *hostsi, *hostsr, *list = NULL;
962 peer_cfg_t *peer_cfg;
963 u_int16_t group;
964 bool private;
965
966 sa_payload = (sa_payload_t*)message->get_payload(message,
967 SECURITY_ASSOCIATION_V1);
968 if (!sa_payload)
969 {
970 DBG1(DBG_IKE, "sa payload missing");
971 return send_notify(this, INVALID_PAYLOAD_TYPE);
972 }
973
974 this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
975
976 if (!get_ts(this, message))
977 {
978 return FAILED;
979 }
980 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
981 tsi = linked_list_create_with_items(this->tsi, NULL);
982 tsr = linked_list_create_with_items(this->tsr, NULL);
983 this->tsi = this->tsr = NULL;
984 hostsi = get_dynamic_hosts(this->ike_sa, FALSE);
985 hostsr = get_dynamic_hosts(this->ike_sa, TRUE);
986 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
987 hostsr, hostsi);
988 hostsi->destroy(hostsi);
989 hostsr->destroy(hostsr);
990 if (this->config)
991 {
992 this->tsi = select_ts(this, FALSE, tsi);
993 this->tsr = select_ts(this, TRUE, tsr);
994 }
995 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
996 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
997 if (!this->config || !this->tsi || !this->tsr)
998 {
999 DBG1(DBG_IKE, "no matching CHILD_SA config found");
1000 return send_notify(this, INVALID_ID_INFORMATION);
1001 }
1002
1003 if (this->config->use_ipcomp(this->config))
1004 {
1005 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
1006 {
1007 DBG1(DBG_IKE, "IPComp is not supported if either peer is "
1008 "natted, IPComp disabled");
1009 }
1010 else
1011 {
1012 list = sa_payload->get_ipcomp_proposals(sa_payload,
1013 &this->cpi_i);
1014 if (!list->get_count(list))
1015 {
1016 DBG1(DBG_IKE, "expected IPComp proposal but peer did "
1017 "not send one, IPComp disabled");
1018 this->cpi_i = 0;
1019 }
1020 }
1021 }
1022 if (!list || !list->get_count(list))
1023 {
1024 DESTROY_IF(list);
1025 list = sa_payload->get_proposals(sa_payload);
1026 }
1027 private = this->ike_sa->supports_extension(this->ike_sa,
1028 EXT_STRONGSWAN);
1029 this->proposal = this->config->select_proposal(this->config,
1030 list, FALSE, private);
1031 list->destroy_offset(list, offsetof(proposal_t, destroy));
1032
1033 get_lifetimes(this);
1034 apply_lifetimes(this, sa_payload);
1035
1036 if (!this->proposal)
1037 {
1038 DBG1(DBG_IKE, "no matching proposal found, sending %N",
1039 notify_type_names, NO_PROPOSAL_CHOSEN);
1040 return send_notify(this, NO_PROPOSAL_CHOSEN);
1041 }
1042 this->spi_i = this->proposal->get_spi(this->proposal);
1043
1044 if (!get_nonce(this, &this->nonce_i, message))
1045 {
1046 return send_notify(this, INVALID_PAYLOAD_TYPE);
1047 }
1048
1049 if (this->proposal->get_algorithm(this->proposal,
1050 DIFFIE_HELLMAN_GROUP, &group, NULL))
1051 {
1052 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
1053 group);
1054 if (!this->dh)
1055 {
1056 DBG1(DBG_IKE, "negotiated DH group %N not supported",
1057 diffie_hellman_group_names, group);
1058 return send_notify(this, INVALID_KEY_INFORMATION);
1059 }
1060 if (!get_ke(this, message))
1061 {
1062 return send_notify(this, INVALID_PAYLOAD_TYPE);
1063 }
1064 }
1065
1066 check_for_rekeyed_child(this);
1067
1068 this->child_sa = child_sa_create(
1069 this->ike_sa->get_my_host(this->ike_sa),
1070 this->ike_sa->get_other_host(this->ike_sa),
1071 this->config, this->reqid, this->udp);
1072
1073 tsi = linked_list_create_with_items(this->tsi, NULL);
1074 tsr = linked_list_create_with_items(this->tsr, NULL);
1075 this->tsi = this->tsr = NULL;
1076 charon->bus->narrow(charon->bus, this->child_sa,
1077 NARROW_RESPONDER, tsr, tsi);
1078 if (tsi->remove_first(tsi, (void**)&this->tsi) != SUCCESS ||
1079 tsr->remove_first(tsr, (void**)&this->tsr) != SUCCESS)
1080 {
1081 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1082 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1083 return send_notify(this, INVALID_ID_INFORMATION);
1084 }
1085 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
1086 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
1087
1088 return NEED_MORE;
1089 }
1090 case QM_NEGOTIATED:
1091 {
1092 if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
1093 has_notify_errors(this, message))
1094 {
1095 return SUCCESS;
1096 }
1097 if (!install(this))
1098 {
1099 ike_sa_t *ike_sa = this->ike_sa;
1100 task_t *task;
1101
1102 task = (task_t*)quick_delete_create(this->ike_sa,
1103 this->proposal->get_protocol(this->proposal),
1104 this->spi_i, TRUE, TRUE);
1105 /* flush_queue() destroys the current task */
1106 ike_sa->flush_queue(ike_sa, TASK_QUEUE_PASSIVE);
1107 ike_sa->queue_task(ike_sa, task);
1108 return ALREADY_DONE;
1109 }
1110 return SUCCESS;
1111 }
1112 default:
1113 return FAILED;
1114 }
1115 }
1116
1117 METHOD(task_t, build_r, status_t,
1118 private_quick_mode_t *this, message_t *message)
1119 {
1120 switch (this->state)
1121 {
1122 case QM_INIT:
1123 {
1124 sa_payload_t *sa_payload;
1125 encap_t encap;
1126
1127 this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
1128 if (!this->spi_r)
1129 {
1130 DBG1(DBG_IKE, "allocating SPI from kernel failed");
1131 return send_notify(this, NO_PROPOSAL_CHOSEN);
1132 }
1133 this->proposal->set_spi(this->proposal, this->spi_r);
1134
1135 if (this->cpi_i)
1136 {
1137 this->cpi_r = this->child_sa->alloc_cpi(this->child_sa);
1138 if (!this->cpi_r)
1139 {
1140 DBG1(DBG_IKE, "unable to allocate a CPI from "
1141 "kernel, IPComp disabled");
1142 return send_notify(this, NO_PROPOSAL_CHOSEN);
1143 }
1144 }
1145
1146 if (this->udp && this->mode == MODE_TRANSPORT)
1147 {
1148 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
1149 add_nat_oa_payloads(this, message);
1150 }
1151
1152 encap = get_encap(this->ike_sa, this->udp);
1153 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
1154 this->lifetime, this->lifebytes, AUTH_NONE,
1155 this->mode, encap, this->cpi_r);
1156 message->add_payload(message, &sa_payload->payload_interface);
1157
1158 if (!add_nonce(this, &this->nonce_r, message))
1159 {
1160 return FAILED;
1161 }
1162 if (this->dh)
1163 {
1164 add_ke(this, message);
1165 }
1166
1167 add_ts(this, message);
1168
1169 this->state = QM_NEGOTIATED;
1170 return NEED_MORE;
1171 }
1172 default:
1173 return FAILED;
1174 }
1175 }
1176
1177 METHOD(task_t, process_i, status_t,
1178 private_quick_mode_t *this, message_t *message)
1179 {
1180 switch (this->state)
1181 {
1182 case QM_INIT:
1183 {
1184 sa_payload_t *sa_payload;
1185 linked_list_t *list = NULL;
1186 bool private;
1187
1188 sa_payload = (sa_payload_t*)message->get_payload(message,
1189 SECURITY_ASSOCIATION_V1);
1190 if (!sa_payload)
1191 {
1192 DBG1(DBG_IKE, "sa payload missing");
1193 return send_notify(this, NO_PROPOSAL_CHOSEN);
1194 }
1195 if (this->cpi_i)
1196 {
1197 list = sa_payload->get_ipcomp_proposals(sa_payload,
1198 &this->cpi_r);
1199 if (!list->get_count(list))
1200 {
1201 DBG1(DBG_IKE, "peer did not acccept our IPComp proposal, "
1202 "IPComp disabled");
1203 this->cpi_i = 0;
1204 }
1205 }
1206 if (!list || !list->get_count(list))
1207 {
1208 DESTROY_IF(list);
1209 list = sa_payload->get_proposals(sa_payload);
1210 }
1211 private = this->ike_sa->supports_extension(this->ike_sa,
1212 EXT_STRONGSWAN);
1213 this->proposal = this->config->select_proposal(this->config,
1214 list, FALSE, private);
1215 list->destroy_offset(list, offsetof(proposal_t, destroy));
1216 if (!this->proposal)
1217 {
1218 DBG1(DBG_IKE, "no matching proposal found");
1219 return send_notify(this, NO_PROPOSAL_CHOSEN);
1220 }
1221 this->spi_r = this->proposal->get_spi(this->proposal);
1222
1223 apply_lifetimes(this, sa_payload);
1224
1225 if (!get_nonce(this, &this->nonce_r, message))
1226 {
1227 return send_notify(this, INVALID_PAYLOAD_TYPE);
1228 }
1229 if (this->dh && !get_ke(this, message))
1230 {
1231 return send_notify(this, INVALID_KEY_INFORMATION);
1232 }
1233 if (!get_ts(this, message))
1234 {
1235 return send_notify(this, INVALID_PAYLOAD_TYPE);
1236 }
1237 if (!install(this))
1238 {
1239 return send_notify(this, NO_PROPOSAL_CHOSEN);
1240 }
1241 this->state = QM_NEGOTIATED;
1242 return NEED_MORE;
1243 }
1244 default:
1245 return FAILED;
1246 }
1247 }
1248
1249 METHOD(task_t, get_type, task_type_t,
1250 private_quick_mode_t *this)
1251 {
1252 return TASK_QUICK_MODE;
1253 }
1254
1255 METHOD(quick_mode_t, use_reqid, void,
1256 private_quick_mode_t *this, u_int32_t reqid)
1257 {
1258 this->reqid = reqid;
1259 }
1260
1261 METHOD(quick_mode_t, rekey, void,
1262 private_quick_mode_t *this, u_int32_t spi)
1263 {
1264 this->rekey = spi;
1265 }
1266
1267 METHOD(task_t, migrate, void,
1268 private_quick_mode_t *this, ike_sa_t *ike_sa)
1269 {
1270 chunk_free(&this->nonce_i);
1271 chunk_free(&this->nonce_r);
1272 DESTROY_IF(this->tsi);
1273 DESTROY_IF(this->tsr);
1274 DESTROY_IF(this->proposal);
1275 DESTROY_IF(this->child_sa);
1276 DESTROY_IF(this->dh);
1277
1278 this->ike_sa = ike_sa;
1279 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1280 this->state = QM_INIT;
1281 this->tsi = NULL;
1282 this->tsr = NULL;
1283 this->proposal = NULL;
1284 this->child_sa = NULL;
1285 this->dh = NULL;
1286 this->spi_i = 0;
1287 this->spi_r = 0;
1288
1289 if (!this->initiator)
1290 {
1291 DESTROY_IF(this->config);
1292 this->config = NULL;
1293 }
1294 }
1295
1296 METHOD(task_t, destroy, void,
1297 private_quick_mode_t *this)
1298 {
1299 chunk_free(&this->nonce_i);
1300 chunk_free(&this->nonce_r);
1301 DESTROY_IF(this->tsi);
1302 DESTROY_IF(this->tsr);
1303 DESTROY_IF(this->proposal);
1304 DESTROY_IF(this->child_sa);
1305 DESTROY_IF(this->config);
1306 DESTROY_IF(this->dh);
1307 free(this);
1308 }
1309
1310 /*
1311 * Described in header.
1312 */
1313 quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1314 traffic_selector_t *tsi, traffic_selector_t *tsr)
1315 {
1316 private_quick_mode_t *this;
1317
1318 INIT(this,
1319 .public = {
1320 .task = {
1321 .get_type = _get_type,
1322 .migrate = _migrate,
1323 .destroy = _destroy,
1324 },
1325 .use_reqid = _use_reqid,
1326 .rekey = _rekey,
1327 },
1328 .ike_sa = ike_sa,
1329 .initiator = config != NULL,
1330 .config = config,
1331 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1332 .state = QM_INIT,
1333 .tsi = tsi ? tsi->clone(tsi) : NULL,
1334 .tsr = tsr ? tsr->clone(tsr) : NULL,
1335 );
1336
1337 if (config)
1338 {
1339 this->public.task.build = _build_i;
1340 this->public.task.process = _process_i;
1341 }
1342 else
1343 {
1344 this->public.task.build = _build_r;
1345 this->public.task.process = _process_r;
1346 }
1347
1348 return &this->public;
1349 }