hostapd: Update vendor branch to 0.6.10
[dragonfly.git] / contrib / hostapd / src / eap_server / eap_md5.c
blobdee2dc5a013e542c2977b7ef6d83b8083ad0c3c8
1 /*
2 * hostapd / EAP-MD5 server
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #include "common.h"
18 #include "eap_i.h"
19 #include "eap_common/chap.h"
22 #define CHALLENGE_LEN 16
24 struct eap_md5_data {
25 u8 challenge[CHALLENGE_LEN];
26 enum { CONTINUE, SUCCESS, FAILURE } state;
30 static void * eap_md5_init(struct eap_sm *sm)
32 struct eap_md5_data *data;
34 data = os_zalloc(sizeof(*data));
35 if (data == NULL)
36 return NULL;
37 data->state = CONTINUE;
39 return data;
43 static void eap_md5_reset(struct eap_sm *sm, void *priv)
45 struct eap_md5_data *data = priv;
46 os_free(data);
50 static struct wpabuf * eap_md5_buildReq(struct eap_sm *sm, void *priv, u8 id)
52 struct eap_md5_data *data = priv;
53 struct wpabuf *req;
55 if (os_get_random(data->challenge, CHALLENGE_LEN)) {
56 wpa_printf(MSG_ERROR, "EAP-MD5: Failed to get random data");
57 data->state = FAILURE;
58 return NULL;
61 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHALLENGE_LEN,
62 EAP_CODE_REQUEST, id);
63 if (req == NULL) {
64 wpa_printf(MSG_ERROR, "EAP-MD5: Failed to allocate memory for "
65 "request");
66 data->state = FAILURE;
67 return NULL;
70 wpabuf_put_u8(req, CHALLENGE_LEN);
71 wpabuf_put_data(req, data->challenge, CHALLENGE_LEN);
72 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", data->challenge,
73 CHALLENGE_LEN);
75 data->state = CONTINUE;
77 return req;
81 static Boolean eap_md5_check(struct eap_sm *sm, void *priv,
82 struct wpabuf *respData)
84 const u8 *pos;
85 size_t len;
87 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &len);
88 if (pos == NULL || len < 1) {
89 wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame");
90 return TRUE;
92 if (*pos != CHAP_MD5_LEN || 1 + CHAP_MD5_LEN > len) {
93 wpa_printf(MSG_INFO, "EAP-MD5: Invalid response "
94 "(response_len=%d payload_len=%lu",
95 *pos, (unsigned long) len);
96 return TRUE;
99 return FALSE;
103 static void eap_md5_process(struct eap_sm *sm, void *priv,
104 struct wpabuf *respData)
106 struct eap_md5_data *data = priv;
107 const u8 *pos;
108 size_t plen;
109 u8 hash[CHAP_MD5_LEN], id;
111 if (sm->user == NULL || sm->user->password == NULL ||
112 sm->user->password_hash) {
113 wpa_printf(MSG_INFO, "EAP-MD5: Plaintext password not "
114 "configured");
115 data->state = FAILURE;
116 return;
119 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &plen);
120 if (pos == NULL || *pos != CHAP_MD5_LEN || plen < 1 + CHAP_MD5_LEN)
121 return; /* Should not happen - frame already validated */
123 pos++; /* Skip response len */
124 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, CHAP_MD5_LEN);
126 id = eap_get_id(respData);
127 chap_md5(id, sm->user->password, sm->user->password_len,
128 data->challenge, CHALLENGE_LEN, hash);
130 if (os_memcmp(hash, pos, CHAP_MD5_LEN) == 0) {
131 wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success");
132 data->state = SUCCESS;
133 } else {
134 wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Failure");
135 data->state = FAILURE;
140 static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv)
142 struct eap_md5_data *data = priv;
143 return data->state != CONTINUE;
147 static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv)
149 struct eap_md5_data *data = priv;
150 return data->state == SUCCESS;
154 int eap_server_md5_register(void)
156 struct eap_method *eap;
157 int ret;
159 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
160 EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
161 if (eap == NULL)
162 return -1;
164 eap->init = eap_md5_init;
165 eap->reset = eap_md5_reset;
166 eap->buildReq = eap_md5_buildReq;
167 eap->check = eap_md5_check;
168 eap->process = eap_md5_process;
169 eap->isDone = eap_md5_isDone;
170 eap->isSuccess = eap_md5_isSuccess;
172 ret = eap_server_method_register(eap);
173 if (ret)
174 eap_server_method_free(eap);
175 return ret;