$search
00001 /* 00002 * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) 00003 * Copyright (c) 2004-2006, 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 static void * eap_md5_init(struct eap_sm *sm) 00023 { 00024 /* No need for private data. However, must return non-NULL to indicate 00025 * success. */ 00026 return (void *) 1; 00027 } 00028 00029 00030 static void eap_md5_deinit(struct eap_sm *sm, void *priv) 00031 { 00032 } 00033 00034 00035 static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, 00036 struct eap_method_ret *ret, 00037 const struct wpabuf *reqData) 00038 { 00039 struct wpabuf *resp; 00040 const u8 *pos, *challenge, *password; 00041 u8 *rpos, id; 00042 size_t len, challenge_len, password_len; 00043 00044 password = eap_get_config_password(sm, &password_len); 00045 if (password == NULL) { 00046 wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); 00047 eap_sm_request_password(sm); 00048 ret->ignore = TRUE; 00049 return NULL; 00050 } 00051 00052 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); 00053 if (pos == NULL || len == 0) { 00054 wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", 00055 pos, (unsigned long) len); 00056 ret->ignore = TRUE; 00057 return NULL; 00058 } 00059 00060 /* 00061 * CHAP Challenge: 00062 * Value-Size (1 octet) | Value(Challenge) | Name(optional) 00063 */ 00064 challenge_len = *pos++; 00065 if (challenge_len == 0 || challenge_len > len - 1) { 00066 wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " 00067 "(challenge_len=%lu len=%lu)", 00068 (unsigned long) challenge_len, (unsigned long) len); 00069 ret->ignore = TRUE; 00070 return NULL; 00071 } 00072 ret->ignore = FALSE; 00073 challenge = pos; 00074 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", 00075 challenge, challenge_len); 00076 00077 wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); 00078 ret->methodState = METHOD_DONE; 00079 ret->decision = DECISION_COND_SUCC; 00080 ret->allowNotifications = TRUE; 00081 00082 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, 00083 EAP_CODE_RESPONSE, eap_get_id(reqData)); 00084 if (resp == NULL) 00085 return NULL; 00086 00087 /* 00088 * CHAP Response: 00089 * Value-Size (1 octet) | Value(Response) | Name(optional) 00090 */ 00091 wpabuf_put_u8(resp, CHAP_MD5_LEN); 00092 00093 id = eap_get_id(resp); 00094 rpos = wpabuf_put(resp, CHAP_MD5_LEN); 00095 chap_md5(id, password, password_len, challenge, challenge_len, rpos); 00096 wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); 00097 00098 return resp; 00099 } 00100 00101 00102 int eap_peer_md5_register(void) 00103 { 00104 struct eap_method *eap; 00105 int ret; 00106 00107 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 00108 EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); 00109 if (eap == NULL) 00110 return -1; 00111 00112 eap->init = eap_md5_init; 00113 eap->deinit = eap_md5_deinit; 00114 eap->process = eap_md5_process; 00115 00116 ret = eap_peer_method_register(eap); 00117 if (ret) 00118 eap_peer_method_free(eap); 00119 return ret; 00120 }