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>