Annotation of embedaddon/strongswan/src/libcharon/plugins/ha/ha_dispatcher.c, revision 1.1.1.1
1.1 misho 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, ¤t))
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>