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