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

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