Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2012-2018 Tobias Brunner
        !             3:  * Copyright (C) 2006-2009 Martin Willi
        !             4:  * HSR Hochschule fuer Technik Rapperswil
        !             5:  *
        !             6:  * This program is free software; you can redistribute it and/or modify it
        !             7:  * under the terms of the GNU General Public License as published by the
        !             8:  * Free Software Foundation; either version 2 of the License, or (at your
        !             9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            10:  *
        !            11:  * This program is distributed in the hope that it will be useful, but
        !            12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            14:  * for more details.
        !            15:  */
        !            16: 
        !            17: #include "eap_authenticator.h"
        !            18: 
        !            19: #include <daemon.h>
        !            20: #include <sa/ikev2/keymat_v2.h>
        !            21: #include <sa/eap/eap_method.h>
        !            22: #include <encoding/payloads/auth_payload.h>
        !            23: #include <encoding/payloads/eap_payload.h>
        !            24: 
        !            25: typedef struct private_eap_authenticator_t private_eap_authenticator_t;
        !            26: 
        !            27: /**
        !            28:  * Private data of an eap_authenticator_t object.
        !            29:  */
        !            30: struct private_eap_authenticator_t {
        !            31: 
        !            32:        /**
        !            33:         * Public authenticator_t interface.
        !            34:         */
        !            35:        eap_authenticator_t public;
        !            36: 
        !            37:        /**
        !            38:         * Assigned IKE_SA
        !            39:         */
        !            40:        ike_sa_t *ike_sa;
        !            41: 
        !            42:        /**
        !            43:         * others nonce to include in AUTH calculation
        !            44:         */
        !            45:        chunk_t received_nonce;
        !            46: 
        !            47:        /**
        !            48:         * our nonce to include in AUTH calculation
        !            49:         */
        !            50:        chunk_t sent_nonce;
        !            51: 
        !            52:        /**
        !            53:         * others IKE_SA_INIT message data to include in AUTH calculation
        !            54:         */
        !            55:        chunk_t received_init;
        !            56: 
        !            57:        /**
        !            58:         * our IKE_SA_INIT message data to include in AUTH calculation
        !            59:         */
        !            60:        chunk_t sent_init;
        !            61: 
        !            62:        /**
        !            63:         * Reserved bytes of ID payload
        !            64:         */
        !            65:        char reserved[3];
        !            66: 
        !            67:        /**
        !            68:         * PPK to use
        !            69:         */
        !            70:        chunk_t ppk;
        !            71: 
        !            72:        /**
        !            73:         * Add a NO_PPK_AUTH notify
        !            74:         */
        !            75:        bool no_ppk_auth;
        !            76: 
        !            77:        /**
        !            78:         * Current EAP method processing
        !            79:         */
        !            80:        eap_method_t *method;
        !            81: 
        !            82:        /**
        !            83:         * MSK used to build and verify auth payload
        !            84:         */
        !            85:        chunk_t msk;
        !            86: 
        !            87:        /**
        !            88:         * EAP authentication method completed successfully
        !            89:         */
        !            90:        bool eap_complete;
        !            91: 
        !            92:        /**
        !            93:         * Set if we require mutual EAP due EAP-only authentication
        !            94:         */
        !            95:        bool require_mutual;
        !            96: 
        !            97:        /**
        !            98:         * authentication payload verified successfully
        !            99:         */
        !           100:        bool auth_complete;
        !           101: 
        !           102:        /**
        !           103:         * generated EAP payload
        !           104:         */
        !           105:        eap_payload_t *eap_payload;
        !           106: 
        !           107:        /**
        !           108:         * EAP identity of peer
        !           109:         */
        !           110:        identification_t *eap_identity;
        !           111: };
        !           112: 
        !           113: /**
        !           114:  * load an EAP method
        !           115:  */
        !           116: static eap_method_t *load_method(private_eap_authenticator_t *this,
        !           117:                                                        eap_type_t type, uint32_t vendor, eap_role_t role)
        !           118: {
        !           119:        identification_t *server, *peer, *aaa;
        !           120:        auth_cfg_t *auth;
        !           121: 
        !           122:        if (role == EAP_SERVER)
        !           123:        {
        !           124:                server = this->ike_sa->get_my_id(this->ike_sa);
        !           125:                peer = this->ike_sa->get_other_id(this->ike_sa);
        !           126:                auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           127:        }
        !           128:        else
        !           129:        {
        !           130:                server = this->ike_sa->get_other_id(this->ike_sa);
        !           131:                peer = this->ike_sa->get_my_id(this->ike_sa);
        !           132:                auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
        !           133:        }
        !           134:        if (this->eap_identity)
        !           135:        {
        !           136:                peer = this->eap_identity;
        !           137:        }
        !           138:        aaa = auth->get(auth, AUTH_RULE_AAA_IDENTITY);
        !           139:        if (aaa)
        !           140:        {
        !           141:                server = aaa;
        !           142:        }
        !           143:        return charon->eap->create_instance(charon->eap, type, vendor,
        !           144:                                                                                role, server, peer);
        !           145: }
        !           146: 
        !           147: /**
        !           148:  * Initiate EAP conversation as server
        !           149:  */
        !           150: static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this,
        !           151:                                                                                  bool do_identity)
        !           152: {
        !           153:        auth_cfg_t *auth;
        !           154:        eap_type_t type;
        !           155:        identification_t *id;
        !           156:        uint32_t vendor;
        !           157:        eap_payload_t *out;
        !           158:        char *action;
        !           159: 
        !           160:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           161: 
        !           162:        /* initiate EAP-Identity exchange if required */
        !           163:        if (!this->eap_identity && do_identity)
        !           164:        {
        !           165:                id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
        !           166:                if (id)
        !           167:                {
        !           168:                        if (id->get_type(id) == ID_ANY)
        !           169:                        {
        !           170:                                this->method = load_method(this, EAP_IDENTITY, 0, EAP_SERVER);
        !           171:                                if (this->method)
        !           172:                                {
        !           173:                                        if (this->method->initiate(this->method, &out) == NEED_MORE)
        !           174:                                        {
        !           175:                                                DBG1(DBG_IKE, "initiating %N method (id 0x%02X)",
        !           176:                                                         eap_type_names, EAP_IDENTITY,
        !           177:                                                         this->method->get_identifier(this->method));
        !           178:                                                return out;
        !           179:                                        }
        !           180:                                        this->method->destroy(this->method);
        !           181:                                }
        !           182:                                DBG1(DBG_IKE, "EAP-Identity request configured, "
        !           183:                                         "but not supported");
        !           184:                        }
        !           185:                        else
        !           186:                        {
        !           187:                                DBG1(DBG_IKE, "using configured EAP-Identity %Y", id);
        !           188:                                this->eap_identity = id->clone(id);
        !           189:                        }
        !           190:                }
        !           191:        }
        !           192:        /* invoke real EAP method */
        !           193:        type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
        !           194:        vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
        !           195:        action = "loading";
        !           196:        this->method = load_method(this, type, vendor, EAP_SERVER);
        !           197:        if (this->method)
        !           198:        {
        !           199:                action = "initiating";
        !           200:                if (this->method->initiate(this->method, &out) == NEED_MORE)
        !           201:                {
        !           202:                        type = this->method->get_type(this->method, &vendor);
        !           203:                        if (vendor)
        !           204:                        {
        !           205:                                DBG1(DBG_IKE, "initiating EAP vendor type %d-%d method (id 0x%02X)",
        !           206:                                         type, vendor, out->get_identifier(out));
        !           207:                        }
        !           208:                        else
        !           209:                        {
        !           210:                                DBG1(DBG_IKE, "initiating %N method (id 0x%02X)", eap_type_names,
        !           211:                                         type, out->get_identifier(out));
        !           212:                        }
        !           213:                        return out;
        !           214:                }
        !           215:                /* type might have changed for virtual methods */
        !           216:                type = this->method->get_type(this->method, &vendor);
        !           217:        }
        !           218:        if (vendor)
        !           219:        {
        !           220:                DBG1(DBG_IKE, "%s EAP vendor type %d-%d method failed",
        !           221:                                          action, type, vendor);
        !           222:        }
        !           223:        else
        !           224:        {
        !           225:                DBG1(DBG_IKE, "%s %N method failed", action, eap_type_names, type);
        !           226:        }
        !           227:        return eap_payload_create_code(EAP_FAILURE, 0);
        !           228: }
        !           229: 
        !           230: /**
        !           231:  * Replace the existing EAP-Identity in other auth config
        !           232:  */
        !           233: static void replace_eap_identity(private_eap_authenticator_t *this)
        !           234: {
        !           235:        identification_t *eap_identity;
        !           236:        auth_cfg_t *cfg;
        !           237: 
        !           238:        eap_identity = this->eap_identity->clone(this->eap_identity);
        !           239:        cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           240:        cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, eap_identity);
        !           241: }
        !           242: 
        !           243: /**
        !           244:  * Handle EAP exchange as server
        !           245:  */
        !           246: static eap_payload_t* server_process_eap(private_eap_authenticator_t *this,
        !           247:                                                                                 eap_payload_t *in)
        !           248: {
        !           249:        eap_type_t type, received_type, conf_type;
        !           250:        uint32_t vendor, received_vendor, conf_vendor;
        !           251:        eap_payload_t *out;
        !           252:        auth_cfg_t *auth;
        !           253: 
        !           254:        if (in->get_code(in) != EAP_RESPONSE)
        !           255:        {
        !           256:                DBG1(DBG_IKE, "received %N, sending %N",
        !           257:                         eap_code_names, in->get_code(in), eap_code_names, EAP_FAILURE);
        !           258:                return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
        !           259:        }
        !           260: 
        !           261:        type = this->method->get_type(this->method, &vendor);
        !           262:        received_type = in->get_type(in, &received_vendor);
        !           263:        if (type != received_type || vendor != received_vendor)
        !           264:        {
        !           265:                if (received_vendor == 0 && received_type == EAP_NAK)
        !           266:                {
        !           267:                        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           268:                        conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
        !           269:                        conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
        !           270:                        if ((type == EAP_IDENTITY && !vendor) ||
        !           271:                                (type == conf_type && vendor == conf_vendor))
        !           272:                        {
        !           273:                                DBG1(DBG_IKE, "received %N, sending %N",
        !           274:                                         eap_type_names, EAP_NAK, eap_code_names, EAP_FAILURE);
        !           275:                                return eap_payload_create_code(EAP_FAILURE,
        !           276:                                                                                           in->get_identifier(in));
        !           277:                        }
        !           278:                        /* virtual methods handle NAKs in process() */
        !           279:                }
        !           280:                else
        !           281:                {
        !           282:                        DBG1(DBG_IKE, "received invalid EAP response, sending %N",
        !           283:                                 eap_code_names, EAP_FAILURE);
        !           284:                        return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
        !           285:                }
        !           286:        }
        !           287: 
        !           288:        switch (this->method->process(this->method, in, &out))
        !           289:        {
        !           290:                case NEED_MORE:
        !           291:                        return out;
        !           292:                case SUCCESS:
        !           293:                        if (!vendor && type == EAP_IDENTITY)
        !           294:                        {
        !           295:                                chunk_t data;
        !           296: 
        !           297:                                if (this->method->get_msk(this->method, &data) == SUCCESS)
        !           298:                                {
        !           299:                                        this->eap_identity = identification_create_from_data(data);
        !           300:                                        DBG1(DBG_IKE, "received EAP identity '%Y'",
        !           301:                                                 this->eap_identity);
        !           302:                                        replace_eap_identity(this);
        !           303:                                }
        !           304:                                /* restart EAP exchange, but with real method */
        !           305:                                this->method->destroy(this->method);
        !           306:                                return server_initiate_eap(this, FALSE);
        !           307:                        }
        !           308:                        if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
        !           309:                        {
        !           310:                                this->msk = chunk_clone(this->msk);
        !           311:                        }
        !           312:                        if (vendor)
        !           313:                        {
        !           314:                                DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
        !           315:                                         "%sMSK established", type, vendor,
        !           316:                                         this->msk.ptr ? "" : "no ");
        !           317:                        }
        !           318:                        else
        !           319:                        {
        !           320:                                DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
        !           321:                                         eap_type_names, type, this->msk.ptr ? "" : "no ");
        !           322:                        }
        !           323:                        this->ike_sa->set_condition(this->ike_sa, COND_EAP_AUTHENTICATED,
        !           324:                                                                                TRUE);
        !           325:                        this->eap_complete = TRUE;
        !           326:                        return eap_payload_create_code(EAP_SUCCESS, in->get_identifier(in));
        !           327:                case FAILED:
        !           328:                default:
        !           329:                        /* type might have changed for virtual methods */
        !           330:                        type = this->method->get_type(this->method, &vendor);
        !           331:                        if (vendor)
        !           332:                        {
        !           333:                                DBG1(DBG_IKE, "EAP vendor specific method %d-%d failed for "
        !           334:                                         "peer %Y", type, vendor,
        !           335:                                         this->ike_sa->get_other_id(this->ike_sa));
        !           336:                        }
        !           337:                        else
        !           338:                        {
        !           339:                                DBG1(DBG_IKE, "EAP method %N failed for peer %Y",
        !           340:                                         eap_type_names, type,
        !           341:                                         this->ike_sa->get_other_id(this->ike_sa));
        !           342:                        }
        !           343:                        return eap_payload_create_code(EAP_FAILURE, in->get_identifier(in));
        !           344:        }
        !           345: }
        !           346: 
        !           347: /**
        !           348:  * Processing method for a peer
        !           349:  */
        !           350: static eap_payload_t* client_process_eap(private_eap_authenticator_t *this,
        !           351:                                                                                 eap_payload_t *in)
        !           352: {
        !           353:        eap_type_t type, conf_type;
        !           354:        uint32_t vendor, conf_vendor;
        !           355:        auth_cfg_t *auth;
        !           356:        eap_payload_t *out;
        !           357:        identification_t *id;
        !           358: 
        !           359:        type = in->get_type(in, &vendor);
        !           360: 
        !           361:        if (!vendor && type == EAP_IDENTITY)
        !           362:        {
        !           363:                DESTROY_IF(this->eap_identity);
        !           364:                auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
        !           365:                id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
        !           366:                if (!id || id->get_type(id) == ID_ANY)
        !           367:                {
        !           368:                        id = this->ike_sa->get_my_id(this->ike_sa);
        !           369:                }
        !           370:                DBG1(DBG_IKE, "server requested %N (id 0x%02X), sending '%Y'",
        !           371:                         eap_type_names, type, in->get_identifier(in), id);
        !           372:                this->eap_identity = id->clone(id);
        !           373: 
        !           374:                this->method = load_method(this, type, vendor, EAP_PEER);
        !           375:                if (this->method)
        !           376:                {
        !           377:                        if (this->method->process(this->method, in, &out) == SUCCESS)
        !           378:                        {
        !           379:                                this->method->destroy(this->method);
        !           380:                                this->method = NULL;
        !           381:                                return out;
        !           382:                        }
        !           383:                        this->method->destroy(this->method);
        !           384:                        this->method = NULL;
        !           385:                }
        !           386:                /* FIXME: sending a Nak is not correct here as EAP_IDENTITY (1) is no
        !           387:                 * EAP method (types 3-253, 255) */
        !           388:                DBG1(DBG_IKE, "%N not supported, sending EAP_NAK",
        !           389:                         eap_type_names, type);
        !           390:                return eap_payload_create_nak(in->get_identifier(in), 0, 0, FALSE);
        !           391:        }
        !           392:        if (this->method == NULL)
        !           393:        {
        !           394:                if (vendor)
        !           395:                {
        !           396:                        DBG1(DBG_IKE, "server requested vendor specific EAP method %d-%d ",
        !           397:                                                  "(id 0x%02X)", type, vendor, in->get_identifier(in));
        !           398:                }
        !           399:                else
        !           400:                {
        !           401:                        DBG1(DBG_IKE, "server requested %N authentication (id 0x%02X)",
        !           402:                                 eap_type_names, type, in->get_identifier(in));
        !           403:                }
        !           404:                auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
        !           405:                conf_type = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE);
        !           406:                conf_vendor = (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR);
        !           407:                if (conf_type != EAP_NAK &&
        !           408:                   (conf_type != type || conf_vendor != vendor))
        !           409:                {
        !           410:                        if (conf_vendor)
        !           411:                        {
        !           412:                                DBG1(DBG_IKE, "requesting EAP method %d-%d, sending EAP_NAK",
        !           413:                                         conf_type, conf_vendor);
        !           414:                        }
        !           415:                        else
        !           416:                        {
        !           417:                                DBG1(DBG_IKE, "requesting %N authentication, sending EAP_NAK",
        !           418:                                         eap_type_names, conf_type);
        !           419:                        }
        !           420:                        return eap_payload_create_nak(in->get_identifier(in), conf_type,
        !           421:                                                                                  conf_vendor, in->is_expanded(in));
        !           422:                }
        !           423:                this->method = load_method(this, type, vendor, EAP_PEER);
        !           424:                if (!this->method)
        !           425:                {
        !           426:                        DBG1(DBG_IKE, "EAP method not supported, sending EAP_NAK");
        !           427:                        return eap_payload_create_nak(in->get_identifier(in), 0, 0,
        !           428:                                                                                  in->is_expanded(in));
        !           429:                }
        !           430:        }
        !           431: 
        !           432:        type = this->method->get_type(this->method, &vendor);
        !           433: 
        !           434:        if (this->method->process(this->method, in, &out) == NEED_MORE)
        !           435:        {       /* client methods should never return SUCCESS */
        !           436:                return out;
        !           437:        }
        !           438: 
        !           439:        if (vendor)
        !           440:        {
        !           441:                DBG1(DBG_IKE, "vendor specific EAP method %d-%d failed", type, vendor);
        !           442:        }
        !           443:        else
        !           444:        {
        !           445:                DBG1(DBG_IKE, "%N method failed", eap_type_names, type);
        !           446:        }
        !           447:        return NULL;
        !           448: }
        !           449: 
        !           450: /**
        !           451:  * Verify AUTH payload
        !           452:  */
        !           453: static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
        !           454:                                                chunk_t nonce, chunk_t init)
        !           455: {
        !           456:        auth_payload_t *auth_payload;
        !           457:        notify_payload_t *notify;
        !           458:        chunk_t auth_data, recv_auth_data;
        !           459:        identification_t *other_id;
        !           460:        auth_cfg_t *auth;
        !           461:        keymat_v2_t *keymat;
        !           462:        eap_type_t type;
        !           463:        uint32_t vendor;
        !           464: 
        !           465:        auth_payload = (auth_payload_t*)message->get_payload(message,
        !           466:                                                                                                                 PLV2_AUTH);
        !           467:        if (!auth_payload)
        !           468:        {
        !           469:                DBG1(DBG_IKE, "AUTH payload missing");
        !           470:                return FALSE;
        !           471:        }
        !           472:        recv_auth_data = auth_payload->get_data(auth_payload);
        !           473: 
        !           474:        if (this->ike_sa->supports_extension(this->ike_sa, EXT_PPK) &&
        !           475:                !this->ppk.ptr)
        !           476:        {       /* look for a NO_PPK_AUTH notify if we have no PPK */
        !           477:                notify = message->get_notify(message, NO_PPK_AUTH);
        !           478:                if (notify)
        !           479:                {
        !           480:                        DBG1(DBG_IKE, "no PPK available, using NO_PPK_AUTH notify");
        !           481:                        recv_auth_data = notify->get_notification_data(notify);
        !           482:                }
        !           483:        }
        !           484: 
        !           485:        other_id = this->ike_sa->get_other_id(this->ike_sa);
        !           486:        keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
        !           487:        if (!keymat->get_psk_sig(keymat, TRUE, init, nonce, this->msk, this->ppk,
        !           488:                                                         other_id, this->reserved, &auth_data))
        !           489:        {
        !           490:                return FALSE;
        !           491:        }
        !           492:        if (!auth_data.len || !chunk_equals_const(auth_data, recv_auth_data))
        !           493:        {
        !           494:                DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
        !           495:                         this->msk.ptr ? "" : "out");
        !           496:                chunk_free(&auth_data);
        !           497:                return FALSE;
        !           498:        }
        !           499:        chunk_free(&auth_data);
        !           500: 
        !           501:        DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
        !           502:                 other_id, auth_class_names, AUTH_CLASS_EAP);
        !           503:        this->auth_complete = TRUE;
        !           504:        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           505:        auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
        !           506: 
        !           507:        type = this->method->get_type(this->method, &vendor);
        !           508:        auth->add(auth, AUTH_RULE_EAP_TYPE, type);
        !           509:        if (vendor)
        !           510:        {
        !           511:                auth->add(auth, AUTH_RULE_EAP_VENDOR, vendor);
        !           512:        }
        !           513:        return TRUE;
        !           514: }
        !           515: 
        !           516: /**
        !           517:  * Build AUTH payload
        !           518:  */
        !           519: static bool build_auth(private_eap_authenticator_t *this, message_t *message,
        !           520:                                           chunk_t nonce, chunk_t init)
        !           521: {
        !           522:        auth_payload_t *auth_payload;
        !           523:        identification_t *my_id;
        !           524:        chunk_t auth_data;
        !           525:        keymat_v2_t *keymat;
        !           526: 
        !           527:        my_id = this->ike_sa->get_my_id(this->ike_sa);
        !           528:        keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
        !           529: 
        !           530:        DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N",
        !           531:                 my_id, auth_class_names, AUTH_CLASS_EAP);
        !           532: 
        !           533:        if (!keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk, this->ppk,
        !           534:                                                         my_id, this->reserved, &auth_data))
        !           535:        {
        !           536:                return FALSE;
        !           537:        }
        !           538:        auth_payload = auth_payload_create();
        !           539:        auth_payload->set_auth_method(auth_payload, AUTH_PSK);
        !           540:        auth_payload->set_data(auth_payload, auth_data);
        !           541:        message->add_payload(message, (payload_t*)auth_payload);
        !           542:        chunk_free(&auth_data);
        !           543: 
        !           544:        if (this->no_ppk_auth)
        !           545:        {
        !           546:                if (!keymat->get_psk_sig(keymat, FALSE, init, nonce, this->msk,
        !           547:                                                        chunk_empty, my_id, this->reserved, &auth_data))
        !           548:                {
        !           549:                        DBG1(DBG_IKE, "failed adding NO_PPK_AUTH notify");
        !           550:                        return FALSE;
        !           551:                }
        !           552:                message->add_notify(message, FALSE, NO_PPK_AUTH, auth_data);
        !           553:                chunk_free(&auth_data);
        !           554:        }
        !           555:        return TRUE;
        !           556: }
        !           557: 
        !           558: METHOD(authenticator_t, process_server, status_t,
        !           559:        private_eap_authenticator_t *this, message_t *message)
        !           560: {
        !           561:        eap_payload_t *eap_payload;
        !           562: 
        !           563:        if (this->eap_complete)
        !           564:        {
        !           565:                if (!verify_auth(this, message, this->sent_nonce, this->received_init))
        !           566:                {
        !           567:                        return FAILED;
        !           568:                }
        !           569:                if (this->method->get_auth)
        !           570:                {
        !           571:                        auth_cfg_t *auth;
        !           572: 
        !           573:                        auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
        !           574:                        auth->merge(auth, this->method->get_auth(this->method), FALSE);
        !           575:                }
        !           576:                return NEED_MORE;
        !           577:        }
        !           578: 
        !           579:        if (!this->method)
        !           580:        {
        !           581:                this->eap_payload = server_initiate_eap(this, TRUE);
        !           582:        }
        !           583:        else
        !           584:        {
        !           585:                eap_payload = (eap_payload_t*)message->get_payload(message,
        !           586:                                                                                                        PLV2_EAP);
        !           587:                if (!eap_payload)
        !           588:                {
        !           589:                        return FAILED;
        !           590:                }
        !           591:                this->eap_payload = server_process_eap(this, eap_payload);
        !           592:        }
        !           593:        return NEED_MORE;
        !           594: }
        !           595: 
        !           596: METHOD(authenticator_t, build_server, status_t,
        !           597:        private_eap_authenticator_t *this, message_t *message)
        !           598: {
        !           599:        if (this->eap_payload)
        !           600:        {
        !           601:                eap_code_t code;
        !           602: 
        !           603:                code = this->eap_payload->get_code(this->eap_payload);
        !           604:                message->add_payload(message, (payload_t*)this->eap_payload);
        !           605:                this->eap_payload = NULL;
        !           606:                if (code == EAP_FAILURE)
        !           607:                {
        !           608:                        return FAILED;
        !           609:                }
        !           610:                return NEED_MORE;
        !           611:        }
        !           612:        if (this->eap_complete && this->auth_complete &&
        !           613:                build_auth(this, message, this->received_nonce, this->sent_init))
        !           614:        {
        !           615:                return SUCCESS;
        !           616:        }
        !           617:        return FAILED;
        !           618: }
        !           619: 
        !           620: METHOD(authenticator_t, process_client, status_t,
        !           621:        private_eap_authenticator_t *this, message_t *message)
        !           622: {
        !           623:        eap_payload_t *eap_payload;
        !           624: 
        !           625:        if (this->eap_complete)
        !           626:        {
        !           627:                if (!verify_auth(this, message, this->sent_nonce, this->received_init))
        !           628:                {
        !           629:                        return FAILED;
        !           630:                }
        !           631:                if (this->require_mutual && !this->method->is_mutual(this->method))
        !           632:                {       /* we require mutual authentication due to EAP-only */
        !           633:                        uint32_t vendor;
        !           634: 
        !           635:                        DBG1(DBG_IKE, "EAP-only authentication requires a mutual and "
        !           636:                                 "MSK deriving EAP method, but %N is not",
        !           637:                                 eap_type_names, this->method->get_type(this->method, &vendor));
        !           638:                        return FAILED;
        !           639:                }
        !           640:                return SUCCESS;
        !           641:        }
        !           642: 
        !           643:        eap_payload = (eap_payload_t*)message->get_payload(message,
        !           644:                                                                                                        PLV2_EAP);
        !           645:        if (eap_payload)
        !           646:        {
        !           647:                switch (eap_payload->get_code(eap_payload))
        !           648:                {
        !           649:                        case EAP_REQUEST:
        !           650:                        {
        !           651:                                this->eap_payload = client_process_eap(this, eap_payload);
        !           652:                                if (this->eap_payload)
        !           653:                                {
        !           654:                                        return NEED_MORE;
        !           655:                                }
        !           656:                                return FAILED;
        !           657:                        }
        !           658:                        case EAP_SUCCESS:
        !           659:                        {
        !           660:                                eap_type_t type;
        !           661:                                uint32_t vendor;
        !           662:                                auth_cfg_t *cfg;
        !           663: 
        !           664:                                if (this->method->get_msk(this->method, &this->msk) == SUCCESS)
        !           665:                                {
        !           666:                                        this->msk = chunk_clone(this->msk);
        !           667:                                }
        !           668:                                type = this->method->get_type(this->method, &vendor);
        !           669:                                if (vendor)
        !           670:                                {
        !           671:                                        DBG1(DBG_IKE, "EAP vendor specific method %d-%d succeeded, "
        !           672:                                                 "%sMSK established", type, vendor,
        !           673:                                                 this->msk.ptr ? "" : "no ");
        !           674:                                }
        !           675:                                else
        !           676:                                {
        !           677:                                        DBG1(DBG_IKE, "EAP method %N succeeded, %sMSK established",
        !           678:                                                 eap_type_names, type, this->msk.ptr ? "" : "no ");
        !           679:                                }
        !           680:                                cfg = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
        !           681:                                cfg->add(cfg, AUTH_RULE_EAP_TYPE, type);
        !           682:                                if (vendor)
        !           683:                                {
        !           684:                                        cfg->add(cfg, AUTH_RULE_EAP_VENDOR, vendor);
        !           685:                                }
        !           686:                                this->eap_complete = TRUE;
        !           687:                                return NEED_MORE;
        !           688:                        }
        !           689:                        case EAP_FAILURE:
        !           690:                        default:
        !           691:                        {
        !           692:                                DBG1(DBG_IKE, "received %N, EAP authentication failed",
        !           693:                                         eap_code_names, eap_payload->get_code(eap_payload));
        !           694:                                return FAILED;
        !           695:                        }
        !           696:                }
        !           697:        }
        !           698:        return FAILED;
        !           699: }
        !           700: 
        !           701: METHOD(authenticator_t, build_client, status_t,
        !           702:        private_eap_authenticator_t *this, message_t *message)
        !           703: {
        !           704:        if (this->eap_payload)
        !           705:        {
        !           706:                message->add_payload(message, (payload_t*)this->eap_payload);
        !           707:                this->eap_payload = NULL;
        !           708:                return NEED_MORE;
        !           709:        }
        !           710:        if (this->eap_complete &&
        !           711:                build_auth(this, message, this->received_nonce, this->sent_init))
        !           712:        {
        !           713:                return NEED_MORE;
        !           714:        }
        !           715:        return NEED_MORE;
        !           716: }
        !           717: 
        !           718: METHOD(authenticator_t, is_mutual, bool,
        !           719:        private_eap_authenticator_t *this)
        !           720: {
        !           721:        if (this->method)
        !           722:        {
        !           723:                uint32_t vendor;
        !           724: 
        !           725:                if (this->method->get_type(this->method, &vendor) != EAP_IDENTITY ||
        !           726:                        vendor != 0)
        !           727:                {
        !           728:                        return this->method->is_mutual(this->method);
        !           729:                }
        !           730:        }
        !           731:        /* we don't know yet, but insist on it after EAP is complete */
        !           732:        this->require_mutual = TRUE;
        !           733:        return TRUE;
        !           734: }
        !           735: 
        !           736: METHOD(authenticator_t, use_ppk, void,
        !           737:        private_eap_authenticator_t *this, chunk_t ppk, bool no_ppk_auth)
        !           738: {
        !           739:        this->ppk = ppk;
        !           740:        this->no_ppk_auth = no_ppk_auth;
        !           741: }
        !           742: 
        !           743: METHOD(authenticator_t, destroy, void,
        !           744:        private_eap_authenticator_t *this)
        !           745: {
        !           746:        DESTROY_IF(this->method);
        !           747:        DESTROY_IF(this->eap_payload);
        !           748:        DESTROY_IF(this->eap_identity);
        !           749:        chunk_free(&this->msk);
        !           750:        free(this);
        !           751: }
        !           752: 
        !           753: /*
        !           754:  * Described in header.
        !           755:  */
        !           756: eap_authenticator_t *eap_authenticator_create_builder(ike_sa_t *ike_sa,
        !           757:                                                                        chunk_t received_nonce, chunk_t sent_nonce,
        !           758:                                                                        chunk_t received_init, chunk_t sent_init,
        !           759:                                                                        char reserved[3])
        !           760: {
        !           761:        private_eap_authenticator_t *this;
        !           762: 
        !           763:        INIT(this,
        !           764:                .public = {
        !           765:                        .authenticator = {
        !           766:                                .build = _build_client,
        !           767:                                .process = _process_client,
        !           768:                                .use_ppk = _use_ppk,
        !           769:                                .is_mutual = _is_mutual,
        !           770:                                .destroy = _destroy,
        !           771:                        },
        !           772:                },
        !           773:                .ike_sa = ike_sa,
        !           774:                .received_init = received_init,
        !           775:                .received_nonce = received_nonce,
        !           776:                .sent_init = sent_init,
        !           777:                .sent_nonce = sent_nonce,
        !           778:        );
        !           779:        memcpy(this->reserved, reserved, sizeof(this->reserved));
        !           780: 
        !           781:        return &this->public;
        !           782: }
        !           783: 
        !           784: /*
        !           785:  * Described in header.
        !           786:  */
        !           787: eap_authenticator_t *eap_authenticator_create_verifier(ike_sa_t *ike_sa,
        !           788:                                                                        chunk_t received_nonce, chunk_t sent_nonce,
        !           789:                                                                        chunk_t received_init, chunk_t sent_init,
        !           790:                                                                        char reserved[3])
        !           791: {
        !           792:        private_eap_authenticator_t *this;
        !           793: 
        !           794:        INIT(this,
        !           795:                .public = {
        !           796:                        .authenticator = {
        !           797:                                .build = _build_server,
        !           798:                                .process = _process_server,
        !           799:                                .use_ppk = _use_ppk,
        !           800:                                .is_mutual = _is_mutual,
        !           801:                                .destroy = _destroy,
        !           802:                        },
        !           803:                },
        !           804:                .ike_sa = ike_sa,
        !           805:                .received_init = received_init,
        !           806:                .received_nonce = received_nonce,
        !           807:                .sent_init = sent_init,
        !           808:                .sent_nonce = sent_nonce,
        !           809:        );
        !           810:        memcpy(this->reserved, reserved, sizeof(this->reserved));
        !           811: 
        !           812:        return &this->public;
        !           813: }

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