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