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