16d49e1aeSJan Lentfer /* 26d49e1aeSJan Lentfer * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) 3*3ff40c12SJohn Marino * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> 46d49e1aeSJan Lentfer * 5*3ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license. 6*3ff40c12SJohn Marino * See README for more details. 76d49e1aeSJan Lentfer */ 86d49e1aeSJan Lentfer 96d49e1aeSJan Lentfer #include "includes.h" 106d49e1aeSJan Lentfer 116d49e1aeSJan Lentfer #include "common.h" 126d49e1aeSJan Lentfer #include "eap_i.h" 136d49e1aeSJan Lentfer #include "eap_common/chap.h" 146d49e1aeSJan Lentfer 156d49e1aeSJan Lentfer 166d49e1aeSJan Lentfer static void * eap_md5_init(struct eap_sm *sm) 176d49e1aeSJan Lentfer { 186d49e1aeSJan Lentfer /* No need for private data. However, must return non-NULL to indicate 196d49e1aeSJan Lentfer * success. */ 206d49e1aeSJan Lentfer return (void *) 1; 216d49e1aeSJan Lentfer } 226d49e1aeSJan Lentfer 236d49e1aeSJan Lentfer 246d49e1aeSJan Lentfer static void eap_md5_deinit(struct eap_sm *sm, void *priv) 256d49e1aeSJan Lentfer { 266d49e1aeSJan Lentfer } 276d49e1aeSJan Lentfer 286d49e1aeSJan Lentfer 296d49e1aeSJan Lentfer static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, 306d49e1aeSJan Lentfer struct eap_method_ret *ret, 316d49e1aeSJan Lentfer const struct wpabuf *reqData) 326d49e1aeSJan Lentfer { 336d49e1aeSJan Lentfer struct wpabuf *resp; 346d49e1aeSJan Lentfer const u8 *pos, *challenge, *password; 356d49e1aeSJan Lentfer u8 *rpos, id; 366d49e1aeSJan Lentfer size_t len, challenge_len, password_len; 376d49e1aeSJan Lentfer 386d49e1aeSJan Lentfer password = eap_get_config_password(sm, &password_len); 396d49e1aeSJan Lentfer if (password == NULL) { 406d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); 416d49e1aeSJan Lentfer eap_sm_request_password(sm); 426d49e1aeSJan Lentfer ret->ignore = TRUE; 436d49e1aeSJan Lentfer return NULL; 446d49e1aeSJan Lentfer } 456d49e1aeSJan Lentfer 466d49e1aeSJan Lentfer pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); 476d49e1aeSJan Lentfer if (pos == NULL || len == 0) { 486d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", 496d49e1aeSJan Lentfer pos, (unsigned long) len); 506d49e1aeSJan Lentfer ret->ignore = TRUE; 516d49e1aeSJan Lentfer return NULL; 526d49e1aeSJan Lentfer } 536d49e1aeSJan Lentfer 546d49e1aeSJan Lentfer /* 556d49e1aeSJan Lentfer * CHAP Challenge: 566d49e1aeSJan Lentfer * Value-Size (1 octet) | Value(Challenge) | Name(optional) 576d49e1aeSJan Lentfer */ 586d49e1aeSJan Lentfer challenge_len = *pos++; 596d49e1aeSJan Lentfer if (challenge_len == 0 || challenge_len > len - 1) { 606d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " 616d49e1aeSJan Lentfer "(challenge_len=%lu len=%lu)", 626d49e1aeSJan Lentfer (unsigned long) challenge_len, (unsigned long) len); 636d49e1aeSJan Lentfer ret->ignore = TRUE; 646d49e1aeSJan Lentfer return NULL; 656d49e1aeSJan Lentfer } 666d49e1aeSJan Lentfer ret->ignore = FALSE; 676d49e1aeSJan Lentfer challenge = pos; 686d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", 696d49e1aeSJan Lentfer challenge, challenge_len); 706d49e1aeSJan Lentfer 716d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); 726d49e1aeSJan Lentfer ret->methodState = METHOD_DONE; 73*3ff40c12SJohn Marino ret->decision = DECISION_COND_SUCC; 746d49e1aeSJan Lentfer ret->allowNotifications = TRUE; 756d49e1aeSJan Lentfer 766d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, 776d49e1aeSJan Lentfer EAP_CODE_RESPONSE, eap_get_id(reqData)); 786d49e1aeSJan Lentfer if (resp == NULL) 796d49e1aeSJan Lentfer return NULL; 806d49e1aeSJan Lentfer 816d49e1aeSJan Lentfer /* 826d49e1aeSJan Lentfer * CHAP Response: 836d49e1aeSJan Lentfer * Value-Size (1 octet) | Value(Response) | Name(optional) 846d49e1aeSJan Lentfer */ 856d49e1aeSJan Lentfer wpabuf_put_u8(resp, CHAP_MD5_LEN); 866d49e1aeSJan Lentfer 876d49e1aeSJan Lentfer id = eap_get_id(resp); 886d49e1aeSJan Lentfer rpos = wpabuf_put(resp, CHAP_MD5_LEN); 89*3ff40c12SJohn Marino if (chap_md5(id, password, password_len, challenge, challenge_len, 90*3ff40c12SJohn Marino rpos)) { 91*3ff40c12SJohn Marino wpa_printf(MSG_INFO, "EAP-MD5: CHAP MD5 operation failed"); 92*3ff40c12SJohn Marino ret->ignore = TRUE; 93*3ff40c12SJohn Marino wpabuf_free(resp); 94*3ff40c12SJohn Marino return NULL; 95*3ff40c12SJohn Marino } 966d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); 976d49e1aeSJan Lentfer 986d49e1aeSJan Lentfer return resp; 996d49e1aeSJan Lentfer } 1006d49e1aeSJan Lentfer 1016d49e1aeSJan Lentfer 1026d49e1aeSJan Lentfer int eap_peer_md5_register(void) 1036d49e1aeSJan Lentfer { 1046d49e1aeSJan Lentfer struct eap_method *eap; 1056d49e1aeSJan Lentfer int ret; 1066d49e1aeSJan Lentfer 1076d49e1aeSJan Lentfer eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 1086d49e1aeSJan Lentfer EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); 1096d49e1aeSJan Lentfer if (eap == NULL) 1106d49e1aeSJan Lentfer return -1; 1116d49e1aeSJan Lentfer 1126d49e1aeSJan Lentfer eap->init = eap_md5_init; 1136d49e1aeSJan Lentfer eap->deinit = eap_md5_deinit; 1146d49e1aeSJan Lentfer eap->process = eap_md5_process; 1156d49e1aeSJan Lentfer 1166d49e1aeSJan Lentfer ret = eap_peer_method_register(eap); 1176d49e1aeSJan Lentfer if (ret) 1186d49e1aeSJan Lentfer eap_peer_method_free(eap); 1196d49e1aeSJan Lentfer return ret; 1206d49e1aeSJan Lentfer } 121