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