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