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