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