Return to ha_dispatcher.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / ha |
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: }