]> git.ipfire.org Git - thirdparty/strongswan.git/blame_incremental - src/libcharon/plugins/ha/ha_dispatcher.c
nm: Don't set DL_LIBS to 'none required' in configure script
[thirdparty/strongswan.git] / src / libcharon / plugins / ha / ha_dispatcher.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2016-2024 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 *
5 * Copyright (C) secunet Security Networks AG
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18#include "ha_dispatcher.h"
19
20#include <daemon.h>
21#include <sa/ikev2/keymat_v2.h>
22#include <sa/ikev1/keymat_v1.h>
23#include <processing/jobs/callback_job.h>
24#include <processing/jobs/adopt_children_job.h>
25
26typedef struct private_ha_dispatcher_t private_ha_dispatcher_t;
27typedef struct ha_key_exchange_t ha_key_exchange_t;
28
29/**
30 * Private data of an ha_dispatcher_t object.
31 */
32struct private_ha_dispatcher_t {
33
34 /**
35 * Public ha_dispatcher_t interface.
36 */
37 ha_dispatcher_t public;
38
39 /**
40 * socket to pull messages from
41 */
42 ha_socket_t *socket;
43
44 /**
45 * segments to control
46 */
47 ha_segments_t *segments;
48
49 /**
50 * Cache for resync
51 */
52 ha_cache_t *cache;
53
54 /**
55 * Kernel helper
56 */
57 ha_kernel_t *kernel;
58
59 /**
60 * HA enabled pool
61 */
62 ha_attribute_t *attr;
63};
64
65/**
66 * KE implementation for HA synced KE shared secrets
67 */
68struct ha_key_exchange_t {
69
70 /**
71 * Public interface
72 */
73 key_exchange_t ke;
74
75 /**
76 * Shared secret
77 */
78 chunk_t secret;
79
80 /**
81 * Own public value (IKEv1 only)
82 */
83 chunk_t pub;
84};
85
86METHOD(key_exchange_t, ke_get_shared_secret, bool,
87 ha_key_exchange_t *this, chunk_t *secret)
88{
89 *secret = chunk_clone(this->secret);
90 return TRUE;
91}
92
93METHOD(key_exchange_t, ke_get_public_key, bool,
94 ha_key_exchange_t *this, chunk_t *value)
95{
96 *value = chunk_clone(this->pub);
97 return TRUE;
98}
99
100METHOD(key_exchange_t, ke_destroy, void,
101 ha_key_exchange_t *this)
102{
103 free(this);
104}
105
106/**
107 * Create a HA synced KE implementation
108 */
109static key_exchange_t *ha_key_exchange_create(chunk_t secret, chunk_t pub)
110{
111 ha_key_exchange_t *this;
112
113 INIT(this,
114 .ke = {
115 .get_shared_secret = _ke_get_shared_secret,
116 .get_public_key = _ke_get_public_key,
117 .destroy = _ke_destroy,
118 },
119 .secret = secret,
120 .pub = pub,
121 );
122
123 return &this->ke;
124}
125
126/**
127 * Add the given KE methods to a proposal
128 */
129static void add_ke_methods_to_proposal(proposal_t *proposal, uint16_t ke_alg,
130 chunk_t add_kes)
131{
132 int i, count;
133
134 if (ke_alg)
135 {
136 proposal->add_algorithm(proposal, KEY_EXCHANGE_METHOD, ke_alg, 0);
137 }
138 count = min(add_kes.len / sizeof(uint16_t), MAX_ADDITIONAL_KEY_EXCHANGES);
139 for (i = 0; i < count; i++)
140 {
141 ke_alg = ntohs(((uint16_t*)add_kes.ptr)[i]);
142 if (ke_alg)
143 {
144 proposal->add_algorithm(proposal, i + ADDITIONAL_KEY_EXCHANGE_1,
145 ke_alg, 0);
146 }
147 }
148}
149
150/**
151 * Process messages of type IKE_ADD
152 */
153static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message)
154{
155 ha_message_attribute_t attribute;
156 ha_message_value_t value;
157 enumerator_t *enumerator;
158 ike_sa_t *ike_sa = NULL, *old_sa = NULL;
159 ike_version_t version = IKEV2;
160 uint16_t encr = 0, len = 0, integ = 0, prf = 0, old_prf = PRF_UNDEFINED;
161 uint16_t ke_alg = 0;
162 chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
163 chunk_t secret = chunk_empty, old_skd = chunk_empty;
164 chunk_t add_secret = chunk_empty, add_kes = chunk_empty;
165 chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty;
166 host_t *other = NULL;
167 bool ok = FALSE;
168 auth_method_t method = AUTH_RSA;
169
170 enumerator = message->create_attribute_enumerator(message);
171 while (enumerator->enumerate(enumerator, &attribute, &value))
172 {
173 switch (attribute)
174 {
175 case HA_IKE_ID:
176 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
177 value.ike_sa_id);
178 if (!ike_sa)
179 {
180 ike_sa = ike_sa_create(value.ike_sa_id,
181 value.ike_sa_id->is_initiator(value.ike_sa_id), version);
182 }
183 break;
184 case HA_IKE_REKEY_ID:
185 old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
186 value.ike_sa_id);
187 break;
188 case HA_REMOTE_ADDR:
189 other = value.host->clone(value.host);
190 break;
191 case HA_IKE_VERSION:
192 version = value.u8;
193 break;
194 case HA_NONCE_I:
195 nonce_i = value.chunk;
196 break;
197 case HA_NONCE_R:
198 nonce_r = value.chunk;
199 break;
200 case HA_SECRET:
201 secret = value.chunk;
202 break;
203 case HA_ADD_SECRET:
204 add_secret = value.chunk;
205 break;
206 case HA_LOCAL_DH:
207 dh_local = value.chunk;
208 break;
209 case HA_REMOTE_DH:
210 dh_remote = value.chunk;
211 break;
212 case HA_PSK:
213 psk = value.chunk;
214 break;
215 case HA_OLD_SKD:
216 old_skd = value.chunk;
217 break;
218 case HA_ALG_ENCR:
219 encr = value.u16;
220 break;
221 case HA_ALG_ENCR_LEN:
222 len = value.u16;
223 break;
224 case HA_ALG_INTEG:
225 integ = value.u16;
226 break;
227 case HA_ALG_PRF:
228 prf = value.u16;
229 break;
230 case HA_ALG_OLD_PRF:
231 old_prf = value.u16;
232 break;
233 case HA_ALG_KE:
234 ke_alg = value.u16;
235 break;
236 case HA_ALG_ADD_KES:
237 add_kes = value.chunk;
238 break;
239 case HA_AUTH_METHOD:
240 method = value.u16;
241 break;
242 default:
243 break;
244 }
245 }
246 enumerator->destroy(enumerator);
247
248 if (ike_sa)
249 {
250 proposal_t *proposal;
251 key_exchange_t *ke;
252 array_t *kes = NULL;
253 bool key_update = FALSE;
254
255 proposal = ike_sa->get_proposal(ike_sa);
256 if (!proposal)
257 {
258 proposal = proposal_create(PROTO_IKE, 0);
259 if (integ)
260 {
261 proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
262 }
263 if (encr)
264 {
265 proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
266 }
267 if (prf)
268 {
269 proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, prf, 0);
270 }
271 add_ke_methods_to_proposal(proposal, ke_alg, add_kes);
272 }
273 else
274 {
275 key_update = TRUE;
276 }
277 charon->bus->set_sa(charon->bus, ike_sa);
278 ke = ha_key_exchange_create(secret, dh_local);
279 array_insert_create(&kes, ARRAY_HEAD, ke);
280 if (ike_sa->get_version(ike_sa) == IKEV2)
281 {
282 keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
283
284 if (add_secret.len)
285 {
286 ke = ha_key_exchange_create(add_secret, chunk_empty);
287 array_insert_create(&kes, ARRAY_TAIL, ke);
288 }
289 if (key_update)
290 {
291 old_prf = keymat_v2->get_skd(keymat_v2, &old_skd);
292 }
293 ok = keymat_v2->derive_ike_keys(keymat_v2, proposal, kes, nonce_i,
294 nonce_r, ike_sa->get_id(ike_sa), old_prf, old_skd);
295 }
296 else if (ike_sa->get_version(ike_sa) == IKEV1)
297 {
298 keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
299 shared_key_t *shared = NULL;
300
301 if (psk.len)
302 {
303 method = AUTH_PSK;
304 shared = shared_key_create(SHARED_IKE, chunk_clone(psk));
305 }
306 if (keymat_v1->create_hasher(keymat_v1, proposal))
307 {
308 ok = keymat_v1->derive_ike_keys(keymat_v1, proposal,
309 ke, dh_remote, nonce_i, nonce_r,
310 ike_sa->get_id(ike_sa), method, shared);
311 }
312 DESTROY_IF(shared);
313 }
314 array_destroy_offset(kes, offsetof(key_exchange_t, destroy));
315 if (ok)
316 {
317 if (old_sa)
318 { /* register IKE_SA before calling inherit_post() so no scheduled
319 * jobs are lost */
320 charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
321 ike_sa);
322 ike_sa->inherit_pre(ike_sa, old_sa);
323 ike_sa->inherit_post(ike_sa, old_sa);
324 charon->ike_sa_manager->checkin_and_destroy(
325 charon->ike_sa_manager, old_sa);
326 old_sa = NULL;
327 }
328 if (other)
329 {
330 ike_sa->set_other_host(ike_sa, other);
331 other = NULL;
332 }
333 if (!key_update)
334 {
335 ike_sa->set_state(ike_sa, IKE_CONNECTING);
336 ike_sa->set_proposal(ike_sa, proposal);
337 }
338 this->cache->cache(this->cache, ike_sa, message);
339 message = NULL;
340 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
341 }
342 else
343 {
344 DBG1(DBG_IKE, "HA keymat derivation failed");
345 if (key_update)
346 {
347 charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
348 ike_sa);
349 }
350 else
351 {
352 ike_sa->destroy(ike_sa);
353 charon->bus->set_sa(charon->bus, NULL);
354 }
355 }
356 if (!key_update)
357 {
358 proposal->destroy(proposal);
359 }
360 }
361 if (old_sa)
362 {
363 charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa);
364 }
365 DESTROY_IF(other);
366 DESTROY_IF(message);
367}
368
369/**
370 * Apply all set conditions to the IKE_SA
371 */
372static void set_conditions(ike_sa_t *ike_sa, ike_condition_t conditions)
373{
374 ike_condition_t i, private = (conditions & COND_PRIVATE_MARKER);
375
376 for (i = 0; i < (sizeof(i) * 8) - 1; ++i)
377 {
378 ike_condition_t cond = (1 << i) | private;
379
380 ike_sa->set_condition(ike_sa, cond, (conditions & cond) == cond);
381 }
382}
383
384/**
385 * Apply all enabled extensions to the IKE_SA
386 */
387static void set_extensions(ike_sa_t *ike_sa, ike_extension_t extensions)
388{
389 ike_extension_t i, private = (extensions & EXT_PRIVATE_MARKER);
390
391 for (i = 0; i < (sizeof(i) * 8) - 1; ++i)
392 {
393 ike_extension_t ext = (1 << i) | private;
394
395 if ((extensions & ext) == ext)
396 {
397 ike_sa->enable_extension(ike_sa, ext);
398 }
399 }
400}
401
402/**
403 * Process messages of type IKE_UPDATE
404 */
405static void process_ike_update(private_ha_dispatcher_t *this,
406 ha_message_t *message)
407{
408 ha_message_attribute_t attribute;
409 ha_message_value_t value;
410 enumerator_t *enumerator;
411 ike_sa_t *ike_sa = NULL;
412 peer_cfg_t *peer_cfg = NULL;
413 auth_cfg_t *auth;
414 bool received_vip = FALSE, first_local_vip = TRUE, first_peer_addr = TRUE;
415
416 enumerator = message->create_attribute_enumerator(message);
417 while (enumerator->enumerate(enumerator, &attribute, &value))
418 {
419 if (attribute != HA_IKE_ID && ike_sa == NULL)
420 {
421 /* must be first attribute */
422 break;
423 }
424 switch (attribute)
425 {
426 case HA_IKE_ID:
427 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
428 value.ike_sa_id);
429 break;
430 case HA_LOCAL_ID:
431 ike_sa->set_my_id(ike_sa, value.id->clone(value.id));
432 break;
433 case HA_REMOTE_ID:
434 ike_sa->set_other_id(ike_sa, value.id->clone(value.id));
435 break;
436 case HA_REMOTE_EAP_ID:
437 auth = auth_cfg_create();
438 auth->add(auth, AUTH_RULE_EAP_IDENTITY, value.id->clone(value.id));
439 ike_sa->add_auth_cfg(ike_sa, FALSE, auth);
440 break;
441 case HA_LOCAL_ADDR:
442 ike_sa->set_my_host(ike_sa, value.host->clone(value.host));
443 break;
444 case HA_REMOTE_ADDR:
445 ike_sa->set_other_host(ike_sa, value.host->clone(value.host));
446 break;
447 case HA_LOCAL_VIP:
448 if (first_local_vip)
449 {
450 ike_sa->clear_virtual_ips(ike_sa, TRUE);
451 first_local_vip = FALSE;
452 }
453 ike_sa->add_virtual_ip(ike_sa, TRUE, value.host);
454 break;
455 case HA_REMOTE_VIP:
456 if (!received_vip)
457 {
458 ike_sa->clear_virtual_ips(ike_sa, FALSE);
459 }
460 ike_sa->add_virtual_ip(ike_sa, FALSE, value.host);
461 received_vip = TRUE;
462 break;
463 case HA_PEER_ADDR:
464 if (first_peer_addr)
465 {
466 ike_sa->clear_peer_addresses(ike_sa);
467 first_peer_addr = FALSE;
468 }
469 ike_sa->add_peer_address(ike_sa, value.host->clone(value.host));
470 break;
471 case HA_CONFIG_NAME:
472 peer_cfg = charon->backends->get_peer_cfg_by_name(
473 charon->backends, value.str);
474 if (peer_cfg)
475 {
476 ike_sa->set_peer_cfg(ike_sa, peer_cfg);
477 peer_cfg->destroy(peer_cfg);
478 }
479 else
480 {
481 DBG1(DBG_IKE, "HA is missing nodes peer configuration");
482 charon->ike_sa_manager->checkin_and_destroy(
483 charon->ike_sa_manager, ike_sa);
484 ike_sa = NULL;
485 }
486 break;
487 case HA_EXTENSIONS:
488 set_extensions(ike_sa, value.u32);
489 break;
490 case HA_CONDITIONS:
491 set_conditions(ike_sa, value.u32);
492 break;
493 default:
494 break;
495 }
496 }
497 enumerator->destroy(enumerator);
498
499 if (ike_sa)
500 {
501 if (ike_sa->get_state(ike_sa) == IKE_CONNECTING &&
502 ike_sa->get_peer_cfg(ike_sa))
503 {
504 DBG1(DBG_CFG, "installed HA passive IKE_SA '%s' %H[%Y]...%H[%Y]",
505 ike_sa->get_name(ike_sa),
506 ike_sa->get_my_host(ike_sa), ike_sa->get_my_id(ike_sa),
507 ike_sa->get_other_host(ike_sa), ike_sa->get_other_id(ike_sa));
508 ike_sa->set_state(ike_sa, IKE_PASSIVE);
509 }
510 if (received_vip)
511 {
512 enumerator_t *pools, *vips;
513 host_t *vip;
514 char *pool;
515
516 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
517 if (peer_cfg)
518 {
519 pools = peer_cfg->create_pool_enumerator(peer_cfg);
520 while (pools->enumerate(pools, &pool))
521 {
522 vips = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE);
523 while (vips->enumerate(vips, &vip))
524 {
525 this->attr->reserve(this->attr, pool, vip);
526 }
527 vips->destroy(vips);
528 }
529 pools->destroy(pools);
530 }
531 }
532#ifdef USE_IKEV1
533 if (ike_sa->get_version(ike_sa) == IKEV1)
534 {
535 lib->processor->queue_job(lib->processor, (job_t*)
536 adopt_children_job_create(ike_sa->get_id(ike_sa)));
537 }
538#endif /* USE_IKEV1 */
539 this->cache->cache(this->cache, ike_sa, message);
540 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
541 }
542 else
543 {
544 DBG1(DBG_CFG, "passive HA IKE_SA to update not found");
545 message->destroy(message);
546 }
547}
548
549/**
550 * Process messages of type IKE_MID_INITIATOR/RESPONDER
551 */
552static void process_ike_mid(private_ha_dispatcher_t *this,
553 ha_message_t *message, bool initiator)
554{
555 ha_message_attribute_t attribute;
556 ha_message_value_t value;
557 enumerator_t *enumerator;
558 ike_sa_t *ike_sa = NULL;
559 uint32_t mid = 0;
560
561 enumerator = message->create_attribute_enumerator(message);
562 while (enumerator->enumerate(enumerator, &attribute, &value))
563 {
564 switch (attribute)
565 {
566 case HA_IKE_ID:
567 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
568 value.ike_sa_id);
569 break;
570 case HA_MID:
571 mid = value.u32;
572 break;
573 default:
574 break;
575 }
576 }
577 enumerator->destroy(enumerator);
578
579 if (ike_sa)
580 {
581 if (mid)
582 {
583 ike_sa->set_message_id(ike_sa, initiator, mid);
584 }
585 this->cache->cache(this->cache, ike_sa, message);
586 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
587 }
588 else
589 {
590 message->destroy(message);
591 }
592}
593
594/**
595 * Process messages of type IKE_IV
596 */
597static void process_ike_iv(private_ha_dispatcher_t *this, ha_message_t *message)
598{
599 ha_message_attribute_t attribute;
600 ha_message_value_t value;
601 enumerator_t *enumerator;
602 ike_sa_t *ike_sa = NULL;
603 chunk_t iv = chunk_empty;
604
605 enumerator = message->create_attribute_enumerator(message);
606 while (enumerator->enumerate(enumerator, &attribute, &value))
607 {
608 switch (attribute)
609 {
610 case HA_IKE_ID:
611 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
612 value.ike_sa_id);
613 break;
614 case HA_IV:
615 iv = value.chunk;
616 break;
617 default:
618 break;
619 }
620 }
621 enumerator->destroy(enumerator);
622
623 if (ike_sa)
624 {
625 if (ike_sa->get_version(ike_sa) == IKEV1)
626 {
627 if (iv.len)
628 {
629 keymat_v1_t *keymat;
630
631 keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
632 if (keymat->update_iv(keymat, 0, iv))
633 {
634 keymat->confirm_iv(keymat, 0);
635 }
636 }
637 }
638 this->cache->cache(this->cache, ike_sa, message);
639 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
640 }
641 else
642 {
643 message->destroy(message);
644 }
645}
646
647/**
648 * Process messages of type IKE_DELETE
649 */
650static void process_ike_delete(private_ha_dispatcher_t *this,
651 ha_message_t *message)
652{
653 ha_message_attribute_t attribute;
654 ha_message_value_t value;
655 enumerator_t *enumerator;
656 ike_sa_t *ike_sa = NULL;
657
658 enumerator = message->create_attribute_enumerator(message);
659 while (enumerator->enumerate(enumerator, &attribute, &value))
660 {
661 switch (attribute)
662 {
663 case HA_IKE_ID:
664 ike_sa = charon->ike_sa_manager->checkout(
665 charon->ike_sa_manager, value.ike_sa_id);
666 break;
667 default:
668 break;
669 }
670 }
671 enumerator->destroy(enumerator);
672 if (ike_sa)
673 {
674 this->cache->cache(this->cache, ike_sa, message);
675 charon->ike_sa_manager->checkin_and_destroy(
676 charon->ike_sa_manager, ike_sa);
677 }
678 else
679 {
680 message->destroy(message);
681 }
682}
683
684/**
685 * Lookup a child cfg from the peer cfg by name
686 */
687static child_cfg_t* find_child_cfg(ike_sa_t *ike_sa, char *name)
688{
689 peer_cfg_t *peer_cfg;
690 child_cfg_t *current, *found = NULL;
691 enumerator_t *enumerator;
692
693 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
694 if (peer_cfg)
695 {
696 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
697 while (enumerator->enumerate(enumerator, &current))
698 {
699 if (streq(current->get_name(current), name))
700 {
701 found = current;
702 break;
703 }
704 }
705 enumerator->destroy(enumerator);
706 }
707 return found;
708}
709
710/**
711 * Process messages of type CHILD_ADD
712 */
713static void process_child_add(private_ha_dispatcher_t *this,
714 ha_message_t *message)
715{
716 ha_message_attribute_t attribute;
717 ha_message_value_t value;
718 enumerator_t *enumerator;
719 ike_sa_t *ike_sa = NULL;
720 char *config_name = "";
721 child_cfg_t *config = NULL;
722 child_sa_t *child_sa;
723 proposal_t *proposal;
724 bool initiator = FALSE, failed = FALSE, ok = FALSE;
725 uint32_t inbound_spi = 0, outbound_spi = 0;
726 uint16_t inbound_cpi = 0, outbound_cpi = 0;
727 uint8_t mode = MODE_TUNNEL, ipcomp = 0;
728 uint16_t encr = 0, integ = 0, len = 0, ke_alg = 0;
729 uint16_t esn = NO_EXT_SEQ_NUMBERS;
730 chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
731 chunk_t add_secret = chunk_empty, add_kes = chunk_empty;
732 chunk_t encr_i, integ_i, encr_r, integ_r;
733 linked_list_t *local_ts, *remote_ts;
734 key_exchange_t *ke = NULL;
735 array_t *kes = NULL;
736
737 enumerator = message->create_attribute_enumerator(message);
738 while (enumerator->enumerate(enumerator, &attribute, &value))
739 {
740 switch (attribute)
741 {
742 case HA_IKE_ID:
743 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
744 value.ike_sa_id);
745 break;
746 case HA_CONFIG_NAME:
747 config_name = value.str;
748 break;
749 case HA_INITIATOR:
750 initiator = value.u8;
751 break;
752 case HA_INBOUND_SPI:
753 inbound_spi = value.u32;
754 break;
755 case HA_OUTBOUND_SPI:
756 outbound_spi = value.u32;
757 break;
758 case HA_INBOUND_CPI:
759 inbound_cpi = value.u32;
760 break;
761 case HA_OUTBOUND_CPI:
762 outbound_cpi = value.u32;
763 break;
764 case HA_IPSEC_MODE:
765 mode = value.u8;
766 break;
767 case HA_IPCOMP:
768 ipcomp = value.u8;
769 break;
770 case HA_ALG_ENCR:
771 encr = value.u16;
772 break;
773 case HA_ALG_ENCR_LEN:
774 len = value.u16;
775 break;
776 case HA_ALG_INTEG:
777 integ = value.u16;
778 break;
779 case HA_ALG_KE:
780 ke_alg = value.u16;
781 break;
782 case HA_ALG_ADD_KES:
783 add_kes = value.chunk;
784 break;
785 case HA_ESN:
786 esn = value.u16;
787 break;
788 case HA_NONCE_I:
789 nonce_i = value.chunk;
790 break;
791 case HA_NONCE_R:
792 nonce_r = value.chunk;
793 break;
794 case HA_SECRET:
795 secret = value.chunk;
796 break;
797 case HA_ADD_SECRET:
798 add_secret = value.chunk;
799 break;
800 default:
801 break;
802 }
803 }
804 enumerator->destroy(enumerator);
805
806 if (!ike_sa)
807 {
808 DBG1(DBG_CHD, "IKE_SA for HA CHILD_SA not found");
809 message->destroy(message);
810 return;
811 }
812 config = find_child_cfg(ike_sa, config_name);
813 if (!config)
814 {
815 DBG1(DBG_CHD, "HA is missing nodes child configuration");
816 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
817 message->destroy(message);
818 return;
819 }
820
821 child_sa_create_t data = {
822 .encap = ike_sa->has_condition(ike_sa, COND_NAT_ANY),
823 .cpu = CPU_ID_MAX,
824 };
825 child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
826 ike_sa->get_other_host(ike_sa), config, &data);
827 child_sa->set_mode(child_sa, mode);
828 child_sa->set_protocol(child_sa, PROTO_ESP);
829 child_sa->set_ipcomp(child_sa, ipcomp);
830
831 proposal = proposal_create(PROTO_ESP, 0);
832 if (integ)
833 {
834 proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, integ, 0);
835 }
836 if (encr)
837 {
838 proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, len);
839 }
840 add_ke_methods_to_proposal(proposal, ke_alg, add_kes);
841 proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
842
843 if (secret.len)
844 {
845 ke = ha_key_exchange_create(secret, chunk_empty);
846 array_insert_create(&kes, ARRAY_HEAD, ke);
847 }
848 if (add_secret.len)
849 {
850 ke = ha_key_exchange_create(add_secret, chunk_empty);
851 array_insert_create(&kes, ARRAY_TAIL, ke);
852 }
853 if (ike_sa->get_version(ike_sa) == IKEV2)
854 {
855 keymat_v2_t *keymat_v2 = (keymat_v2_t*)ike_sa->get_keymat(ike_sa);
856
857 ok = keymat_v2->derive_child_keys(keymat_v2, proposal, kes,
858 nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
859 }
860 else if (ike_sa->get_version(ike_sa) == IKEV1)
861 {
862 keymat_v1_t *keymat_v1 = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
863 uint32_t spi_i, spi_r;
864
865 spi_i = initiator ? inbound_spi : outbound_spi;
866 spi_r = initiator ? outbound_spi : inbound_spi;
867
868 ok = keymat_v1->derive_child_keys(keymat_v1, proposal, ke, spi_i, spi_r,
869 nonce_i, nonce_r, &encr_i, &integ_i, &encr_r, &integ_r);
870 }
871 array_destroy_offset(kes, offsetof(key_exchange_t, destroy));
872 if (!ok)
873 {
874 DBG1(DBG_CHD, "HA CHILD_SA key derivation failed");
875 child_sa->destroy(child_sa);
876 proposal->destroy(proposal);
877 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
878 return;
879 }
880 child_sa->set_proposal(child_sa, proposal);
881 child_sa->set_state(child_sa, CHILD_INSTALLING);
882 proposal->destroy(proposal);
883
884 /* TODO: Change CHILD_SA API to avoid cloning twice */
885 local_ts = linked_list_create();
886 remote_ts = linked_list_create();
887 enumerator = message->create_attribute_enumerator(message);
888 while (enumerator->enumerate(enumerator, &attribute, &value))
889 {
890 switch (attribute)
891 {
892 case HA_LOCAL_TS:
893 local_ts->insert_last(local_ts, value.ts->clone(value.ts));
894 break;
895 case HA_REMOTE_TS:
896 remote_ts->insert_last(remote_ts, value.ts->clone(value.ts));
897 break;
898 default:
899 break;
900 }
901 }
902 enumerator->destroy(enumerator);
903
904 child_sa->set_policies(child_sa, local_ts, remote_ts);
905
906 if (initiator)
907 {
908 if (child_sa->install(child_sa, encr_r, integ_r, inbound_spi,
909 inbound_cpi, initiator, TRUE, TRUE) != SUCCESS ||
910 child_sa->install(child_sa, encr_i, integ_i, outbound_spi,
911 outbound_cpi, initiator, FALSE, TRUE) != SUCCESS)
912 {
913 failed = TRUE;
914 }
915 }
916 else
917 {
918 if (child_sa->install(child_sa, encr_i, integ_i, inbound_spi,
919 inbound_cpi, initiator, TRUE, TRUE) != SUCCESS ||
920 child_sa->install(child_sa, encr_r, integ_r, outbound_spi,
921 outbound_cpi, initiator, FALSE, TRUE) != SUCCESS)
922 {
923 failed = TRUE;
924 }
925 }
926 chunk_clear(&encr_i);
927 chunk_clear(&integ_i);
928 chunk_clear(&encr_r);
929 chunk_clear(&integ_r);
930
931 if (failed)
932 {
933 DBG1(DBG_CHD, "HA CHILD_SA installation failed");
934 child_sa->destroy(child_sa);
935 local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
936 remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
937 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
938 message->destroy(message);
939 return;
940 }
941
942#if DEBUG_LEVEL >= 1
943 u_int seg_i, seg_o;
944
945 seg_i = this->kernel->get_segment_spi(this->kernel,
946 ike_sa->get_my_host(ike_sa), inbound_spi);
947 seg_o = this->kernel->get_segment_spi(this->kernel,
948 ike_sa->get_other_host(ike_sa), outbound_spi);
949 DBG1(DBG_CFG, "installed HA CHILD_SA %s{%d} %#R === %#R "
950 "(segment in: %d%s, out: %d%s)", child_sa->get_name(child_sa),
951 child_sa->get_unique_id(child_sa), local_ts, remote_ts,
952 seg_i, this->segments->is_active(this->segments, seg_i) ? "*" : "",
953 seg_o, this->segments->is_active(this->segments, seg_o) ? "*" : "");
954#endif /* DEBUG_LEVEL */
955
956 child_sa->install_policies(child_sa);
957 local_ts->destroy_offset(local_ts, offsetof(traffic_selector_t, destroy));
958 remote_ts->destroy_offset(remote_ts, offsetof(traffic_selector_t, destroy));
959
960 child_sa->set_state(child_sa, CHILD_INSTALLED);
961 ike_sa->add_child_sa(ike_sa, child_sa);
962 message->destroy(message);
963 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
964}
965
966/**
967 * Process messages of type CHILD_DELETE
968 */
969static void process_child_delete(private_ha_dispatcher_t *this,
970 ha_message_t *message)
971{
972 ha_message_attribute_t attribute;
973 ha_message_value_t value;
974 enumerator_t *enumerator;
975 ike_sa_t *ike_sa = NULL;
976 child_sa_t *child_sa;
977 uint32_t spi = 0;
978
979 enumerator = message->create_attribute_enumerator(message);
980 while (enumerator->enumerate(enumerator, &attribute, &value))
981 {
982 switch (attribute)
983 {
984 case HA_IKE_ID:
985 ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
986 value.ike_sa_id);
987 break;
988 case HA_INBOUND_SPI:
989 spi = value.u32;
990 break;
991 default:
992 break;
993 }
994 }
995 enumerator->destroy(enumerator);
996
997 if (ike_sa)
998 {
999 child_sa = ike_sa->get_child_sa(ike_sa, PROTO_ESP, spi, TRUE);
1000 if (child_sa)
1001 {
1002 ike_sa->destroy_child_sa(ike_sa, PROTO_ESP, spi);
1003 }
1004 charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
1005 }
1006 message->destroy(message);
1007}
1008
1009/**
1010 * Process messages of type SEGMENT_TAKE/DROP
1011 */
1012static void process_segment(private_ha_dispatcher_t *this,
1013 ha_message_t *message, bool take)
1014{
1015 ha_message_attribute_t attribute;
1016 ha_message_value_t value;
1017 enumerator_t *enumerator;
1018
1019 enumerator = message->create_attribute_enumerator(message);
1020 while (enumerator->enumerate(enumerator, &attribute, &value))
1021 {
1022 switch (attribute)
1023 {
1024 case HA_SEGMENT:
1025 if (take)
1026 {
1027 DBG1(DBG_CFG, "remote node takes segment %d", value.u16);
1028 this->segments->deactivate(this->segments, value.u16, FALSE);
1029 }
1030 else
1031 {
1032 DBG1(DBG_CFG, "remote node drops segment %d", value.u16);
1033 this->segments->activate(this->segments, value.u16, FALSE);
1034 }
1035 break;
1036 default:
1037 break;
1038 }
1039 }
1040 enumerator->destroy(enumerator);
1041 message->destroy(message);
1042}
1043
1044/**
1045 * Process messages of type STATUS
1046 */
1047static void process_status(private_ha_dispatcher_t *this,
1048 ha_message_t *message)
1049{
1050 ha_message_attribute_t attribute;
1051 ha_message_value_t value;
1052 enumerator_t *enumerator;
1053 segment_mask_t mask = 0;
1054
1055 enumerator = message->create_attribute_enumerator(message);
1056 while (enumerator->enumerate(enumerator, &attribute, &value))
1057 {
1058 switch (attribute)
1059 {
1060 case HA_SEGMENT:
1061 mask |= SEGMENTS_BIT(value.u16);
1062 break;
1063 default:
1064 break;
1065 }
1066 }
1067 enumerator->destroy(enumerator);
1068
1069 this->segments->handle_status(this->segments, mask);
1070 message->destroy(message);
1071}
1072
1073/**
1074 * Process messages of type RESYNC
1075 */
1076static void process_resync(private_ha_dispatcher_t *this,
1077 ha_message_t *message)
1078{
1079 ha_message_attribute_t attribute;
1080 ha_message_value_t value;
1081 enumerator_t *enumerator;
1082
1083 enumerator = message->create_attribute_enumerator(message);
1084 while (enumerator->enumerate(enumerator, &attribute, &value))
1085 {
1086 switch (attribute)
1087 {
1088 case HA_SEGMENT:
1089 this->cache->resync(this->cache, value.u16);
1090 break;
1091 default:
1092 break;
1093 }
1094 }
1095 enumerator->destroy(enumerator);
1096 message->destroy(message);
1097}
1098
1099/**
1100 * Dispatcher job function
1101 */
1102static job_requeue_t dispatch(private_ha_dispatcher_t *this)
1103{
1104 ha_message_t *message;
1105 ha_message_type_t type;
1106
1107 message = this->socket->pull(this->socket);
1108 type = message->get_type(message);
1109 if (type != HA_STATUS)
1110 {
1111 DBG2(DBG_CFG, "received HA %N message", ha_message_type_names,
1112 message->get_type(message));
1113 }
1114 switch (type)
1115 {
1116 case HA_IKE_ADD:
1117 process_ike_add(this, message);
1118 break;
1119 case HA_IKE_UPDATE:
1120 process_ike_update(this, message);
1121 break;
1122 case HA_IKE_MID_INITIATOR:
1123 process_ike_mid(this, message, TRUE);
1124 break;
1125 case HA_IKE_MID_RESPONDER:
1126 process_ike_mid(this, message, FALSE);
1127 break;
1128 case HA_IKE_IV:
1129 process_ike_iv(this, message);
1130 break;
1131 case HA_IKE_DELETE:
1132 process_ike_delete(this, message);
1133 break;
1134 case HA_CHILD_ADD:
1135 process_child_add(this, message);
1136 break;
1137 case HA_CHILD_DELETE:
1138 process_child_delete(this, message);
1139 break;
1140 case HA_SEGMENT_DROP:
1141 process_segment(this, message, FALSE);
1142 break;
1143 case HA_SEGMENT_TAKE:
1144 process_segment(this, message, TRUE);
1145 break;
1146 case HA_STATUS:
1147 process_status(this, message);
1148 break;
1149 case HA_RESYNC:
1150 process_resync(this, message);
1151 break;
1152 default:
1153 DBG1(DBG_CFG, "received unknown HA message type %d", type);
1154 message->destroy(message);
1155 break;
1156 }
1157 return JOB_REQUEUE_DIRECT;
1158}
1159
1160METHOD(ha_dispatcher_t, destroy, void,
1161 private_ha_dispatcher_t *this)
1162{
1163 free(this);
1164}
1165
1166/**
1167 * See header
1168 */
1169ha_dispatcher_t *ha_dispatcher_create(ha_socket_t *socket,
1170 ha_segments_t *segments, ha_cache_t *cache,
1171 ha_kernel_t *kernel, ha_attribute_t *attr)
1172{
1173 private_ha_dispatcher_t *this;
1174
1175
1176 INIT(this,
1177 .public = {
1178 .destroy = _destroy,
1179 },
1180 .socket = socket,
1181 .segments = segments,
1182 .cache = cache,
1183 .kernel = kernel,
1184 .attr = attr,
1185 );
1186 lib->processor->queue_job(lib->processor,
1187 (job_t*)callback_job_create_with_prio((callback_job_cb_t)dispatch, this,
1188 NULL, callback_job_cancel_thread, JOB_PRIO_CRITICAL));
1189
1190 return &this->public;
1191}