Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/phase1.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2012-2017 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * Copyright (C) 2012 Martin Willi
        !             6:  * Copyright (C) 2012 revosec AG
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: #include "phase1.h"
        !            20: 
        !            21: #include <daemon.h>
        !            22: #include <sa/ikev1/keymat_v1.h>
        !            23: #include <encoding/payloads/ke_payload.h>
        !            24: #include <encoding/payloads/nonce_payload.h>
        !            25: #include <collections/linked_list.h>
        !            26: 
        !            27: typedef struct private_phase1_t private_phase1_t;
        !            28: 
        !            29: /**
        !            30:  * Private data of an phase1_t object.
        !            31:  */
        !            32: struct private_phase1_t {
        !            33: 
        !            34:        /**
        !            35:         * Public phase1_t interface.
        !            36:         */
        !            37:        phase1_t public;
        !            38: 
        !            39:        /**
        !            40:         * IKE_SA we negotiate
        !            41:         */
        !            42:        ike_sa_t *ike_sa;
        !            43: 
        !            44:        /**
        !            45:         * Currently selected peer config
        !            46:         */
        !            47:        peer_cfg_t *peer_cfg;
        !            48: 
        !            49:        /**
        !            50:         * Other possible peer config candidates
        !            51:         */
        !            52:        linked_list_t *candidates;
        !            53: 
        !            54:        /**
        !            55:         * Acting as initiator
        !            56:         */
        !            57:        bool initiator;
        !            58: 
        !            59:        /**
        !            60:         * Extracted SA payload bytes
        !            61:         */
        !            62:        chunk_t sa_payload;
        !            63: 
        !            64:        /**
        !            65:         * DH exchange
        !            66:         */
        !            67:        diffie_hellman_t *dh;
        !            68: 
        !            69:        /**
        !            70:         * Keymat derivation (from SA)
        !            71:         */
        !            72:        keymat_v1_t *keymat;
        !            73: 
        !            74:        /**
        !            75:         * Received public DH value from peer
        !            76:         */
        !            77:        chunk_t dh_value;
        !            78: 
        !            79:        /**
        !            80:         * Initiators nonce
        !            81:         */
        !            82:        chunk_t nonce_i;
        !            83: 
        !            84:        /**
        !            85:         * Responder nonce
        !            86:         */
        !            87:        chunk_t nonce_r;
        !            88: };
        !            89: 
        !            90: /**
        !            91:  * Get the first authentication config from peer config
        !            92:  */
        !            93: static auth_cfg_t *get_auth_cfg(peer_cfg_t *peer_cfg, bool local)
        !            94: {
        !            95:        enumerator_t *enumerator;
        !            96:        auth_cfg_t *cfg = NULL;
        !            97: 
        !            98:        enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
        !            99:        enumerator->enumerate(enumerator, &cfg);
        !           100:        enumerator->destroy(enumerator);
        !           101:        return cfg;
        !           102: }
        !           103: 
        !           104: /**
        !           105:  * Find a shared key for the given identities
        !           106:  */
        !           107: static shared_key_t *find_shared_key(identification_t *my_id, host_t *me,
        !           108:                                                                         identification_t *other_id, host_t *other)
        !           109: {
        !           110:        identification_t *any_id = NULL;
        !           111:        shared_key_t *shared_key;
        !           112: 
        !           113:        if (!other_id)
        !           114:        {
        !           115:                any_id = identification_create_from_encoding(ID_ANY, chunk_empty);
        !           116:                other_id = any_id;
        !           117:        }
        !           118:        shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
        !           119:                                                                                  my_id, other_id);
        !           120:        if (!shared_key)
        !           121:        {
        !           122:                DBG1(DBG_IKE, "no shared key found for '%Y'[%H] - '%Y'[%H]",
        !           123:                         my_id, me, other_id, other);
        !           124:        }
        !           125:        DESTROY_IF(any_id);
        !           126:        return shared_key;
        !           127: }
        !           128: 
        !           129: /**
        !           130:  * Lookup a shared secret for this IKE_SA
        !           131:  */
        !           132: static shared_key_t *lookup_shared_key(private_phase1_t *this,
        !           133:                                                                           peer_cfg_t *peer_cfg)
        !           134: {
        !           135:        host_t *me, *other;
        !           136:        identification_t *my_id, *other_id;
        !           137:        shared_key_t *shared_key = NULL;
        !           138:        auth_cfg_t *my_auth, *other_auth;
        !           139:        enumerator_t *enumerator;
        !           140: 
        !           141:        me = this->ike_sa->get_my_host(this->ike_sa);
        !           142:        other = this->ike_sa->get_other_host(this->ike_sa);
        !           143: 
        !           144:        if (peer_cfg)
        !           145:        {       /* as initiator or aggressive responder, use identities */
        !           146:                my_auth = get_auth_cfg(peer_cfg, TRUE);
        !           147:                other_auth = get_auth_cfg(peer_cfg, FALSE);
        !           148:                if (my_auth && other_auth)
        !           149:                {
        !           150:                        my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
        !           151:                        if (peer_cfg->use_aggressive(peer_cfg))
        !           152:                        {
        !           153:                                other_id = this->ike_sa->get_other_id(this->ike_sa);
        !           154:                        }
        !           155:                        else
        !           156:                        {
        !           157:                                other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
        !           158:                        }
        !           159:                        if (my_id)
        !           160:                        {
        !           161:                                shared_key = find_shared_key(my_id, me, other_id, other);
        !           162:                        }
        !           163:                }
        !           164:        }
        !           165:        else
        !           166:        {       /* as responder, we try to find a config by IP addresses and use the
        !           167:                 * configured identities to find the PSK */
        !           168:                enumerator = charon->backends->create_peer_cfg_enumerator(
        !           169:                                                                charon->backends, me, other, NULL, NULL, IKEV1);
        !           170:                while (enumerator->enumerate(enumerator, &peer_cfg))
        !           171:                {
        !           172:                        my_auth = get_auth_cfg(peer_cfg, TRUE);
        !           173:                        other_auth = get_auth_cfg(peer_cfg, FALSE);
        !           174:                        if (my_auth && other_auth)
        !           175:                        {
        !           176:                                my_id = my_auth->get(my_auth, AUTH_RULE_IDENTITY);
        !           177:                                other_id = other_auth->get(other_auth, AUTH_RULE_IDENTITY);
        !           178:                                if (my_id)
        !           179:                                {
        !           180:                                        shared_key = find_shared_key(my_id, me, other_id, other);
        !           181:                                        if (shared_key)
        !           182:                                        {
        !           183:                                                break;
        !           184:                                        }
        !           185:                                }
        !           186:                        }
        !           187:                }
        !           188:                enumerator->destroy(enumerator);
        !           189:        }
        !           190:        if (!shared_key)
        !           191:        {       /* try to get a PSK for IP addresses */
        !           192:                my_id = identification_create_from_sockaddr(me->get_sockaddr(me));
        !           193:                other_id = identification_create_from_sockaddr(
        !           194:                                                                                                        other->get_sockaddr(other));
        !           195:                if (my_id && other_id)
        !           196:                {
        !           197:                        shared_key = lib->credmgr->get_shared(lib->credmgr, SHARED_IKE,
        !           198:                                                                                                  my_id, other_id);
        !           199:                }
        !           200:                DESTROY_IF(my_id);
        !           201:                DESTROY_IF(other_id);
        !           202:                if (!shared_key)
        !           203:                {
        !           204:                        DBG1(DBG_IKE, "no shared key found for %H - %H", me, other);
        !           205:                }
        !           206:        }
        !           207:        return shared_key;
        !           208: }
        !           209: 
        !           210: METHOD(phase1_t, create_hasher, bool,
        !           211:        private_phase1_t *this)
        !           212: {
        !           213:        return this->keymat->create_hasher(this->keymat,
        !           214:                                                        this->ike_sa->get_proposal(this->ike_sa));
        !           215: }
        !           216: 
        !           217: METHOD(phase1_t, create_dh, bool,
        !           218:        private_phase1_t *this, diffie_hellman_group_t group)
        !           219: {
        !           220:        this->dh = this->keymat->keymat.create_dh(&this->keymat->keymat, group);
        !           221:        return this->dh != NULL;
        !           222: }
        !           223: 
        !           224: METHOD(phase1_t, derive_keys, bool,
        !           225:        private_phase1_t *this, peer_cfg_t *peer_cfg, auth_method_t method)
        !           226: {
        !           227:        shared_key_t *shared_key = NULL;
        !           228: 
        !           229:        switch (method)
        !           230:        {
        !           231:                case AUTH_PSK:
        !           232:                case AUTH_XAUTH_INIT_PSK:
        !           233:                case AUTH_XAUTH_RESP_PSK:
        !           234:                        shared_key = lookup_shared_key(this, peer_cfg);
        !           235:                        if (!shared_key)
        !           236:                        {
        !           237:                                return FALSE;
        !           238:                        }
        !           239:                        break;
        !           240:                default:
        !           241:                        break;
        !           242:        }
        !           243: 
        !           244:        if (!this->keymat->derive_ike_keys(this->keymat,
        !           245:                                                this->ike_sa->get_proposal(this->ike_sa),
        !           246:                                                this->dh, this->dh_value, this->nonce_i, this->nonce_r,
        !           247:                                                this->ike_sa->get_id(this->ike_sa), method, shared_key))
        !           248:        {
        !           249:                DESTROY_IF(shared_key);
        !           250:                DBG1(DBG_IKE, "key derivation for %N failed", auth_method_names, method);
        !           251:                return FALSE;
        !           252:        }
        !           253:        charon->bus->ike_keys(charon->bus, this->ike_sa, this->dh, this->dh_value,
        !           254:                                                  this->nonce_i, this->nonce_r, NULL, shared_key,
        !           255:                                                  method);
        !           256:        DESTROY_IF(shared_key);
        !           257:        return TRUE;
        !           258: }
        !           259: 
        !           260: /**
        !           261:  * Check if a peer skipped authentication by using Hybrid authentication
        !           262:  */
        !           263: static bool skipped_auth(private_phase1_t *this,
        !           264:                                                 auth_method_t method, bool local)
        !           265: {
        !           266:        bool initiator;
        !           267: 
        !           268:        initiator = local == this->initiator;
        !           269:        if (initiator && method == AUTH_HYBRID_INIT_RSA)
        !           270:        {
        !           271:                return TRUE;
        !           272:        }
        !           273:        if (!initiator && method == AUTH_HYBRID_RESP_RSA)
        !           274:        {
        !           275:                return TRUE;
        !           276:        }
        !           277:        return FALSE;
        !           278: }
        !           279: 
        !           280: /**
        !           281:  * Check if remote authentication constraints fulfilled
        !           282:  */
        !           283: static bool check_constraints(private_phase1_t *this, auth_method_t method)
        !           284: {
        !           285:        identification_t *id;
        !           286:        auth_cfg_t *auth, *cfg;
        !           287:        peer_cfg_t *peer_cfg;
        !           288: 
        !           289:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           290:        /* auth identity to comply */
        !           291:        id = this->ike_sa->get_other_id(this->ike_sa);
        !           292:        auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id));
        !           293:        if (skipped_auth(this, method, FALSE))
        !           294:        {
        !           295:                return TRUE;
        !           296:        }
        !           297:        peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa);
        !           298:        cfg = get_auth_cfg(peer_cfg, FALSE);
        !           299:        return cfg && auth->complies(auth, cfg, TRUE);
        !           300: }
        !           301: 
        !           302: /**
        !           303:  * Save authentication information after authentication succeeded
        !           304:  */
        !           305: static void save_auth_cfg(private_phase1_t *this,
        !           306:                                                  auth_method_t method, bool local)
        !           307: {
        !           308:        auth_cfg_t *auth;
        !           309: 
        !           310:        if (skipped_auth(this, method, local))
        !           311:        {
        !           312:                return;
        !           313:        }
        !           314:        auth = auth_cfg_create();
        !           315:        /* for local config, we _copy_ entries from the config, as it contains
        !           316:         * certificates we must send later. */
        !           317:        auth->merge(auth, this->ike_sa->get_auth_cfg(this->ike_sa, local), local);
        !           318:        this->ike_sa->add_auth_cfg(this->ike_sa, local, auth);
        !           319: }
        !           320: 
        !           321: /**
        !           322:  * Create an authenticator instance
        !           323:  */
        !           324: static authenticator_t* create_authenticator(private_phase1_t *this,
        !           325:                                                                                         auth_method_t method, chunk_t id)
        !           326: {
        !           327:        authenticator_t *authenticator;
        !           328: 
        !           329:        authenticator = authenticator_create_v1(this->ike_sa, this->initiator,
        !           330:                                                method, this->dh, this->dh_value, this->sa_payload, id);
        !           331:        if (!authenticator)
        !           332:        {
        !           333:                DBG1(DBG_IKE, "negotiated authentication method %N not supported",
        !           334:                         auth_method_names, method);
        !           335:        }
        !           336:        return authenticator;
        !           337: }
        !           338: 
        !           339: METHOD(phase1_t, verify_auth, bool,
        !           340:        private_phase1_t *this, auth_method_t method, message_t *message,
        !           341:        chunk_t id_data)
        !           342: {
        !           343:        authenticator_t *authenticator;
        !           344:        status_t status;
        !           345: 
        !           346:        authenticator = create_authenticator(this, method, id_data);
        !           347:        if (authenticator)
        !           348:        {
        !           349:                status = authenticator->process(authenticator, message);
        !           350:                authenticator->destroy(authenticator);
        !           351:                if (status == SUCCESS && check_constraints(this, method))
        !           352:                {
        !           353:                        save_auth_cfg(this, method, FALSE);
        !           354:                        return TRUE;
        !           355:                }
        !           356:        }
        !           357:        return FALSE;
        !           358: }
        !           359: 
        !           360: METHOD(phase1_t, build_auth, bool,
        !           361:        private_phase1_t *this, auth_method_t method, message_t *message,
        !           362:        chunk_t id_data)
        !           363: {
        !           364:        authenticator_t *authenticator;
        !           365:        status_t status;
        !           366: 
        !           367:        authenticator = create_authenticator(this, method, id_data);
        !           368:        if (authenticator)
        !           369:        {
        !           370:                status = authenticator->build(authenticator, message);
        !           371:                authenticator->destroy(authenticator);
        !           372:                if (status == SUCCESS)
        !           373:                {
        !           374:                        save_auth_cfg(this, method, TRUE);
        !           375:                        return TRUE;
        !           376:                }
        !           377:        }
        !           378:        return FALSE;
        !           379: }
        !           380: 
        !           381: /**
        !           382:  * Get the two auth classes from local or remote config
        !           383:  */
        !           384: static void get_auth_class(peer_cfg_t *peer_cfg, bool local,
        !           385:                                                   auth_class_t *c1, auth_class_t *c2)
        !           386: {
        !           387:        enumerator_t *enumerator;
        !           388:        auth_cfg_t *auth;
        !           389: 
        !           390:        *c1 = *c2 = AUTH_CLASS_ANY;
        !           391: 
        !           392:        enumerator = peer_cfg->create_auth_cfg_enumerator(peer_cfg, local);
        !           393:        while (enumerator->enumerate(enumerator, &auth))
        !           394:        {
        !           395:                if (*c1 == AUTH_CLASS_ANY)
        !           396:                {
        !           397:                        *c1 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
        !           398:                }
        !           399:                else
        !           400:                {
        !           401:                        *c2 = (uintptr_t)auth->get(auth, AUTH_RULE_AUTH_CLASS);
        !           402:                        break;
        !           403:                }
        !           404:        }
        !           405:        enumerator->destroy(enumerator);
        !           406: }
        !           407: 
        !           408: /**
        !           409:  * Select an auth method to use by checking what key we have
        !           410:  */
        !           411: static auth_method_t get_pubkey_method(private_phase1_t *this, auth_cfg_t *auth)
        !           412: {
        !           413:        auth_method_t method = AUTH_NONE;
        !           414:        identification_t *id;
        !           415:        private_key_t *private;
        !           416: 
        !           417:        if (auth)
        !           418:        {
        !           419:                id = (identification_t*)auth->get(auth, AUTH_RULE_IDENTITY);
        !           420:                if (id)
        !           421:                {
        !           422:                        private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, NULL);
        !           423:                        if (private)
        !           424:                        {
        !           425:                                switch (private->get_type(private))
        !           426:                                {
        !           427:                                        case KEY_RSA:
        !           428:                                                method = AUTH_RSA;
        !           429:                                                break;
        !           430:                                        case KEY_ECDSA:
        !           431:                                                switch (private->get_keysize(private))
        !           432:                                                {
        !           433:                                                        case 256:
        !           434:                                                                method = AUTH_ECDSA_256;
        !           435:                                                                break;
        !           436:                                                        case 384:
        !           437:                                                                method = AUTH_ECDSA_384;
        !           438:                                                                break;
        !           439:                                                        case 521:
        !           440:                                                                method = AUTH_ECDSA_521;
        !           441:                                                                break;
        !           442:                                                        default:
        !           443:                                                                DBG1(DBG_IKE, "%d bit ECDSA private key size not "
        !           444:                                                                         "supported", private->get_keysize(private));
        !           445:                                                                break;
        !           446:                                                }
        !           447:                                                break;
        !           448:                                        default:
        !           449:                                                DBG1(DBG_IKE, "private key of type %N not supported",
        !           450:                                                         key_type_names, private->get_type(private));
        !           451:                                                break;
        !           452:                                }
        !           453:                                private->destroy(private);
        !           454:                        }
        !           455:                        else
        !           456:                        {
        !           457:                                DBG1(DBG_IKE, "no private key found for '%Y'", id);
        !           458:                        }
        !           459:                }
        !           460:        }
        !           461:        return method;
        !           462: }
        !           463: 
        !           464: /**
        !           465:  * Calculate authentication method from a peer config
        !           466:  */
        !           467: static auth_method_t calc_auth_method(private_phase1_t *this,
        !           468:                                                                          peer_cfg_t *peer_cfg)
        !           469: {
        !           470:        auth_class_t i1, i2, r1, r2;
        !           471: 
        !           472:        get_auth_class(peer_cfg, this->initiator, &i1, &i2);
        !           473:        get_auth_class(peer_cfg, !this->initiator, &r1, &r2);
        !           474: 
        !           475:        if (i1 == AUTH_CLASS_PUBKEY && r1 == AUTH_CLASS_PUBKEY)
        !           476:        {
        !           477:                if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
        !           478:                {
        !           479:                        /* for any pubkey method, return RSA */
        !           480:                        return AUTH_RSA;
        !           481:                }
        !           482:                if (i2 == AUTH_CLASS_XAUTH)
        !           483:                {
        !           484:                        return AUTH_XAUTH_INIT_RSA;
        !           485:                }
        !           486:                if (r2 == AUTH_CLASS_XAUTH)
        !           487:                {
        !           488:                        return AUTH_XAUTH_RESP_RSA;
        !           489:                }
        !           490:        }
        !           491:        if (i1 == AUTH_CLASS_PSK && r1 == AUTH_CLASS_PSK)
        !           492:        {
        !           493:                if (i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
        !           494:                {
        !           495:                        return AUTH_PSK;
        !           496:                }
        !           497:                if (i2 == AUTH_CLASS_XAUTH)
        !           498:                {
        !           499:                        return AUTH_XAUTH_INIT_PSK;
        !           500:                }
        !           501:                if (r2 == AUTH_CLASS_XAUTH)
        !           502:                {
        !           503:                        return AUTH_XAUTH_RESP_PSK;
        !           504:                }
        !           505:        }
        !           506:        if (i1 == AUTH_CLASS_XAUTH && r1 == AUTH_CLASS_PUBKEY &&
        !           507:                i2 == AUTH_CLASS_ANY && r2 == AUTH_CLASS_ANY)
        !           508:        {
        !           509:                return AUTH_HYBRID_INIT_RSA;
        !           510:        }
        !           511:        return AUTH_NONE;
        !           512: }
        !           513: 
        !           514: METHOD(phase1_t, get_auth_method, auth_method_t,
        !           515:        private_phase1_t *this, peer_cfg_t *peer_cfg)
        !           516: {
        !           517:        auth_method_t method;
        !           518: 
        !           519:        method = calc_auth_method(this, peer_cfg);
        !           520:        if (method == AUTH_RSA)
        !           521:        {
        !           522:                return get_pubkey_method(this, get_auth_cfg(peer_cfg, TRUE));
        !           523:        }
        !           524:        return method;
        !           525: }
        !           526: 
        !           527: /**
        !           528:  * Check if a peer config can be used with a given auth method
        !           529:  */
        !           530: static bool check_auth_method(private_phase1_t *this, peer_cfg_t *peer_cfg,
        !           531:                                                          auth_method_t given)
        !           532: {
        !           533:        auth_method_t method;
        !           534: 
        !           535:        method = calc_auth_method(this, peer_cfg);
        !           536:        switch (given)
        !           537:        {
        !           538:                case AUTH_ECDSA_256:
        !           539:                case AUTH_ECDSA_384:
        !           540:                case AUTH_ECDSA_521:
        !           541:                        return method == AUTH_RSA;
        !           542:                default:
        !           543:                        return method == given;
        !           544:        }
        !           545: }
        !           546: 
        !           547: METHOD(phase1_t, select_config, peer_cfg_t*,
        !           548:        private_phase1_t *this, auth_method_t method, bool aggressive,
        !           549:        identification_t *id)
        !           550: {
        !           551:        enumerator_t *enumerator;
        !           552:        peer_cfg_t *current;
        !           553:        host_t *me, *other;
        !           554:        int unusable = 0;
        !           555: 
        !           556:        if (this->peer_cfg)
        !           557:        {       /* try to find an alternative config */
        !           558:                if (this->candidates->remove_first(this->candidates,
        !           559:                                                                                  (void**)&current) != SUCCESS)
        !           560:                {
        !           561:                        DBG1(DBG_CFG, "no alternative config found");
        !           562:                        return NULL;
        !           563:                }
        !           564:                DBG1(DBG_CFG, "switching to peer config '%s'",
        !           565:                         current->get_name(current));
        !           566:                return current;
        !           567:        }
        !           568: 
        !           569:        me = this->ike_sa->get_my_host(this->ike_sa);
        !           570:        other = this->ike_sa->get_other_host(this->ike_sa);
        !           571:        DBG1(DBG_CFG, "looking for %N peer configs matching %H...%H[%Y]",
        !           572:                 auth_method_names, method, me, other, id);
        !           573:        enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
        !           574:                                                                                                        me, other, NULL, id, IKEV1);
        !           575:        while (enumerator->enumerate(enumerator, &current))
        !           576:        {
        !           577:                if (check_auth_method(this, current, method) &&
        !           578:                        current->use_aggressive(current) == aggressive)
        !           579:                {
        !           580:                        current->get_ref(current);
        !           581:                        if (!this->peer_cfg)
        !           582:                        {
        !           583:                                this->peer_cfg = current;
        !           584:                        }
        !           585:                        else
        !           586:                        {
        !           587:                                this->candidates->insert_last(this->candidates, current);
        !           588:                        }
        !           589:                }
        !           590:                else
        !           591:                {
        !           592:                        unusable++;
        !           593:                }
        !           594:        }
        !           595:        enumerator->destroy(enumerator);
        !           596: 
        !           597:        if (this->peer_cfg)
        !           598:        {
        !           599:                DBG1(DBG_CFG, "selected peer config \"%s\"",
        !           600:                         this->peer_cfg->get_name(this->peer_cfg));
        !           601:                return this->peer_cfg->get_ref(this->peer_cfg);
        !           602:        }
        !           603:        if (unusable)
        !           604:        {
        !           605:                DBG1(DBG_IKE, "found %d matching config%s, but none allows %N "
        !           606:                         "authentication using %s Mode", unusable, unusable > 1 ? "s" : "",
        !           607:                         auth_method_names, method, aggressive ? "Aggressive" : "Main");
        !           608:                return NULL;
        !           609:        }
        !           610:        DBG1(DBG_IKE, "no peer config found");
        !           611:        return NULL;
        !           612: }
        !           613: 
        !           614: METHOD(phase1_t, get_id, identification_t*,
        !           615:        private_phase1_t *this, peer_cfg_t *peer_cfg, bool local)
        !           616: {
        !           617:        identification_t *id = NULL;
        !           618:        auth_cfg_t *auth;
        !           619: 
        !           620:        auth = get_auth_cfg(peer_cfg, local);
        !           621:        if (auth)
        !           622:        {
        !           623:                id = auth->get(auth, AUTH_RULE_IDENTITY);
        !           624:                if (local && (!id || id->get_type(id) == ID_ANY))
        !           625:                {       /* no ID configured, use local IP address */
        !           626:                        host_t *me;
        !           627: 
        !           628:                        me = this->ike_sa->get_my_host(this->ike_sa);
        !           629:                        if (!me->is_anyaddr(me))
        !           630:                        {
        !           631:                                id = identification_create_from_sockaddr(me->get_sockaddr(me));
        !           632:                                auth->add(auth, AUTH_RULE_IDENTITY, id);
        !           633:                        }
        !           634:                }
        !           635:        }
        !           636:        return id;
        !           637: }
        !           638: 
        !           639: METHOD(phase1_t, has_virtual_ip, bool,
        !           640:        private_phase1_t *this, peer_cfg_t *peer_cfg)
        !           641: {
        !           642:        enumerator_t *enumerator;
        !           643:        bool found = FALSE;
        !           644:        host_t *host;
        !           645: 
        !           646:        enumerator = peer_cfg->create_virtual_ip_enumerator(peer_cfg);
        !           647:        found = enumerator->enumerate(enumerator, &host);
        !           648:        enumerator->destroy(enumerator);
        !           649: 
        !           650:        return found;
        !           651: }
        !           652: 
        !           653: METHOD(phase1_t, has_pool, bool,
        !           654:        private_phase1_t *this, peer_cfg_t *peer_cfg)
        !           655: {
        !           656:        enumerator_t *enumerator;
        !           657:        bool found = FALSE;
        !           658:        char *pool;
        !           659: 
        !           660:        enumerator = peer_cfg->create_pool_enumerator(peer_cfg);
        !           661:        found = enumerator->enumerate(enumerator, &pool);
        !           662:        enumerator->destroy(enumerator);
        !           663: 
        !           664:        return found;
        !           665: }
        !           666: 
        !           667: METHOD(phase1_t, save_sa_payload, bool,
        !           668:        private_phase1_t *this, message_t *message)
        !           669: {
        !           670:        enumerator_t *enumerator;
        !           671:        payload_t *payload, *sa = NULL;
        !           672:        chunk_t data;
        !           673:        size_t offset = IKE_HEADER_LENGTH;
        !           674: 
        !           675:        enumerator = message->create_payload_enumerator(message);
        !           676:        while (enumerator->enumerate(enumerator, &payload))
        !           677:        {
        !           678:                if (payload->get_type(payload) == PLV1_SECURITY_ASSOCIATION)
        !           679:                {
        !           680:                        sa = payload;
        !           681:                        break;
        !           682:                }
        !           683:                else
        !           684:                {
        !           685:                        offset += payload->get_length(payload);
        !           686:                }
        !           687:        }
        !           688:        enumerator->destroy(enumerator);
        !           689: 
        !           690:        data = message->get_packet_data(message);
        !           691:        if (sa && data.len >= offset + sa->get_length(sa))
        !           692:        {
        !           693:                /* Get SA payload without 4 byte fixed header */
        !           694:                data = chunk_skip(data, offset);
        !           695:                data.len = sa->get_length(sa);
        !           696:                data = chunk_skip(data, 4);
        !           697:                this->sa_payload = chunk_clone(data);
        !           698:                return TRUE;
        !           699:        }
        !           700:        DBG1(DBG_IKE, "unable to extract SA payload encoding");
        !           701:        return FALSE;
        !           702: }
        !           703: 
        !           704: METHOD(phase1_t, add_nonce_ke, bool,
        !           705:        private_phase1_t *this, message_t *message)
        !           706: {
        !           707:        nonce_payload_t *nonce_payload;
        !           708:        ke_payload_t *ke_payload;
        !           709:        nonce_gen_t *nonceg;
        !           710:        chunk_t nonce;
        !           711: 
        !           712:        ke_payload = ke_payload_create_from_diffie_hellman(PLV1_KEY_EXCHANGE,
        !           713:                                                                                                           this->dh);
        !           714:        if (!ke_payload)
        !           715:        {
        !           716:                DBG1(DBG_IKE, "creating KE payload failed");
        !           717:                return FALSE;
        !           718:        }
        !           719:        message->add_payload(message, &ke_payload->payload_interface);
        !           720: 
        !           721:        nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
        !           722:        if (!nonceg)
        !           723:        {
        !           724:                DBG1(DBG_IKE, "no nonce generator found to create nonce");
        !           725:                return FALSE;
        !           726:        }
        !           727:        if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &nonce))
        !           728:        {
        !           729:                DBG1(DBG_IKE, "nonce allocation failed");
        !           730:                nonceg->destroy(nonceg);
        !           731:                return FALSE;
        !           732:        }
        !           733:        nonceg->destroy(nonceg);
        !           734: 
        !           735:        nonce_payload = nonce_payload_create(PLV1_NONCE);
        !           736:        nonce_payload->set_nonce(nonce_payload, nonce);
        !           737:        message->add_payload(message, &nonce_payload->payload_interface);
        !           738: 
        !           739:        if (this->initiator)
        !           740:        {
        !           741:                this->nonce_i = nonce;
        !           742:        }
        !           743:        else
        !           744:        {
        !           745:                this->nonce_r = nonce;
        !           746:        }
        !           747:        return TRUE;
        !           748: }
        !           749: 
        !           750: METHOD(phase1_t, get_nonce_ke, bool,
        !           751:        private_phase1_t *this, message_t *message)
        !           752: {
        !           753:        nonce_payload_t *nonce_payload;
        !           754:        ke_payload_t *ke_payload;
        !           755: 
        !           756:        ke_payload = (ke_payload_t*)message->get_payload(message, PLV1_KEY_EXCHANGE);
        !           757:        if (!ke_payload)
        !           758:        {
        !           759:                DBG1(DBG_IKE, "KE payload missing in message");
        !           760:                return FALSE;
        !           761:        }
        !           762:        this->dh_value = chunk_clone(ke_payload->get_key_exchange_data(ke_payload));
        !           763:        if (!this->dh->set_other_public_value(this->dh, this->dh_value))
        !           764:        {
        !           765:                DBG1(DBG_IKE, "unable to apply received KE value");
        !           766:                return FALSE;
        !           767:        }
        !           768: 
        !           769:        nonce_payload = (nonce_payload_t*)message->get_payload(message, PLV1_NONCE);
        !           770:        if (!nonce_payload)
        !           771:        {
        !           772:                DBG1(DBG_IKE, "NONCE payload missing in message");
        !           773:                return FALSE;
        !           774:        }
        !           775: 
        !           776:        if (this->initiator)
        !           777:        {
        !           778:                this->nonce_r = nonce_payload->get_nonce(nonce_payload);
        !           779:        }
        !           780:        else
        !           781:        {
        !           782:                this->nonce_i = nonce_payload->get_nonce(nonce_payload);
        !           783:        }
        !           784:        return TRUE;
        !           785: }
        !           786: 
        !           787: METHOD(phase1_t, destroy, void,
        !           788:        private_phase1_t *this)
        !           789: {
        !           790:        DESTROY_IF(this->peer_cfg);
        !           791:        this->candidates->destroy_offset(this->candidates,
        !           792:                                                                         offsetof(peer_cfg_t, destroy));
        !           793:        chunk_free(&this->sa_payload);
        !           794:        DESTROY_IF(this->dh);
        !           795:        free(this->dh_value.ptr);
        !           796:        free(this->nonce_i.ptr);
        !           797:        free(this->nonce_r.ptr);
        !           798:        free(this);
        !           799: }
        !           800: 
        !           801: /**
        !           802:  * See header
        !           803:  */
        !           804: phase1_t *phase1_create(ike_sa_t *ike_sa, bool initiator)
        !           805: {
        !           806:        private_phase1_t *this;
        !           807: 
        !           808:        INIT(this,
        !           809:                .public = {
        !           810:                        .create_hasher = _create_hasher,
        !           811:                        .create_dh = _create_dh,
        !           812:                        .derive_keys = _derive_keys,
        !           813:                        .get_auth_method = _get_auth_method,
        !           814:                        .get_id = _get_id,
        !           815:                        .select_config = _select_config,
        !           816:                        .has_virtual_ip = _has_virtual_ip,
        !           817:                        .has_pool = _has_pool,
        !           818:                        .verify_auth = _verify_auth,
        !           819:                        .build_auth = _build_auth,
        !           820:                        .save_sa_payload = _save_sa_payload,
        !           821:                        .add_nonce_ke = _add_nonce_ke,
        !           822:                        .get_nonce_ke = _get_nonce_ke,
        !           823:                        .destroy = _destroy,
        !           824:                },
        !           825:                .candidates = linked_list_create(),
        !           826:                .ike_sa = ike_sa,
        !           827:                .initiator = initiator,
        !           828:                .keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa),
        !           829:        );
        !           830: 
        !           831:        return &this->public;
        !           832: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>