Add quick mode ID payloads only if establishing a non-host2host tunnel
[strongswan.git] / src / libcharon / sa / 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/keymat_v1.h>
22 #include <encoding/payloads/sa_payload.h>
23 #include <encoding/payloads/nonce_payload.h>
24 #include <encoding/payloads/id_payload.h>
25
26 typedef struct private_quick_mode_t private_quick_mode_t;
27
28 /**
29 * Private members of a quick_mode_t task.
30 */
31 struct private_quick_mode_t {
32
33 /**
34 * Public methods and task_t interface.
35 */
36 quick_mode_t public;
37
38 /**
39 * Assigned IKE_SA.
40 */
41 ike_sa_t *ike_sa;
42
43 /**
44 * TRUE if we are initiating quick mode
45 */
46 bool initiator;
47
48 /**
49 * Traffic selector of initiator
50 */
51 traffic_selector_t *tsi;
52
53 /**
54 * Traffic selector of responder
55 */
56 traffic_selector_t *tsr;
57
58 /**
59 * Initiators nonce
60 */
61 chunk_t nonce_i;
62
63 /**
64 * Responder nonce
65 */
66 chunk_t nonce_r;
67
68 /**
69 * Initiators ESP SPI
70 */
71 u_int32_t spi_i;
72
73 /**
74 * Responder ESP SPI
75 */
76 u_int32_t spi_r;
77
78 /**
79 * selected CHILD_SA proposal
80 */
81 proposal_t *proposal;
82
83 /**
84 * Config of CHILD_SA to establish
85 */
86 child_cfg_t *config;
87
88 /**
89 * CHILD_SA we are about to establish
90 */
91 child_sa_t *child_sa;
92
93 /**
94 * IKEv1 keymat
95 */
96 keymat_v1_t *keymat;
97
98 /** states of quick mode */
99 enum {
100 QM_INIT,
101 QM_NEGOTIATED,
102 } state;
103 };
104
105 /**
106 * Install negotiated CHILD_SA
107 */
108 static bool install(private_quick_mode_t *this)
109 {
110 status_t status, status_i, status_o;
111 chunk_t encr_i, encr_r, integ_i, integ_r;
112 linked_list_t *tsi, *tsr;
113
114 this->child_sa->set_proposal(this->child_sa, this->proposal);
115 this->child_sa->set_state(this->child_sa, CHILD_INSTALLING);
116 this->child_sa->set_mode(this->child_sa, MODE_TUNNEL);
117 this->child_sa->set_protocol(this->child_sa,
118 this->proposal->get_protocol(this->proposal));
119
120 status_i = status_o = FAILED;
121 encr_i = encr_r = integ_i = integ_r = chunk_empty;
122 tsi = linked_list_create();
123 tsr = linked_list_create();
124 tsi->insert_last(tsi, this->tsi);
125 tsr->insert_last(tsr, this->tsr);
126 if (this->keymat->derive_child_keys(this->keymat, this->proposal, NULL,
127 this->spi_i, this->spi_r, this->nonce_i, this->nonce_r,
128 &encr_i, &integ_i, &encr_r, &integ_r))
129 {
130 if (this->initiator)
131 {
132 status_i = this->child_sa->install(this->child_sa, encr_r, integ_r,
133 this->spi_i, 0, TRUE, FALSE, tsi, tsr);
134 status_o = this->child_sa->install(this->child_sa, encr_i, integ_i,
135 this->spi_r, 0, FALSE, FALSE, tsi, tsr);
136 }
137 else
138 {
139 status_i = this->child_sa->install(this->child_sa, encr_i, integ_i,
140 this->spi_r, 0, TRUE, FALSE, tsr, tsi);
141 status_o = this->child_sa->install(this->child_sa, encr_r, integ_r,
142 this->spi_i, 0, FALSE, FALSE, tsr, tsi);
143 }
144 }
145 chunk_clear(&integ_i);
146 chunk_clear(&integ_r);
147 chunk_clear(&encr_i);
148 chunk_clear(&encr_r);
149
150 if (status_i != SUCCESS || status_o != SUCCESS)
151 {
152 DBG1(DBG_IKE, "unable to install %s%s%sIPsec SA (SAD) in kernel",
153 (status_i != SUCCESS) ? "inbound " : "",
154 (status_i != SUCCESS && status_o != SUCCESS) ? "and ": "",
155 (status_o != SUCCESS) ? "outbound " : "");
156 tsi->destroy(tsi);
157 tsr->destroy(tsr);
158 return FALSE;
159 }
160
161 if (this->initiator)
162 {
163 status = this->child_sa->add_policies(this->child_sa, tsi, tsr);
164 }
165 else
166 {
167 status = this->child_sa->add_policies(this->child_sa, tsr, tsi);
168 }
169 tsi->destroy(tsi);
170 tsr->destroy(tsr);
171 if (status != SUCCESS)
172 {
173 DBG1(DBG_IKE, "unable to install IPsec policies (SPD) in kernel");
174 return FALSE;
175 }
176
177 charon->bus->child_keys(charon->bus, this->child_sa, this->initiator,
178 NULL, this->nonce_i, this->nonce_r);
179
180 /* add to IKE_SA, and remove from task */
181 this->child_sa->set_state(this->child_sa, CHILD_INSTALLED);
182 this->ike_sa->add_child_sa(this->ike_sa, this->child_sa);
183
184 DBG0(DBG_IKE, "CHILD_SA %s{%d} established "
185 "with SPIs %.8x_i %.8x_o and TS %#R=== %#R",
186 this->child_sa->get_name(this->child_sa),
187 this->child_sa->get_reqid(this->child_sa),
188 ntohl(this->child_sa->get_spi(this->child_sa, TRUE)),
189 ntohl(this->child_sa->get_spi(this->child_sa, FALSE)),
190 this->child_sa->get_traffic_selectors(this->child_sa, TRUE),
191 this->child_sa->get_traffic_selectors(this->child_sa, FALSE));
192
193 charon->bus->child_updown(charon->bus, this->child_sa, TRUE);
194
195 this->child_sa = NULL;
196
197 return TRUE;
198 }
199
200 /**
201 * Generate and add NONCE
202 */
203 static bool add_nonce(private_quick_mode_t *this, chunk_t *nonce,
204 message_t *message)
205 {
206 nonce_payload_t *nonce_payload;
207 rng_t *rng;
208
209 rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
210 if (!rng)
211 {
212 DBG1(DBG_IKE, "no RNG found to create nonce");
213 return FALSE;
214 }
215 rng->allocate_bytes(rng, NONCE_SIZE, nonce);
216 rng->destroy(rng);
217
218 nonce_payload = nonce_payload_create(NONCE_V1);
219 nonce_payload->set_nonce(nonce_payload, *nonce);
220 message->add_payload(message, &nonce_payload->payload_interface);
221
222 return TRUE;
223 }
224
225 /**
226 * Extract nonce from NONCE payload
227 */
228 static bool get_nonce(private_quick_mode_t *this, chunk_t *nonce,
229 message_t *message)
230 {
231 nonce_payload_t *nonce_payload;
232
233 nonce_payload = (nonce_payload_t*)message->get_payload(message, NONCE_V1);
234 if (!nonce_payload)
235 {
236 DBG1(DBG_IKE, "NONCE payload missing in message");
237 return FALSE;
238 }
239 *nonce = nonce_payload->get_nonce(nonce_payload);
240
241 return TRUE;
242 }
243
244 /**
245 * Select a traffic selector from configuration
246 */
247 static traffic_selector_t* select_ts(private_quick_mode_t *this, bool initiator)
248 {
249 traffic_selector_t *ts;
250 linked_list_t *list;
251 host_t *host;
252
253 if (initiator)
254 {
255 host = this->ike_sa->get_my_host(this->ike_sa);
256 }
257 else
258 {
259 host = this->ike_sa->get_other_host(this->ike_sa);
260 }
261 list = this->config->get_traffic_selectors(this->config, initiator,
262 NULL, host);
263 if (list->get_first(list, (void**)&ts) == SUCCESS)
264 {
265 if (list->get_count(list) > 1)
266 {
267 DBG1(DBG_IKE, "configuration has more than one %s traffic selector,"
268 " using first IKEv1", initiator ? "initiator" : "responder");
269 }
270 ts = ts->clone(ts);
271 }
272 else
273 {
274 DBG1(DBG_IKE, "%s traffic selector missing in configuration",
275 initiator ? "initiator" : "responder");
276 ts = NULL;
277 }
278 list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
279 return ts;
280 }
281
282 /**
283 * Add selected traffic selectors to message
284 */
285 static void add_ts(private_quick_mode_t *this, message_t *message,
286 bool initiator)
287 {
288 id_payload_t *id_payload;
289 host_t *hsi, *hsr;
290
291 if (initiator)
292 {
293 hsi = this->ike_sa->get_my_host(this->ike_sa);
294 hsr = this->ike_sa->get_other_host(this->ike_sa);
295 }
296 else
297 {
298 hsr = this->ike_sa->get_my_host(this->ike_sa);
299 hsi = this->ike_sa->get_other_host(this->ike_sa);
300 }
301 /* add ID payload only if negotiating non host2host tunnels */
302 if (!this->tsi->is_host(this->tsi, hsi) ||
303 !this->tsr->is_host(this->tsr, hsr) ||
304 this->tsi->get_protocol(this->tsi) ||
305 this->tsr->get_protocol(this->tsr) ||
306 this->tsi->get_from_port(this->tsi) ||
307 this->tsr->get_from_port(this->tsr) ||
308 this->tsi->get_to_port(this->tsi) != 65535 ||
309 this->tsr->get_to_port(this->tsr) != 65535)
310 {
311 id_payload = id_payload_create_from_ts(this->tsi);
312 message->add_payload(message, &id_payload->payload_interface);
313 id_payload = id_payload_create_from_ts(this->tsr);
314 message->add_payload(message, &id_payload->payload_interface);
315 }
316 }
317
318 /**
319 * Get traffic selectors from received message
320 */
321 static bool get_ts(private_quick_mode_t *this, message_t *message,
322 bool initiator)
323 {
324 traffic_selector_t *tsi = NULL, *tsr = NULL;
325 enumerator_t *enumerator;
326 id_payload_t *id_payload;
327 payload_t *payload;
328 host_t *hsi, *hsr;
329 bool first = TRUE;
330
331 enumerator = message->create_payload_enumerator(message);
332 while (enumerator->enumerate(enumerator, &payload))
333 {
334 if (payload->get_type(payload) == ID_V1)
335 {
336 id_payload = (id_payload_t*)payload;
337
338 if (first)
339 {
340 tsi = id_payload->get_ts(id_payload);
341 first = FALSE;
342 }
343 else
344 {
345 tsr = id_payload->get_ts(id_payload);
346 break;
347 }
348 }
349 }
350 enumerator->destroy(enumerator);
351
352 /* create host2host selectors if ID payloads missing */
353 if (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 if (!tsi)
364 {
365 tsi = traffic_selector_create_from_subnet(hsi->clone(hsi),
366 hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0);
367 }
368 if (!tsr)
369 {
370 tsr = traffic_selector_create_from_subnet(hsr->clone(hsr),
371 hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0);
372 }
373 if (initiator)
374 {
375 /* check if peer selection valid */
376 if (!tsr->is_contained_in(tsr, this->tsr) ||
377 !tsi->is_contained_in(tsi, this->tsi))
378 {
379 DBG1(DBG_IKE, "peer selected invalid traffic selectors: ",
380 "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr);
381 tsi->destroy(tsi);
382 tsr->destroy(tsr);
383 return FALSE;
384 }
385 this->tsi->destroy(this->tsi);
386 this->tsr->destroy(this->tsr);
387 this->tsi = tsi;
388 this->tsr = tsr;
389 }
390 else
391 {
392 this->tsi = tsi;
393 this->tsr = tsr;
394 }
395 return TRUE;
396 }
397
398 METHOD(task_t, build_i, status_t,
399 private_quick_mode_t *this, message_t *message)
400 {
401 switch (this->state)
402 {
403 case QM_INIT:
404 {
405 enumerator_t *enumerator;
406 sa_payload_t *sa_payload;
407 linked_list_t *list;
408 proposal_t *proposal;
409
410 this->child_sa = child_sa_create(
411 this->ike_sa->get_my_host(this->ike_sa),
412 this->ike_sa->get_other_host(this->ike_sa),
413 this->config, 0, FALSE);
414
415 list = this->config->get_proposals(this->config, TRUE);
416
417 this->spi_i = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
418 if (!this->spi_i)
419 {
420 DBG1(DBG_IKE, "allocating SPI from kernel failed");
421 return FAILED;
422 }
423 enumerator = list->create_enumerator(list);
424 while (enumerator->enumerate(enumerator, &proposal))
425 {
426 proposal->set_spi(proposal, this->spi_i);
427 }
428 enumerator->destroy(enumerator);
429
430 sa_payload = sa_payload_create_from_proposal_list(
431 SECURITY_ASSOCIATION_V1, list);
432 list->destroy_offset(list, offsetof(proposal_t, destroy));
433 message->add_payload(message, &sa_payload->payload_interface);
434
435 if (!add_nonce(this, &this->nonce_i, message))
436 {
437 return FAILED;
438 }
439 this->tsi = select_ts(this, TRUE);
440 this->tsr = select_ts(this, FALSE);
441 if (!this->tsi || !this->tsr)
442 {
443 return FAILED;
444 }
445 add_ts(this, message, TRUE);
446 return NEED_MORE;
447 }
448 case QM_NEGOTIATED:
449 {
450 return SUCCESS;
451 }
452 default:
453 return FAILED;
454 }
455 }
456
457 METHOD(task_t, process_r, status_t,
458 private_quick_mode_t *this, message_t *message)
459 {
460 switch (this->state)
461 {
462 case QM_INIT:
463 {
464 sa_payload_t *sa_payload;
465 linked_list_t *tsi, *tsr, *list;
466 peer_cfg_t *peer_cfg;
467 host_t *me, *other;
468
469 if (!get_ts(this, message, FALSE))
470 {
471 return FAILED;
472 }
473 me = this->ike_sa->get_virtual_ip(this->ike_sa, TRUE);
474 if (!me)
475 {
476 me = this->ike_sa->get_my_host(this->ike_sa);
477 }
478 other = this->ike_sa->get_virtual_ip(this->ike_sa, FALSE);
479 if (!other)
480 {
481 other = this->ike_sa->get_other_host(this->ike_sa);
482 }
483 peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
484 tsi = linked_list_create();
485 tsr = linked_list_create();
486 tsi->insert_last(tsi, this->tsi);
487 tsr->insert_last(tsr, this->tsr);
488 this->config = peer_cfg->select_child_cfg(peer_cfg, tsr, tsi,
489 me, other);
490 tsi->destroy(tsi);
491 tsr->destroy(tsr);
492 if (!this->config)
493 {
494 DBG1(DBG_IKE, "no child config found");
495 return FAILED;
496 }
497
498 sa_payload = (sa_payload_t*)message->get_payload(message,
499 SECURITY_ASSOCIATION_V1);
500 if (!sa_payload)
501 {
502 DBG1(DBG_IKE, "sa payload missing");
503 return FAILED;
504 }
505 list = sa_payload->get_proposals(sa_payload);
506 this->proposal = this->config->select_proposal(this->config,
507 list, TRUE, FALSE);
508 list->destroy_offset(list, offsetof(proposal_t, destroy));
509 if (!this->proposal)
510 {
511 DBG1(DBG_IKE, "no matching proposal found");
512 return FAILED;
513 }
514 this->spi_i = this->proposal->get_spi(this->proposal);
515
516 if (!get_nonce(this, &this->nonce_i, message))
517 {
518 return FAILED;
519 }
520 this->child_sa = child_sa_create(
521 this->ike_sa->get_my_host(this->ike_sa),
522 this->ike_sa->get_other_host(this->ike_sa),
523 this->config, 0, FALSE);
524 return NEED_MORE;
525 }
526 case QM_NEGOTIATED:
527 {
528 if (!install(this))
529 {
530 return FAILED;
531 }
532 return SUCCESS;
533 }
534 default:
535 return FAILED;
536 }
537 }
538
539 METHOD(task_t, build_r, status_t,
540 private_quick_mode_t *this, message_t *message)
541 {
542 switch (this->state)
543 {
544 case QM_INIT:
545 {
546 sa_payload_t *sa_payload;
547
548 this->spi_r = this->child_sa->alloc_spi(this->child_sa, PROTO_ESP);
549 if (!this->spi_r)
550 {
551 DBG1(DBG_IKE, "allocating SPI from kernel failed");
552 return FAILED;
553 }
554 this->proposal->set_spi(this->proposal, this->spi_r);
555
556 sa_payload = sa_payload_create_from_proposal(
557 SECURITY_ASSOCIATION_V1, this->proposal);
558 message->add_payload(message, &sa_payload->payload_interface);
559
560 if (!add_nonce(this, &this->nonce_r, message))
561 {
562 return FAILED;
563 }
564 add_ts(this, message, FALSE);
565
566 this->state = QM_NEGOTIATED;
567 return NEED_MORE;
568 }
569 default:
570 return FAILED;
571 }
572 }
573
574 METHOD(task_t, process_i, status_t,
575 private_quick_mode_t *this, message_t *message)
576 {
577 switch (this->state)
578 {
579 case QM_INIT:
580 {
581 sa_payload_t *sa_payload;
582 linked_list_t *list;
583
584 sa_payload = (sa_payload_t*)message->get_payload(message,
585 SECURITY_ASSOCIATION_V1);
586 if (!sa_payload)
587 {
588 DBG1(DBG_IKE, "sa payload missing");
589 return FAILED;
590 }
591 list = sa_payload->get_proposals(sa_payload);
592 this->proposal = this->config->select_proposal(this->config,
593 list, TRUE, FALSE);
594 list->destroy_offset(list, offsetof(proposal_t, destroy));
595 if (!this->proposal)
596 {
597 DBG1(DBG_IKE, "no matching proposal found");
598 return FAILED;
599 }
600 this->spi_r = this->proposal->get_spi(this->proposal);
601
602 if (!get_nonce(this, &this->nonce_r, message))
603 {
604 return FAILED;
605 }
606 if (!get_ts(this, message, TRUE))
607 {
608 return FAILED;
609 }
610 if (!install(this))
611 {
612 return FAILED;
613 }
614 this->state = QM_NEGOTIATED;
615 return NEED_MORE;
616 }
617 default:
618 return FAILED;
619 }
620 }
621
622 METHOD(task_t, get_type, task_type_t,
623 private_quick_mode_t *this)
624 {
625 return TASK_QUICK_MODE;
626 }
627
628 METHOD(task_t, migrate, void,
629 private_quick_mode_t *this, ike_sa_t *ike_sa)
630 {
631 this->ike_sa = ike_sa;
632 }
633
634 METHOD(task_t, destroy, void,
635 private_quick_mode_t *this)
636 {
637 chunk_free(&this->nonce_i);
638 chunk_free(&this->nonce_r);
639 DESTROY_IF(this->tsi);
640 DESTROY_IF(this->tsr);
641 DESTROY_IF(this->proposal);
642 DESTROY_IF(this->child_sa);
643 DESTROY_IF(this->config);
644 free(this);
645 }
646
647 /*
648 * Described in header.
649 */
650 quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
651 traffic_selector_t *tsi, traffic_selector_t *tsr)
652 {
653 private_quick_mode_t *this;
654
655 INIT(this,
656 .public = {
657 .task = {
658 .get_type = _get_type,
659 .migrate = _migrate,
660 .destroy = _destroy,
661 },
662 },
663 .ike_sa = ike_sa,
664 .initiator = config != NULL,
665 .config = config,
666 .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
667 .state = QM_INIT,
668 );
669
670 if (config)
671 {
672 this->public.task.build = _build_i;
673 this->public.task.process = _process_i;
674 }
675 else
676 {
677 this->public.task.build = _build_r;
678 this->public.task.process = _process_r;
679 }
680
681 return &this->public;
682 }