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