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