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