Annotation of embedaddon/strongswan/src/libcharon/plugins/eap_sim/eap_sim_peer.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2007-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_sim_peer.h"
        !            17: 
        !            18: #include <daemon.h>
        !            19: 
        !            20: #include <simaka_message.h>
        !            21: #include <simaka_manager.h>
        !            22: 
        !            23: /* number of tries we do authenticate */
        !            24: #define MAX_TRIES 3
        !            25: 
        !            26: /* number of triplets for one authentication */
        !            27: #define TRIPLET_COUNT 3
        !            28: 
        !            29: /** length of the AT_NONCE_MT nonce value */
        !            30: #define NONCE_LEN 16
        !            31: 
        !            32: typedef struct private_eap_sim_peer_t private_eap_sim_peer_t;
        !            33: 
        !            34: /**
        !            35:  * Private data of an eap_sim_peer_t object.
        !            36:  */
        !            37: struct private_eap_sim_peer_t {
        !            38: 
        !            39:        /**
        !            40:         * Public authenticator_t interface.
        !            41:         */
        !            42:        eap_sim_peer_t public;
        !            43: 
        !            44:        /**
        !            45:         * SIM backend manager
        !            46:         */
        !            47:        simaka_manager_t *mgr;
        !            48: 
        !            49:        /**
        !            50:         * permanent ID of peer
        !            51:         */
        !            52:        identification_t *permanent;
        !            53: 
        !            54:        /**
        !            55:         * Pseudonym identity the peer uses
        !            56:         */
        !            57:        identification_t *pseudonym;
        !            58: 
        !            59:        /**
        !            60:         * Reauthentication identity the peer uses
        !            61:         */
        !            62:        identification_t *reauth;
        !            63: 
        !            64:        /**
        !            65:         * EAP message identifier
        !            66:         */
        !            67:        uint8_t identifier;
        !            68: 
        !            69:        /**
        !            70:         * EAP-SIM crypto helper
        !            71:         */
        !            72:        simaka_crypto_t *crypto;
        !            73: 
        !            74:        /**
        !            75:         * how many times we try to authenticate
        !            76:         */
        !            77:        int tries;
        !            78: 
        !            79:        /**
        !            80:         * version list received from server
        !            81:         */
        !            82:        chunk_t version_list;
        !            83: 
        !            84:        /**
        !            85:         * Nonce value used in AT_NONCE_MT/AT_NONCE_S
        !            86:         */
        !            87:        chunk_t nonce;
        !            88: 
        !            89:        /**
        !            90:         * MSK, used for EAP-SIM based IKEv2 authentication
        !            91:         */
        !            92:        chunk_t msk;
        !            93: 
        !            94:        /**
        !            95:         * Master key, if reauthentication is used
        !            96:         */
        !            97:        char mk[HASH_SIZE_SHA1];
        !            98: 
        !            99:        /**
        !           100:         * Counter value if reauthentication is used
        !           101:         */
        !           102:        uint16_t counter;
        !           103: };
        !           104: 
        !           105: /* version of SIM protocol we speak */
        !           106: static chunk_t version = chunk_from_chars(0x00,0x01);
        !           107: 
        !           108: /**
        !           109:  * Generate a payload from a message, destroy message
        !           110:  */
        !           111: static bool generate_payload(simaka_message_t *message, chunk_t data,
        !           112:                                                         eap_payload_t **out)
        !           113: {
        !           114:        chunk_t chunk;
        !           115:        bool ok;
        !           116: 
        !           117:        ok = message->generate(message, data, &chunk);
        !           118:        if (ok)
        !           119:        {
        !           120:                *out = eap_payload_create_data_own(chunk);
        !           121:        }
        !           122:        message->destroy(message);
        !           123:        return ok;
        !           124: }
        !           125: 
        !           126: /**
        !           127:  * Create a SIM_CLIENT_ERROR
        !           128:  */
        !           129: static bool create_client_error(private_eap_sim_peer_t *this,
        !           130:                                                                simaka_client_error_t code, eap_payload_t **out)
        !           131: {
        !           132:        simaka_message_t *message;
        !           133:        uint16_t encoded;
        !           134: 
        !           135:        DBG1(DBG_IKE, "sending client error '%N'", simaka_client_error_names, code);
        !           136: 
        !           137:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
        !           138:                                                                        SIM_CLIENT_ERROR, this->crypto);
        !           139:        encoded = htons(code);
        !           140:        message->add_attribute(message, AT_CLIENT_ERROR_CODE,
        !           141:                                                   chunk_create((char*)&encoded, sizeof(encoded)));
        !           142:        return generate_payload(message, chunk_empty, out);
        !           143: }
        !           144: 
        !           145: /**
        !           146:  * process an EAP-SIM/Request/Start message
        !           147:  */
        !           148: static status_t process_start(private_eap_sim_peer_t *this,
        !           149:                                                          simaka_message_t *in, eap_payload_t **out)
        !           150: {
        !           151:        simaka_message_t *message;
        !           152:        enumerator_t *enumerator;
        !           153:        simaka_attribute_t type;
        !           154:        chunk_t data, id = chunk_empty;
        !           155:        rng_t *rng;
        !           156:        bool supported = FALSE;
        !           157:        simaka_attribute_t id_req = 0;
        !           158: 
        !           159:        /* reset previously uses reauthentication/pseudonym data */
        !           160:        this->crypto->clear_keys(this->crypto);
        !           161:        DESTROY_IF(this->pseudonym);
        !           162:        this->pseudonym = NULL;
        !           163:        DESTROY_IF(this->reauth);
        !           164:        this->reauth = NULL;
        !           165: 
        !           166:        enumerator = in->create_attribute_enumerator(in);
        !           167:        while (enumerator->enumerate(enumerator, &type, &data))
        !           168:        {
        !           169:                switch (type)
        !           170:                {
        !           171:                        case AT_VERSION_LIST:
        !           172:                        {
        !           173:                                free(this->version_list.ptr);
        !           174:                                this->version_list = chunk_clone(data);
        !           175:                                while (data.len >= version.len)
        !           176:                                {
        !           177:                                        if (memeq(data.ptr, version.ptr, version.len))
        !           178:                                        {
        !           179:                                                supported = TRUE;
        !           180:                                                break;
        !           181:                                        }
        !           182:                                }
        !           183:                                break;
        !           184:                        }
        !           185:                        case AT_ANY_ID_REQ:
        !           186:                        case AT_FULLAUTH_ID_REQ:
        !           187:                        case AT_PERMANENT_ID_REQ:
        !           188:                                id_req = type;
        !           189:                                break;
        !           190:                        default:
        !           191:                                if (!simaka_attribute_skippable(type))
        !           192:                                {
        !           193:                                        enumerator->destroy(enumerator);
        !           194:                                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           195:                                        {
        !           196:                                                return FAILED;
        !           197:                                        }
        !           198:                                        return NEED_MORE;
        !           199:                                }
        !           200:                                break;
        !           201:                }
        !           202:        }
        !           203:        enumerator->destroy(enumerator);
        !           204: 
        !           205:        if (!supported)
        !           206:        {
        !           207:                DBG1(DBG_IKE, "server does not support EAP-SIM version number 1");
        !           208:                if (!create_client_error(this, SIM_UNSUPPORTED_VERSION, out))
        !           209:                {
        !           210:                        return FAILED;
        !           211:                }
        !           212:                return NEED_MORE;
        !           213:        }
        !           214: 
        !           215:        switch (id_req)
        !           216:        {
        !           217:                case AT_ANY_ID_REQ:
        !           218:                        this->reauth = this->mgr->card_get_reauth(this->mgr,
        !           219:                                                                        this->permanent, this->mk, &this->counter);
        !           220:                        if (this->reauth)
        !           221:                        {
        !           222:                                id = this->reauth->get_encoding(this->reauth);
        !           223:                                break;
        !           224:                        }
        !           225:                        /* FALL */
        !           226:                case AT_FULLAUTH_ID_REQ:
        !           227:                        this->pseudonym = this->mgr->card_get_pseudonym(this->mgr,
        !           228:                                                                                                                        this->permanent);
        !           229:                        if (this->pseudonym)
        !           230:                        {
        !           231:                                id = this->pseudonym->get_encoding(this->pseudonym);
        !           232:                                break;
        !           233:                        }
        !           234:                        /* FALL */
        !           235:                case AT_PERMANENT_ID_REQ:
        !           236:                        id = this->permanent->get_encoding(this->permanent);
        !           237:                        break;
        !           238:                default:
        !           239:                        break;
        !           240:        }
        !           241: 
        !           242:        /* generate AT_NONCE_MT value */
        !           243:        rng = this->crypto->get_rng(this->crypto);
        !           244:        free(this->nonce.ptr);
        !           245:        if (!rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
        !           246:        {
        !           247:                return FAILED;
        !           248:        }
        !           249: 
        !           250:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
        !           251:                                                                        SIM_START, this->crypto);
        !           252:        if (!this->reauth)
        !           253:        {
        !           254:                message->add_attribute(message, AT_SELECTED_VERSION, version);
        !           255:                message->add_attribute(message, AT_NONCE_MT, this->nonce);
        !           256:        }
        !           257:        if (id.len)
        !           258:        {
        !           259:                message->add_attribute(message, AT_IDENTITY, id);
        !           260:        }
        !           261:        if (!generate_payload(message, chunk_empty, out))
        !           262:        {
        !           263:                return FAILED;
        !           264:        }
        !           265:        return NEED_MORE;
        !           266: }
        !           267: 
        !           268: /**
        !           269:  * process an EAP-SIM/Request/Challenge message
        !           270:  */
        !           271: static status_t process_challenge(private_eap_sim_peer_t *this,
        !           272:                                                                  simaka_message_t *in, eap_payload_t **out)
        !           273: {
        !           274:        simaka_message_t *message;
        !           275:        enumerator_t *enumerator;
        !           276:        simaka_attribute_t type;
        !           277:        chunk_t data, rands = chunk_empty, kcs, kc, sreses, sres, mk;
        !           278:        identification_t *id;
        !           279: 
        !           280:        if (this->tries-- <= 0)
        !           281:        {
        !           282:                /* give up without notification. This hack is required as some buggy
        !           283:                 * server implementations won't respect our client-error. */
        !           284:                return FAILED;
        !           285:        }
        !           286: 
        !           287:        enumerator = in->create_attribute_enumerator(in);
        !           288:        while (enumerator->enumerate(enumerator, &type, &data))
        !           289:        {
        !           290:                switch (type)
        !           291:                {
        !           292:                        case AT_RAND:
        !           293:                                rands = data;
        !           294:                                break;
        !           295:                        default:
        !           296:                                if (!simaka_attribute_skippable(type))
        !           297:                                {
        !           298:                                        enumerator->destroy(enumerator);
        !           299:                                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           300:                                        {
        !           301:                                                return FAILED;
        !           302:                                        }
        !           303:                                        return NEED_MORE;
        !           304:                                }
        !           305:                                break;
        !           306:                }
        !           307:        }
        !           308:        enumerator->destroy(enumerator);
        !           309: 
        !           310:        /* excepting two or three RAND, each 16 bytes. We require two valid
        !           311:         * and different RANDs */
        !           312:        if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
        !           313:                memeq_const(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
        !           314:        {
        !           315:                DBG1(DBG_IKE, "no valid AT_RAND received");
        !           316:                if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
        !           317:                {
        !           318:                        return FAILED;
        !           319:                }
        !           320:                return NEED_MORE;
        !           321:        }
        !           322:        /* get two or three KCs/SRESes from SIM using RANDs */
        !           323:        kcs = kc = chunk_alloca(rands.len / 2);
        !           324:        sreses = sres = chunk_alloca(rands.len / 4);
        !           325:        while (rands.len >= SIM_RAND_LEN)
        !           326:        {
        !           327:                if (!this->mgr->card_get_triplet(this->mgr, this->permanent,
        !           328:                                                                                 rands.ptr, sres.ptr, kc.ptr))
        !           329:                {
        !           330:                        DBG1(DBG_IKE, "unable to get EAP-SIM triplet");
        !           331:                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           332:                        {
        !           333:                                return FAILED;
        !           334:                        }
        !           335:                        return NEED_MORE;
        !           336:                }
        !           337:                DBG3(DBG_IKE, "got triplet for RAND %b\n  Kc %b\n  SRES %b",
        !           338:                         rands.ptr, SIM_RAND_LEN, sres.ptr, SIM_SRES_LEN, kc.ptr, SIM_KC_LEN);
        !           339:                kc = chunk_skip(kc, SIM_KC_LEN);
        !           340:                sres = chunk_skip(sres, SIM_SRES_LEN);
        !           341:                rands = chunk_skip(rands, SIM_RAND_LEN);
        !           342:        }
        !           343: 
        !           344:        id = this->permanent;
        !           345:        if (this->pseudonym)
        !           346:        {
        !           347:                id = this->pseudonym;
        !           348:        }
        !           349:        data = chunk_cata("cccc", kcs, this->nonce, this->version_list, version);
        !           350:        chunk_clear(&this->msk);
        !           351:        if (!this->crypto->derive_keys_full(this->crypto, id, data, &mk, &this->msk))
        !           352:        {
        !           353:                return FAILED;
        !           354:        }
        !           355:        memcpy(this->mk, mk.ptr, mk.len);
        !           356:        chunk_clear(&mk);
        !           357: 
        !           358:        /* Verify AT_MAC attribute, signature is over "EAP packet | NONCE_MT", and
        !           359:         * parse() again after key derivation, reading encrypted attributes */
        !           360:        if (!in->verify(in, this->nonce) || !in->parse(in))
        !           361:        {
        !           362:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           363:                {
        !           364:                        return FAILED;
        !           365:                }
        !           366:                return NEED_MORE;
        !           367:        }
        !           368: 
        !           369:        enumerator = in->create_attribute_enumerator(in);
        !           370:        while (enumerator->enumerate(enumerator, &type, &data))
        !           371:        {
        !           372:                switch (type)
        !           373:                {
        !           374:                        case AT_NEXT_REAUTH_ID:
        !           375:                                this->counter = 0;
        !           376:                                id = identification_create_from_data(data);
        !           377:                                this->mgr->card_set_reauth(this->mgr, this->permanent, id,
        !           378:                                                                                   this->mk, this->counter);
        !           379:                                id->destroy(id);
        !           380:                                break;
        !           381:                        case AT_NEXT_PSEUDONYM:
        !           382:                                id = identification_create_from_data(data);
        !           383:                                this->mgr->card_set_pseudonym(this->mgr, this->permanent, id);
        !           384:                                id->destroy(id);
        !           385:                                break;
        !           386:                        default:
        !           387:                                break;
        !           388:                }
        !           389:        }
        !           390:        enumerator->destroy(enumerator);
        !           391: 
        !           392:        /* build response with AT_MAC, built over "EAP packet | n*SRES" */
        !           393:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
        !           394:                                                                        SIM_CHALLENGE, this->crypto);
        !           395:        if (!generate_payload(message, sreses, out))
        !           396:        {
        !           397:                return FAILED;
        !           398:        }
        !           399:        return NEED_MORE;
        !           400: }
        !           401: 
        !           402: /**
        !           403:  * Check if a received counter value is acceptable
        !           404:  */
        !           405: static bool counter_too_small(private_eap_sim_peer_t *this, chunk_t chunk)
        !           406: {
        !           407:        uint16_t counter;
        !           408: 
        !           409:        memcpy(&counter, chunk.ptr, sizeof(counter));
        !           410:        counter = htons(counter);
        !           411:        return counter < this->counter;
        !           412: }
        !           413: 
        !           414: /**
        !           415:  * process an EAP-SIM/Request/Re-Authentication message
        !           416:  */
        !           417: static status_t process_reauthentication(private_eap_sim_peer_t *this,
        !           418:                                                                        simaka_message_t *in, eap_payload_t **out)
        !           419: {
        !           420:        simaka_message_t *message;
        !           421:        enumerator_t *enumerator;
        !           422:        simaka_attribute_t type;
        !           423:        chunk_t data, counter = chunk_empty, nonce = chunk_empty, id = chunk_empty;
        !           424: 
        !           425:        if (!this->reauth)
        !           426:        {
        !           427:                DBG1(DBG_IKE, "received %N, but not expected",
        !           428:                         simaka_subtype_names, SIM_REAUTHENTICATION);
        !           429:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           430:                {
        !           431:                        return FAILED;
        !           432:                }
        !           433:                return NEED_MORE;
        !           434:        }
        !           435: 
        !           436:        if (!this->crypto->derive_keys_reauth(this->crypto,
        !           437:                                                                        chunk_create(this->mk, HASH_SIZE_SHA1)))
        !           438:        {
        !           439:                return FAILED;
        !           440:        }
        !           441: 
        !           442:        /* verify MAC and parse again with decryption key */
        !           443:        if (!in->verify(in, chunk_empty) || !in->parse(in))
        !           444:        {
        !           445:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           446:                {
        !           447:                        return FAILED;
        !           448:                }
        !           449:                return NEED_MORE;
        !           450:        }
        !           451: 
        !           452:        enumerator = in->create_attribute_enumerator(in);
        !           453:        while (enumerator->enumerate(enumerator, &type, &data))
        !           454:        {
        !           455:                switch (type)
        !           456:                {
        !           457:                        case AT_COUNTER:
        !           458:                                counter = data;
        !           459:                                break;
        !           460:                        case AT_NONCE_S:
        !           461:                                nonce = data;
        !           462:                                break;
        !           463:                        case AT_NEXT_REAUTH_ID:
        !           464:                                id = data;
        !           465:                                break;
        !           466:                        default:
        !           467:                                if (!simaka_attribute_skippable(type))
        !           468:                                {
        !           469:                                        enumerator->destroy(enumerator);
        !           470:                                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           471:                                        {
        !           472:                                                return FAILED;
        !           473:                                        }
        !           474:                                        return NEED_MORE;
        !           475:                                }
        !           476:                                break;
        !           477:                }
        !           478:        }
        !           479:        enumerator->destroy(enumerator);
        !           480: 
        !           481:        if (!nonce.len || !counter.len)
        !           482:        {
        !           483:                DBG1(DBG_IKE, "EAP-SIM/Request/Re-Authentication message incomplete");
        !           484:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           485:                {
        !           486:                        return FAILED;
        !           487:                }
        !           488:                return NEED_MORE;
        !           489:        }
        !           490: 
        !           491:        message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
        !           492:                                                                        SIM_REAUTHENTICATION, this->crypto);
        !           493:        if (counter_too_small(this, counter))
        !           494:        {
        !           495:                DBG1(DBG_IKE, "reauthentication counter too small");
        !           496:                message->add_attribute(message, AT_COUNTER_TOO_SMALL, chunk_empty);
        !           497:        }
        !           498:        else
        !           499:        {
        !           500:                chunk_clear(&this->msk);
        !           501:                if (!this->crypto->derive_keys_reauth_msk(this->crypto,
        !           502:                                                this->reauth, counter, nonce,
        !           503:                                                chunk_create(this->mk, HASH_SIZE_SHA1), &this->msk))
        !           504:                {
        !           505:                        message->destroy(message);
        !           506:                        return FAILED;
        !           507:                }
        !           508:                if (id.len)
        !           509:                {
        !           510:                        identification_t *reauth;
        !           511: 
        !           512:                        reauth = identification_create_from_data(data);
        !           513:                        this->mgr->card_set_reauth(this->mgr, this->permanent, reauth,
        !           514:                                                                           this->mk, this->counter);
        !           515:                        reauth->destroy(reauth);
        !           516:                }
        !           517:        }
        !           518:        message->add_attribute(message, AT_COUNTER, counter);
        !           519:        if (!generate_payload(message, nonce, out))
        !           520:        {
        !           521:                return FAILED;
        !           522:        }
        !           523:        return NEED_MORE;
        !           524: }
        !           525: 
        !           526: /**
        !           527:  * process an EAP-SIM/Request/Notification message
        !           528:  */
        !           529: static status_t process_notification(private_eap_sim_peer_t *this,
        !           530:                                                                         simaka_message_t *in, eap_payload_t **out)
        !           531: {
        !           532:        simaka_message_t *message;
        !           533:        enumerator_t *enumerator;
        !           534:        simaka_attribute_t type;
        !           535:        chunk_t data;
        !           536:        bool success = TRUE;
        !           537: 
        !           538:        enumerator = in->create_attribute_enumerator(in);
        !           539:        while (enumerator->enumerate(enumerator, &type, &data))
        !           540:        {
        !           541:                if (type == AT_NOTIFICATION)
        !           542:                {
        !           543:                        uint16_t code;
        !           544: 
        !           545:                        memcpy(&code, data.ptr, sizeof(code));
        !           546:                        code = ntohs(code);
        !           547: 
        !           548:                        /* test success bit */
        !           549:                        if (!(data.ptr[0] & 0x80))
        !           550:                        {
        !           551:                                DBG1(DBG_IKE, "received EAP-SIM notification error '%N'",
        !           552:                                         simaka_notification_names, code);
        !           553:                        }
        !           554:                        else
        !           555:                        {
        !           556:                                DBG1(DBG_IKE, "received EAP-SIM notification '%N'",
        !           557:                                         simaka_notification_names, code);
        !           558:                        }
        !           559:                }
        !           560:                else if (!simaka_attribute_skippable(type))
        !           561:                {
        !           562:                        success = FALSE;
        !           563:                        break;
        !           564:                }
        !           565:        }
        !           566:        enumerator->destroy(enumerator);
        !           567: 
        !           568:        if (success)
        !           569:        {       /* empty notification reply */
        !           570:                message = simaka_message_create(FALSE, this->identifier, EAP_SIM,
        !           571:                                                                                SIM_NOTIFICATION, this->crypto);
        !           572:                if (!generate_payload(message, chunk_empty, out))
        !           573:                {
        !           574:                        return FAILED;
        !           575:                }
        !           576:        }
        !           577:        else
        !           578:        {
        !           579:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           580:                {
        !           581:                        return FAILED;
        !           582:                }
        !           583:        }
        !           584:        return NEED_MORE;
        !           585: }
        !           586: 
        !           587: METHOD(eap_method_t, process, status_t,
        !           588:        private_eap_sim_peer_t *this, eap_payload_t *in, eap_payload_t **out)
        !           589: {
        !           590:        simaka_message_t *message;
        !           591:        status_t status;
        !           592: 
        !           593:        /* store received EAP message identifier */
        !           594:        this->identifier = in->get_identifier(in);
        !           595: 
        !           596:        message = simaka_message_create_from_payload(in->get_data(in), this->crypto);
        !           597:        if (!message)
        !           598:        {
        !           599:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           600:                {
        !           601:                        return FAILED;
        !           602:                }
        !           603:                return NEED_MORE;
        !           604:        }
        !           605:        if (!message->parse(message))
        !           606:        {
        !           607:                message->destroy(message);
        !           608:                if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           609:                {
        !           610:                        return FAILED;
        !           611:                }
        !           612:                return NEED_MORE;
        !           613:        }
        !           614:        switch (message->get_subtype(message))
        !           615:        {
        !           616:                case SIM_START:
        !           617:                        status = process_start(this, message, out);
        !           618:                        break;
        !           619:                case SIM_CHALLENGE:
        !           620:                        status = process_challenge(this, message, out);
        !           621:                        break;
        !           622:                case SIM_REAUTHENTICATION:
        !           623:                        status = process_reauthentication(this, message, out);
        !           624:                        break;
        !           625:                case SIM_NOTIFICATION:
        !           626:                        status = process_notification(this, message, out);
        !           627:                        break;
        !           628:                default:
        !           629:                        DBG1(DBG_IKE, "unable to process EAP-SIM subtype %N",
        !           630:                                 simaka_subtype_names, message->get_subtype(message));
        !           631:                        if (!create_client_error(this, SIM_UNABLE_TO_PROCESS, out))
        !           632:                        {
        !           633:                                status = FAILED;
        !           634:                        }
        !           635:                        else
        !           636:                        {
        !           637:                                status = NEED_MORE;
        !           638:                        }
        !           639:                        break;
        !           640:        }
        !           641:        message->destroy(message);
        !           642:        return status;
        !           643: }
        !           644: 
        !           645: METHOD(eap_method_t, initiate, status_t,
        !           646:        private_eap_sim_peer_t *this, eap_payload_t **out)
        !           647: {
        !           648:        /* peer never initiates */
        !           649:        return FAILED;
        !           650: }
        !           651: 
        !           652: METHOD(eap_method_t, get_type, eap_type_t,
        !           653:        private_eap_sim_peer_t *this, uint32_t *vendor)
        !           654: {
        !           655:        *vendor = 0;
        !           656:        return EAP_SIM;
        !           657: }
        !           658: 
        !           659: METHOD(eap_method_t, get_msk, status_t,
        !           660:        private_eap_sim_peer_t *this, chunk_t *msk)
        !           661: {
        !           662:        if (this->msk.ptr)
        !           663:        {
        !           664:                *msk = this->msk;
        !           665:                return SUCCESS;
        !           666:        }
        !           667:        return FAILED;
        !           668: }
        !           669: 
        !           670: METHOD(eap_method_t, get_identifier, uint8_t,
        !           671:        private_eap_sim_peer_t *this)
        !           672: {
        !           673:        return this->identifier;
        !           674: }
        !           675: 
        !           676: METHOD(eap_method_t, set_identifier, void,
        !           677:        private_eap_sim_peer_t *this, uint8_t identifier)
        !           678: {
        !           679:        this->identifier = identifier;
        !           680: }
        !           681: 
        !           682: METHOD(eap_method_t, is_mutual, bool,
        !           683:        private_eap_sim_peer_t *this)
        !           684: {
        !           685:        return TRUE;
        !           686: }
        !           687: 
        !           688: METHOD(eap_method_t, destroy, void,
        !           689:        private_eap_sim_peer_t *this)
        !           690: {
        !           691:        this->permanent->destroy(this->permanent);
        !           692:        DESTROY_IF(this->pseudonym);
        !           693:        DESTROY_IF(this->reauth);
        !           694:        this->crypto->destroy(this->crypto);
        !           695:        free(this->version_list.ptr);
        !           696:        free(this->nonce.ptr);
        !           697:        free(this->msk.ptr);
        !           698:        free(this);
        !           699: }
        !           700: 
        !           701: /*
        !           702:  * Described in header.
        !           703:  */
        !           704: eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
        !           705:                                                                        identification_t *peer)
        !           706: {
        !           707:        private_eap_sim_peer_t *this;
        !           708: 
        !           709:        INIT(this,
        !           710:                .public = {
        !           711:                        .interface = {
        !           712:                                .initiate = _initiate,
        !           713:                                .process = _process,
        !           714:                                .get_type = _get_type,
        !           715:                                .is_mutual = _is_mutual,
        !           716:                                .get_msk = _get_msk,
        !           717:                                .get_identifier = _get_identifier,
        !           718:                                .set_identifier = _set_identifier,
        !           719:                                .destroy = _destroy,
        !           720:                        },
        !           721:                },
        !           722:                .crypto = simaka_crypto_create(EAP_SIM),
        !           723:                .mgr = lib->get(lib, "sim-manager"),
        !           724:        );
        !           725: 
        !           726:        if (!this->crypto)
        !           727:        {
        !           728:                free(this);
        !           729:                return NULL;
        !           730:        }
        !           731: 
        !           732:        this->permanent = peer->clone(peer);
        !           733:        this->tries = MAX_TRIES;
        !           734: 
        !           735:        return &this->public;
        !           736: }

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