1*6d49e1aeSJan Lentfer /* 2*6d49e1aeSJan Lentfer * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) 3*6d49e1aeSJan Lentfer * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4*6d49e1aeSJan Lentfer * 5*6d49e1aeSJan Lentfer * This program is free software; you can redistribute it and/or modify 6*6d49e1aeSJan Lentfer * it under the terms of the GNU General Public License version 2 as 7*6d49e1aeSJan Lentfer * published by the Free Software Foundation. 8*6d49e1aeSJan Lentfer * 9*6d49e1aeSJan Lentfer * Alternatively, this software may be distributed under the terms of BSD 10*6d49e1aeSJan Lentfer * license. 11*6d49e1aeSJan Lentfer * 12*6d49e1aeSJan Lentfer * See README and COPYING for more details. 13*6d49e1aeSJan Lentfer */ 14*6d49e1aeSJan Lentfer 15*6d49e1aeSJan Lentfer #include "includes.h" 16*6d49e1aeSJan Lentfer 17*6d49e1aeSJan Lentfer #include "common.h" 18*6d49e1aeSJan Lentfer #include "eap_i.h" 19*6d49e1aeSJan Lentfer #include "eap_common/chap.h" 20*6d49e1aeSJan Lentfer 21*6d49e1aeSJan Lentfer 22*6d49e1aeSJan Lentfer static void * eap_md5_init(struct eap_sm *sm) 23*6d49e1aeSJan Lentfer { 24*6d49e1aeSJan Lentfer /* No need for private data. However, must return non-NULL to indicate 25*6d49e1aeSJan Lentfer * success. */ 26*6d49e1aeSJan Lentfer return (void *) 1; 27*6d49e1aeSJan Lentfer } 28*6d49e1aeSJan Lentfer 29*6d49e1aeSJan Lentfer 30*6d49e1aeSJan Lentfer static void eap_md5_deinit(struct eap_sm *sm, void *priv) 31*6d49e1aeSJan Lentfer { 32*6d49e1aeSJan Lentfer } 33*6d49e1aeSJan Lentfer 34*6d49e1aeSJan Lentfer 35*6d49e1aeSJan Lentfer static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, 36*6d49e1aeSJan Lentfer struct eap_method_ret *ret, 37*6d49e1aeSJan Lentfer const struct wpabuf *reqData) 38*6d49e1aeSJan Lentfer { 39*6d49e1aeSJan Lentfer struct wpabuf *resp; 40*6d49e1aeSJan Lentfer const u8 *pos, *challenge, *password; 41*6d49e1aeSJan Lentfer u8 *rpos, id; 42*6d49e1aeSJan Lentfer size_t len, challenge_len, password_len; 43*6d49e1aeSJan Lentfer 44*6d49e1aeSJan Lentfer password = eap_get_config_password(sm, &password_len); 45*6d49e1aeSJan Lentfer if (password == NULL) { 46*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); 47*6d49e1aeSJan Lentfer eap_sm_request_password(sm); 48*6d49e1aeSJan Lentfer ret->ignore = TRUE; 49*6d49e1aeSJan Lentfer return NULL; 50*6d49e1aeSJan Lentfer } 51*6d49e1aeSJan Lentfer 52*6d49e1aeSJan Lentfer pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, reqData, &len); 53*6d49e1aeSJan Lentfer if (pos == NULL || len == 0) { 54*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", 55*6d49e1aeSJan Lentfer pos, (unsigned long) len); 56*6d49e1aeSJan Lentfer ret->ignore = TRUE; 57*6d49e1aeSJan Lentfer return NULL; 58*6d49e1aeSJan Lentfer } 59*6d49e1aeSJan Lentfer 60*6d49e1aeSJan Lentfer /* 61*6d49e1aeSJan Lentfer * CHAP Challenge: 62*6d49e1aeSJan Lentfer * Value-Size (1 octet) | Value(Challenge) | Name(optional) 63*6d49e1aeSJan Lentfer */ 64*6d49e1aeSJan Lentfer challenge_len = *pos++; 65*6d49e1aeSJan Lentfer if (challenge_len == 0 || challenge_len > len - 1) { 66*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " 67*6d49e1aeSJan Lentfer "(challenge_len=%lu len=%lu)", 68*6d49e1aeSJan Lentfer (unsigned long) challenge_len, (unsigned long) len); 69*6d49e1aeSJan Lentfer ret->ignore = TRUE; 70*6d49e1aeSJan Lentfer return NULL; 71*6d49e1aeSJan Lentfer } 72*6d49e1aeSJan Lentfer ret->ignore = FALSE; 73*6d49e1aeSJan Lentfer challenge = pos; 74*6d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", 75*6d49e1aeSJan Lentfer challenge, challenge_len); 76*6d49e1aeSJan Lentfer 77*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); 78*6d49e1aeSJan Lentfer ret->methodState = METHOD_DONE; 79*6d49e1aeSJan Lentfer ret->decision = DECISION_UNCOND_SUCC; 80*6d49e1aeSJan Lentfer ret->allowNotifications = TRUE; 81*6d49e1aeSJan Lentfer 82*6d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, 83*6d49e1aeSJan Lentfer EAP_CODE_RESPONSE, eap_get_id(reqData)); 84*6d49e1aeSJan Lentfer if (resp == NULL) 85*6d49e1aeSJan Lentfer return NULL; 86*6d49e1aeSJan Lentfer 87*6d49e1aeSJan Lentfer /* 88*6d49e1aeSJan Lentfer * CHAP Response: 89*6d49e1aeSJan Lentfer * Value-Size (1 octet) | Value(Response) | Name(optional) 90*6d49e1aeSJan Lentfer */ 91*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, CHAP_MD5_LEN); 92*6d49e1aeSJan Lentfer 93*6d49e1aeSJan Lentfer id = eap_get_id(resp); 94*6d49e1aeSJan Lentfer rpos = wpabuf_put(resp, CHAP_MD5_LEN); 95*6d49e1aeSJan Lentfer chap_md5(id, password, password_len, challenge, challenge_len, rpos); 96*6d49e1aeSJan Lentfer wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, CHAP_MD5_LEN); 97*6d49e1aeSJan Lentfer 98*6d49e1aeSJan Lentfer return resp; 99*6d49e1aeSJan Lentfer } 100*6d49e1aeSJan Lentfer 101*6d49e1aeSJan Lentfer 102*6d49e1aeSJan Lentfer int eap_peer_md5_register(void) 103*6d49e1aeSJan Lentfer { 104*6d49e1aeSJan Lentfer struct eap_method *eap; 105*6d49e1aeSJan Lentfer int ret; 106*6d49e1aeSJan Lentfer 107*6d49e1aeSJan Lentfer eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 108*6d49e1aeSJan Lentfer EAP_VENDOR_IETF, EAP_TYPE_MD5, "MD5"); 109*6d49e1aeSJan Lentfer if (eap == NULL) 110*6d49e1aeSJan Lentfer return -1; 111*6d49e1aeSJan Lentfer 112*6d49e1aeSJan Lentfer eap->init = eap_md5_init; 113*6d49e1aeSJan Lentfer eap->deinit = eap_md5_deinit; 114*6d49e1aeSJan Lentfer eap->process = eap_md5_process; 115*6d49e1aeSJan Lentfer 116*6d49e1aeSJan Lentfer ret = eap_peer_method_register(eap); 117*6d49e1aeSJan Lentfer if (ret) 118*6d49e1aeSJan Lentfer eap_peer_method_free(eap); 119*6d49e1aeSJan Lentfer return ret; 120*6d49e1aeSJan Lentfer } 121