Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_aka/eap_aka_server.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2006-2009 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 "eap_aka_server.h"
        !            17: 
        !            18: #include <daemon.h>
        !            19: #include <library.h>
        !            20: 
        !            21: #include <simaka_message.h>
        !            22: #include <simaka_crypto.h>
        !            23: #include <simaka_manager.h>
        !            24: 
        !            25: /** length of the AT_NONCE_S value */
        !            26: #define NONCE_LEN 16
        !            27: 
        !            28: typedef struct private_eap_aka_server_t private_eap_aka_server_t;
        !            29: 
        !            30: /**
        !            31:  * Private data of an eap_aka_server_t object.
        !            32:  */
        !            33: struct private_eap_aka_server_t {
        !            34: 
        !            35:        /**
        !            36:         * Public authenticator_t interface.
        !            37:         */
        !            38:        eap_aka_server_t public;
        !            39: 
        !            40:        /**
        !            41:         * AKA backend manager
        !            42:         */
        !            43:        simaka_manager_t *mgr;
        !            44: 
        !            45:        /**
        !            46:         * EAP-AKA crypto helper
        !            47:         */
        !            48:        simaka_crypto_t *crypto;
        !            49: 
        !            50:        /**
        !            51:         * permanent ID of the peer
        !            52:         */
        !            53:        identification_t *permanent;
        !            54: 
        !            55:        /**
        !            56:         * pseudonym ID of peer
        !            57:         */
        !            58:        identification_t *pseudonym;
        !            59: 
        !            60:        /**
        !            61:         * reauthentication ID of peer
        !            62:         */
        !            63:        identification_t *reauth;
        !            64: 
        !            65:        /**
        !            66:         * EAP message identifier
        !            67:         */
        !            68:        uint8_t identifier;
        !            69: 
        !            70:        /**
        !            71:         * Expected Result XRES
        !            72:         */
        !            73:        chunk_t xres;
        !            74: 
        !            75:        /**
        !            76:         * Random value RAND
        !            77:         */
        !            78:        chunk_t rand;
        !            79: 
        !            80:        /**
        !            81:         * MSK
        !            82:         */
        !            83:        chunk_t msk;
        !            84: 
        !            85:        /**
        !            86:         * Nonce value used in AT_NONCE_S
        !            87:         */
        !            88:        chunk_t nonce;
        !            89: 
        !            90:        /**
        !            91:         * Counter value negotiated, network order
        !            92:         */
        !            93:        chunk_t counter;
        !            94: 
        !            95:        /**
        !            96:         * Do we request fast reauthentication?
        !            97:         */
        !            98:        bool use_reauth;
        !            99: 
        !           100:        /**
        !           101:         * Do we request pseudonym identities?
        !           102:         */
        !           103:        bool use_pseudonym;
        !           104: 
        !           105:        /**
        !           106:         * Do we request permanent identities?
        !           107:         */
        !           108:        bool use_permanent;
        !           109: 
        !           110:        /**
        !           111:         * EAP-AKA message we have initiated
        !           112:         */
        !           113:        simaka_subtype_t pending;
        !           114: 
        !           115:        /**
        !           116:         * Did the client send a synchronize request?
        !           117:         */
        !           118:        bool synchronized;
        !           119: };
        !           120: 
        !           121: /**
        !           122:  * Generate a payload from a message, destroy message
        !           123:  */
        !           124: static bool generate_payload(simaka_message_t *message, chunk_t data,
        !           125:                                                         eap_payload_t **out)
        !           126: {
        !           127:        chunk_t chunk;
        !           128:        bool ok;
        !           129: 
        !           130:        ok = message->generate(message, data, &chunk);
        !           131:        if (ok)
        !           132:        {
        !           133:                *out = eap_payload_create_data_own(chunk);
        !           134:        }
        !           135:        message->destroy(message);
        !           136:        return ok;
        !           137: }
        !           138: 
        !           139: /**
        !           140:  * Create EAP-AKA/Request/Identity message
        !           141:  */
        !           142: static status_t identity(private_eap_aka_server_t *this, eap_payload_t **out)
        !           143: {
        !           144:        simaka_message_t *message;
        !           145: 
        !           146:        message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
        !           147:                                                                        AKA_IDENTITY, this->crypto);
        !           148:        if (this->use_reauth)
        !           149:        {
        !           150:                message->add_attribute(message, AT_ANY_ID_REQ, chunk_empty);
        !           151:        }
        !           152:        else if (this->use_pseudonym)
        !           153:        {
        !           154:                message->add_attribute(message, AT_FULLAUTH_ID_REQ, chunk_empty);
        !           155:        }
        !           156:        else if (this->use_permanent)
        !           157:        {
        !           158:                message->add_attribute(message, AT_PERMANENT_ID_REQ, chunk_empty);
        !           159:        }
        !           160:        if (!generate_payload(message, chunk_empty, out))
        !           161:        {
        !           162:                return FAILED;
        !           163:        }
        !           164:        this->pending = AKA_IDENTITY;
        !           165:        return NEED_MORE;
        !           166: }
        !           167: 
        !           168: /**
        !           169:  * Create EAP-AKA/Request/Challenge message
        !           170:  */
        !           171: static status_t challenge(private_eap_aka_server_t *this, eap_payload_t **out)
        !           172: {
        !           173:        simaka_message_t *message;
        !           174:        char rand[AKA_RAND_LEN], xres[AKA_RES_MAX];
        !           175:        char ck[AKA_CK_LEN], ik[AKA_IK_LEN], autn[AKA_AUTN_LEN];
        !           176:        int xres_len;
        !           177:        chunk_t data, mk;
        !           178:        identification_t *id;
        !           179: 
        !           180:        if (!this->mgr->provider_get_quintuplet(this->mgr, this->permanent,
        !           181:                                                                                rand, xres, &xres_len, ck, ik, autn))
        !           182:        {
        !           183:                if (this->use_pseudonym)
        !           184:                {
        !           185:                        /* probably received a pseudonym/reauth id we couldn't map */
        !           186:                        DBG1(DBG_IKE, "failed to map pseudonym/reauth identity '%Y', "
        !           187:                                 "fallback to permanent identity request", this->permanent);
        !           188:                        this->use_pseudonym = FALSE;
        !           189:                        DESTROY_IF(this->pseudonym);
        !           190:                        this->pseudonym = NULL;
        !           191:                        return identity(this, out);
        !           192:                }
        !           193:                return FAILED;
        !           194:        }
        !           195:        id = this->permanent;
        !           196:        if (this->pseudonym)
        !           197:        {
        !           198:                id = this->pseudonym;
        !           199:        }
        !           200:        data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN),
        !           201:                                          chunk_create(ck, AKA_CK_LEN));
        !           202:        chunk_clear(&this->msk);
        !           203:        if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
        !           204:        {
        !           205:                return FAILED;
        !           206:        }
        !           207:        this->rand = chunk_clone(chunk_create(rand, AKA_RAND_LEN));
        !           208:        this->xres = chunk_clone(chunk_create(xres, xres_len));
        !           209: 
        !           210:        message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
        !           211:                                                                        AKA_CHALLENGE, this->crypto);
        !           212:        message->add_attribute(message, AT_RAND, this->rand);
        !           213:        message->add_attribute(message, AT_AUTN, chunk_create(autn, AKA_AUTN_LEN));
        !           214:        id = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk.ptr);
        !           215:        free(mk.ptr);
        !           216:        if (id)
        !           217:        {
        !           218:                message->add_attribute(message, AT_NEXT_REAUTH_ID,
        !           219:                                                           id->get_encoding(id));
        !           220:                id->destroy(id);
        !           221:        }
        !           222:        id = this->mgr->provider_gen_pseudonym(this->mgr, this->permanent);
        !           223:        if (id)
        !           224:        {
        !           225:                message->add_attribute(message, AT_NEXT_PSEUDONYM,
        !           226:                                                           id->get_encoding(id));
        !           227:                id->destroy(id);
        !           228:        }
        !           229:        if (!generate_payload(message, chunk_empty, out))
        !           230:        {
        !           231:                return FAILED;
        !           232:        }
        !           233:        this->pending = AKA_CHALLENGE;
        !           234:        return NEED_MORE;
        !           235: }
        !           236: 
        !           237: /**
        !           238:  * Initiate  EAP-AKA/Request/Re-authentication message
        !           239:  */
        !           240: static status_t reauthenticate(private_eap_aka_server_t *this,
        !           241:                                                           char mk[HASH_SIZE_SHA1], uint16_t counter,
        !           242:                                                           eap_payload_t **out)
        !           243: {
        !           244:        simaka_message_t *message;
        !           245:        identification_t *next;
        !           246:        chunk_t mkc;
        !           247:        rng_t *rng;
        !           248: 
        !           249:        DBG1(DBG_IKE, "initiating EAP-AKA reauthentication");
        !           250: 
        !           251:        rng = this->crypto->get_rng(this->crypto);
        !           252:        if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
        !           253:        {
        !           254:                return FAILED;
        !           255:        }
        !           256: 
        !           257:        mkc = chunk_create(mk, HASH_SIZE_SHA1);
        !           258:        counter = htons(counter);
        !           259:        this->counter = chunk_clone(chunk_create((char*)&counter, sizeof(counter)));
        !           260: 
        !           261:        if (!this->crypto->derive_keys_reauth(this->crypto, mkc) ||
        !           262:                !this->crypto->derive_keys_reauth_msk(this->crypto,
        !           263:                                        this->reauth, this->counter, this->nonce, mkc, &this->msk))
        !           264:        {
        !           265:                return FAILED;
        !           266:        }
        !           267: 
        !           268:        message = simaka_message_create(TRUE, this->identifier++, EAP_AKA,
        !           269:                                                                        AKA_REAUTHENTICATION, this->crypto);
        !           270:        message->add_attribute(message, AT_COUNTER, this->counter);
        !           271:        message->add_attribute(message, AT_NONCE_S, this->nonce);
        !           272:        next = this->mgr->provider_gen_reauth(this->mgr, this->permanent, mk);
        !           273:        if (next)
        !           274:        {
        !           275:                message->add_attribute(message, AT_NEXT_REAUTH_ID,
        !           276:                                                           next->get_encoding(next));
        !           277:                next->destroy(next);
        !           278:        }
        !           279:        if (!generate_payload(message, chunk_empty, out))
        !           280:        {
        !           281:                return FAILED;
        !           282:        }
        !           283:        this->pending = SIM_REAUTHENTICATION;
        !           284:        return NEED_MORE;
        !           285: }
        !           286: 
        !           287: METHOD(eap_method_t, initiate, status_t,
        !           288:        private_eap_aka_server_t *this, eap_payload_t **out)
        !           289: {
        !           290:        if (this->use_permanent || this->use_pseudonym || this->use_reauth)
        !           291:        {
        !           292:                return identity(this, out);
        !           293:        }
        !           294:        return challenge(this, out);
        !           295: }
        !           296: 
        !           297: /**
        !           298:  * Process EAP-AKA/Response/Identity message
        !           299:  */
        !           300: static status_t process_identity(private_eap_aka_server_t *this,
        !           301:                                                                 simaka_message_t *in, eap_payload_t **out)
        !           302: {
        !           303:        identification_t *permanent, *id;
        !           304:        enumerator_t *enumerator;
        !           305:        simaka_attribute_t type;
        !           306:        chunk_t data, identity = chunk_empty;
        !           307: 
        !           308:        if (this->pending != AKA_IDENTITY)
        !           309:        {
        !           310:                DBG1(DBG_IKE, "received %N, but not expected",
        !           311:                         simaka_subtype_names, AKA_IDENTITY);
        !           312:                return FAILED;
        !           313:        }
        !           314: 
        !           315:        enumerator = in->create_attribute_enumerator(in);
        !           316:        while (enumerator->enumerate(enumerator, &type, &data))
        !           317:        {
        !           318:                switch (type)
        !           319:                {
        !           320:                        case AT_IDENTITY:
        !           321:                                identity = data;
        !           322:                                break;
        !           323:                        default:
        !           324:                                if (!simaka_attribute_skippable(type))
        !           325:                                {
        !           326:                                        enumerator->destroy(enumerator);
        !           327:                                        return FAILED;
        !           328:                                }
        !           329:                                break;
        !           330:                }
        !           331:        }
        !           332:        enumerator->destroy(enumerator);
        !           333: 
        !           334:        if (!identity.len)
        !           335:        {
        !           336:                DBG1(DBG_IKE, "received incomplete Identity response");
        !           337:                return FAILED;
        !           338:        }
        !           339: 
        !           340:        id = identification_create_from_data(identity);
        !           341:        if (this->use_reauth)
        !           342:        {
        !           343:                char mk[HASH_SIZE_SHA1];
        !           344:                uint16_t counter;
        !           345: 
        !           346:                permanent = this->mgr->provider_is_reauth(this->mgr, id, mk, &counter);
        !           347:                if (permanent)
        !           348:                {
        !           349:                        this->permanent->destroy(this->permanent);
        !           350:                        this->permanent = permanent;
        !           351:                        this->reauth = id;
        !           352:                        return reauthenticate(this, mk, counter, out);
        !           353:                }
        !           354:                /* unable to map, maybe a pseudonym? */
        !           355:                DBG1(DBG_IKE, "'%Y' is not a reauth identity", id);
        !           356:                this->use_reauth = FALSE;
        !           357:        }
        !           358:        if (this->use_pseudonym)
        !           359:        {
        !           360:                permanent = this->mgr->provider_is_pseudonym(this->mgr, id);
        !           361:                if (permanent)
        !           362:                {
        !           363:                        this->permanent->destroy(this->permanent);
        !           364:                        this->permanent = permanent;
        !           365:                        this->pseudonym = id->clone(id);
        !           366:                        /* we already have a new permanent identity now */
        !           367:                        this->use_permanent = FALSE;
        !           368:                }
        !           369:                else
        !           370:                {
        !           371:                        DBG1(DBG_IKE, "'%Y' is not a pseudonym", id);
        !           372:                }
        !           373:        }
        !           374:        if (!this->pseudonym && this->use_permanent)
        !           375:        {
        !           376:                /* got a permanent identity or a pseudonym reauth id wou couldn't map,
        !           377:                 * try to get quintuplets */
        !           378:                DBG1(DBG_IKE, "received identity '%Y'", id);
        !           379:                this->permanent->destroy(this->permanent);
        !           380:                this->permanent = id->clone(id);
        !           381:        }
        !           382:        id->destroy(id);
        !           383: 
        !           384:        return challenge(this, out);
        !           385: }
        !           386: 
        !           387: /**
        !           388:  * Process EAP-AKA/Response/Challenge message
        !           389:  */
        !           390: static status_t process_challenge(private_eap_aka_server_t *this,
        !           391:                                                                  simaka_message_t *in)
        !           392: {
        !           393:        enumerator_t *enumerator;
        !           394:        simaka_attribute_t type;
        !           395:        chunk_t data, res = chunk_empty;
        !           396: 
        !           397:        if (this->pending != AKA_CHALLENGE)
        !           398:        {
        !           399:                DBG1(DBG_IKE, "received %N, but not expected",
        !           400:                         simaka_subtype_names, AKA_CHALLENGE);
        !           401:                return FAILED;
        !           402:        }
        !           403:        /* verify MAC of EAP message, AT_MAC */
        !           404:        if (!in->verify(in, chunk_empty))
        !           405:        {
        !           406:                return FAILED;
        !           407:        }
        !           408:        enumerator = in->create_attribute_enumerator(in);
        !           409:        while (enumerator->enumerate(enumerator, &type, &data))
        !           410:        {
        !           411:                switch (type)
        !           412:                {
        !           413:                        case AT_RES:
        !           414:                                res = data;
        !           415:                                break;
        !           416:                        default:
        !           417:                                if (!simaka_attribute_skippable(type))
        !           418:                                {
        !           419:                                        enumerator->destroy(enumerator);
        !           420:                                        return FAILED;
        !           421:                                }
        !           422:                                break;
        !           423:                }
        !           424:        }
        !           425:        enumerator->destroy(enumerator);
        !           426: 
        !           427:        /* compare received RES against stored XRES */
        !           428:        if (!chunk_equals_const(res, this->xres))
        !           429:        {
        !           430:                DBG1(DBG_IKE, "received RES does not match XRES");
        !           431:                return FAILED;
        !           432:        }
        !           433:        return SUCCESS;
        !           434: }
        !           435: 
        !           436: /**
        !           437:  * process an EAP-AKA/Response/Reauthentication message
        !           438:  */
        !           439: static status_t process_reauthentication(private_eap_aka_server_t *this,
        !           440:                                                                        simaka_message_t *in, eap_payload_t **out)
        !           441: {
        !           442:        enumerator_t *enumerator;
        !           443:        simaka_attribute_t type;
        !           444:        chunk_t data, counter = chunk_empty;
        !           445:        bool too_small = FALSE;
        !           446: 
        !           447:        if (this->pending != AKA_REAUTHENTICATION)
        !           448:        {
        !           449:                DBG1(DBG_IKE, "received %N, but not expected",
        !           450:                         simaka_subtype_names, AKA_REAUTHENTICATION);
        !           451:                return FAILED;
        !           452:        }
        !           453:        /* verify AT_MAC attribute, signature is over "EAP packet | NONCE_S"  */
        !           454:        if (!in->verify(in, this->nonce))
        !           455:        {
        !           456:                return FAILED;
        !           457:        }
        !           458: 
        !           459:        enumerator = in->create_attribute_enumerator(in);
        !           460:        while (enumerator->enumerate(enumerator, &type, &data))
        !           461:        {
        !           462:                switch (type)
        !           463:                {
        !           464:                        case AT_COUNTER:
        !           465:                                counter = data;
        !           466:                                break;
        !           467:                        case AT_COUNTER_TOO_SMALL:
        !           468:                                too_small = TRUE;
        !           469:                                break;
        !           470:                        default:
        !           471:                                if (!simaka_attribute_skippable(type))
        !           472:                                {
        !           473:                                        enumerator->destroy(enumerator);
        !           474:                                        return FAILED;
        !           475:                                }
        !           476:                                break;
        !           477:                }
        !           478:        }
        !           479:        enumerator->destroy(enumerator);
        !           480: 
        !           481:        if (too_small)
        !           482:        {
        !           483:                DBG1(DBG_IKE, "received %N, initiating full authentication",
        !           484:                         simaka_attribute_names, AT_COUNTER_TOO_SMALL);
        !           485:                this->use_reauth = FALSE;
        !           486:                this->crypto->clear_keys(this->crypto);
        !           487:                return challenge(this, out);
        !           488:        }
        !           489:        if (!chunk_equals_const(counter, this->counter))
        !           490:        {
        !           491:                DBG1(DBG_IKE, "received counter does not match");
        !           492:                return FAILED;
        !           493:        }
        !           494:        return SUCCESS;
        !           495: }
        !           496: 
        !           497: /**
        !           498:  * Process EAP-AKA/Response/SynchronizationFailure message
        !           499:  */
        !           500: static status_t process_synchronize(private_eap_aka_server_t *this,
        !           501:                                                                        simaka_message_t *in, eap_payload_t **out)
        !           502: {
        !           503:        enumerator_t *enumerator;
        !           504:        simaka_attribute_t type;
        !           505:        chunk_t data, auts = chunk_empty;
        !           506: 
        !           507:        if (this->synchronized)
        !           508:        {
        !           509:                DBG1(DBG_IKE, "received %N, but peer did already resynchronize",
        !           510:                         simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE);
        !           511:                return FAILED;
        !           512:        }
        !           513: 
        !           514:        DBG1(DBG_IKE, "received synchronization request, retrying...");
        !           515: 
        !           516:        enumerator = in->create_attribute_enumerator(in);
        !           517:        while (enumerator->enumerate(enumerator, &type, &data))
        !           518:        {
        !           519:                switch (type)
        !           520:                {
        !           521:                        case AT_AUTS:
        !           522:                                auts = data;
        !           523:                                break;
        !           524:                        default:
        !           525:                                if (!simaka_attribute_skippable(type))
        !           526:                                {
        !           527:                                        enumerator->destroy(enumerator);
        !           528:                                        return FAILED;
        !           529:                                }
        !           530:                                break;
        !           531:                }
        !           532:        }
        !           533:        enumerator->destroy(enumerator);
        !           534: 
        !           535:        if (!auts.len)
        !           536:        {
        !           537:                DBG1(DBG_IKE, "synchronization request didn't contain usable AUTS");
        !           538:                return FAILED;
        !           539:        }
        !           540: 
        !           541:        if (!this->mgr->provider_resync(this->mgr, this->permanent,
        !           542:                                                                        this->rand.ptr, auts.ptr))
        !           543:        {
        !           544:                DBG1(DBG_IKE, "no AKA provider found supporting "
        !           545:                         "resynchronization for '%Y'", this->permanent);
        !           546:                return FAILED;
        !           547:        }
        !           548:        this->synchronized = TRUE;
        !           549:        return challenge(this, out);
        !           550: }
        !           551: 
        !           552: /**
        !           553:  * Process EAP-AKA/Response/ClientErrorCode message
        !           554:  */
        !           555: static status_t process_client_error(private_eap_aka_server_t *this,
        !           556:                                                                         simaka_message_t *in)
        !           557: {
        !           558:        enumerator_t *enumerator;
        !           559:        simaka_attribute_t type;
        !           560:        chunk_t data;
        !           561: 
        !           562:        enumerator = in->create_attribute_enumerator(in);
        !           563:        while (enumerator->enumerate(enumerator, &type, &data))
        !           564:        {
        !           565:                if (type == AT_CLIENT_ERROR_CODE)
        !           566:                {
        !           567:                        uint16_t code;
        !           568: 
        !           569:                        memcpy(&code, data.ptr, sizeof(code));
        !           570:                        DBG1(DBG_IKE, "received EAP-AKA client error '%N'",
        !           571:                                 simaka_client_error_names, ntohs(code));
        !           572:                }
        !           573:                else if (!simaka_attribute_skippable(type))
        !           574:                {
        !           575:                        break;
        !           576:                }
        !           577:        }
        !           578:        enumerator->destroy(enumerator);
        !           579:        return FAILED;
        !           580: }
        !           581: 
        !           582: /**
        !           583:  * Process EAP-AKA/Response/AuthenticationReject message
        !           584:  */
        !           585: static status_t process_authentication_reject(private_eap_aka_server_t *this,
        !           586:                                                                                          simaka_message_t *in)
        !           587: {
        !           588:        DBG1(DBG_IKE, "received %N, authentication failed",
        !           589:                 simaka_subtype_names, in->get_subtype(in));
        !           590:        return FAILED;
        !           591: }
        !           592: 
        !           593: METHOD(eap_method_t, process, status_t,
        !           594:        private_eap_aka_server_t *this, eap_payload_t *in, eap_payload_t **out)
        !           595: {
        !           596:        simaka_message_t *message;
        !           597:        status_t status;
        !           598: 
        !           599:        message = simaka_message_create_from_payload(in->get_data(in), this->crypto);
        !           600:        if (!message)
        !           601:        {
        !           602:                return FAILED;
        !           603:        }
        !           604:        if (!message->parse(message))
        !           605:        {
        !           606:                message->destroy(message);
        !           607:                return FAILED;
        !           608:        }
        !           609:        switch (message->get_subtype(message))
        !           610:        {
        !           611:                case AKA_IDENTITY:
        !           612:                        status = process_identity(this, message, out);
        !           613:                        break;
        !           614:                case AKA_CHALLENGE:
        !           615:                        status = process_challenge(this, message);
        !           616:                        break;
        !           617:                case AKA_REAUTHENTICATION:
        !           618:                        status = process_reauthentication(this, message, out);
        !           619:                        break;
        !           620:                case AKA_SYNCHRONIZATION_FAILURE:
        !           621:                        status = process_synchronize(this, message, out);
        !           622:                        break;
        !           623:                case AKA_CLIENT_ERROR:
        !           624:                        status = process_client_error(this, message);
        !           625:                        break;
        !           626:                case AKA_AUTHENTICATION_REJECT:
        !           627:                        status = process_authentication_reject(this, message);
        !           628:                        break;
        !           629:                default:
        !           630:                        DBG1(DBG_IKE, "unable to process EAP-AKA subtype %N",
        !           631:                                 simaka_subtype_names, message->get_subtype(message));
        !           632:                        status = FAILED;
        !           633:                        break;
        !           634:        }
        !           635:        message->destroy(message);
        !           636:        return status;
        !           637: }
        !           638: 
        !           639: METHOD(eap_method_t, get_type, eap_type_t,
        !           640:        private_eap_aka_server_t *this, uint32_t *vendor)
        !           641: {
        !           642:        *vendor = 0;
        !           643:        return EAP_AKA;
        !           644: }
        !           645: 
        !           646: METHOD(eap_method_t, get_msk, status_t,
        !           647:        private_eap_aka_server_t *this, chunk_t *msk)
        !           648: {
        !           649:        if (this->msk.ptr)
        !           650:        {
        !           651:                *msk = this->msk;
        !           652:                return SUCCESS;
        !           653:        }
        !           654:        return FAILED;
        !           655: }
        !           656: 
        !           657: METHOD(eap_method_t, get_identifier, uint8_t,
        !           658:        private_eap_aka_server_t *this)
        !           659: {
        !           660:        return this->identifier;
        !           661: }
        !           662: 
        !           663: METHOD(eap_method_t, set_identifier, void,
        !           664:        private_eap_aka_server_t *this, uint8_t identifier)
        !           665: {
        !           666:        this->identifier = identifier;
        !           667: }
        !           668: 
        !           669: METHOD(eap_method_t, is_mutual, bool,
        !           670:        private_eap_aka_server_t *this)
        !           671: {
        !           672:        return TRUE;
        !           673: }
        !           674: 
        !           675: METHOD(eap_method_t, destroy, void,
        !           676:        private_eap_aka_server_t *this)
        !           677: {
        !           678:        this->crypto->destroy(this->crypto);
        !           679:        this->permanent->destroy(this->permanent);
        !           680:        DESTROY_IF(this->pseudonym);
        !           681:        DESTROY_IF(this->reauth);
        !           682:        free(this->xres.ptr);
        !           683:        free(this->rand.ptr);
        !           684:        free(this->nonce.ptr);
        !           685:        free(this->msk.ptr);
        !           686:        free(this->counter.ptr);
        !           687:        free(this);
        !           688: }
        !           689: 
        !           690: /*
        !           691:  * Described in header.
        !           692:  */
        !           693: eap_aka_server_t *eap_aka_server_create(identification_t *server,
        !           694:                                                                                identification_t *peer)
        !           695: {
        !           696:        private_eap_aka_server_t *this;
        !           697: 
        !           698:        INIT(this,
        !           699:                .public = {
        !           700:                        .interface = {
        !           701:                                .initiate = _initiate,
        !           702:                                .process = _process,
        !           703:                                .get_type = _get_type,
        !           704:                                .is_mutual = _is_mutual,
        !           705:                                .get_msk = _get_msk,
        !           706:                                .get_identifier = _get_identifier,
        !           707:                                .set_identifier = _set_identifier,
        !           708:                                .destroy = _destroy,
        !           709:                        },
        !           710:                },
        !           711:                .crypto = simaka_crypto_create(EAP_AKA),
        !           712:                .mgr = lib->get(lib, "aka-manager"),
        !           713:        );
        !           714: 
        !           715:        if (!this->crypto)
        !           716:        {
        !           717:                free(this);
        !           718:                return NULL;
        !           719:        }
        !           720: 
        !           721:        this->permanent = peer->clone(peer);
        !           722:        this->use_reauth = this->use_pseudonym = this->use_permanent =
        !           723:                lib->settings->get_bool(lib->settings,
        !           724:                                                "%s.plugins.eap-aka.request_identity", TRUE, lib->ns);
        !           725: 
        !           726:        /* generate a non-zero identifier */
        !           727:        do {
        !           728:                this->identifier = random();
        !           729:        } while (!this->identifier);
        !           730: 
        !           731:        return &this->public;
        !           732: }

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