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