$search
00001 /* 00002 * hostapd / EAP-MD5 server 00003 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 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; /* Should not happen - frame already validated */ 00122 00123 pos++; /* Skip response len */ 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 }