Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_eap/xauth_eap.c, revision 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>