Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_eap/xauth_eap.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2011 Martin Willi
                      3:  * Copyright (C) 2011 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "xauth_eap.h"
                     17: 
                     18: #include <daemon.h>
                     19: 
                     20: #include <library.h>
                     21: #include <credentials/sets/callback_cred.h>
                     22: 
                     23: typedef struct private_xauth_eap_t private_xauth_eap_t;
                     24: 
                     25: /**
                     26:  * Private data of an xauth_eap_t object.
                     27:  */
                     28: struct private_xauth_eap_t {
                     29: 
                     30:        /**
                     31:         * Public interface.
                     32:         */
                     33:        xauth_eap_t public;
                     34: 
                     35:        /**
                     36:         * ID of the server
                     37:         */
                     38:        identification_t *server;
                     39: 
                     40:        /**
                     41:         * ID of the peer
                     42:         */
                     43:        identification_t *peer;
                     44: 
                     45:        /**
                     46:         * Callback credential set
                     47:         */
                     48:        callback_cred_t *cred;
                     49: 
                     50:        /**
                     51:         * XAuth password
                     52:         */
                     53:        chunk_t pass;
                     54: };
                     55: 
                     56: /**
                     57:  * Callback credential set function
                     58:  */
                     59: static shared_key_t* shared_cb(private_xauth_eap_t *this, shared_key_type_t type,
                     60:                                                           identification_t *me, identification_t *other,
                     61:                                                           id_match_t *match_me, id_match_t *match_other)
                     62: {
                     63:        shared_key_t *shared;
                     64: 
                     65:        if (!this->pass.len)
                     66:        {
                     67:                return NULL;
                     68:        }
                     69:        if (type != SHARED_EAP && type != SHARED_ANY)
                     70:        {
                     71:                return NULL;
                     72:        }
                     73:        if (me)
                     74:        {
                     75:                if (!this->peer->equals(this->peer, me))
                     76:                {
                     77:                        return NULL;
                     78:                }
                     79:                if (match_me)
                     80:                {
                     81:                        *match_me = ID_MATCH_PERFECT;
                     82:                }
                     83:        }
                     84:        else if (match_me)
                     85:        {
                     86:                *match_me = ID_MATCH_ANY;
                     87:        }
                     88:        if (other)
                     89:        {
                     90:                if (!this->server->equals(this->server, other))
                     91:                {
                     92:                        return NULL;
                     93:                }
                     94:                if (match_other)
                     95:                {
                     96:                        *match_other = ID_MATCH_PERFECT;
                     97:                }
                     98:        }
                     99:        else if (match_other)
                    100:        {
                    101:                *match_other = ID_MATCH_ANY;
                    102:        }
                    103:        shared = shared_key_create(SHARED_EAP, chunk_clone(this->pass));
                    104:        this->pass = chunk_empty;
                    105:        return shared;
                    106: }
                    107: 
                    108: /**
                    109:  * Do EAP exchanges to verify secret
                    110:  */
                    111: static bool verify_eap(private_xauth_eap_t *this, eap_method_t *backend)
                    112: {
                    113:        eap_payload_t *request, *response;
                    114:        eap_method_t *frontend;
                    115:        eap_type_t type;
                    116:        uint32_t vendor;
                    117:        status_t status;
                    118: 
                    119:        if (backend->initiate(backend, &request) != NEED_MORE)
                    120:        {
                    121:                return FALSE;
                    122:        }
                    123:        type = request->get_type(request, &vendor);
                    124:        frontend = charon->eap->create_instance(charon->eap, type, vendor,
                    125:                                                                                        EAP_PEER, this->server, this->peer);
                    126:        if (!frontend)
                    127:        {
                    128:                DBG1(DBG_IKE, "XAuth-EAP backend requested %N, but not supported",
                    129:                         eap_type_names, type);
                    130:                request->destroy(request);
                    131:                return FALSE;
                    132:        }
                    133:        while (TRUE)
                    134:        {
                    135:                /* credential set is active in frontend only, but not in backend */
                    136:                lib->credmgr->add_local_set(lib->credmgr, &this->cred->set, TRUE);
                    137:                status = frontend->process(frontend, request, &response);
                    138:                lib->credmgr->remove_local_set(lib->credmgr, &this->cred->set);
                    139:                request->destroy(request);
                    140:                if (status != NEED_MORE)
                    141:                {       /* clients should never return SUCCESS */
                    142:                        frontend->destroy(frontend);
                    143:                        return FALSE;
                    144:                }
                    145:                status = backend->process(backend, response, &request);
                    146:                response->destroy(response);
                    147:                switch (status)
                    148:                {
                    149:                        case SUCCESS:
                    150:                                frontend->destroy(frontend);
                    151:                                return TRUE;
                    152:                        case NEED_MORE:
                    153:                                break;
                    154:                        default:
                    155:                                frontend->destroy(frontend);
                    156:                                return FALSE;
                    157:                }
                    158:        }
                    159: }
                    160: 
                    161: METHOD(xauth_method_t, initiate, status_t,
                    162:        private_xauth_eap_t *this, cp_payload_t **out)
                    163: {
                    164:        cp_payload_t *cp;
                    165: 
                    166:        cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
                    167:        cp->add_attribute(cp, configuration_attribute_create_chunk(
                    168:                                PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
                    169:        cp->add_attribute(cp, configuration_attribute_create_chunk(
                    170:                                PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
                    171:        *out = cp;
                    172:        return NEED_MORE;
                    173: }
                    174: 
                    175: METHOD(xauth_method_t, process, status_t,
                    176:        private_xauth_eap_t *this, cp_payload_t *in, cp_payload_t **out)
                    177: {
                    178:        configuration_attribute_t *attr;
                    179:        enumerator_t *enumerator;
                    180:        identification_t *id;
                    181:        chunk_t user = chunk_empty;
                    182:        eap_method_t *backend;
                    183:        eap_type_t type;
                    184:        char *name;
                    185:        bool ok;
                    186: 
                    187:        enumerator = in->create_attribute_enumerator(in);
                    188:        while (enumerator->enumerate(enumerator, &attr))
                    189:        {
                    190:                switch (attr->get_type(attr))
                    191:                {
                    192:                        case XAUTH_USER_NAME:
                    193:                                user = attr->get_chunk(attr);
                    194:                                break;
                    195:                        case XAUTH_USER_PASSWORD:
                    196:                                this->pass = attr->get_chunk(attr);
                    197:                                break;
                    198:                        default:
                    199:                                break;
                    200:                }
                    201:        }
                    202:        enumerator->destroy(enumerator);
                    203: 
                    204:        if (!user.ptr || !this->pass.ptr)
                    205:        {
                    206:                DBG1(DBG_IKE, "peer did not respond to our XAuth request");
                    207:                return FAILED;
                    208:        }
                    209:        if (user.len)
                    210:        {
                    211:                id = identification_create_from_data(user);
                    212:                if (!id)
                    213:                {
                    214:                        DBG1(DBG_IKE, "failed to parse provided XAuth username");
                    215:                        return FAILED;
                    216:                }
                    217:                this->peer->destroy(this->peer);
                    218:                this->peer = id;
                    219:        }
                    220:        if (this->pass.len && this->pass.ptr[this->pass.len - 1] == 0)
                    221:        {       /* fix null-terminated passwords (Android etc.) */
                    222:                this->pass.len -= 1;
                    223:        }
                    224: 
                    225:        name = lib->settings->get_str(lib->settings,
                    226:                                                                  "%s.plugins.xauth-eap.backend", "radius",
                    227:                                                                  lib->ns);
                    228:        type = eap_type_from_string(name);
                    229:        if (!type)
                    230:        {
                    231:                DBG1(DBG_CFG, "Unknown XAuth-EAP method: %s", name);
                    232:                return FAILED;
                    233:        }
                    234:        backend = charon->eap->create_instance(charon->eap, type, 0, EAP_SERVER,
                    235:                                                                                   this->server, this->peer);
                    236:        if (!backend)
                    237:        {
                    238:                DBG1(DBG_CFG, "XAuth-EAP method backend not supported: %s", name);
                    239:                return FAILED;
                    240:        }
                    241:        ok = verify_eap(this, backend);
                    242:        backend->destroy(backend);
                    243:        if (ok)
                    244:        {
                    245:                return SUCCESS;
                    246:        }
                    247:        return FAILED;
                    248: }
                    249: 
                    250: METHOD(xauth_method_t, get_identity, identification_t*,
                    251:        private_xauth_eap_t *this)
                    252: {
                    253:        return this->peer;
                    254: }
                    255: 
                    256: METHOD(xauth_method_t, destroy, void,
                    257:        private_xauth_eap_t *this)
                    258: {
                    259:        this->cred->destroy(this->cred);
                    260:        this->server->destroy(this->server);
                    261:        this->peer->destroy(this->peer);
                    262:        free(this);
                    263: }
                    264: 
                    265: /*
                    266:  * Described in header.
                    267:  */
                    268: xauth_eap_t *xauth_eap_create_server(identification_t *server,
                    269:                                                                         identification_t *peer, char *profile)
                    270: {
                    271:        private_xauth_eap_t *this;
                    272: 
                    273:        INIT(this,
                    274:                .public = {
                    275:                        .xauth_method = {
                    276:                                .initiate = _initiate,
                    277:                                .process = _process,
                    278:                                .get_identity = _get_identity,
                    279:                                .destroy = _destroy,
                    280:                        },
                    281:                },
                    282:                .server = server->clone(server),
                    283:                .peer = peer->clone(peer),
                    284:        );
                    285: 
                    286:        this->cred = callback_cred_create_shared((void*)shared_cb, this);
                    287: 
                    288:        return &this->public;
                    289: }

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