Return to eap_md5.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / eap_md5 |
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: }