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