Use traffic selectors passed to quick mode constructor as initiator
[strongswan.git] / src / libcharon / sa / ikev1 / tasks / quick_mode.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "quick_mode.h"
20
21 #include <string.h>
22
23 #include <daemon.h>
24 #include <sa/ikev1/keymat_v1.h>
25 #include <encoding/payloads/sa_payload.h>
26 #include <encoding/payloads/nonce_payload.h>
27 #include <encoding/payloads/ke_payload.h>
28 #include <encoding/payloads/id_payload.h>
29 #include <encoding/payloads/payload.h>
30 #include <sa/ikev1/tasks/informational.h>
31 #include <sa/ikev1/tasks/quick_delete.h>
32 #include <processing/jobs/inactivity_job.h>
33
34 typedef struct private_quick_mode_t private_quick_mode_t;
35
36 /**
37 * Private members of a quick_mode_t task.
38 */
39 struct private_quick_mode_t {
40
41 /**
42 * Public methods and task_t interface.
43 */
44 quick_mode_t public;
45
46 /**
47 * Assigned IKE_SA.
48 */
49 ike_sa_t *ike_sa;
50
51 /**
52 * TRUE if we are initiating quick mode
53 */
54 bool initiator;
55
56 /**
57 * Traffic selector of initiator
58 */
59 traffic_selector_t *tsi;
60
61 /**
62 * Traffic selector of responder
63 */
64 traffic_selector_t *tsr;
65
66 /**
67 * Initiators nonce
68 */
69 chunk_t nonce_i;
70
71 /**
72 * Responder nonce
73 */
74 chunk_t nonce_r;
75
76 /**
77 * Initiators ESP SPI
78 */
79 u_int32_t spi_i;
80
81 /**
82 * Responder ESP SPI
83 */
84 u_int32_t spi_r;
85
86 /**
87 * Initiators IPComp CPI
88 */
89 u_int16_t cpi_i;
90
91 /**
92 * Responders IPComp CPI
93 */
94 u_int16_t cpi_r;
95
96 /**
97 * selected CHILD_SA proposal
98 */
99 proposal_t *proposal;
100
101 /**
102 * Config of CHILD_SA to establish
103 */
104 child_cfg_t *config;
105
106 /**
107 * CHILD_SA we are about to establish
108 */
109 child_sa_t *child_sa;
110
111 /**
112 * IKEv1 keymat
113 */
114 keymat_v1_t *keymat;
115
116 /**
117 * DH exchange, when PFS is in use
118 */
119 diffie_hellman_t *dh;
120
121 /**
122 * Negotiated lifetime of new SA
123 */
124 u_int32_t lifetime;
125
126 /**
127 * Negotaited lifebytes of new SA
128 */
129 u_int64_t lifebytes;
130
131 /**
132 * Reqid to use, 0 for auto-allocate
133 */
134 u_int32_t reqid;
135
136 /**
137 * SPI of SA we rekey
138 */
139 u_int32_t rekey;
140
141 /**
142 * Negotiated mode, tunnel or transport
143 */
144 ipsec_mode_t mode;
145
146 /**
147 * Use UDP encapsulation
148 */
149 bool udp;
150
151 /** states of quick mode */
152 enum {
153 QM_INIT,
154 QM_NEGOTIATED,
155 } state;
156 };
157
158 /**
159 * Schedule inactivity timeout for CHILD_SA with reqid, if enabled
160 */
161 static void schedule_inactivity_timeout(private_quick_mode_t *this)
162 {
163 u_int32_t timeout;
164 bool close_ike;
165
166 timeout = this->config->get_inactivity(this->config);
167 if (timeout)
168 {
169 close_ike = lib->settings->get_bool(lib->settings,
170 "%s.inactivity_close_ike", FALSE, charon->name);
171 lib->scheduler->schedule_job(lib->scheduler, (job_t*)
172 inactivity_job_create(this->child_sa->get_reqid(this->child_sa),
173 timeout, close_ike), timeout);
174 }
175 }
176
177 /**
178 * Install negotiated CHILD_SA
179 */
180 static bool install(private_quick_mode_t *this)
181 {
182 status_t status, status_i, status_o;
183 chunk_t encr_i, encr_r, integ_i, integ_r;
184 linked_list_t *tsi, *tsr;
185 child_sa_t *old = NULL;
186
187 this->child_sa->set_proposal(this->child_sa, this->proposal);
188 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
189 this->child_sa->set_mode(this->child_sa, this->mode);
190
191 if (this->cpi_i && this->cpi_r)
192 { /* DEFLATE is the only transform we currently support */
193 this->child_sa->set_ipcomp(this->child_sa, IPCOMP_DEFLATE);
194 }
195 else
196 {
197 this->cpi_i = this->cpi_r = 0;
198 }
199
200 this->child_sa->set_protocol(this->child_sa,
201 this->proposal->get_protocol(this->proposal));
202
203 status_i = status_o = FAILED;
204 encr_i = encr_r = integ_i = integ_r = chunk_empty;
205 tsi = linked_list_create();
206 tsr = linked_list_create();
207 tsi->insert_last(tsi, this->tsi->clone(this->tsi));
208 tsr->insert_last(tsr, this->tsr->clone(this->tsr));
209 if (this->initiator)
210 {
211 charon->bus->narrow(charon->bus, this->child_sa,
212 NARROW_INITIATOR_POST_AUTH, tsi, tsr);
213 }
214 else
215 {
216 charon->bus->narrow(charon->bus, this->child_sa,
217 NARROW_RESPONDER, tsr, tsi);
218 }
219 if (tsi->get_count(tsi) == 0 || tsr->get_count(tsr) == 0)
220 {
221 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
222 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
223 DBG1(DBG_IKE, "no acceptable traffic selectors found");
224 return FALSE;
225 }
226
227 if (this->keymat->derive_child_keys(this->keymat, this->proposal, this->dh,
228 this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
229 &encr_i, &integ_i, &encr_r, &integ_r))
230 {
231 if (this->initiator)
232 {
233 status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
234 this->spi_i, this->cpi_i, TRUE, FALSE, tsi, tsr);
235 status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
236 this->spi_r, this->cpi_r, FALSE, FALSE, tsi, tsr);
237 }
238 else
239 {
240 status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
241 this->spi_r, this->cpi_r, TRUE, FALSE, tsr, tsi);
242 status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
243 this->spi_i, this->cpi_i, FALSE, FALSE, tsr, tsi);
244 }
245 }
246 chunk_clear(&integ_i);
247 chunk_clear(&integ_r);
248 chunk_clear(&encr_i);
249 chunk_clear(&encr_r);
250
251 if (status_i != SUCCESS || status_o != SUCCESS)
252 {
253 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
254 (status_i != SUCCESS) ? "inbound " : "",
255 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
256 (status_o != SUCCESS) ? "outbound " : "");
257 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
258 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
259 return FALSE;
260 }
261
262 if (this->initiator)
263 {
264 status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
265 }
266 else
267 {
268 status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
269 }
270 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
271 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
272 if (status != SUCCESS)
273 {
274 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
275 return FALSE;
276 }
277
278 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
279 this->dh, this->nonce_i, this->nonce_r);
280
281 /* add to IKE_SA, and remove from task */
282 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
283 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
284
285 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
286 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
287 this->child_sa->get_name(this->child_sa),
288 this->child_sa->get_reqid(this->child_sa),
289 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
290 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
291 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
292 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
293
294 if (this->rekey)
295 {
296 old = this->ike_sa->get_child_sa(this->ike_sa,
297 this->proposal->get_protocol(this->proposal),
298 this->rekey, TRUE);
299 }
300 if (old)
301 {
302 charon->bus->child_rekey(charon->bus, old, this->child_sa);
303 }
304 else
305 {
306 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
307 }
308 if (!this->rekey)
309 {
310 schedule_inactivity_timeout(this);
311 }
312 this->child_sa = NULL;
313 return TRUE;
314 }
315
316 /**
317 * Generate and add NONCE
318 */
319 static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
320 message_t *message)
321 {
322 nonce_payload_t *nonce_payload;
323 nonce_gen_t *nonceg;
324
325 nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
326 if (!nonceg)
327 {
328 DBG1(DBG_IKE, "no nonce generator found to create nonce");
329 return FALSE;
330 }
331 nonceg->allocate_nonce(nonceg, NONCE_SIZE, nonce);
332 nonceg->destroy(nonceg);
333
334 nonce_payload = nonce_payload_create(NONCE_V1);
335 nonce_payload->set_nonce(nonce_payload, *nonce);
336 message->add_payload(message, &nonce_payload->payload_interface);
337
338 return TRUE;
339 }
340
341 /**
342 * Extract nonce from NONCE payload
343 */
344 static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
345 message_t *message)
346 {
347 nonce_payload_t *nonce_payload;
348
349 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
350 if (!nonce_payload)
351 {
352 DBG1(DBG_IKE, "NONCE payload missing in message");
353 return FALSE;
354 }
355 *nonce = nonce_payload->get_nonce(nonce_payload);
356
357 return TRUE;
358 }
359
360 /**
361 * Add KE payload to message
362 */
363 static void add_ke(private_quick_mode_t *this, message_t *message)
364 {
365 ke_payload_t *ke_payload;
366
367 ke_payload = ke_payload_create_from_diffie_hellman(KEY_EXCHANGE_V1, this->dh);
368 message->add_payload(message, &ke_payload->payload_interface);
369 }
370
371 /**
372 * Get DH value from a KE payload
373 */
374 static bool get_ke(private_quick_mode_t *this, message_t *message)
375 {
376 ke_payload_t *ke_payload;
377
378 ke_payload = (ke_payload_t*)message->get_payload(message, KEY_EXCHANGE_V1);
379 if (!ke_payload)
380 {
381 DBG1(DBG_IKE, "KE payload missing");
382 return FALSE;
383 }
384 this->dh->set_other_public_value(this->dh,
385 ke_payload->get_key_exchange_data(ke_payload));
386 return TRUE;
387 }
388
389 /**
390 * Select a traffic selector from configuration
391 */
392 static traffic_selector_t* select_ts(private_quick_mode_t *this, bool local,
393 linked_list_t *supplied)
394 {
395 traffic_selector_t *ts;
396 linked_list_t *list;
397 host_t *host;
398
399 host = this->ike_sa->get_virtual_ip(this->ike_sa, local);
400 if (!host)
401 {
402 if (local)
403 {
404 host = this->ike_sa->get_my_host(this->ike_sa);
405 }
406 else
407 {
408 host = this->ike_sa->get_other_host(this->ike_sa);
409 }
410 }
411 list = this->config->get_traffic_selectors(this->config, local,
412 supplied, host);
413 if (list->get_first(list, (void**)&ts) == SUCCESS)
414 {
415 if (list->get_count(list) > 1)
416 {
417 DBG1(DBG_IKE, "configuration has more than one %s traffic selector,"
418 " using first only", local ? "local" : "remote");
419 }
420 ts = ts->clone(ts);
421 }
422 else
423 {
424 DBG1(DBG_IKE, "%s traffic selector missing in configuration",
425 local ? "local" : "local");
426 ts = NULL;
427 }
428 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
429 return ts;
430 }
431
432 /**
433 * Add selected traffic selectors to message
434 */
435 static void add_ts(private_quick_mode_t *this, message_t *message)
436 {
437 id_payload_t *id_payload;
438 host_t *hsi, *hsr;
439
440 if (this->initiator)
441 {
442 hsi = this->ike_sa->get_my_host(this->ike_sa);
443 hsr = this->ike_sa->get_other_host(this->ike_sa);
444 }
445 else
446 {
447 hsr = this->ike_sa->get_my_host(this->ike_sa);
448 hsi = this->ike_sa->get_other_host(this->ike_sa);
449 }
450 /* add ID payload only if negotiating non host2host tunnels */
451 if (!this->tsi->is_host(this->tsi, hsi) ||
452 !this->tsr->is_host(this->tsr, hsr) ||
453 this->tsi->get_protocol(this->tsi) ||
454 this->tsr->get_protocol(this->tsr) ||
455 this->tsi->get_from_port(this->tsi) ||
456 this->tsr->get_from_port(this->tsr) ||
457 this->tsi->get_to_port(this->tsi) != 65535 ||
458 this->tsr->get_to_port(this->tsr) != 65535)
459 {
460 id_payload = id_payload_create_from_ts(this->tsi);
461 message->add_payload(message, &id_payload->payload_interface);
462 id_payload = id_payload_create_from_ts(this->tsr);
463 message->add_payload(message, &id_payload->payload_interface);
464 }
465 }
466
467 /**
468 * Get traffic selectors from received message
469 */
470 static bool get_ts(private_quick_mode_t *this, message_t *message)
471 {
472 traffic_selector_t *tsi = NULL, *tsr = NULL;
473 enumerator_t *enumerator;
474 id_payload_t *id_payload;
475 payload_t *payload;
476 host_t *hsi, *hsr;
477 bool first = TRUE;
478
479 enumerator = message->create_payload_enumerator(message);
480 while (enumerator->enumerate(enumerator, &payload))
481 {
482 if (payload->get_type(payload) == ID_V1)
483 {
484 id_payload = (id_payload_t*)payload;
485
486 if (first)
487 {
488 tsi = id_payload->get_ts(id_payload);
489 first = FALSE;
490 }
491 else
492 {
493 tsr = id_payload->get_ts(id_payload);
494 break;
495 }
496 }
497 }
498 enumerator->destroy(enumerator);
499
500 /* create host2host selectors if ID payloads missing */
501 if (this->initiator)
502 {
503 hsi = this->ike_sa->get_my_host(this->ike_sa);
504 hsr = this->ike_sa->get_other_host(this->ike_sa);
505 }
506 else
507 {
508 hsr = this->ike_sa->get_my_host(this->ike_sa);
509 hsi = this->ike_sa->get_other_host(this->ike_sa);
510 }
511 if (!tsi)
512 {
513 tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
514 hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0);
515 }
516 if (!tsr)
517 {
518 tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
519 hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0);
520 }
521 if (this->initiator)
522 {
523 /* check if peer selection valid */
524 if (!tsr->is_contained_in(tsr, this->tsr) ||
525 !tsi->is_contained_in(tsi, this->tsi))
526 {
527 DBG1(DBG_IKE, "peer selected invalid traffic selectors: ",
528 "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
529 tsi->destroy(tsi);
530 tsr->destroy(tsr);
531 return FALSE;
532 }
533 this->tsi->destroy(this->tsi);
534 this->tsr->destroy(this->tsr);
535 this->tsi = tsi;
536 this->tsr = tsr;
537 }
538 else
539 {
540 this->tsi = tsi;
541 this->tsr = tsr;
542 }
543 return TRUE;
544 }
545
546 /**
547 * Add NAT-OA payloads
548 */
549 static void add_nat_oa_payloads(private_quick_mode_t *this, message_t *message)
550 {
551 identification_t *id;
552 id_payload_t *nat_oa;
553 host_t *src, *dst;
554
555 src = message->get_source(message);
556 dst = message->get_destination(message);
557
558 src = this->initiator ? src : dst;
559 dst = this->initiator ? dst : src;
560
561 /* first NAT-OA is the initiator's address */
562 id = identification_create_from_sockaddr(src->get_sockaddr(src));
563 nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
564 message->add_payload(message, (payload_t*)nat_oa);
565 id->destroy(id);
566
567 /* second NAT-OA is that of the responder */
568 id = identification_create_from_sockaddr(dst->get_sockaddr(dst));
569 nat_oa = id_payload_create_from_identification(NAT_OA_V1, id);
570 message->add_payload(message, (payload_t*)nat_oa);
571 id->destroy(id);
572 }
573
574 /**
575 * Look up lifetimes
576 */
577 static void get_lifetimes(private_quick_mode_t *this)
578 {
579 lifetime_cfg_t *lft;
580
581 lft = this->config->get_lifetime(this->config);
582 if (lft->time.life)
583 {
584 this->lifetime = lft->time.life;
585 }
586 else if (lft->bytes.life)
587 {
588 this->lifebytes = lft->bytes.life;
589 }
590 free(lft);
591 }
592
593 /**
594 * Check and apply lifetimes
595 */
596 static void apply_lifetimes(private_quick_mode_t *this, sa_payload_t *sa_payload)
597 {
598 u_int32_t lifetime;
599 u_int64_t lifebytes;
600
601 lifetime = sa_payload->get_lifetime(sa_payload);
602 lifebytes = sa_payload->get_lifebytes(sa_payload);
603 if (this->lifetime != lifetime)
604 {
605 DBG1(DBG_IKE, "received %us lifetime, configured %us",
606 lifetime, this->lifetime);
607 this->lifetime = lifetime;
608 }
609 if (this->lifebytes != lifebytes)
610 {
611 DBG1(DBG_IKE, "received %llu lifebytes, configured %llu",
612 lifebytes, this->lifebytes);
613 this->lifebytes = lifebytes;
614 }
615 }
616
617 /**
618 * Set the task ready to build notify error message
619 */
620 static status_t send_notify(private_quick_mode_t *this, notify_type_t type)
621 {
622 notify_payload_t *notify;
623
624 notify = notify_payload_create_from_protocol_and_type(NOTIFY_V1,
625 PROTO_ESP, type);
626 notify->set_spi(notify, this->spi_i);
627
628 this->ike_sa->queue_task(this->ike_sa,
629 (task_t*)informational_create(this->ike_sa, notify));
630 /* cancel all active/passive tasks in favour of informational */
631 this->ike_sa->flush_queue(this->ike_sa,
632 this->initiator ? TASK_QUEUE_ACTIVE : TASK_QUEUE_PASSIVE);
633 return ALREADY_DONE;
634 }
635
636 METHOD(task_t, build_i, status_t,
637 private_quick_mode_t *this, message_t *message)
638 {
639 switch (this->state)
640 {
641 case QM_INIT:
642 {
643 enumerator_t *enumerator;
644 sa_payload_t *sa_payload;
645 linked_list_t *list, *tsi, *tsr;
646 proposal_t *proposal;
647 diffie_hellman_group_t group;
648
649 this->udp = this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY);
650 this->mode = this->config->get_mode(this->config);
651 this->child_sa = child_sa_create(
652 this->ike_sa->get_my_host(this->ike_sa),
653 this->ike_sa->get_other_host(this->ike_sa),
654 this->config, this->reqid, this->udp);
655
656 if (this->udp && this->mode == MODE_TRANSPORT)
657 {
658 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
659 add_nat_oa_payloads(this, message);
660 }
661
662 if (this->config->use_ipcomp(this->config))
663 {
664 if (this->udp)
665 {
666 DBG1(DBG_IKE, "IPComp is not supported if either peer is "
667 "natted, IPComp disabled");
668 }
669 else
670 {
671 this->cpi_i = this->child_sa->alloc_cpi(this->child_sa);
672 if (!this->cpi_i)
673 {
674 DBG1(DBG_IKE, "unable to allocate a CPI from kernel, "
675 "IPComp disabled");
676 }
677 }
678 }
679
680 this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
681 if (!this->spi_i)
682 {
683 DBG1(DBG_IKE, "allocating SPI from kernel failed");
684 return FAILED;
685 }
686
687 list = this->config->get_proposals(this->config, FALSE);
688 enumerator = list->create_enumerator(list);
689 while (enumerator->enumerate(enumerator, &proposal))
690 {
691 proposal->set_spi(proposal, this->spi_i);
692 }
693 enumerator->destroy(enumerator);
694
695 get_lifetimes(this);
696 sa_payload = sa_payload_create_from_proposals_v1(list,
697 this->lifetime, this->lifebytes, AUTH_NONE,
698 this->mode, this->udp, this->cpi_i);
699 list->destroy_offset(list, offsetof(proposal_t, destroy));
700 message->add_payload(message, &sa_payload->payload_interface);
701
702 if (!add_nonce(this, &this->nonce_i, message))
703 {
704 return FAILED;
705 }
706
707 group = this->config->get_dh_group(this->config);
708 if (group != MODP_NONE)
709 {
710 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
711 group);
712 if (!this->dh)
713 {
714 DBG1(DBG_IKE, "configured DH group %N not supported",
715 diffie_hellman_group_names, group);
716 return FAILED;
717 }
718 add_ke(this, message);
719 }
720 if (!this->tsi)
721 {
722 this->tsi = select_ts(this, TRUE, NULL);
723 }
724 if (!this->tsr)
725 {
726 this->tsr = select_ts(this, FALSE, NULL);
727 }
728 tsi = linked_list_create();
729 tsr = linked_list_create();
730 tsi->insert_last(tsi, this->tsi);
731 tsr->insert_last(tsr, this->tsr);
732 this->tsi = this->tsr = NULL;
733 charon->bus->narrow(charon->bus, this->child_sa,
734 NARROW_INITIATOR_PRE_AUTH, tsi, tsr);
735 tsi->remove_first(tsi, (void**)&this->tsi);
736 tsr->remove_first(tsr, (void**)&this->tsr);
737 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
738 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
739 if (!this->tsi || !this->tsr)
740 {
741 return FAILED;
742 }
743 add_ts(this, message);
744 return NEED_MORE;
745 }
746 case QM_NEGOTIATED:
747 {
748 return SUCCESS;
749 }
750 default:
751 return FAILED;
752 }
753 }
754
755 /**
756 * Check for notify errors, return TRUE if error found
757 */
758 static bool has_notify_errors(private_quick_mode_t *this, message_t *message)
759 {
760 enumerator_t *enumerator;
761 payload_t *payload;
762 bool err = FALSE;
763
764 enumerator = message->create_payload_enumerator(message);
765 while (enumerator->enumerate(enumerator, &payload))
766 {
767 if (payload->get_type(payload) == NOTIFY_V1)
768 {
769 notify_payload_t *notify;
770 notify_type_t type;
771
772 notify = (notify_payload_t*)payload;
773 type = notify->get_notify_type(notify);
774 if (type < 16384)
775 {
776
777 DBG1(DBG_IKE, "received %N error notify",
778 notify_type_names, type);
779 err = TRUE;
780 }
781 else
782 {
783 DBG1(DBG_IKE, "received %N notify", notify_type_names, type);
784 }
785 }
786 }
787 enumerator->destroy(enumerator);
788
789 return err;
790 }
791
792 /**
793 * Check if this is a rekey for an existing CHILD_SA, reuse reqid if so
794 */
795 static void check_for_rekeyed_child(private_quick_mode_t *this)
796 {
797 enumerator_t *enumerator, *policies;
798 traffic_selector_t *local, *remote;
799 child_sa_t *child_sa;
800
801 enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
802 while (this->reqid == 0 && enumerator->enumerate(enumerator, &child_sa))
803 {
804 if (child_sa->get_state(child_sa) == CHILD_INSTALLED &&
805 streq(child_sa->get_name(child_sa),
806 this->config->get_name(this->config)))
807 {
808 policies = child_sa->create_policy_enumerator(child_sa);
809 if (policies->enumerate(policies, &local, &remote))
810 {
811 if (local->equals(local, this->tsr) &&
812 remote->equals(remote, this->tsi) &&
813 this->proposal->equals(this->proposal,
814 child_sa->get_proposal(child_sa)))
815 {
816 this->reqid = child_sa->get_reqid(child_sa);
817 this->rekey = child_sa->get_spi(child_sa, TRUE);
818 child_sa->set_state(child_sa, CHILD_REKEYING);
819 DBG1(DBG_IKE, "detected rekeying of CHILD_SA %s{%u}",
820 child_sa->get_name(child_sa), this->reqid);
821 }
822 }
823 policies->destroy(policies);
824 }
825 }
826 enumerator->destroy(enumerator);
827 }
828
829 METHOD(task_t, process_r, status_t,
830 private_quick_mode_t *this, message_t *message)
831 {
832 switch (this->state)
833 {
834 case QM_INIT:
835 {
836 sa_payload_t *sa_payload;
837 linked_list_t *tsi, *tsr, *list = NULL;
838 peer_cfg_t *peer_cfg;
839 host_t *me, *other;
840 u_int16_t group;
841 bool private;
842
843 if (!get_ts(this, message))
844 {
845 return FAILED;
846 }
847 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
848 if (!me)
849 {
850 me = this->ike_sa->get_my_host(this->ike_sa);
851 }
852 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
853 if (!other)
854 {
855 other = this->ike_sa->get_other_host(this->ike_sa);
856 }
857 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
858 tsi = linked_list_create();
859 tsr = linked_list_create();
860 tsi->insert_last(tsi, this->tsi);
861 tsr->insert_last(tsr, this->tsr);
862 this->tsi = this->tsr = NULL;
863 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
864 me, other);
865 if (this->config)
866 {
867 this->tsi = select_ts(this, FALSE, tsi);
868 this->tsr = select_ts(this, TRUE, tsr);
869 }
870 tsi->destroy_offset(tsi, offsetof(traffic_selector_t, destroy));
871 tsr->destroy_offset(tsr, offsetof(traffic_selector_t, destroy));
872 if (!this->config || !this->tsi || !this->tsr)
873 {
874 DBG1(DBG_IKE, "no matching CHILD_SA config found");
875 return send_notify(this, INVALID_ID_INFORMATION);
876 }
877
878 sa_payload = (sa_payload_t*)message->get_payload(message,
879 SECURITY_ASSOCIATION_V1);
880 if (!sa_payload)
881 {
882 DBG1(DBG_IKE, "sa payload missing");
883 return send_notify(this, INVALID_PAYLOAD_TYPE);
884 }
885 if (this->config->use_ipcomp(this->config))
886 {
887 if (this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY))
888 {
889 DBG1(DBG_IKE, "IPComp is not supported if either peer is "
890 "natted, IPComp disabled");
891 }
892 else
893 {
894 list = sa_payload->get_ipcomp_proposals(sa_payload,
895 &this->cpi_i);
896 if (!list->get_count(list))
897 {
898 DBG1(DBG_IKE, "expected IPComp proposal but peer did "
899 "not send one, IPComp disabled");
900 this->cpi_i = 0;
901 }
902 }
903 }
904 if (!list || !list->get_count(list))
905 {
906 DESTROY_IF(list);
907 list = sa_payload->get_proposals(sa_payload);
908 }
909 private = this->ike_sa->supports_extension(this->ike_sa,
910 EXT_STRONGSWAN);
911 this->proposal = this->config->select_proposal(this->config,
912 list, FALSE, private);
913 list->destroy_offset(list, offsetof(proposal_t, destroy));
914
915 this->mode = sa_payload->get_encap_mode(sa_payload, &this->udp);
916
917 get_lifetimes(this);
918 apply_lifetimes(this, sa_payload);
919
920 if (!this->proposal)
921 {
922 DBG1(DBG_IKE, "no matching proposal found, sending %N",
923 notify_type_names, NO_PROPOSAL_CHOSEN);
924 return send_notify(this, NO_PROPOSAL_CHOSEN);
925 }
926 this->spi_i = this->proposal->get_spi(this->proposal);
927
928 if (!get_nonce(this, &this->nonce_i, message))
929 {
930 return send_notify(this, INVALID_PAYLOAD_TYPE);
931 }
932
933 if (this->proposal->get_algorithm(this->proposal,
934 DIFFIE_HELLMAN_GROUP, &group, NULL))
935 {
936 this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat,
937 group);
938 if (!this->dh)
939 {
940 DBG1(DBG_IKE, "negotiated DH group %N not supported",
941 diffie_hellman_group_names, group);
942 return send_notify(this, INVALID_KEY_INFORMATION);
943 }
944 if (!get_ke(this, message))
945 {
946 return send_notify(this, INVALID_PAYLOAD_TYPE);
947 }
948 }
949
950 check_for_rekeyed_child(this);
951
952 this->child_sa = child_sa_create(
953 this->ike_sa->get_my_host(this->ike_sa),
954 this->ike_sa->get_other_host(this->ike_sa),
955 this->config, this->reqid, this->udp);
956 return NEED_MORE;
957 }
958 case QM_NEGOTIATED:
959 {
960 if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
961 has_notify_errors(this, message))
962 {
963 return SUCCESS;
964 }
965 if (!install(this))
966 {
967 this->ike_sa->flush_queue(this->ike_sa, TASK_QUEUE_PASSIVE);
968 this->ike_sa->queue_task(this->ike_sa,
969 (task_t*)quick_delete_create(this->ike_sa,
970 this->proposal->get_protocol(this->proposal),
971 this->spi_i, TRUE, TRUE));
972 return ALREADY_DONE;
973 }
974 return SUCCESS;
975 }
976 default:
977 return FAILED;
978 }
979 }
980
981 METHOD(task_t, build_r, status_t,
982 private_quick_mode_t *this, message_t *message)
983 {
984 switch (this->state)
985 {
986 case QM_INIT:
987 {
988 sa_payload_t *sa_payload;
989
990 this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
991 if (!this->spi_r)
992 {
993 DBG1(DBG_IKE, "allocating SPI from kernel failed");
994 return send_notify(this, NO_PROPOSAL_CHOSEN);
995 }
996 this->proposal->set_spi(this->proposal, this->spi_r);
997
998 if (this->cpi_i)
999 {
1000 this->cpi_r = this->child_sa->alloc_cpi(this->child_sa);
1001 if (!this->cpi_r)
1002 {
1003 DBG1(DBG_IKE, "unable to allocate a CPI from "
1004 "kernel, IPComp disabled");
1005 return send_notify(this, NO_PROPOSAL_CHOSEN);
1006 }
1007 }
1008
1009 if (this->udp && this->mode == MODE_TRANSPORT)
1010 {
1011 /* TODO-IKEv1: disable NAT-T for TRANSPORT mode by default? */
1012 add_nat_oa_payloads(this, message);
1013 }
1014
1015 sa_payload = sa_payload_create_from_proposal_v1(this->proposal,
1016 this->lifetime, this->lifebytes, AUTH_NONE,
1017 this->mode, this->udp, this->cpi_r);
1018 message->add_payload(message, &sa_payload->payload_interface);
1019
1020 if (!add_nonce(this, &this->nonce_r, message))
1021 {
1022 return FAILED;
1023 }
1024 if (this->dh)
1025 {
1026 add_ke(this, message);
1027 }
1028
1029 add_ts(this, message);
1030
1031 this->state = QM_NEGOTIATED;
1032 return NEED_MORE;
1033 }
1034 default:
1035 return FAILED;
1036 }
1037 }
1038
1039 METHOD(task_t, process_i, status_t,
1040 private_quick_mode_t *this, message_t *message)
1041 {
1042 switch (this->state)
1043 {
1044 case QM_INIT:
1045 {
1046 sa_payload_t *sa_payload;
1047 linked_list_t *list = NULL;
1048 bool private;
1049
1050 sa_payload = (sa_payload_t*)message->get_payload(message,
1051 SECURITY_ASSOCIATION_V1);
1052 if (!sa_payload)
1053 {
1054 DBG1(DBG_IKE, "sa payload missing");
1055 return send_notify(this, NO_PROPOSAL_CHOSEN);
1056 }
1057 if (this->cpi_i)
1058 {
1059 list = sa_payload->get_ipcomp_proposals(sa_payload,
1060 &this->cpi_r);
1061 if (!list->get_count(list))
1062 {
1063 DBG1(DBG_IKE, "peer did not acccept our IPComp proposal, "
1064 "IPComp disabled");
1065 this->cpi_i = 0;
1066 }
1067 }
1068 if (!list || !list->get_count(list))
1069 {
1070 DESTROY_IF(list);
1071 list = sa_payload->get_proposals(sa_payload);
1072 }
1073 private = this->ike_sa->supports_extension(this->ike_sa,
1074 EXT_STRONGSWAN);
1075 this->proposal = this->config->select_proposal(this->config,
1076 list, FALSE, private);
1077 list->destroy_offset(list, offsetof(proposal_t, destroy));
1078 if (!this->proposal)
1079 {
1080 DBG1(DBG_IKE, "no matching proposal found");
1081 return send_notify(this, NO_PROPOSAL_CHOSEN);
1082 }
1083 this->spi_r = this->proposal->get_spi(this->proposal);
1084
1085 apply_lifetimes(this, sa_payload);
1086
1087 if (!get_nonce(this, &this->nonce_r, message))
1088 {
1089 return send_notify(this, INVALID_PAYLOAD_TYPE);
1090 }
1091 if (this->dh && !get_ke(this, message))
1092 {
1093 return send_notify(this, INVALID_KEY_INFORMATION);
1094 }
1095 if (!get_ts(this, message))
1096 {
1097 return send_notify(this, INVALID_PAYLOAD_TYPE);
1098 }
1099 if (!install(this))
1100 {
1101 return send_notify(this, NO_PROPOSAL_CHOSEN);
1102 }
1103 this->state = QM_NEGOTIATED;
1104 return NEED_MORE;
1105 }
1106 default:
1107 return FAILED;
1108 }
1109 }
1110
1111 METHOD(task_t, get_type, task_type_t,
1112 private_quick_mode_t *this)
1113 {
1114 return TASK_QUICK_MODE;
1115 }
1116
1117 METHOD(quick_mode_t, use_reqid, void,
1118 private_quick_mode_t *this, u_int32_t reqid)
1119 {
1120 this->reqid = reqid;
1121 }
1122
1123 METHOD(quick_mode_t, rekey, void,
1124 private_quick_mode_t *this, u_int32_t spi)
1125 {
1126 this->rekey = spi;
1127 }
1128
1129 METHOD(task_t, migrate, void,
1130 private_quick_mode_t *this, ike_sa_t *ike_sa)
1131 {
1132 chunk_free(&this->nonce_i);
1133 chunk_free(&this->nonce_r);
1134 DESTROY_IF(this->tsi);
1135 DESTROY_IF(this->tsr);
1136 DESTROY_IF(this->proposal);
1137 DESTROY_IF(this->child_sa);
1138 DESTROY_IF(this->dh);
1139
1140 this->ike_sa = ike_sa;
1141 this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
1142 this->state = QM_INIT;
1143 this->tsi = NULL;
1144 this->tsr = NULL;
1145 this->proposal = NULL;
1146 this->child_sa = NULL;
1147 this->dh = NULL;
1148 this->spi_i = 0;
1149 this->spi_r = 0;
1150
1151 if (!this->initiator)
1152 {
1153 DESTROY_IF(this->config);
1154 this->config = NULL;
1155 }
1156 }
1157
1158 METHOD(task_t, destroy, void,
1159 private_quick_mode_t *this)
1160 {
1161 chunk_free(&this->nonce_i);
1162 chunk_free(&this->nonce_r);
1163 DESTROY_IF(this->tsi);
1164 DESTROY_IF(this->tsr);
1165 DESTROY_IF(this->proposal);
1166 DESTROY_IF(this->child_sa);
1167 DESTROY_IF(this->config);
1168 DESTROY_IF(this->dh);
1169 free(this);
1170 }
1171
1172 /*
1173 * Described in header.
1174 */
1175 quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
1176 traffic_selector_t *tsi, traffic_selector_t *tsr)
1177 {
1178 private_quick_mode_t *this;
1179
1180 INIT(this,
1181 .public = {
1182 .task = {
1183 .get_type = _get_type,
1184 .migrate = _migrate,
1185 .destroy = _destroy,
1186 },
1187 .use_reqid = _use_reqid,
1188 .rekey = _rekey,
1189 },
1190 .ike_sa = ike_sa,
1191 .initiator = config != NULL,
1192 .config = config,
1193 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
1194 .state = QM_INIT,
1195 .tsi = tsi ? tsi->clone(tsi) : NULL,
1196 .tsr = tsr ? tsr->clone(tsr) : NULL,
1197 );
1198
1199 if (config)
1200 {
1201 this->public.task.build = _build_i;
1202 this->public.task.process = _process_i;
1203 }
1204 else
1205 {
1206 this->public.task.build = _build_r;
1207 this->public.task.process = _process_r;
1208 }
1209
1210 return &this->public;
1211 }