Annotation of embedaddon/strongswan/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c, revision 1.1.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>