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

1.1       misho       1: /*
                      2:  * Copyright (C) 2007-2012 Martin Willi
                      3:  * Copyright (C) 2012 revosec AG
                      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_gtc.h"
                     18: 
                     19: #include <daemon.h>
                     20: #include <library.h>
                     21: 
                     22: #define GTC_REQUEST_MSG "password"
                     23: 
                     24: typedef struct private_eap_gtc_t private_eap_gtc_t;
                     25: 
                     26: /**
                     27:  * Private data of an eap_gtc_t object.
                     28:  */
                     29: struct private_eap_gtc_t {
                     30: 
                     31:        /**
                     32:         * Public authenticator_t interface.
                     33:         */
                     34:        eap_gtc_t public;
                     35: 
                     36:        /**
                     37:         * ID of the server
                     38:         */
                     39:        identification_t *server;
                     40: 
                     41:        /**
                     42:         * ID of the peer
                     43:         */
                     44:        identification_t *peer;
                     45: 
                     46:        /**
                     47:         * EAP message identifier
                     48:         */
                     49:        uint8_t identifier;
                     50: };
                     51: 
                     52: typedef struct eap_gtc_header_t eap_gtc_header_t;
                     53: 
                     54: /**
                     55:  * packed eap GTC header struct
                     56:  */
                     57: struct eap_gtc_header_t {
                     58:        /** EAP code (REQUEST/RESPONSE) */
                     59:        uint8_t code;
                     60:        /** unique message identifier */
                     61:        uint8_t identifier;
                     62:        /** length of whole message */
                     63:        uint16_t length;
                     64:        /** EAP type */
                     65:        uint8_t type;
                     66:        /** type data */
                     67:        uint8_t data[];
                     68: } __attribute__((__packed__));
                     69: 
                     70: METHOD(eap_method_t, initiate_peer, status_t,
                     71:        private_eap_gtc_t *this, eap_payload_t **out)
                     72: {
                     73:        /* peer never initiates */
                     74:        return FAILED;
                     75: }
                     76: 
                     77: METHOD(eap_method_t, initiate_server, status_t,
                     78:        private_eap_gtc_t *this, eap_payload_t **out)
                     79: {
                     80:        eap_gtc_header_t *req;
                     81:        size_t len;
                     82: 
                     83:        len = strlen(GTC_REQUEST_MSG);
                     84:        req = alloca(sizeof(eap_gtc_header_t) + len);
                     85:        req->length = htons(sizeof(eap_gtc_header_t) + len);
                     86:        req->code = EAP_REQUEST;
                     87:        req->identifier = this->identifier;
                     88:        req->type = EAP_GTC;
                     89:        memcpy(req->data, GTC_REQUEST_MSG, len);
                     90: 
                     91:        *out = eap_payload_create_data(chunk_create((void*)req,
                     92:                                                                   sizeof(eap_gtc_header_t) + len));
                     93:        return NEED_MORE;
                     94: }
                     95: 
                     96: METHOD(eap_method_t, process_peer, status_t,
                     97:        private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
                     98: {
                     99:        eap_gtc_header_t *res;
                    100:        shared_key_t *shared;
                    101:        chunk_t key;
                    102:        size_t len;
                    103: 
                    104:        shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
                    105:                                                                          this->peer, this->server);
                    106:        if (shared == NULL)
                    107:        {
                    108:                DBG1(DBG_IKE, "no EAP key found for '%Y' - '%Y'",
                    109:                         this->peer, this->server);
                    110:                return FAILED;
                    111:        }
                    112:        key = shared->get_key(shared);
                    113:        len = key.len;
                    114: 
                    115:        /* TODO: According to the draft we should "SASLprep" password, RFC4013. */
                    116: 
                    117:        this->identifier = in->get_identifier(in);
                    118:        res = alloca(sizeof(eap_gtc_header_t) + len);
                    119:        res->length = htons(sizeof(eap_gtc_header_t) + len);
                    120:        res->code = EAP_RESPONSE;
                    121:        res->identifier = this->identifier;
                    122:        res->type = EAP_GTC;
                    123:        memcpy(res->data, key.ptr, len);
                    124: 
                    125:        shared->destroy(shared);
                    126: 
                    127:        *out = eap_payload_create_data(chunk_create((void*)res,
                    128:                                                                   sizeof(eap_gtc_header_t) + len));
                    129:        return NEED_MORE;
                    130: }
                    131: 
                    132: METHOD(eap_method_t, process_server, status_t,
                    133:        private_eap_gtc_t *this, eap_payload_t *in, eap_payload_t **out)
                    134: {
                    135:        status_t status = FAILED;
                    136:        chunk_t user, pass;
                    137:        xauth_method_t *xauth;
                    138:        cp_payload_t *ci, *co;
                    139:        char *backend;
                    140: 
                    141:        user = this->peer->get_encoding(this->peer);
                    142:        pass = chunk_skip(in->get_data(in), 5);
                    143:        if (this->identifier != in->get_identifier(in) || !pass.len)
                    144:        {
                    145:                DBG1(DBG_IKE, "received invalid EAP-GTC message");
                    146:                return FAILED;
                    147:        }
                    148: 
                    149:        /* get XAuth backend to use for credential verification. Default to PAM
                    150:         * to support legacy EAP-GTC configurations */
                    151:        backend = lib->settings->get_str(lib->settings,
                    152:                                                                "%s.plugins.eap-gtc.backend", "pam", lib->ns);
                    153:        xauth = charon->xauth->create_instance(charon->xauth, backend, XAUTH_SERVER,
                    154:                                                                                   this->server, this->peer);
                    155:        if (!xauth)
                    156:        {
                    157:                DBG1(DBG_IKE, "creating EAP-GTC XAuth backend '%s' failed", backend);
                    158:                return FAILED;
                    159:        }
                    160:        if (xauth->initiate(xauth, &co) == NEED_MORE)
                    161:        {
                    162:                /* assume that "out" contains username/password attributes */
                    163:                co->destroy(co);
                    164:                ci = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
                    165:                ci->add_attribute(ci, configuration_attribute_create_chunk(
                    166:                                        PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, user));
                    167:                ci->add_attribute(ci, configuration_attribute_create_chunk(
                    168:                                        PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, pass));
                    169:                switch (xauth->process(xauth, ci, &co))
                    170:                {
                    171:                        case SUCCESS:
                    172:                                status = SUCCESS;
                    173:                                break;
                    174:                        case NEED_MORE:
                    175:                                /* TODO: multiple exchanges currently not supported */
                    176:                                co->destroy(co);
                    177:                                break;
                    178:                        case FAILED:
                    179:                        default:
                    180:                                break;
                    181:                }
                    182:                ci->destroy(ci);
                    183:        }
                    184:        xauth->destroy(xauth);
                    185:        return status;
                    186: }
                    187: 
                    188: METHOD(eap_method_t, get_type, eap_type_t,
                    189:        private_eap_gtc_t *this, uint32_t *vendor)
                    190: {
                    191:        *vendor = 0;
                    192:        return EAP_GTC;
                    193: }
                    194: 
                    195: METHOD(eap_method_t, get_msk, status_t,
                    196:        private_eap_gtc_t *this, chunk_t *msk)
                    197: {
                    198:        return FAILED;
                    199: }
                    200: 
                    201: METHOD(eap_method_t, get_identifier, uint8_t,
                    202:        private_eap_gtc_t *this)
                    203: {
                    204:        return this->identifier;
                    205: }
                    206: 
                    207: METHOD(eap_method_t, set_identifier, void,
                    208:        private_eap_gtc_t *this, uint8_t identifier)
                    209: {
                    210:        this->identifier = identifier;
                    211: }
                    212: 
                    213: METHOD(eap_method_t, is_mutual, bool,
                    214:        private_eap_gtc_t *this)
                    215: {
                    216:        return FALSE;
                    217: }
                    218: 
                    219: METHOD(eap_method_t, destroy, void,
                    220:        private_eap_gtc_t *this)
                    221: {
                    222:        this->peer->destroy(this->peer);
                    223:        this->server->destroy(this->server);
                    224:        free(this);
                    225: }
                    226: 
                    227: /**
                    228:  * Generic constructor
                    229:  */
                    230: static private_eap_gtc_t *eap_gtc_create_generic(identification_t *server,
                    231:                                                                                                 identification_t *peer)
                    232: {
                    233:        private_eap_gtc_t *this;
                    234: 
                    235:        INIT(this,
                    236:                .public = {
                    237:                        .eap_method_interface = {
                    238:                                .get_type = _get_type,
                    239:                                .is_mutual = _is_mutual,
                    240:                                .get_msk = _get_msk,
                    241:                                .get_identifier = _get_identifier,
                    242:                                .set_identifier = _set_identifier,
                    243:                                .destroy = _destroy,
                    244:                        },
                    245:                },
                    246:                .peer = peer->clone(peer),
                    247:                .server = server->clone(server),
                    248:        );
                    249: 
                    250:        return this;
                    251: }
                    252: 
                    253: /*
                    254:  * see header
                    255:  */
                    256: eap_gtc_t *eap_gtc_create_server(identification_t *server, identification_t *peer)
                    257: {
                    258:        private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
                    259: 
                    260:        this->public.eap_method_interface.initiate = _initiate_server;
                    261:        this->public.eap_method_interface.process = _process_server;
                    262: 
                    263:        /* generate a non-zero identifier */
                    264:        do {
                    265:                this->identifier = random();
                    266:        } while (!this->identifier);
                    267: 
                    268:        return &this->public;
                    269: }
                    270: 
                    271: /*
                    272:  * see header
                    273:  */
                    274: eap_gtc_t *eap_gtc_create_peer(identification_t *server, identification_t *peer)
                    275: {
                    276:        private_eap_gtc_t *this = eap_gtc_create_generic(server, peer);
                    277: 
                    278:        this->public.eap_method_interface.initiate = _initiate_peer;
                    279:        this->public.eap_method_interface.process = _process_peer;
                    280: 
                    281:        return &this->public;
                    282: }

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