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, &current))
                    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>