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

1.1       misho       1: /*
                      2:  * Copyright (C) 2007 Martin Willi
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      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 "eap_md5.h"
                     17: 
                     18: #include <daemon.h>
                     19: #include <library.h>
                     20: #include <crypto/hashers/hasher.h>
                     21: 
                     22: typedef struct private_eap_md5_t private_eap_md5_t;
                     23: 
                     24: /**
                     25:  * Private data of an eap_md5_t object.
                     26:  */
                     27: struct private_eap_md5_t {
                     28: 
                     29:        /**
                     30:         * Public authenticator_t interface.
                     31:         */
                     32:        eap_md5_t public;
                     33: 
                     34:        /**
                     35:         * ID of the server
                     36:         */
                     37:        identification_t *server;
                     38: 
                     39:        /**
                     40:         * ID of the peer
                     41:         */
                     42:        identification_t *peer;
                     43: 
                     44:        /**
                     45:         * challenge sent by the server
                     46:         */
                     47:        chunk_t challenge;
                     48: 
                     49:        /**
                     50:         * EAP message identifier
                     51:         */
                     52:        uint8_t identifier;
                     53: };
                     54: 
                     55: typedef struct eap_md5_header_t eap_md5_header_t;
                     56: 
                     57: /**
                     58:  * packed eap MD5 header struct
                     59:  */
                     60: struct eap_md5_header_t {
                     61:        /** EAP code (REQUEST/RESPONSE) */
                     62:        uint8_t code;
                     63:        /** unique message identifier */
                     64:        uint8_t identifier;
                     65:        /** length of whole message */
                     66:        uint16_t length;
                     67:        /** EAP type */
                     68:        uint8_t type;
                     69:        /** length of value (challenge) */
                     70:        uint8_t value_size;
                     71:        /** actual value */
                     72:        uint8_t value[];
                     73: } __attribute__((__packed__));
                     74: 
                     75: #define CHALLENGE_LEN 16
                     76: #define PAYLOAD_LEN (CHALLENGE_LEN + sizeof(eap_md5_header_t))
                     77: 
                     78: /**
                     79:  * Hash the challenge string, create response
                     80:  */
                     81: static status_t hash_challenge(private_eap_md5_t *this, chunk_t *response,
                     82:                                                           identification_t *me, identification_t *other)
                     83: {
                     84:        shared_key_t *shared;
                     85:        chunk_t concat;
                     86:        hasher_t *hasher;
                     87: 
                     88:        shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, me, other);
                     89:        if (shared == NULL)
                     90:        {
                     91:                DBG1(DBG_IKE, "no EAP key found for hosts '%Y' - '%Y'", me, other);
                     92:                return NOT_FOUND;
                     93:        }
                     94:        concat = chunk_cata("ccc", chunk_from_thing(this->identifier),
                     95:                                                shared->get_key(shared), this->challenge);
                     96:        shared->destroy(shared);
                     97:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
                     98:        if (hasher == NULL)
                     99:        {
                    100:                DBG1(DBG_IKE, "EAP-MD5 failed, MD5 not supported");
                    101:                return FAILED;
                    102:        }
                    103:        if (!hasher->allocate_hash(hasher, concat, response))
                    104:        {
                    105:                hasher->destroy(hasher);
                    106:                return FAILED;
                    107:        }
                    108:        hasher->destroy(hasher);
                    109:        return SUCCESS;
                    110: }
                    111: 
                    112: METHOD(eap_method_t, initiate_peer, status_t,
                    113:        private_eap_md5_t *this, eap_payload_t **out)
                    114: {
                    115:        /* peer never initiates */
                    116:        return FAILED;
                    117: }
                    118: 
                    119: METHOD(eap_method_t, initiate_server, status_t,
                    120:        private_eap_md5_t *this, eap_payload_t **out)
                    121: {
                    122:        rng_t *rng;
                    123:        eap_md5_header_t *req;
                    124: 
                    125:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                    126:        if (!rng || !rng->allocate_bytes(rng, CHALLENGE_LEN, &this->challenge))
                    127:        {
                    128:                DESTROY_IF(rng);
                    129:                return FAILED;
                    130:        }
                    131:        rng->destroy(rng);
                    132: 
                    133:        req = alloca(PAYLOAD_LEN);
                    134:        req->length = htons(PAYLOAD_LEN);
                    135:        req->code = EAP_REQUEST;
                    136:        req->identifier = this->identifier;
                    137:        req->type = EAP_MD5;
                    138:        req->value_size = this->challenge.len;
                    139:        memcpy(req->value, this->challenge.ptr, this->challenge.len);
                    140: 
                    141:        *out = eap_payload_create_data(chunk_create((void*)req, PAYLOAD_LEN));
                    142:        return NEED_MORE;
                    143: }
                    144: 
                    145: METHOD(eap_method_t, process_peer, status_t,
                    146:        private_eap_md5_t *this, eap_payload_t *in, eap_payload_t **out)
                    147: {
                    148:        chunk_t response;
                    149:        chunk_t data;
                    150:        eap_md5_header_t *req;
                    151: 
                    152:        this->identifier = in->get_identifier(in);
                    153:        data = in->get_data(in);
                    154:        if (data.len < 6 || data.ptr[5] + 6 > data.len)
                    155:        {
                    156:                DBG1(DBG_IKE, "received invalid EAP-MD5 message");
                    157:                return FAILED;
                    158:        }
                    159:        this->challenge = chunk_clone(chunk_create(data.ptr + 6, data.ptr[5]));
                    160:        if (hash_challenge(this, &response, this->peer, this->server) != SUCCESS)
                    161:        {
                    162:                return FAILED;
                    163:        }
                    164:        req = alloca(PAYLOAD_LEN);
                    165:        req->length = htons(PAYLOAD_LEN);
                    166:        req->code = EAP_RESPONSE;
                    167:        req->identifier = this->identifier;
                    168:        req->type = EAP_MD5;
                    169:        req->value_size = response.len;
                    170:        memcpy(req->value, response.ptr, response.len);
                    171:        chunk_free(&response);
                    172: 
                    173:        *out = eap_payload_create_data(chunk_create((void*)req, PAYLOAD_LEN));
                    174:        return NEED_MORE;
                    175: }
                    176: 
                    177: METHOD(eap_method_t, process_server, status_t,
                    178:        private_eap_md5_t *this, eap_payload_t *in, eap_payload_t **out)
                    179: {
                    180:        chunk_t response, expected;
                    181:        chunk_t data;
                    182: 
                    183:        data = in->get_data(in);
                    184:        if (this->identifier != in->get_identifier(in) ||
                    185:                data.len < 6 || data.ptr[5] + 6 > data.len)
                    186:        {
                    187:                DBG1(DBG_IKE, "received invalid EAP-MD5 message");
                    188:                return FAILED;
                    189:        }
                    190:        if (hash_challenge(this, &expected, this->server, this->peer) != SUCCESS)
                    191:        {
                    192:                return FAILED;
                    193:        }
                    194:        response = chunk_create(data.ptr + 6, data.ptr[5]);
                    195:        if (response.len < expected.len ||
                    196:                !memeq_const(response.ptr, expected.ptr, expected.len))
                    197:        {
                    198:                chunk_free(&expected);
                    199:                DBG1(DBG_IKE, "EAP-MD5 verification failed");
                    200:                return FAILED;
                    201:        }
                    202:        chunk_free(&expected);
                    203:        return SUCCESS;
                    204: }
                    205: 
                    206: METHOD(eap_method_t, get_type, eap_type_t,
                    207:        private_eap_md5_t *this, uint32_t *vendor)
                    208: {
                    209:        *vendor = 0;
                    210:        return EAP_MD5;
                    211: }
                    212: 
                    213: METHOD(eap_method_t, get_msk, status_t,
                    214:        private_eap_md5_t *this, chunk_t *msk)
                    215: {
                    216:        return FAILED;
                    217: }
                    218: 
                    219: METHOD(eap_method_t, is_mutual, bool,
                    220:        private_eap_md5_t *this)
                    221: {
                    222:        return FALSE;
                    223: }
                    224: 
                    225: METHOD(eap_method_t, get_identifier, uint8_t,
                    226:        private_eap_md5_t *this)
                    227: {
                    228:        return this->identifier;
                    229: }
                    230: 
                    231: METHOD(eap_method_t, set_identifier, void,
                    232:        private_eap_md5_t *this, uint8_t identifier)
                    233: {
                    234:        this->identifier = identifier;
                    235: }
                    236: 
                    237: METHOD(eap_method_t, destroy, void,
                    238:        private_eap_md5_t *this)
                    239: {
                    240:        this->peer->destroy(this->peer);
                    241:        this->server->destroy(this->server);
                    242:        chunk_free(&this->challenge);
                    243:        free(this);
                    244: }
                    245: 
                    246: /*
                    247:  * See header
                    248:  */
                    249: eap_md5_t *eap_md5_create_server(identification_t *server, identification_t *peer)
                    250: {
                    251:        private_eap_md5_t *this;
                    252: 
                    253:        INIT(this,
                    254:                .public = {
                    255:                        .eap_method = {
                    256:                                .initiate = _initiate_server,
                    257:                                .process = _process_server,
                    258:                                .get_type = _get_type,
                    259:                                .is_mutual = _is_mutual,
                    260:                                .get_msk = _get_msk,
                    261:                                .get_identifier = _get_identifier,
                    262:                                .set_identifier = _set_identifier,
                    263:                                .destroy = _destroy,
                    264:                        },
                    265:                },
                    266:                .peer = peer->clone(peer),
                    267:                .server = server->clone(server),
                    268:        );
                    269: 
                    270:        /* generate a non-zero identifier */
                    271:        do {
                    272:                this->identifier = random();
                    273:        } while (!this->identifier);
                    274: 
                    275:        return &this->public;
                    276: }
                    277: 
                    278: /*
                    279:  * See header
                    280:  */
                    281: eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer)
                    282: {
                    283:        private_eap_md5_t *this;
                    284: 
                    285:        INIT(this,
                    286:                .public = {
                    287:                        .eap_method = {
                    288:                                .initiate = _initiate_peer,
                    289:                                .process = _process_peer,
                    290:                                .get_type = _get_type,
                    291:                                .is_mutual = _is_mutual,
                    292:                                .get_msk = _get_msk,
                    293:                                .destroy = _destroy,
                    294:                        },
                    295:                },
                    296:                .peer = peer->clone(peer),
                    297:                .server = server->clone(server),
                    298:        );
                    299: 
                    300:        return &this->public;
                    301: }

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