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