00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "includes.h"
00016
00017 #include "common.h"
00018 #include "eap_i.h"
00019 #include "eap_common/chap.h"
00020
00021
00022 #define CHALLENGE_LEN 16
00023
00024 struct eap_md5_data {
00025 u8 challenge[CHALLENGE_LEN];
00026 enum { CONTINUE, SUCCESS, FAILURE } state;
00027 };
00028
00029
00030 static void * eap_md5_init(struct eap_sm *sm)
00031 {
00032 struct eap_md5_data *data;
00033
00034 data = os_zalloc(sizeof(*data));
00035 if (data == NULL)
00036 return NULL;
00037 data->state = CONTINUE;
00038
00039 return data;
00040 }
00041
00042
00043 static void eap_md5_reset(struct eap_sm *sm, void *priv)
00044 {
00045 struct eap_md5_data *data = priv;
00046 os_free(data);
00047 }
00048
00049
00050 static struct wpabuf * eap_md5_buildReq(struct eap_sm *sm, void *priv, u8 id)
00051 {
00052 struct eap_md5_data *data = priv;
00053 struct wpabuf *req;
00054
00055 if (os_get_random(data->challenge, CHALLENGE_LEN)) {
00056 wpa_printf(MSG_ERROR, "EAP-MD5: Failed to get random data");
00057 data->state = FAILURE;
00058 return NULL;
00059 }
00060
00061 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHALLENGE_LEN,
00062 EAP_CODE_REQUEST, id);
00063 if (req == NULL) {
00064 wpa_printf(MSG_ERROR, "EAP-MD5: Failed to allocate memory for "
00065 "request");
00066 data->state = FAILURE;
00067 return NULL;
00068 }
00069
00070 wpabuf_put_u8(req, CHALLENGE_LEN);
00071 wpabuf_put_data(req, data->challenge, CHALLENGE_LEN);
00072 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", data->challenge,
00073 CHALLENGE_LEN);
00074
00075 data->state = CONTINUE;
00076
00077 return req;
00078 }
00079
00080
00081 static Boolean eap_md5_check(struct eap_sm *sm, void *priv,
00082 struct wpabuf *respData)
00083 {
00084 const u8 *pos;
00085 size_t len;
00086
00087 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &len);
00088 if (pos == NULL || len < 1) {
00089 wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame");
00090 return TRUE;
00091 }
00092 if (*pos != CHAP_MD5_LEN || 1 + CHAP_MD5_LEN > len) {
00093 wpa_printf(MSG_INFO, "EAP-MD5: Invalid response "
00094 "(response_len=%d payload_len=%lu",
00095 *pos, (unsigned long) len);
00096 return TRUE;
00097 }
00098
00099 return FALSE;
00100 }
00101
00102
00103 static void eap_md5_process(struct eap_sm *sm, void *priv,
00104 struct wpabuf *respData)
00105 {
00106 struct eap_md5_data *data = priv;
00107 const u8 *pos;
00108 size_t plen;
00109 u8 hash[CHAP_MD5_LEN], id;
00110
00111 if (sm->user == NULL || sm->user->password == NULL ||
00112 sm->user->password_hash) {
00113 wpa_printf(MSG_INFO, "EAP-MD5: Plaintext password not "
00114 "configured");
00115 data->state = FAILURE;
00116 return;
00117 }
00118
00119 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &plen);
00120 if (pos == NULL || *pos != CHAP_MD5_LEN || plen < 1 + CHAP_MD5_LEN)
00121 return;
00122
00123 pos++;
00124 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, CHAP_MD5_LEN);
00125
00126 id = eap_get_id(respData);
00127 chap_md5(id, sm->user->password, sm->user->password_len,
00128 data->challenge, CHALLENGE_LEN, hash);
00129
00130 if (os_memcmp(hash, pos, CHAP_MD5_LEN) == 0) {
00131 wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success");
00132 data->state = SUCCESS;
00133 } else {
00134 wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Failure");
00135 data->state = FAILURE;
00136 }
00137 }
00138
00139
00140 static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv)
00141 {
00142 struct eap_md5_data *data = priv;
00143 return data->state != CONTINUE;
00144 }
00145
00146
00147 static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv)
00148 {
00149 struct eap_md5_data *data = priv;
00150 return data->state == SUCCESS;
00151 }
00152
00153
00154 int eap_server_md5_register(void)
00155 {
00156 struct eap_method *eap;
00157 int ret;
00158
00159 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
00160 EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5");
00161 if (eap == NULL)
00162 return -1;
00163
00164 eap->init = eap_md5_init;
00165 eap->reset = eap_md5_reset;
00166 eap->buildReq = eap_md5_buildReq;
00167 eap->check = eap_md5_check;
00168 eap->process = eap_md5_process;
00169 eap->isDone = eap_md5_isDone;
00170 eap->isSuccess = eap_md5_isSuccess;
00171
00172 ret = eap_server_method_register(eap);
00173 if (ret)
00174 eap_server_method_free(eap);
00175 return ret;
00176 }