Use nonce_gen instead of rng to generate nonces
[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 return ALREADY_DONE;
609 }
610
611 METHOD(task_t, build_i, status_t,
612 private_quick_mode_t *this, message_t *message)
613 {
614 switch (this->state)
615 {
616 case QM_INIT:
617 {
618 enumerator_t *enumerator;
619 sa_payload_t *sa_payload;
620 linked_list_t *list, *tsi, *tsr;
621 proposal_t *proposal;
622 diffie_hellman_group_t group;
623
624 this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
625 this->child_sa = child_sa_create(
626 this->ike_sa->get_my_host(this->ike_sa),
627 this->ike_sa->get_other_host(this->ike_sa),
628 this->config, this->reqid, this->udp);
629
630 list = this->config->get_proposals(this->config, FALSE);
631
632 this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
633 if (!this->spi_i)
634 {
635 DBG1(DBG_IKE, "allocating SPI from kernel failed");
636 return FAILED;
637 }
638 enumerator = list->create_enumerator(list);
639 while (enumerator->enumerate(enumerator, &proposal))
640 {
641 proposal->set_spi(proposal, this->spi_i);
642 }
643 enumerator->destroy(enumerator);
644
645 this->mode = this->config->get_mode(this->config);
646 if (this->udp && this->mode == MODE_TRANSPORT)
647 {
648 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
649 add_nat_oa_payloads(this, message);
650 }
651
652 get_lifetimes(this);
653 sa_payload = sa_payload_create_from_proposals_v1(list,
654 this->lifetime, this->lifebytes, AUTH_NONE,
655 this->mode, this->udp);
656 list->destroy_offset(list, offsetof(proposal_t, destroy));
657 message->add_payload(message, &sa_payload->payload_interface);
658
659 if (!add_nonce(this, &this->nonce_i, message))
660 {
661 return FAILED;
662 }
663
664 group = this->config->get_dh_group(this->config);
665 if (group != MODP_NONE)
666 {
667 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
668 group);
669 if (!this->dh)
670 {
671 DBG1(DBG_IKE, "configured DH group %N not supported",
672 diffie_hellman_group_names, group);
673 return FAILED;
674 }
675 add_ke(this, message);
676 }
677 this->tsi = select_ts(this, TRUE, NULL);
678 this->tsr = select_ts(this, FALSE, NULL);
679 tsi = linked_list_create();
680 tsr = linked_list_create();
681 tsi->insert_last(tsi, this->tsi);
682 tsr->insert_last(tsr, this->tsr);
683 this->tsi = this->tsr = NULL;
684 charon->bus->narrow(charon->bus, this->child_sa,
685 NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
686 tsi->remove_first(tsi, (void**)&this->tsi);
687 tsr->remove_first(tsr, (void**)&this->tsr);
688 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
689 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
690 if (!this->tsi || !this->tsr)
691 {
692 return FAILED;
693 }
694 add_ts(this, message);
695 return NEED_MORE;
696 }
697 case QM_NEGOTIATED:
698 {
699 return SUCCESS;
700 }
701 default:
702 return FAILED;
703 }
704 }
705
706 /**
707 * Check for notify errors, return TRUE if error found
708 */
709 static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
710 {
711 enumerator_t *enumerator;
712 payload_t *payload;
713 bool err = FALSE;
714
715 enumerator = message->create_payload_enumerator(message);
716 while (enumerator->enumerate(enumerator, &payload))
717 {
718 if (payload->get_type(payload) == NOTIFY_V1)
719 {
720 notify_payload_t *notify;
721 notify_type_t type;
722
723 notify = (notify_payload_t*)payload;
724 type = notify->get_notify_type(notify);
725 if (type < 16384)
726 {
727
728 DBG1(DBG_IKE, "received %N error notify",
729 notify_type_names, type);
730 err = TRUE;
731 }
732 else
733 {
734 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
735 }
736 }
737 }
738 enumerator->destroy(enumerator);
739
740 return err;
741 }
742
743 /**
744 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
745 */
746 static void check_for_rekeyed_child(private_quick_mode_t *this)
747 {
748 enumerator_t *enumerator, *policies;
749 traffic_selector_t *local, *remote;
750 child_sa_t *child_sa;
751
752 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
753 while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
754 {
755 if (child_sa->get_state(child_sa) == CHILD_INSTALLED &&
756 streq(child_sa->get_name(child_sa),
757 this->config->get_name(this->config)))
758 {
759 policies = child_sa->create_policy_enumerator(child_sa);
760 if (policies->enumerate(policies, &local, &remote))
761 {
762 if (local->equals(local, this->tsr) &&
763 remote->equals(remote, this->tsi) &&
764 this->proposal->equals(this->proposal,
765 child_sa->get_proposal(child_sa)))
766 {
767 this->reqid = child_sa->get_reqid(child_sa);
768 this->rekey = child_sa->get_spi(child_sa, TRUE);
769 child_sa->set_state(child_sa, CHILD_REKEYING);
770 DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
771 child_sa->get_name(child_sa), this->reqid);
772 }
773 }
774 policies->destroy(policies);
775 }
776 }
777 enumerator->destroy(enumerator);
778 }
779
780 METHOD(task_t, process_r, status_t,
781 private_quick_mode_t *this, message_t *message)
782 {
783 switch (this->state)
784 {
785 case QM_INIT:
786 {
787 sa_payload_t *sa_payload;
788 linked_list_t *tsi, *tsr, *list;
789 peer_cfg_t *peer_cfg;
790 host_t *me, *other;
791 u_int16_t group;
792 bool private;
793
794 if (!get_ts(this, message))
795 {
796 return FAILED;
797 }
798 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
799 if (!me)
800 {
801 me = this->ike_sa->get_my_host(this->ike_sa);
802 }
803 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
804 if (!other)
805 {
806 other = this->ike_sa->get_other_host(this->ike_sa);
807 }
808 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
809 tsi = linked_list_create();
810 tsr = linked_list_create();
811 tsi->insert_last(tsi, this->tsi);
812 tsr->insert_last(tsr, this->tsr);
813 this->tsi = this->tsr = NULL;
814 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
815 me, other);
816 if (this->config)
817 {
818 this->tsi = select_ts(this, FALSE, tsi);
819 this->tsr = select_ts(this, TRUE, tsr);
820 }
821 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
822 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
823 if (!this->config || !this->tsi || !this->tsr)
824 {
825 DBG1(DBG_IKE, "no matching CHILD_SA config found");
826 return send_notify(this, INVALID_ID_INFORMATION);
827 }
828
829 sa_payload = (sa_payload_t*)message->get_payload(message,
830 SECURITY_ASSOCIATION_V1);
831 if (!sa_payload)
832 {
833 DBG1(DBG_IKE, "sa payload missing");
834 return send_notify(this, INVALID_PAYLOAD_TYPE);
835 }
836 list = sa_payload->get_proposals(sa_payload);
837 private = this->ike_sa->supports_extension(this->ike_sa,
838 EXT_STRONGSWAN);
839 this->proposal = this->config->select_proposal(this->config,
840 list, FALSE, private);
841 list->destroy_offset(list, offsetof(proposal_t, destroy));
842
843 this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
844
845 get_lifetimes(this);
846 apply_lifetimes(this, sa_payload);
847
848 if (!this->proposal)
849 {
850 DBG1(DBG_IKE, "no matching proposal found, sending %N",
851 notify_type_names, NO_PROPOSAL_CHOSEN);
852 return send_notify(this, NO_PROPOSAL_CHOSEN);
853 }
854 this->spi_i = this->proposal->get_spi(this->proposal);
855
856 if (!get_nonce(this, &this->nonce_i, message))
857 {
858 return send_notify(this, INVALID_PAYLOAD_TYPE);
859 }
860
861 if (this->proposal->get_algorithm(this->proposal,
862 DIFFIE_HELLMAN_GROUP, &group, NULL))
863 {
864 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
865 group);
866 if (!this->dh)
867 {
868 DBG1(DBG_IKE, "negotiated DH group %N not supported",
869 diffie_hellman_group_names, group);
870 return send_notify(this, INVALID_KEY_INFORMATION);
871 }
872 if (!get_ke(this, message))
873 {
874 return send_notify(this, INVALID_PAYLOAD_TYPE);
875 }
876 }
877
878 check_for_rekeyed_child(this);
879
880 this->child_sa = child_sa_create(
881 this->ike_sa->get_my_host(this->ike_sa),
882 this->ike_sa->get_other_host(this->ike_sa),
883 this->config, this->reqid, this->udp);
884 return NEED_MORE;
885 }
886 case QM_NEGOTIATED:
887 {
888 if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
889 has_notify_errors(this, message))
890 {
891 return SUCCESS;
892 }
893 if (!install(this))
894 {
895 this->ike_sa->queue_task(this->ike_sa,
896 (task_t*)quick_delete_create(this->ike_sa,
897 this->proposal->get_protocol(this->proposal),
898 this->spi_i, TRUE, TRUE));
899 return ALREADY_DONE;
900 }
901 return SUCCESS;
902 }
903 default:
904 return FAILED;
905 }
906 }
907
908 METHOD(task_t, build_r, status_t,
909 private_quick_mode_t *this, message_t *message)
910 {
911 switch (this->state)
912 {
913 case QM_INIT:
914 {
915 sa_payload_t *sa_payload;
916
917 this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
918 if (!this->spi_r)
919 {
920 DBG1(DBG_IKE, "allocating SPI from kernel failed");
921 return send_notify(this, NO_PROPOSAL_CHOSEN);
922 }
923 this->proposal->set_spi(this->proposal, this->spi_r);
924
925 if (this->udp && this->mode == MODE_TRANSPORT)
926 {
927 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
928 add_nat_oa_payloads(this, message);
929 }
930
931 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
932 this->lifetime, this->lifebytes, AUTH_NONE,
933 this->mode, this->udp);
934 message->add_payload(message, &sa_payload->payload_interface);
935
936 if (!add_nonce(this, &this->nonce_r, message))
937 {
938 return FAILED;
939 }
940 if (this->dh)
941 {
942 add_ke(this, message);
943 }
944
945 add_ts(this, message);
946
947 this->state = QM_NEGOTIATED;
948 return NEED_MORE;
949 }
950 default:
951 return FAILED;
952 }
953 }
954
955 METHOD(task_t, process_i, status_t,
956 private_quick_mode_t *this, message_t *message)
957 {
958 switch (this->state)
959 {
960 case QM_INIT:
961 {
962 sa_payload_t *sa_payload;
963 linked_list_t *list;
964 bool private;
965
966 sa_payload = (sa_payload_t*)message->get_payload(message,
967 SECURITY_ASSOCIATION_V1);
968 if (!sa_payload)
969 {
970 DBG1(DBG_IKE, "sa payload missing");
971 return send_notify(this, NO_PROPOSAL_CHOSEN);
972 }
973 list = sa_payload->get_proposals(sa_payload);
974 private = this->ike_sa->supports_extension(this->ike_sa,
975 EXT_STRONGSWAN);
976 this->proposal = this->config->select_proposal(this->config,
977 list, FALSE, private);
978 list->destroy_offset(list, offsetof(proposal_t, destroy));
979 if (!this->proposal)
980 {
981 DBG1(DBG_IKE, "no matching proposal found");
982 return send_notify(this, NO_PROPOSAL_CHOSEN);
983 }
984 this->spi_r = this->proposal->get_spi(this->proposal);
985
986 apply_lifetimes(this, sa_payload);
987
988 if (!get_nonce(this, &this->nonce_r, message))
989 {
990 return send_notify(this, INVALID_PAYLOAD_TYPE);
991 }
992 if (this->dh && !get_ke(this, message))
993 {
994 return send_notify(this, INVALID_KEY_INFORMATION);
995 }
996 if (!get_ts(this, message))
997 {
998 return send_notify(this, INVALID_PAYLOAD_TYPE);
999 }
1000 if (!install(this))
1001 {
1002 return send_notify(this, NO_PROPOSAL_CHOSEN);
1003 }
1004 this->state = QM_NEGOTIATED;
1005 return NEED_MORE;
1006 }
1007 default:
1008 return FAILED;
1009 }
1010 }
1011
1012 METHOD(task_t, get_type, task_type_t,
1013 private_quick_mode_t *this)
1014 {
1015 return TASK_QUICK_MODE;
1016 }
1017
1018 METHOD(quick_mode_t, use_reqid, void,
1019 private_quick_mode_t *this, u_int32_t reqid)
1020 {
1021 this->reqid = reqid;
1022 }
1023
1024 METHOD(quick_mode_t, rekey, void,
1025 private_quick_mode_t *this, u_int32_t spi)
1026 {
1027 this->rekey = spi;
1028 }
1029
1030 METHOD(task_t, migrate, void,
1031 private_quick_mode_t *this, ike_sa_t *ike_sa)
1032 {
1033 chunk_free(&this->nonce_i);
1034 chunk_free(&this->nonce_r);
1035 DESTROY_IF(this->tsi);
1036 DESTROY_IF(this->tsr);
1037 DESTROY_IF(this->proposal);
1038 DESTROY_IF(this->child_sa);
1039 DESTROY_IF(this->dh);
1040
1041 this->ike_sa = ike_sa;
1042 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1043 this->state = QM_INIT;
1044 this->tsi = NULL;
1045 this->tsr = NULL;
1046 this->proposal = NULL;
1047 this->child_sa = NULL;
1048 this->dh = NULL;
1049 this->spi_i = 0;
1050 this->spi_r = 0;
1051
1052 if (!this->initiator)
1053 {
1054 DESTROY_IF(this->config);
1055 this->config = NULL;
1056 }
1057 }
1058
1059 METHOD(task_t, destroy, void,
1060 private_quick_mode_t *this)
1061 {
1062 chunk_free(&this->nonce_i);
1063 chunk_free(&this->nonce_r);
1064 DESTROY_IF(this->tsi);
1065 DESTROY_IF(this->tsr);
1066 DESTROY_IF(this->proposal);
1067 DESTROY_IF(this->child_sa);
1068 DESTROY_IF(this->config);
1069 DESTROY_IF(this->dh);
1070 free(this);
1071 }
1072
1073 /*
1074 * Described in header.
1075 */
1076 quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1077 traffic_selector_t *tsi, traffic_selector_t *tsr)
1078 {
1079 private_quick_mode_t *this;
1080
1081 INIT(this,
1082 .public = {
1083 .task = {
1084 .get_type = _get_type,
1085 .migrate = _migrate,
1086 .destroy = _destroy,
1087 },
1088 .use_reqid = _use_reqid,
1089 .rekey = _rekey,
1090 },
1091 .ike_sa = ike_sa,
1092 .initiator = config != NULL,
1093 .config = config,
1094 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1095 .state = QM_INIT,
1096 );
1097
1098 if (config)
1099 {
1100 this->public.task.build = _build_i;
1101 this->public.task.process = _process_i;
1102 }
1103 else
1104 {
1105 this->public.task.build = _build_r;
1106 this->public.task.process = _process_r;
1107 }
1108
1109 return &this->public;
1110 }