eap_mschapv2.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26). 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Extensions Protocol, Version 2, for mutual authentication and key 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * derivation. This encapsulates MS-CHAP-v2 protocol which is defined in 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 2759. Use of EAP-MSCHAPV2 derived keys with MPPE cipher is described in 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 3079. 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/ms_funcs.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/wpa_ctrl.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "mschapv2.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_config.h" 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _MSC_VER 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#pragma pack(push, 1) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _MSC_VER */ 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_mschapv2_hdr { 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 op_code; /* MSCHAPV2_OP_* */ 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mschapv2_id; /* usually same as EAP identifier; must be changed 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * for challenges, but not for success/failure */ 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ms_length[2]; /* Note: misaligned; length - 5 */ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by data */ 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Response Data field */ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ms_response { 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 peer_challenge[MSCHAPV2_CHAL_LEN]; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 reserved[8]; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* Change-Password Data field */ 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct ms_change_password { 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 encr_password[516]; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 encr_hash[16]; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 peer_challenge[MSCHAPV2_CHAL_LEN]; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 reserved[8]; 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags[2]; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef _MSC_VER 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#pragma pack(pop) 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* _MSC_VER */ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MSCHAPV2_OP_CHALLENGE 1 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MSCHAPV2_OP_RESPONSE 2 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MSCHAPV2_OP_SUCCESS 3 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MSCHAPV2_OP_FAILURE 4 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MSCHAPV2_OP_CHANGE_PASSWORD 7 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ERROR_RESTRICTED_LOGON_HOURS 646 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ERROR_ACCT_DISABLED 647 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ERROR_PASSWD_EXPIRED 648 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ERROR_NO_DIALIN_PERMISSION 649 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ERROR_AUTHENTICATION_FAILURE 691 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define ERROR_CHANGING_PASSWORD 709 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define PASSWD_CHANGE_CHAL_LEN 16 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MSCHAPV2_KEY_LEN 16 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_mschapv2_data { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int auth_response_valid; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int prev_error; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN]; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int passwd_change_challenge_valid; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int passwd_change_version; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optional challenge values generated in EAP-FAST Phase 1 negotiation 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *peer_challenge; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *auth_challenge; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int phase2; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int master_key_valid; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int success; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *prev_challenge; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_mschapv2_deinit(struct eap_sm *sm, void *priv); 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_mschapv2_init(struct eap_sm *sm) 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->peer_challenge) { 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peer_challenge == NULL) { 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_mschapv2_deinit(sm, data); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->peer_challenge, sm->peer_challenge, 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MSCHAPV2_CHAL_LEN); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->auth_challenge) { 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth_challenge == NULL) { 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_mschapv2_deinit(sm, data); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->auth_challenge, sm->auth_challenge, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MSCHAPV2_CHAL_LEN); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->phase2 = sm->init_phase2; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_mschapv2_deinit(struct eap_sm *sm, void *priv) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data = priv; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->peer_challenge); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->auth_challenge); 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->prev_challenge); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_mschapv2_challenge_reply( 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mschapv2_id, const u8 *auth_challenge) 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_hdr *ms; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *peer_challenge; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ms_len; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ms_response *r; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pwhash; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password2(sm, &password_len, &pwhash); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (identity == NULL || password == NULL) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms = wpabuf_put(resp, sizeof(*ms)); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms->op_code = MSCHAPV2_OP_RESPONSE; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms->mschapv2_id = mschapv2_id; 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->prev_error) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: this does not seem to be enough when processing two 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * or more failure messages. IAS did not increment mschapv2_id 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * in its own packets, but it seemed to expect the peer to 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * increment this for all packets(?). 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms->mschapv2_id++; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(ms->ms_length, ms_len); 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */ 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Response */ 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r = wpabuf_put(resp, sizeof(*r)); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge = r->peer_challenge; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->peer_challenge) { 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in Phase 1"); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge = data->peer_challenge; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) { 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(r->reserved, 0, 8); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->auth_challenge) { 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in Phase 1"); 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt auth_challenge = data->auth_challenge; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mschapv2_derive_response(identity, identity_len, password, 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password_len, pwhash, auth_challenge, 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer_challenge, r->nt_response, 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_response, data->master_key)) { 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive " 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "response"); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_response_valid = 1; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->master_key_valid = 1; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt r->flags = 0; /* reserved, must be zero */ 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, identity, identity_len); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(response)", id, ms->mschapv2_id); 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to private EAP method data from eap_mschapv2_init() 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: Pointer to EAP-MSCHAPv2 header from the request 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req_len: Length of the EAP-MSCHAPv2 data 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier used in the request 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * no reply available 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_mschapv2_challenge( 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_mschapv2_data *data, 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_len, u8 id) 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, challenge_len; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *challenge; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_identity(sm, &len) == NULL || 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_get_config_password(sm, &len) == NULL) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge"); 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req_len < sizeof(*req) + 1) { 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data " 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(len %lu)", (unsigned long) req_len); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (req + 1); 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge_len = *pos++; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = req_len - sizeof(*req) - 1; 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (challenge_len != MSCHAPV2_CHAL_LEN) { 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%lu", (unsigned long) challenge_len); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < challenge_len) { 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " packet: len=%lu challenge_len=%lu", 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, (unsigned long) challenge_len); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->passwd_change_challenge_valid) { 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using challenge from the " 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failure message"); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge = data->passwd_change_challenge; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge = pos; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += challenge_len; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len -= challenge_len; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt challenge); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_mschapv2_password_changed(struct eap_sm *sm, 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data) 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config && config->new_password) { 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_EVENT_PASSWORD_CHANGED 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-MSCHAPV2: Password changed successfully"); 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_error = 0; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(config->password); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->password = os_malloc(16); 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->password_len = 16; 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->password) { 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash(config->new_password, 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->new_password_len, 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->password); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(config->new_password); 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->password = config->new_password; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->password_len = config->new_password_len; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->new_password = NULL; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->new_password_len = 0; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to private EAP method data from eap_mschapv2_init() 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: Pointer to EAP-MSCHAPv2 header from the request 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req_len: Length of the EAP-MSCHAPv2 data 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier used in th erequest 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * no reply available 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data, 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_mschapv2_hdr *req, 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_len, u8 id) 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = req_len - sizeof(*req); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (req + 1); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->auth_response_valid || 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mschapv2_verify_auth_response(data->auth_response, pos, len)) { 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "response in success request"); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len -= 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (len > 0 && *pos == ' ') { 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len--; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message", 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded"); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: Only op_code of the EAP-MSCHAPV2 header is included in success 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * message. */ 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) { 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "buffer for success response"); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, MSCHAPV2_OP_SUCCESS); /* op_code */ 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->success = 1; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->prev_error == ERROR_PASSWD_EXPIRED) 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_mschapv2_password_changed(sm, data); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_mschapv2_failure_txt(struct eap_sm *sm, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data, char *txt) 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos, *msg = ""; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int retry = 1; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* For example: 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = txt; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos && os_strncmp(pos, "E=", 2) == 0) { 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_error = atoi(pos); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d", 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_error); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, ' '); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos && os_strncmp(pos, "R=", 2) == 0) { 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retry = atoi(pos); 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed", 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retry == 1 ? "" : "not "); 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, ' '); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos && os_strncmp(pos, "C=", 2) == 0) { 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int hex_len; 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hex_len = os_strchr(pos, ' ') - (char *) pos; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hexstr2bin(pos, data->passwd_change_challenge, 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PASSWD_CHANGE_CHAL_LEN)) { 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid " 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failure challenge"); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure " 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge", 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_challenge, 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PASSWD_CHANGE_CHAL_LEN); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_challenge_valid = 1; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure " 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "challenge len %d", hex_len); 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, ' '); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field " 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "was not present in failure message"); 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos && os_strncmp(pos, "V=", 2) == 0) { 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_version = atoi(pos); 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing " 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "protocol version %d", data->passwd_change_version); 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = os_strchr(pos, ' '); 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos && os_strncmp(pos, "M=", 2) == 0) { 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = pos; 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_WARNING, 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error " 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d)", 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg, retry == 1 ? "" : "not ", data->prev_error); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->prev_error == ERROR_PASSWD_EXPIRED && 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_version == 3 && config) { 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->new_password == NULL) { 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-MSCHAPV2: Password expired - password " 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "change required"); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_new_password(sm); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (retry == 1 && config) { 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could prevent the current password from being used 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * again at least for some period of time */ 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!config->mschapv2_retry) 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_identity(sm); 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_password(sm); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->mschapv2_retry = 1; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (config) { 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: prevent retries using same username/password */ 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->mschapv2_retry = 0; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return retry == 1; 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_mschapv2_change_password( 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_sm *sm, struct eap_mschapv2_data *data, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ms_len; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *username, *password, *new_password; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t username_len, password_len, new_password_len; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_hdr *ms; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct ms_change_password *cp; 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 password_hash[16], password_hash_hash[16]; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pwhash; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username = eap_get_config_identity(sm, &username_len); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password2(sm, &password_len, &pwhash); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password = eap_get_config_new_password(sm, &new_password_len); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (username == NULL || password == NULL || new_password == NULL) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username = mschapv2_remove_domain(username, &username_len); 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_COND_SUCC; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms_len = sizeof(*ms) + sizeof(*cp); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms = wpabuf_put(resp, sizeof(*ms)); 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms->mschapv2_id = req->mschapv2_id + 1; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(ms->ms_length, ms_len); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp = wpabuf_put(resp, sizeof(*cp)); 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Encrypted-Password */ 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pwhash) { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (encrypt_pw_block_with_password_hash( 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password, new_password_len, 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, cp->encr_password)) 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (new_password_encrypted_with_old_nt_password_hash( 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password, new_password_len, 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len, cp->encr_password)) 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Encrypted-Hash */ 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pwhash) { 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 new_password_hash[16]; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash(new_password, new_password_len, 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password_hash); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash_encrypted_with_block(password, 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password_hash, 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp->encr_hash); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt old_nt_password_hash_encrypted_with_new_nt_password_hash( 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password, new_password_len, 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password, password_len, cp->encr_hash); 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer-Challenge */ 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Reserved, must be zero */ 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cp->reserved, 0, 8); 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* NT-Response */ 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN); 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp->peer_challenge, MSCHAPV2_CHAL_LEN); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len); 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password", 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password, new_password_len); 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_password, new_password_len, 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp->nt_response); 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response", 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Authenticator response is not really needed yet, but calculate it 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * here so that challenges need not be saved. */ 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt generate_authenticator_response(new_password, new_password_len, 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp->peer_challenge, 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_challenge, 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt username, username_len, 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cp->nt_response, data->auth_response); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->auth_response_valid = 1; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Likewise, generate master_key here since we have the needed data 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * available. */ 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nt_password_hash(new_password, new_password_len, password_hash); 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_nt_password_hash(password_hash, password_hash_hash); 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt get_master_key(password_hash_hash, cp->nt_response, data->master_key); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->master_key_valid = 1; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Flags */ 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(cp->flags, 0, 2); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(change pw)", id, ms->mschapv2_id); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(resp); 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Pointer to private EAP method data from eap_mschapv2_init() 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req: Pointer to EAP-MSCHAPv2 header from the request 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @req_len: Length of the EAP-MSCHAPv2 data 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @id: EAP identifier used in th erequest 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * no reply available 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm, 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data, 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_mschapv2_hdr *req, 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_len, u8 id) 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *msdata = (const u8 *) (req + 1); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *buf; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = req_len - sizeof(*req); 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int retry = 0; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure"); 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data", 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msdata, len); 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_mschapv2_failure_txt() expects a nul terminated string, so we 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * must allocate a large enough temporary buffer to create that since 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the received message does not include nul termination. 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_malloc(len + 1); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (buf) { 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(buf, msdata, len); 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf[len] = '\0'; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt retry = eap_mschapv2_failure_txt(sm, data, buf); 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->prev_error == ERROR_PASSWD_EXPIRED && 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->passwd_change_version == 3) { 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config && config->new_password) 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_mschapv2_change_password(sm, data, ret, req, 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config && config->pending_req_new_password) 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) { 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: could try to retry authentication, e.g, after having 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * changed the username/password. In this case, EAP MS-CHAP-v2 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Failure Response would not be sent here. */ 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Note: Only op_code of the EAP-MSCHAPV2 header is included in failure 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * message. */ 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, MSCHAPV2_OP_FAILURE); /* op_code */ 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_mschapv2_check_config(struct eap_sm *sm) 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_identity(sm, &len) == NULL) { 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured"); 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_identity(sm); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_get_config_password(sm, &len) == NULL) { 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_sm_request_password(sm); 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len, 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_mschapv2_hdr *ms) 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t ms_len = WPA_GET_BE16(ms->ms_length); 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ms_len == len) 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu " 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ms_len=%lu", (unsigned long) len, (unsigned long) ms_len); 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->workaround) { 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Some authentication servers use invalid ms_len, 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ignore it for interoperability. */ 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore" 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " invalid ms_len %lu (len %lu)", 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) ms_len, 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len); 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Store a copy of the challenge message, so that it can be processed 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * again in case retry is allowed after a possible failure. 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->prev_challenge); 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_challenge = wpabuf_dup(reqData); 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 request 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @priv: Pointer to private EAP method data from eap_mschapv2_init() 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ret: Return values from EAP request validation and processing 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reqData: EAP request to be processed (eapReqData) 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * no reply available 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data = priv; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_mschapv2_hdr *ms; 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int using_prev_challenge = 0; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id; 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_mschapv2_check_config(sm)) { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (config->mschapv2_retry && data->prev_challenge && 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->prev_error == ERROR_AUTHENTICATION_FAILURE) { 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Replacing pending packet " 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the previous challenge"); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reqData = data->prev_challenge; 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt using_prev_challenge = 1; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt config->mschapv2_retry = 0; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData, 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &len); 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < sizeof(*ms) + 1) { 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms = (const struct eap_mschapv2_hdr *) pos; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_mschapv2_check_mslen(sm, len, ms)) { 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(reqData); 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d", 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id, ms->mschapv2_id); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (ms->op_code) { 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MSCHAPV2_OP_CHALLENGE: 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!using_prev_challenge) 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_mschapv2_copy_challenge(data, reqData); 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_mschapv2_challenge(sm, data, ret, ms, len, id); 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MSCHAPV2_OP_SUCCESS: 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_mschapv2_success(sm, data, ret, ms, len, id); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case MSCHAPV2_OP_FAILURE: 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_mschapv2_failure(sm, data, ret, ms, len, id); 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ms->op_code); 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data = priv; 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->success && data->master_key_valid; 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_mschapv2_data *data = priv; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int key_len; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!data->master_key_valid || !data->success) 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 2 * MSCHAPV2_KEY_LEN; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(key_len); 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e., 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */ 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0); 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MSCHAPV2_KEY_LEN, 0, 0); 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key, key_len); 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = key_len; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * eap_peer_mschapv2_register - Register EAP-MSCHAPv2 peer method 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to register EAP-MSCHAPv2 peer method into the EAP 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * method list. 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_mschapv2_register(void) 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MSCHAPV2"); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_mschapv2_init; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_mschapv2_deinit; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_mschapv2_process; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_mschapv2_isKeyAvailable; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_mschapv2_getKey; 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_peer_method_register(eap); 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_peer_method_free(eap); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 884