2 * hostapd / EAP-MD5 server
3 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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
12 * See README and COPYING for more details.
18 #include <netinet/in.h>
26 #define CHALLENGE_LEN 16
29 u8 challenge[CHALLENGE_LEN];
30 enum { CONTINUE, SUCCESS, FAILURE } state;
34 static void * eap_md5_init(struct eap_sm *sm)
36 struct eap_md5_data *data;
38 data = malloc(sizeof(*data));
41 memset(data, 0, sizeof(*data));
42 data->state = CONTINUE;
48 static void eap_md5_reset(struct eap_sm *sm, void *priv)
50 struct eap_md5_data *data = priv;
55 static u8 * eap_md5_buildReq(struct eap_sm *sm, void *priv, int id,
58 struct eap_md5_data *data = priv;
62 if (hostapd_get_rand(data->challenge, CHALLENGE_LEN)) {
63 wpa_printf(MSG_ERROR, "EAP-MD5: Failed to get random data");
64 data->state = FAILURE;
68 *reqDataLen = sizeof(*req) + 2 + CHALLENGE_LEN;
69 req = malloc(*reqDataLen);
71 wpa_printf(MSG_ERROR, "EAP-MD5: Failed to allocate memory for "
73 data->state = FAILURE;
77 req->code = EAP_CODE_REQUEST;
79 req->length = htons(*reqDataLen);
80 pos = (u8 *) (req + 1);
81 *pos++ = EAP_TYPE_MD5;
82 *pos++ = CHALLENGE_LEN;
83 memcpy(pos, data->challenge, CHALLENGE_LEN);
84 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", pos, CHALLENGE_LEN);
86 data->state = CONTINUE;
92 static Boolean eap_md5_check(struct eap_sm *sm, void *priv,
93 u8 *respData, size_t respDataLen)
99 resp = (struct eap_hdr *) respData;
100 pos = (u8 *) (resp + 1);
101 if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_MD5 ||
102 (len = ntohs(resp->length)) > respDataLen) {
103 wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame");
107 if (*pos != MD5_MAC_LEN ||
108 sizeof(*resp) + 2 + MD5_MAC_LEN > len) {
109 wpa_printf(MSG_INFO, "EAP-MD5: Invalid response "
110 "(response_len=%d respDataLen=%lu",
111 *pos, (unsigned long) respDataLen);
119 static void eap_md5_process(struct eap_sm *sm, void *priv,
120 u8 *respData, size_t respDataLen)
122 struct eap_md5_data *data = priv;
123 struct eap_hdr *resp;
126 u8 hash[MD5_MAC_LEN];
128 if (sm->user == NULL || sm->user->password == NULL) {
129 wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
130 data->state = FAILURE;
134 resp = (struct eap_hdr *) respData;
135 pos = (u8 *) (resp + 1);
136 pos += 2; /* Skip type and len */
137 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, MD5_MAC_LEN);
140 MD5Update(&context, &resp->identifier, 1);
141 MD5Update(&context, sm->user->password, sm->user->password_len);
142 MD5Update(&context, data->challenge, CHALLENGE_LEN);
143 MD5Final(hash, &context);
145 if (memcmp(hash, pos, MD5_MAC_LEN) == 0) {
146 wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success");
147 data->state = SUCCESS;
149 wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Failure");
150 data->state = FAILURE;
155 static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv)
157 struct eap_md5_data *data = priv;
158 return data->state != CONTINUE;
162 static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv)
164 struct eap_md5_data *data = priv;
165 return data->state == SUCCESS;
169 const struct eap_method eap_method_md5 =
171 .method = EAP_TYPE_MD5,
173 .init = eap_md5_init,
174 .reset = eap_md5_reset,
175 .buildReq = eap_md5_buildReq,
176 .check = eap_md5_check,
177 .process = eap_md5_process,
178 .isDone = eap_md5_isDone,
179 .isSuccess = eap_md5_isSuccess,