18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) 361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/chap.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_md5_init(struct eap_sm *sm) 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* No need for private data. However, must return non-NULL to indicate 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * success. */ 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return (void *) 1; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_md5_deinit(struct eap_sm *sm, void *priv) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *challenge, *password; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, id; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, challenge_len, password_len; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (password == NULL) { 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_password(sm); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len == 0) { 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, (unsigned long) len); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CHAP Challenge: 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Value-Size (1 octet) | Value(Challenge) | Name(optional) 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len = *pos++; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge_len == 0 || challenge_len > len - 1) { 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(challenge_len=%lu len=%lu)", 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) challenge_len, (unsigned long) len); 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge = pos; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge, challenge_len); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CHAP Response: 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Value-Size (1 octet) | Value(Response) | Name(optional) 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, CHAP_MD5_LEN); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(resp); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, CHAP_MD5_LEN); 8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (chap_md5(id, password, password_len, challenge, challenge_len, 9061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt rpos)) { 9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MD5: CHAP MD5 operation failed"); 9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt ret->ignore = TRUE; 9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpabuf_free(resp); 9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt return NULL; 9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_md5_register(void) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_md5_init; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_md5_deinit; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_md5_process; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 121