139beb93cSSam Leffler /* 239beb93cSSam Leffler * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) 339beb93cSSam Leffler * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "common.h" 1839beb93cSSam Leffler #include "eap_i.h" 1939beb93cSSam Leffler #include "eap_common/chap.h" 2039beb93cSSam Leffler 2139beb93cSSam Leffler 2239beb93cSSam Leffler static void * eap_md5_init(struct eap_sm *sm) 2339beb93cSSam Leffler { 2439beb93cSSam Leffler /* No need for private data. However, must return non-NULL to indicate 2539beb93cSSam Leffler * success. */ 2639beb93cSSam Leffler return (void *) 1; 2739beb93cSSam Leffler } 2839beb93cSSam Leffler 2939beb93cSSam Leffler 3039beb93cSSam Leffler static void eap_md5_deinit(struct eap_sm *sm, void *priv) 3139beb93cSSam Leffler { 3239beb93cSSam Leffler } 3339beb93cSSam Leffler 3439beb93cSSam Leffler 3539beb93cSSam Leffler static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, 3639beb93cSSam Leffler struct eap_method_ret *ret, 3739beb93cSSam Leffler const struct wpabuf *reqData) 3839beb93cSSam Leffler { 3939beb93cSSam Leffler struct wpabuf *resp; 4039beb93cSSam Leffler const u8 *pos, *challenge, *password; 4139beb93cSSam Leffler u8 *rpos, id; 4239beb93cSSam Leffler size_t len, challenge_len, password_len; 4339beb93cSSam Leffler 4439beb93cSSam Leffler password = eap_get_config_password(sm, &password_len); 4539beb93cSSam Leffler if (password == NULL) { 4639beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); 4739beb93cSSam Leffler eap_sm_request_password(sm); 4839beb93cSSam Leffler ret->ignore = TRUE; 4939beb93cSSam Leffler return NULL; 5039beb93cSSam Leffler } 5139beb93cSSam Leffler 5239beb93cSSam Leffler pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); 5339beb93cSSam Leffler if (pos == NULL || len == 0) { 5439beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", 5539beb93cSSam Leffler pos, (unsigned long) len); 5639beb93cSSam Leffler ret->ignore = TRUE; 5739beb93cSSam Leffler return NULL; 5839beb93cSSam Leffler } 5939beb93cSSam Leffler 6039beb93cSSam Leffler /* 6139beb93cSSam Leffler * CHAP Challenge: 6239beb93cSSam Leffler * Value-Size (1 octet) | Value(Challenge) | Name(optional) 6339beb93cSSam Leffler */ 6439beb93cSSam Leffler challenge_len = *pos++; 6539beb93cSSam Leffler if (challenge_len == 0 || challenge_len > len - 1) { 6639beb93cSSam Leffler wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " 6739beb93cSSam Leffler "(challenge_len=%lu len=%lu)", 6839beb93cSSam Leffler (unsigned long) challenge_len, (unsigned long) len); 6939beb93cSSam Leffler ret->ignore = TRUE; 7039beb93cSSam Leffler return NULL; 7139beb93cSSam Leffler } 7239beb93cSSam Leffler ret->ignore = FALSE; 7339beb93cSSam Leffler challenge = pos; 7439beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", 7539beb93cSSam Leffler challenge, challenge_len); 7639beb93cSSam Leffler 7739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); 7839beb93cSSam Leffler ret->methodState = METHOD_DONE; 7939beb93cSSam Leffler ret->decision = DECISION_UNCOND_SUCC; 8039beb93cSSam Leffler ret->allowNotifications = TRUE; 8139beb93cSSam Leffler 8239beb93cSSam Leffler resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, 8339beb93cSSam Leffler EAP_CODE_RESPONSE, eap_get_id(reqData)); 8439beb93cSSam Leffler if (resp == NULL) 8539beb93cSSam Leffler return NULL; 8639beb93cSSam Leffler 8739beb93cSSam Leffler /* 8839beb93cSSam Leffler * CHAP Response: 8939beb93cSSam Leffler * Value-Size (1 octet) | Value(Response) | Name(optional) 9039beb93cSSam Leffler */ 9139beb93cSSam Leffler wpabuf_put_u8(resp, CHAP_MD5_LEN); 9239beb93cSSam Leffler 9339beb93cSSam Leffler id = eap_get_id(resp); 9439beb93cSSam Leffler rpos = wpabuf_put(resp, CHAP_MD5_LEN); 9539beb93cSSam Leffler chap_md5(id, password, password_len, challenge, challenge_len, rpos); 9639beb93cSSam Leffler wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); 9739beb93cSSam Leffler 9839beb93cSSam Leffler return resp; 9939beb93cSSam Leffler } 10039beb93cSSam Leffler 10139beb93cSSam Leffler 10239beb93cSSam Leffler int eap_peer_md5_register(void) 10339beb93cSSam Leffler { 10439beb93cSSam Leffler struct eap_method *eap; 10539beb93cSSam Leffler int ret; 10639beb93cSSam Leffler 10739beb93cSSam Leffler eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 10839beb93cSSam Leffler EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); 10939beb93cSSam Leffler if (eap == NULL) 11039beb93cSSam Leffler return -1; 11139beb93cSSam Leffler 11239beb93cSSam Leffler eap->init = eap_md5_init; 11339beb93cSSam Leffler eap->deinit = eap_md5_deinit; 11439beb93cSSam Leffler eap->process = eap_md5_process; 11539beb93cSSam Leffler 11639beb93cSSam Leffler ret = eap_peer_method_register(eap); 11739beb93cSSam Leffler if (ret) 11839beb93cSSam Leffler eap_peer_method_free(eap); 11939beb93cSSam Leffler return ret; 12039beb93cSSam Leffler } 121