1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This file implements EAP peer part of EAP-MSCHAPV2 method (EAP type 26). 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * draft-kamath-pppext-eap-mschapv2-00.txt defines the Microsoft EAP CHAP 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Extensions Protocol, Version 2, for mutual authentication and key 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * derivation. This encapsulates MS-CHAP-v2 protocol which is defined in 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 2759. Use of EAP-MSCHAPV2 derived keys with MPPE cipher is described in 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * RFC 3079. 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_i.h" 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eap_config.h" 27b349ef9e9f3f5399bf96b3c1c663cb9e547f50a1Dmitry Shmidt#include "crypto/ms_funcs.h" 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_ctrl.h" 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "mschapv2.h" 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef _MSC_VER 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#pragma pack(push, 1) 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* _MSC_VER */ 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_mschapv2_hdr { 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 op_code; /* MSCHAPV2_OP_* */ 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 mschapv2_id; /* usually same as EAP identifier; must be changed 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * for challenges, but not for success/failure */ 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 ms_length[2]; /* Note: misaligned; length - 5 */ 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* followed by data */ 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} STRUCT_PACKED; 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Response Data field */ 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ms_response { 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 peer_challenge[MSCHAPV2_CHAL_LEN]; 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 reserved[8]; 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 flags; 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} STRUCT_PACKED; 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* Change-Password Data field */ 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct ms_change_password { 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 encr_password[516]; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 encr_hash[16]; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 peer_challenge[MSCHAPV2_CHAL_LEN]; 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 reserved[8]; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 flags[2]; 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} STRUCT_PACKED; 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#ifdef _MSC_VER 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#pragma pack(pop) 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#endif /* _MSC_VER */ 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MSCHAPV2_OP_CHALLENGE 1 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MSCHAPV2_OP_RESPONSE 2 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MSCHAPV2_OP_SUCCESS 3 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MSCHAPV2_OP_FAILURE 4 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MSCHAPV2_OP_CHANGE_PASSWORD 7 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ERROR_RESTRICTED_LOGON_HOURS 646 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ERROR_ACCT_DISABLED 647 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ERROR_PASSWD_EXPIRED 648 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ERROR_NO_DIALIN_PERMISSION 649 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ERROR_AUTHENTICATION_FAILURE 691 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define ERROR_CHANGING_PASSWORD 709 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define PASSWD_CHANGE_CHAL_LEN 16 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#define MSCHAPV2_KEY_LEN 16 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstruct eap_mschapv2_data { 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int auth_response_valid; 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int prev_error; 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN]; 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int passwd_change_challenge_valid; 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int passwd_change_version; 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Optional challenge values generated in EAP-FAST Phase 1 negotiation 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *peer_challenge; 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *auth_challenge; 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int phase2; 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int master_key_valid; 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int success; 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *prev_challenge; 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_mschapv2_deinit(struct eap_sm *sm, void *priv); 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void * eap_mschapv2_init(struct eap_sm *sm) 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data; 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data = os_zalloc(sizeof(*data)); 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data == NULL) 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->peer_challenge) { 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->peer_challenge = os_malloc(MSCHAPV2_CHAL_LEN); 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->peer_challenge == NULL) { 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_mschapv2_deinit(sm, data); 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->peer_challenge, sm->peer_challenge, 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MSCHAPV2_CHAL_LEN); 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->auth_challenge) { 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->auth_challenge = os_malloc(MSCHAPV2_CHAL_LEN); 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->auth_challenge == NULL) { 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_mschapv2_deinit(sm, data); 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(data->auth_challenge, sm->auth_challenge, 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MSCHAPV2_CHAL_LEN); 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->phase2 = sm->init_phase2; 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data; 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_mschapv2_deinit(struct eap_sm *sm, void *priv) 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data = priv; 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->peer_challenge); 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data->auth_challenge); 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->prev_challenge); 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(data); 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_mschapv2_challenge_reply( 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 mschapv2_id, const u8 *auth_challenge) 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_hdr *ms; 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *peer_challenge; 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ms_len; 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ms_response *r; 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t identity_len, password_len; 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *identity, *password; 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pwhash; 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password = eap_get_config_password2(sm, &password_len, &pwhash); 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (identity == NULL || password == NULL) 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_RESPONSE, id); 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms = wpabuf_put(resp, sizeof(*ms)); 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms->op_code = MSCHAPV2_OP_RESPONSE; 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms->mschapv2_id = mschapv2_id; 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->prev_error) { 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * TODO: this does not seem to be enough when processing two 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * or more failure messages. IAS did not increment mschapv2_id 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * in its own packets, but it seemed to expect the peer to 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * increment this for all packets(?). 187526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 188526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms->mschapv2_id++; 189526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 190526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(ms->ms_length, ms_len); 191526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 192526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */ 193526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 194526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Response */ 195526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt r = wpabuf_put(resp, sizeof(*r)); 196526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peer_challenge = r->peer_challenge; 197526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->peer_challenge) { 198526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " 199526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in Phase 1"); 200526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peer_challenge = data->peer_challenge; 201526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); 202526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (os_get_random(peer_challenge, MSCHAPV2_CHAL_LEN)) { 203526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(resp); 204526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 205526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 206526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(r->reserved, 0, 8); 207526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->auth_challenge) { 208526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " 209526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "in Phase 1"); 210526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt auth_challenge = data->auth_challenge; 211526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 212526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mschapv2_derive_response(identity, identity_len, password, 213526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password_len, pwhash, auth_challenge, 214526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt peer_challenge, r->nt_response, 215526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->auth_response, data->master_key); 216526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->auth_response_valid = 1; 217526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->master_key_valid = 1; 218526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 219526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt r->flags = 0; /* reserved, must be zero */ 220526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 221526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_data(resp, identity, identity_len); 222526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " 223526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(response)", id, ms->mschapv2_id); 224526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 225526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 226526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 227526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 228526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 229526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message 230526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 231526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data: Pointer to private EAP method data from eap_mschapv2_init() 232526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ret: Return values from EAP request validation and processing 233526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @req: Pointer to EAP-MSCHAPv2 header from the request 234526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @req_len: Length of the EAP-MSCHAPv2 data 235526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @id: EAP identifier used in the request 236526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 237526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * no reply available 238526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 239526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_mschapv2_challenge( 240526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_sm *sm, struct eap_mschapv2_data *data, 241526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, 242526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t req_len, u8 id) 243526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 244526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len, challenge_len; 245526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos, *challenge; 246526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 247526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_get_config_identity(sm, &len) == NULL || 248526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_get_config_password(sm, &len) == NULL) 249526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 250526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 251526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge"); 252526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (req_len < sizeof(*req) + 1) { 253526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data " 254526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(len %lu)", (unsigned long) req_len); 255526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 256526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 257526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 258526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (const u8 *) (req + 1); 259526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt challenge_len = *pos++; 260526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = req_len - sizeof(*req) - 1; 261526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (challenge_len != MSCHAPV2_CHAL_LEN) { 262526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " 263526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%lu", (unsigned long) challenge_len); 264526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 265526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 266526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 267526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 268526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (len < challenge_len) { 269526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" 270526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " packet: len=%lu challenge_len=%lu", 271526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len, (unsigned long) challenge_len); 272526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 273526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 274526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 275526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 276526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->passwd_change_challenge_valid) { 277526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Using challenge from the " 278526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "failure message"); 279526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt challenge = data->passwd_change_challenge; 280526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 281526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt challenge = pos; 282526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += challenge_len; 283526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len -= challenge_len; 284526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", 285526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos, len); 286526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 287526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = FALSE; 288526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_MAY_CONT; 289526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 290526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = TRUE; 291526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 292526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, 293526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt challenge); 294526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 295526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 296526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 297526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_mschapv2_password_changed(struct eap_sm *sm, 298526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data) 299526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 300526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 301526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config && config->new_password) { 302526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 303526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_EVENT_PASSWORD_CHANGED 304526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP-MSCHAPV2: Password changed successfully"); 305526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->prev_error = 0; 306526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(config->password); 307526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { 308526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->password = os_malloc(16); 309526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->password_len = 16; 310526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config->password) { 311526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nt_password_hash(config->new_password, 312526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->new_password_len, 313526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->password); 314526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 315526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(config->new_password); 316526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 317526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->password = config->new_password; 318526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->password_len = config->new_password_len; 319526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 320526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->new_password = NULL; 321526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->new_password_len = 0; 322526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 323526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 324526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 325526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 326526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 327526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message 328526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 329526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data: Pointer to private EAP method data from eap_mschapv2_init() 330526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ret: Return values from EAP request validation and processing 331526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @req: Pointer to EAP-MSCHAPv2 header from the request 332526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @req_len: Length of the EAP-MSCHAPv2 data 333526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @id: EAP identifier used in th erequest 334526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 335526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * no reply available 336526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 337526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, 338526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data, 339526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 340526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_mschapv2_hdr *req, 341526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t req_len, u8 id) 342526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 343526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 344526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 345526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 346526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 347526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); 348526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len = req_len - sizeof(*req); 349526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = (const u8 *) (req + 1); 350526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->auth_response_valid || 351526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt mschapv2_verify_auth_response(data->auth_response, pos, len)) { 352526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " 353526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "response in success request"); 354526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 355526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 356526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 357526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 358526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; 359526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len -= 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; 360526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt while (len > 0 && *pos == ' ') { 361526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 362526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt len--; 363526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 364526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message", 365526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos, len); 366526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded"); 367526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 368526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Note: Only op_code of the EAP-MSCHAPV2 header is included in success 369526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * message. */ 370526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, 371526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_RESPONSE, id); 372526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) { 373526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " 374526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "buffer for success response"); 375526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 376526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 377526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 378526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 379526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(resp, MSCHAPV2_OP_SUCCESS); /* op_code */ 380526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 381526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 382526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 383526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = FALSE; 384526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->success = 1; 385526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 386526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->prev_error == ERROR_PASSWD_EXPIRED) 387526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_mschapv2_password_changed(sm, data); 388526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 389526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 390526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 391526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 392526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 393526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_mschapv2_failure_txt(struct eap_sm *sm, 394526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data, char *txt) 395526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 396526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *pos, *msg = ""; 397526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int retry = 1; 398526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 399526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 400526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* For example: 401526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure 402526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 403526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 404526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = txt; 405526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 406526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos && os_strncmp(pos, "E=", 2) == 0) { 407526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 408526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->prev_error = atoi(pos); 409526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d", 410526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->prev_error); 411526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = os_strchr(pos, ' '); 412526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos) 413526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 414526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 415526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 416526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos && os_strncmp(pos, "R=", 2) == 0) { 417526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 418526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt retry = atoi(pos); 419526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed", 420526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt retry == 1 ? "" : "not "); 421526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = os_strchr(pos, ' '); 422526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos) 423526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 424526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 425526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 426526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos && os_strncmp(pos, "C=", 2) == 0) { 427526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int hex_len; 428526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 429526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hex_len = os_strchr(pos, ' ') - (char *) pos; 430526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { 431526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (hexstr2bin(pos, data->passwd_change_challenge, 432526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt PASSWD_CHANGE_CHAL_LEN)) { 433526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid " 434526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "failure challenge"); 435526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 436526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure " 437526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "challenge", 438526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_challenge, 439526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt PASSWD_CHANGE_CHAL_LEN); 440526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_challenge_valid = 1; 441526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 442526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 443526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure " 444526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "challenge len %d", hex_len); 445526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 446526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = os_strchr(pos, ' '); 447526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos) 448526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 449526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 450526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field " 451526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "was not present in failure message"); 452526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 453526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 454526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos && os_strncmp(pos, "V=", 2) == 0) { 455526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 456526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_version = atoi(pos); 457526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing " 458526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "protocol version %d", data->passwd_change_version); 459526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = os_strchr(pos, ' '); 460526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos) 461526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos++; 462526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 463526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 464526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos && os_strncmp(pos, "M=", 2) == 0) { 465526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos += 2; 466526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg = pos; 467526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 468526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->msg_ctx, MSG_WARNING, 469526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error " 470526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%d)", 471526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msg, retry == 1 ? "" : "not ", data->prev_error); 472526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->prev_error == ERROR_PASSWD_EXPIRED && 473526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_version == 3 && config) { 474526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config->new_password == NULL) { 475526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 476526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "EAP-MSCHAPV2: Password expired - password " 477526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "change required"); 478526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_request_new_password(sm); 479526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 480526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (retry == 1 && config) { 481526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: could prevent the current password from being used 482526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * again at least for some period of time */ 483526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!config->mschapv2_retry) 484526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_request_identity(sm); 485526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_request_password(sm); 486526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->mschapv2_retry = 1; 487526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (config) { 488526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: prevent retries using same username/password */ 489526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->mschapv2_retry = 0; 490526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 491526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 492526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return retry == 1; 493526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 494526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 495526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 496526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_mschapv2_change_password( 497526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_sm *sm, struct eap_mschapv2_data *data, 498526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) 499526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 500526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 501526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ms_len; 502526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *username, *password, *new_password; 503526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t username_len, password_len, new_password_len; 504526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_hdr *ms; 505526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct ms_change_password *cp; 506526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 password_hash[16], password_hash_hash[16]; 507526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int pwhash; 508526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 509526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt username = eap_get_config_identity(sm, &username_len); 510526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password = eap_get_config_password2(sm, &password_len, &pwhash); 511526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password = eap_get_config_new_password(sm, &new_password_len); 512526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (username == NULL || password == NULL || new_password == NULL) 513526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 514526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 515526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt username = mschapv2_remove_domain(username, &username_len); 516526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 517526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = FALSE; 518526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_MAY_CONT; 519526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_COND_SUCC; 520526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = TRUE; 521526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 522526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms_len = sizeof(*ms) + sizeof(*cp); 523526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, 524526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_RESPONSE, id); 525526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) 526526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 527526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 528526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms = wpabuf_put(resp, sizeof(*ms)); 529526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; 530526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms->mschapv2_id = req->mschapv2_id + 1; 531526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt WPA_PUT_BE16(ms->ms_length, ms_len); 532526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp = wpabuf_put(resp, sizeof(*cp)); 533526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 534526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Encrypted-Password */ 535526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pwhash) { 536526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (encrypt_pw_block_with_password_hash( 537526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password, new_password_len, 538526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password, cp->encr_password)) 539526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 540526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 541526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (new_password_encrypted_with_old_nt_password_hash( 542526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password, new_password_len, 543526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password, password_len, cp->encr_password)) 544526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 545526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 546526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 547526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Encrypted-Hash */ 548526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pwhash) { 549526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 new_password_hash[16]; 550526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nt_password_hash(new_password, new_password_len, 551526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password_hash); 552526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nt_password_hash_encrypted_with_block(password, 553526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password_hash, 554526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp->encr_hash); 555526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else { 556526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt old_nt_password_hash_encrypted_with_new_nt_password_hash( 557526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password, new_password_len, 558526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt password, password_len, cp->encr_hash); 559526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 560526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 561526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Peer-Challenge */ 562526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) 563526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt goto fail; 564526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 565526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Reserved, must be zero */ 566526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(cp->reserved, 0, 8); 567526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 568526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* NT-Response */ 569526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", 570526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_challenge, PASSWD_CHANGE_CHAL_LEN); 571526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", 572526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp->peer_challenge, MSCHAPV2_CHAL_LEN); 573526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", 574526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt username, username_len); 575526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: new password", 576526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password, new_password_len); 577526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, 578526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt username, username_len, 579526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt new_password, new_password_len, 580526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp->nt_response); 581526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: NT-Response", 582526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp->nt_response, MSCHAPV2_NT_RESPONSE_LEN); 583526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 584526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Authenticator response is not really needed yet, but calculate it 585526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * here so that challenges need not be saved. */ 586526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt generate_authenticator_response(new_password, new_password_len, 587526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp->peer_challenge, 588526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_challenge, 589526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt username, username_len, 590526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt cp->nt_response, data->auth_response); 591526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->auth_response_valid = 1; 592526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 593526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Likewise, generate master_key here since we have the needed data 594526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * available. */ 595526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt nt_password_hash(new_password, new_password_len, password_hash); 596526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt hash_nt_password_hash(password_hash, password_hash_hash); 597526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt get_master_key(password_hash_hash, cp->nt_response, data->master_key); 598526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->master_key_valid = 1; 599526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 600526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Flags */ 601526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(cp->flags, 0, 2); 602526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 603526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " 604526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "(change pw)", id, ms->mschapv2_id); 605526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 606526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 607526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 608526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtfail: 609526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(resp); 610526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 611526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 612526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 613526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 614526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 615526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message 616526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 617526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @data: Pointer to private EAP method data from eap_mschapv2_init() 618526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ret: Return values from EAP request validation and processing 619526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @req: Pointer to EAP-MSCHAPv2 header from the request 620526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @req_len: Length of the EAP-MSCHAPv2 data 621526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @id: EAP identifier used in th erequest 622526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 623526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * no reply available 624526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 625526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm, 626526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data, 627526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 628526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_mschapv2_hdr *req, 629526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t req_len, u8 id) 630526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 631526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpabuf *resp; 632526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *msdata = (const u8 *) (req + 1); 633526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *buf; 634526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len = req_len - sizeof(*req); 635526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int retry = 0; 636526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 637526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure"); 638526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data", 639526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt msdata, len); 640526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 641526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_mschapv2_failure_txt() expects a nul terminated string, so we 642526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * must allocate a large enough temporary buffer to create that since 643526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * the received message does not include nul termination. 644526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 645526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(len + 1); 646526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (buf) { 647526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf, msdata, len); 648526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[len] = '\0'; 649526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt retry = eap_mschapv2_failure_txt(sm, data, buf); 650526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 651526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 652526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 653526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = FALSE; 654526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->methodState = METHOD_DONE; 655526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->decision = DECISION_FAIL; 656526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->allowNotifications = FALSE; 657526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 658526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (data->prev_error == ERROR_PASSWD_EXPIRED && 659526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->passwd_change_version == 3) { 660526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 661526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config && config->new_password) 662526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_mschapv2_change_password(sm, data, ret, req, 663526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id); 664526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config && config->pending_req_new_password) 665526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 666526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) { 667526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* TODO: could try to retry authentication, e.g, after having 668526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * changed the username/password. In this case, EAP MS-CHAP-v2 669526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Failure Response would not be sent here. */ 670526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 671526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 672526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 673526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Note: Only op_code of the EAP-MSCHAPV2 header is included in failure 674526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * message. */ 675526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, 676526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_CODE_RESPONSE, id); 677526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (resp == NULL) 678526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 679526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 680526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_put_u8(resp, MSCHAPV2_OP_FAILURE); /* op_code */ 681526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 682526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return resp; 683526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 684526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 685526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 686526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_mschapv2_check_config(struct eap_sm *sm) 687526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 688526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 689526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 690526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_get_config_identity(sm, &len) == NULL) { 691526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured"); 692526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_request_identity(sm); 693526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 694526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 695526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 696526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_get_config_password(sm, &len) == NULL) { 697526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); 698526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_sm_request_password(sm); 699526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 700526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 701526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 702526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 703526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 704526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 705526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 706526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len, 707526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_mschapv2_hdr *ms) 708526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 709526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t ms_len = WPA_GET_BE16(ms->ms_length); 710526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 711526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ms_len == len) 712526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 713526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 714526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%lu " 715526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "ms_len=%lu", (unsigned long) len, (unsigned long) ms_len); 716526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (sm->workaround) { 717526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* Some authentication servers use invalid ms_len, 718526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * ignore it for interoperability. */ 719526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore" 720526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt " invalid ms_len %lu (len %lu)", 721526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) ms_len, 722526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt (unsigned long) len); 723526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 724526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 725526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 726526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 727526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 728526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 729526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 730526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic void eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, 731526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *reqData) 732526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 733526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* 734526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Store a copy of the challenge message, so that it can be processed 735526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * again in case retry is allowed after a possible failure. 736526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 737526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpabuf_free(data->prev_challenge); 738526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->prev_challenge = wpabuf_dup(reqData); 739526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 740526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 741526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 742526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 743526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_mschapv2_process - Process an EAP-MSCHAPv2 request 744526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() 745526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @priv: Pointer to private EAP method data from eap_mschapv2_init() 746526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @ret: Return values from EAP request validation and processing 747526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * @reqData: EAP request to be processed (eapReqData) 748526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if 749526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * no reply available 750526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 751526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, 752526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method_ret *ret, 753526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct wpabuf *reqData) 754526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 755526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data = priv; 756526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 757526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const struct eap_mschapv2_hdr *ms; 758526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int using_prev_challenge = 0; 759526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt const u8 *pos; 760526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt size_t len; 761526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 id; 762526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 763526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_mschapv2_check_config(sm)) { 764526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 765526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 766526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 767526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 768526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (config->mschapv2_retry && data->prev_challenge && 769526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt data->prev_error == ERROR_AUTHENTICATION_FAILURE) { 770526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Replacing pending packet " 771526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "with the previous challenge"); 772526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 773526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt reqData = data->prev_challenge; 774526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt using_prev_challenge = 1; 775526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt config->mschapv2_retry = 0; 776526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 777526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 778526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData, 779526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt &len); 780526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (pos == NULL || len < sizeof(*ms) + 1) { 781526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 782526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 783526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 784526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 785526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms = (const struct eap_mschapv2_hdr *) pos; 786526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap_mschapv2_check_mslen(sm, len, ms)) { 787526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 788526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 789526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 790526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 791526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id = eap_get_id(reqData); 792526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d", 793526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt id, ms->mschapv2_id); 794526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 795526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (ms->op_code) { 796526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case MSCHAPV2_OP_CHALLENGE: 797526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!using_prev_challenge) 798526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_mschapv2_copy_challenge(data, reqData); 799526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_mschapv2_challenge(sm, data, ret, ms, len, id); 800526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case MSCHAPV2_OP_SUCCESS: 801526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_mschapv2_success(sm, data, ret, ms, len, id); 802526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case MSCHAPV2_OP_FAILURE: 803526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return eap_mschapv2_failure(sm, data, ret, ms, len, id); 804526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt default: 805526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", 806526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ms->op_code); 807526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret->ignore = TRUE; 808526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 809526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 810526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 811526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 812526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 813526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) 814526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 815526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data = priv; 816526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return data->success && data->master_key_valid; 817526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 818526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 819526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 820526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) 821526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 822526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_mschapv2_data *data = priv; 823526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt u8 *key; 824526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int key_len; 825526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 826526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!data->master_key_valid || !data->success) 827526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 828526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 829526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key_len = 2 * MSCHAPV2_KEY_LEN; 830526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 831526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key = os_malloc(key_len); 832526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (key == NULL) 833526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return NULL; 834526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 835526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, i.e., 836526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */ 837526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 1, 0); 838526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, 839526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt MSCHAPV2_KEY_LEN, 0, 0); 840526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 841526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", 842526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt key, key_len); 843526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 844526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt *len = key_len; 845526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return key; 846526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 847526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 848526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 849526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/** 850526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * eap_peer_mschapv2_register - Register EAP-MSCHAPv2 peer method 851526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Returns: 0 on success, -1 on failure 852526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 853526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This function is used to register EAP-MSCHAPv2 peer method into the EAP 854526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * method list. 855526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 856526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtint eap_peer_mschapv2_register(void) 857526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 858526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct eap_method *eap; 859526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 860526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 861526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 862526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 863526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "MSCHAPV2"); 864526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (eap == NULL) 865526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -1; 866526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 867526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->init = eap_mschapv2_init; 868526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->deinit = eap_mschapv2_deinit; 869526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->process = eap_mschapv2_process; 870526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->isKeyAvailable = eap_mschapv2_isKeyAvailable; 871526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap->getKey = eap_mschapv2_getKey; 872526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 873526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = eap_peer_method_register(eap); 874526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) 875526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt eap_peer_method_free(eap); 876526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 877526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 878