--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/eapol/eapol_framework/eapol_common/type/mschapv2/core/eap_type_mschapv2_server.cpp Thu Dec 17 08:47:43 2009 +0200
@@ -0,0 +1,1406 @@
+/*
+* Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: EAP and WLAN authentication protocols.
+*
+*/
+
+
+// This is enumeration of EAPOL source code.
+#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+ #undef EAP_FILE_NUMBER_ENUM
+ #define EAP_FILE_NUMBER_ENUM 99
+ #undef EAP_FILE_NUMBER_DATE
+ #define EAP_FILE_NUMBER_DATE 1127594498
+#endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
+
+
+
+#include "eap_am_memory.h"
+#include "eap_tools.h"
+#include "eap_type_mschapv2.h"
+#include "eap_buffer.h"
+#include "eap_master_session_key.h"
+#include "eap_network_id_selector.h"
+#include "eap_tlv_message_data.h"
+#include "eap_automatic_variable.h"
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::server_packet_process(
+ eap_header_wr_c * const received_eap,
+ const u32_t eap_packet_length)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ eap_status_e status = eap_status_drop_packet_quietly;
+
+#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
+ if (m_session.get_state() != eap_type_mschapv2_state_none
+ && m_use_implicit_challenge == false
+ && m_identifier != received_eap->get_identifier())
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+ else
+ {
+ m_identifier = received_eap->get_identifier();
+ }
+#endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
+
+ if (received_eap->get_type() == eap_type_identity)
+ {
+ status = handle_identity_response_message();
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ if (received_eap->get_code() == eap_code_success
+ || received_eap->get_code() == eap_code_failure)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+ else if (received_eap->get_code() == eap_code_response) // Response
+ {
+ if (eap_packet_length <= eap_header_base_c::get_header_length())
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ // MsChapV2
+ if (received_eap->get_type() == eap_type_mschapv2)
+ {
+ status = server_mschapv2_packet_process(
+ received_eap,
+ eap_packet_length);
+ }
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::server_mschapv2_packet_process(
+ eap_header_wr_c * const received_eap,
+ const u32_t eap_packet_length)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ eap_status_e status = eap_status_drop_packet_quietly;
+
+ u32_t type_data_length = received_eap->get_type_data_length();
+
+ mschapv2_header_c mschapv2_header(
+ m_am_tools,
+ received_eap->get_type_data_offset(0, type_data_length),
+ type_data_length);
+
+ if (mschapv2_header.check_header() != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ if (eap_packet_length <= eap_header_base_c::get_header_length())
+ {
+ EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: illegal mschapv2 packet length\n")));
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ if ((mschapv2_header.get_opcode() == mschapv2_opcode_response
+ || mschapv2_header.get_opcode() == mschapv2_opcode_change_password)
+ && type_data_length != mschapv2_header.get_ms_length())
+ {
+ EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: illegal mschapv2 packet length\n")));
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ switch (mschapv2_header.get_opcode())
+ {
+ case mschapv2_opcode_response:
+ status = server_handle_challenge_response(mschapv2_header);
+ break;
+
+ case mschapv2_opcode_success:
+ status = server_handle_success_response();
+ break;
+
+ case mschapv2_opcode_failure:
+ status = server_handle_failure_response();
+ break;
+
+ case mschapv2_opcode_change_password:
+ status = server_handle_password_change(mschapv2_header);
+ break;
+
+ default:
+ break;
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+bool eap_type_mschapv2_c::check_expired_password()
+{
+ if (m_do_password_expiration_tests == true)
+ {
+ if (m_password_expired == false)
+ {
+ m_password_expired = true;
+ }
+ else
+ {
+ m_password_expired = false;
+ }
+
+ return m_password_expired;
+ }
+
+ return false;
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+static const u8_t eap_mschapv2_challenge_response_message[] = "Message1";
+static const u8_t eap_mschapv2_failure_message[] = "Message3";
+
+
+eap_status_e eap_type_mschapv2_c::server_handle_challenge_response(mschapv2_header_c &machapv2_packet)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ eap_status_e status = eap_status_header_corrupted;
+
+ mschapv2_response_c response(
+ m_am_tools,
+ machapv2_packet.get_data(),
+ machapv2_packet.get_data_length());
+ if (response.get_is_valid() == false)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): response packet:"),
+ response.get_header_buffer(response.get_header_buffer_length()),
+ response.get_header_buffer_length()));
+
+ if (response.check_header() != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ if (!m_session.is_valid_state(eap_type_mschapv2_state_challenge_response))
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ // Check username
+ m_am_tools->memmove(
+ m_peer_challenge,
+ response.get_peer_challenge(),
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE);
+
+#if defined(USE_FAST_EAP_TYPE)
+ if (m_use_EAP_FAST_challenge == true)
+ {
+ // Note the received authenticator challenge is zero bytes in EAP-FAST.
+ if (m_client_EAP_FAST_challenge.get_is_valid_data() == false
+ || m_client_EAP_FAST_challenge.get_data_length() != EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
+ }
+
+ m_am_tools->memmove(
+ m_peer_challenge,
+ m_client_EAP_FAST_challenge.get_data(),
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE);
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("client_handle_challenge_request(): EAP-FAST m_peer_challenge"),
+ m_peer_challenge,
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE));
+ }
+#endif //#if defined(USE_FAST_EAP_TYPE)
+
+ crypto_nt_hash_c nt_hash(m_am_tools);
+ if (nt_hash.get_is_valid() == false)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ status = nt_hash.nt_password_hash(
+ &m_password_utf8,
+ &m_password_hash,
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = nt_hash.hash_nt_password_hash(
+ &m_password_hash,
+ &m_password_hash_hash,
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_password_utf8"),
+ m_password_utf8.get_data(),
+ m_password_utf8.get_data_length()));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_authenticator_challenge"),
+ m_authenticator_challenge,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_peer_challenge"),
+ m_peer_challenge,
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_password_hash"),
+ m_password_hash.get_data(),
+ m_password_hash.get_data_length()));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_username_utf8"),
+ m_username_utf8.get_data(),
+ m_username_utf8.get_data_length()));
+
+ status = generate_nt_response(
+ m_authenticator_challenge,
+ m_peer_challenge,
+ m_username_utf8.get_data(),
+ m_username_utf8.get_data_length(),
+ &m_password_hash,
+ m_nt_response);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_nt_response:"),
+ m_nt_response,
+ EAP_MSCHAPV2_NT_RESPONSE_SIZE));
+
+ // Check peer_response == nt_response
+ if (m_am_tools->memcmp(
+ m_nt_response,
+ response.get_nt_response(),
+ EAP_MSCHAPV2_NT_RESPONSE_SIZE)
+ == 0)
+ {
+ EAP_TRACE_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): correct password\n")));
+
+ // Is password expired?
+ if (check_expired_password() == true)
+ {
+ m_error_code = EAP_MSCHAPV2_ERROR_PASSWD_EXPIRED;
+ bool retry_allowed = true; // ?
+
+ u32_t message_length = sizeof(eap_mschapv2_challenge_response_message) - 1;
+
+ status = send_failure_request(
+ retry_allowed,
+ eap_mschapv2_challenge_response_message,
+ message_length);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ m_session.set_state(eap_type_mschapv2_state_challenge_response, eap_type_mschapv2_state_change_password_response);
+
+ // Any other restrictions?
+ status = eap_status_ok;
+ }
+ else
+ {
+ u32_t message_length = sizeof(eap_mschapv2_challenge_response_message) - 1;
+
+ status = send_success_request(
+ eap_mschapv2_challenge_response_message,
+ message_length);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ m_session.set_state(eap_type_mschapv2_state_challenge_response, eap_type_mschapv2_state_success_response);
+ status = eap_status_ok;
+ }
+ }
+ else // Incorrect password
+ {
+ EAP_TRACE_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("ERROR: EAP_type_MSCHAPV2: server_handle_challenge_response(): incorrect password\n")));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): m_nt_response:"),
+ m_nt_response,
+ EAP_MSCHAPV2_NT_RESPONSE_SIZE));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_challenge_response(): response.get_nt_response():"),
+ response.get_nt_response(),
+ EAP_MSCHAPV2_NT_RESPONSE_SIZE));
+
+ m_error_code = EAP_MSCHAPV2_ERROR_AUTHENTICATION_FAILURE;
+
+ bool retry_allowed = true; // TEST
+
+ u32_t message_length = sizeof(eap_mschapv2_failure_message) - 1;
+
+ status = send_failure_request(
+ retry_allowed,
+ eap_mschapv2_failure_message,
+ message_length);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+#if defined(USE_FAST_EAP_TYPE)
+ if (m_use_EAP_FAST_challenge == true)
+ {
+ (void) send_error_notification(eap_status_tunnel_compromise_error);
+ }
+#endif //#if defined(USE_FAST_EAP_TYPE)
+
+ m_session.set_state(eap_type_mschapv2_state_challenge_response, eap_type_mschapv2_state_challenge_response);
+ status = eap_status_ok;
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::server_handle_success_response()
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ eap_status_e status = eap_status_drop_packet_quietly;
+
+ if (m_session.is_valid_state(eap_type_mschapv2_state_success_response))
+ {
+ eap_master_session_key_c key(
+ m_am_tools,
+ eap_type_mschapv2);
+
+ status = generate_session_key(&key);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = get_type_partner()->packet_data_crypto_keys(&m_send_network_id, &key);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = finish_successful_authentication();
+
+ m_session.set_state(eap_type_mschapv2_state_success_response);
+
+ status = eap_status_ok;
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::server_handle_failure_response()
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ if (m_session.is_valid_state(eap_type_mschapv2_state_failure_response))
+ {
+ finish_unsuccessful_authentication(false);
+ m_session.set_state(eap_type_mschapv2_state_failure_response);
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+static const u8_t eap_mschapv2_password_change_message[] = "Message4";
+
+eap_status_e eap_type_mschapv2_c::server_handle_password_change(mschapv2_header_c &machapv2_packet)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ if (!m_session.is_valid_state(eap_type_mschapv2_state_change_password_response))
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_drop_packet_quietly);
+ }
+
+ if (machapv2_packet.get_data_length() < mschapv2_change_password_c::get_header_minimum_size())
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
+ }
+
+ mschapv2_change_password_c change_password_payload(
+ m_am_tools,
+ machapv2_packet.get_data(),
+ machapv2_packet.get_data_length());
+ if (change_password_payload.get_is_valid() == false)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ if (change_password_payload.check_header() != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
+ }
+
+ m_am_tools->memmove(
+ m_peer_challenge,
+ change_password_payload.get_peer_challenge(),
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE);
+
+#if defined(USE_FAST_EAP_TYPE)
+ if (m_use_EAP_FAST_challenge == true)
+ {
+ if (m_client_EAP_FAST_challenge.get_is_valid_data() == false
+ || m_client_EAP_FAST_challenge.get_data_length() != EAP_MSCHAPV2_PEER_CHALLENGE_SIZE
+ || m_client_EAP_FAST_challenge.compare(m_peer_challenge, EAP_MSCHAPV2_PEER_CHALLENGE_SIZE) != 0)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_authentication_failure);
+ }
+ }
+#endif //#if defined(USE_FAST_EAP_TYPE)
+
+ // Encypted-Password has been made by NewPasswordEncryptedWithOldNtPassword()
+ eap_variable_data_c old_password_hash(m_am_tools);
+
+ crypto_nt_hash_c nt_hash(m_am_tools);
+ if (nt_hash.get_is_valid() == false)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ eap_status_e status = nt_hash.nt_password_hash(
+ &m_password_utf8,
+ &old_password_hash,
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+
+ eap_variable_data_c tmp_password_unicode(
+ m_am_tools);
+
+ eap_variable_data_c tmp_password_utf8(
+ m_am_tools);
+
+ u8_t * new_password = 0;
+
+ u32_t pw_size;
+
+ {
+ pw_block_s * new_pw_block = new pw_block_s;
+
+ eap_automatic_variable_c<pw_block_s> automatic_new_pw_block(m_am_tools, new_pw_block);
+
+ if (!new_pw_block)
+ {
+ status = eap_status_allocation_error;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = rc4_decrypt(
+ change_password_payload.get_encrypted_pw_block(), // cypher
+ sizeof(pw_block_s),
+ old_password_hash.get_data(EAP_MSCHAPV2_MD4_DIGEST_SIZE), // key
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE,
+ reinterpret_cast<u8_t *>(new_pw_block)); // plain
+
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+#ifdef EAP_BIG_ENDIAN
+ pw_size = eap_ntohl(new_pw_block->password_length);
+#else
+ pw_size = new_pw_block->password_length;
+#endif
+ if (pw_size > EAP_MSCHAPV2_PASSWORD_MAX_SIZE)
+ {
+ const u32_t message_length = sizeof(eap_mschapv2_password_change_message) - 1;
+ m_error_code = EAP_MSCHAPV2_ERROR_CHANGING_PASSWORD;
+ bool retry_allowed = true;
+
+ status = send_failure_request(
+ retry_allowed,
+ eap_mschapv2_password_change_message,
+ message_length);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ m_session.set_state(eap_type_mschapv2_state_change_password_response, eap_type_mschapv2_state_change_password_response);
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+ }
+
+ status = tmp_password_unicode.set_copy_of_buffer(
+ (reinterpret_cast<u8_t *>(new_pw_block)) + EAP_MSCHAPV2_PASSWORD_MAX_SIZE - pw_size, // offset,
+ pw_size);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = m_am_tools->convert_unicode_to_utf8(tmp_password_utf8, tmp_password_unicode);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+ }
+
+ // Encrypted-Hash has been made by old_nt_password_hash_encrypted_with_new_password_hash()
+
+ eap_variable_data_c new_password_hash(m_am_tools);
+
+ status = nt_hash.nt_password_hash(
+ &tmp_password_utf8,
+ &new_password_hash,
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ eap_variable_data_c encrypted_pw_hash(m_am_tools);
+
+ status = old_nt_password_hash_encrypted_with_new_nt_password_hash(
+ &new_password_hash,
+ &m_password_hash,
+ &encrypted_pw_hash);
+ if (status != eap_status_ok)
+ {
+ delete [] new_password;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ if (m_am_tools->memcmp(
+ encrypted_pw_hash.get_data(EAP_MSCHAPV2_MD4_DIGEST_SIZE),
+ change_password_payload.get_encrypted_hash(),
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE) == 0)
+ {
+ EAP_TRACE_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_password_change(): password change accepted\n")));
+
+ // Checked
+
+ // Store new password
+ status = m_password_utf8.set_copy_of_buffer(&tmp_password_utf8);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = m_password_hash.set_copy_of_buffer(&new_password_hash);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = nt_hash.hash_nt_password_hash(
+ &m_password_hash,
+ &m_password_hash_hash,
+ EAP_MSCHAPV2_MD4_DIGEST_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("server_handle_password_change(): m_authenticator_challenge"),
+ m_authenticator_challenge,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("server_handle_password_change(): m_peer_challenge"),
+ m_peer_challenge,
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE));
+
+ // Generate new nt_response
+ status = generate_nt_response(
+ m_authenticator_challenge,
+ m_peer_challenge,
+ m_username_utf8.get_data(),
+ m_username_utf8.get_data_length(),
+ &m_password_hash,
+ m_nt_response);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ // Send Success request
+
+ u8_t message[] = "";
+ u32_t message_length = 0;
+
+ status = send_success_request(
+ message,
+ message_length);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ m_session.set_state(eap_type_mschapv2_state_change_password_response, eap_type_mschapv2_state_success_response);
+ }
+ else // Challenge response didn't match
+ {
+ EAP_TRACE_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: server_handle_password_change(): password change NOT accepted\n")));
+
+ delete [] new_password;
+
+ u32_t message_length = sizeof(eap_mschapv2_password_change_message) - 1;
+ m_error_code = EAP_MSCHAPV2_ERROR_CHANGING_PASSWORD;
+ bool retry_allowed = true;
+
+ status = send_failure_request(
+ retry_allowed,
+ eap_mschapv2_password_change_message,
+ message_length);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ m_session.set_state(eap_type_mschapv2_state_change_password_response, eap_type_mschapv2_state_failure_response);
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+EAP_FUNC_EXPORT eap_status_e eap_type_mschapv2_c::handle_identity_response_message()
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ eap_status_e status = eap_status_process_general_error;
+
+ // Send challenge
+
+ status = m_rand.add_rand_seed_hw_ticks();
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+
+#if defined(USE_FAST_EAP_TYPE)
+ if (m_use_EAP_FAST_challenge == true
+ && m_server_EAP_FAST_challenge.get_is_valid_data() == true
+ && m_server_EAP_FAST_challenge.get_data_length() == EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)
+ {
+ m_am_tools->memmove(
+ m_authenticator_challenge,
+ m_server_EAP_FAST_challenge.get_data(),
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE);
+ }
+ else
+#endif //#if defined(USE_FAST_EAP_TYPE)
+#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
+ if (m_use_implicit_challenge == true)
+ {
+ eap_variable_data_c memory_store_key(m_am_tools);
+
+ eap_status_e status = memory_store_key.set_copy_of_buffer(
+ EAP_MSCHAPV2_IMPLICIT_CHALLENGE_HANDLE_KEY,
+ sizeof(EAP_MSCHAPV2_IMPLICIT_CHALLENGE_HANDLE_KEY));
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = memory_store_key.add_data(
+ &m_is_client,
+ sizeof(m_is_client));
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ eap_am_network_id_c receive_network_id(m_am_tools,
+ m_send_network_id.get_destination_id(),
+ m_send_network_id.get_source_id(),
+ m_send_network_id.get_type());
+
+ eap_network_id_selector_c state_selector(
+ m_am_tools,
+ &receive_network_id);
+
+ status = memory_store_key.add_data(
+ &state_selector);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ eap_tlv_message_data_c tlv_data(m_am_tools);
+
+ status = m_am_tools->memory_store_get_data(
+ &memory_store_key,
+ &tlv_data);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: handle_identity_response_message(): cannot get credentials\n")));
+ }
+ else
+ {
+ EAP_TRACE_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: handle_identity_response_message(): credentials found\n")));
+
+ // Parse read data.
+ eap_array_c<eap_tlv_header_c> tlv_blocks(m_am_tools);
+
+ status = tlv_data.parse_message_data(&tlv_blocks);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ bool implicit_challenge_read(false);
+
+ for (u32_t ind = 0ul; ind < tlv_blocks.get_object_count(); ind++)
+ {
+ eap_tlv_header_c * const tlv = tlv_blocks.get_object(ind);
+ if (tlv != 0)
+ {
+ if (tlv->get_type() == eap_type_mschapv2_implicit_challenge)
+ {
+ m_am_tools->memmove(
+ m_authenticator_challenge,
+ tlv->get_value(tlv->get_value_length()),
+ tlv->get_value_length());
+
+ implicit_challenge_read = true;
+ }
+ }
+ } // for()
+
+ if (implicit_challenge_read == false)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+ }
+ }
+ }
+ else
+#endif //#if defined(EAP_USE_TTLS_PLAIN_MS_CHAP_V2_HACK)
+ {
+ status = m_rand.get_rand_bytes(m_authenticator_challenge, EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("handle_identity_response_message(): m_authenticator_challenge"),
+ m_authenticator_challenge,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE));
+
+ const u32_t name_length = m_username_utf8.get_data_length();
+
+ const u32_t type_data_length = EAP_MSCHAPV2_HEADER_SIZE // OpCode, MS-CHAPv2-ID and MS-Length
+ + mschapv2_challenge_c::get_header_minimum_size()
+ + name_length;
+
+ const u32_t packet_length = eap_header_base_c::get_type_data_start_offset(m_use_eap_expanded_type)
+ + type_data_length;
+
+ eap_buf_chain_wr_c * packet = create_send_packet(packet_length);
+ if (!packet)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ eap_header_base_c eap_header(
+ m_am_tools,
+ packet->get_data_offset(m_offset, packet_length),
+ packet_length);
+ if (eap_header.get_is_valid() == false)
+ {
+ delete packet;
+ packet = 0;
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+ }
+ eap_header.set_code(eap_code_request);
+ eap_header.set_identifier(++m_identifier);
+ eap_header.set_length(
+ static_cast<u16_t>(packet_length),
+ m_use_eap_expanded_type);
+ eap_header.set_type(
+ eap_type_mschapv2,
+ m_use_eap_expanded_type);
+
+ mschapv2_header_c mschapv2_header(
+ m_am_tools,
+ eap_header.get_type_data_offset(0, eap_header.get_type_data_length()),
+ eap_header.get_type_data_length());
+
+ mschapv2_header.set_opcode(mschapv2_opcode_challenge);
+ mschapv2_header.set_mschapv2_id(static_cast<u8_t>(++m_mschapv2id));
+ mschapv2_header.set_ms_length(static_cast<u16_t>(type_data_length));
+
+ mschapv2_challenge_c challenge_packet(
+ m_am_tools,
+ mschapv2_header.get_data(),
+ mschapv2_header.get_data_length());
+ if (challenge_packet.get_is_valid() == false)
+ {
+ delete packet;
+ packet = 0;
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+#if defined(USE_FAST_EAP_TYPE)
+ if (m_use_EAP_FAST_challenge == true)
+ {
+ // EAP-FAST sends authenticator challenge containing only zeroes.
+ challenge_packet.set_challenge(EAP_MSCHAPV2_ZERO_CHALLENGE);
+ }
+ else
+#endif //#if defined(USE_FAST_EAP_TYPE)
+ {
+ challenge_packet.set_challenge(m_authenticator_challenge);
+ }
+
+ challenge_packet.set_value_size();
+ challenge_packet.set_name(m_username_utf8.get_data(name_length));
+
+ // This must be set before packet_send() call to allow
+ // the plain MsChapv2 to work.
+ m_session.set_state(eap_type_mschapv2_state_identity_response);
+
+ // Send packet
+ status = packet_send(packet, packet_length);
+
+ delete packet;
+ packet = 0;
+
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::send_failure_request(
+ const bool retry_allowed,
+ const u8_t * const message,
+ const u32_t message_length)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: send_failure_request\n")));
+
+ u32_t retry = 0;
+ if (retry_allowed)
+ {
+ retry = 1;
+ }
+
+ // Generate new auth_challenge
+
+ eap_status_e status = m_rand.add_rand_seed_hw_ticks();
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+#if defined(USE_FAST_EAP_TYPE)
+ if (m_use_EAP_FAST_challenge == true
+ && m_client_EAP_FAST_challenge.get_is_valid_data() == true
+ && m_client_EAP_FAST_challenge.get_data_length() == EAP_MSCHAPV2_PEER_CHALLENGE_SIZE)
+ {
+ m_am_tools->memmove(
+ m_peer_challenge,
+ m_client_EAP_FAST_challenge.get_data(),
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE);
+ }
+ else
+#endif //#if defined(USE_FAST_EAP_TYPE)
+ {
+ status = m_rand.get_rand_bytes(m_authenticator_challenge, EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: send_failure_request(): m_authenticator_challenge"),
+ m_authenticator_challenge,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("EAP_type_MSCHAPV2: send_failure_request(): m_peer_challenge"),
+ m_peer_challenge,
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE));
+
+ u8_t * auth_challenge_str = new u8_t[EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE * 2];
+ if (!auth_challenge_str)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ u32_t length = 2 * EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE;
+
+ status = m_am_tools->convert_bytes_to_hex_ascii(
+ m_authenticator_challenge,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE,
+ auth_challenge_str,
+ &length);
+ if (status != eap_status_ok
+ || length != 2 * EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE)
+ {
+ delete [] auth_challenge_str;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+ }
+
+ m_am_tools->convert_ascii_to_uppercase(auth_challenge_str, length);
+
+ const u32_t type_data_length =
+ + EAP_MSCHAPV2_HEADER_SIZE // OpCode, MS-CHAPv2-ID and MS-Length
+ + EAP_MSCHAPV2_FAILURE_REQUEST_SIZE
+ + message_length;
+
+ const u32_t packet_length
+ = eap_header_base_c::get_type_data_start_offset(m_use_eap_expanded_type)
+ + type_data_length;
+
+ eap_buf_chain_wr_c * packet = create_send_packet(packet_length);
+ if (!packet)
+ {
+ delete [] auth_challenge_str;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ eap_header_base_c eap_header(
+ m_am_tools,
+ packet->get_data_offset(m_offset, packet_length),
+ packet_length);
+ if (eap_header.get_is_valid() == false)
+ {
+ delete [] auth_challenge_str;
+ delete packet;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+ }
+ eap_header.set_code(eap_code_request);
+ eap_header.set_identifier(++m_identifier);
+ eap_header.set_length(
+ static_cast<u16_t>(packet_length),
+ m_use_eap_expanded_type);
+ eap_header.set_type(
+ eap_type_mschapv2,
+ m_use_eap_expanded_type);
+
+ mschapv2_header_c mschapv2_header(
+ m_am_tools,
+ eap_header.get_type_data_offset(0, eap_header.get_type_data_length()),
+ eap_header.get_type_data_length());
+
+ mschapv2_header.set_opcode(mschapv2_opcode_failure);
+ mschapv2_header.set_mschapv2_id(static_cast<u8_t>(++m_mschapv2id));
+ mschapv2_header.set_ms_length(static_cast<u16_t>(type_data_length));
+
+ u8_t * failure_data = mschapv2_header.get_data(); // @{...}
+ if (failure_data == 0)
+ {
+ delete [] auth_challenge_str;
+ delete packet;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+ if (m_am_tools->snprintf(
+ failure_data,
+ EAP_MSCHAPV2_FAILURE_REQUEST_SIZE,
+ "E=%010u R=%1u C=12345678901234567890123456789012 V=%010u M=", // auth_challenge will be set by memcpy
+ m_error_code,
+ retry,
+ 3L) != EAP_MSCHAPV2_FAILURE_REQUEST_SIZE)
+ {
+ delete [] auth_challenge_str;
+ delete packet;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ m_am_tools->memmove(
+ failure_data + 12 + 1 + 3 + 1 + 2, // pointer to just after "C="
+ auth_challenge_str,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE * 2);
+
+ delete [] auth_challenge_str;
+
+ if (message_length != 0)
+ {
+ // Copy message to end of packet
+ m_am_tools->memmove(
+ failure_data + EAP_MSCHAPV2_FAILURE_REQUEST_SIZE,
+ message,
+ message_length);
+ }
+
+ status = packet_send(packet, packet_length);
+ delete packet;
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::send_success_request(
+ const u8_t * const message,
+ const u32_t message_length)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ EAP_TRACE_DEBUG(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("EAP_type_MSCHAPV2: send_success_request\n")));
+
+ u8_t * auth_response = new u8_t[EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE];
+ if (!auth_response)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("send_success_request(): m_authenticator_challenge"),
+ m_authenticator_challenge,
+ EAP_MSCHAPV2_AUTHENTICATOR_CHALLENGE_SIZE));
+
+ EAP_TRACE_DATA_DEBUG(
+ m_am_tools,
+ TRACE_FLAGS_DEFAULT,
+ (EAPL("send_success_request(): m_peer_challenge"),
+ m_peer_challenge,
+ EAP_MSCHAPV2_PEER_CHALLENGE_SIZE));
+
+ eap_status_e status = generate_authenticator_response(
+ m_password_hash_hash.get_data(EAP_MSCHAPV2_MD4_DIGEST_SIZE),
+ m_nt_response,
+ m_peer_challenge,
+ m_authenticator_challenge,
+ m_username_utf8.get_data(),
+ m_username_utf8.get_data_length(),
+ auth_response);
+ if (status != eap_status_ok)
+ {
+ delete [] auth_response;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ const u32_t ms_data_length
+ = EAP_MSCHAPV2_HEADER_SIZE
+ + EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE
+ + EAP_MSCHAPV2_MESSAGE_PREFIX_SIZE
+ + message_length;
+
+ const u32_t packet_length
+ = eap_header_base_c::get_type_data_start_offset(m_use_eap_expanded_type)
+ + ms_data_length;
+
+ eap_buf_chain_wr_c * packet = create_send_packet(packet_length);
+ if (!packet)
+ {
+ delete [] auth_response;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ eap_header_base_c eap_header(
+ m_am_tools,
+ packet->get_data_offset(m_offset, packet_length),
+ packet_length);
+ if (eap_header.get_is_valid() == false)
+ {
+ delete [] auth_response;
+ delete packet;
+ packet = 0;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
+ }
+ eap_header.set_code(eap_code_request);
+ eap_header.set_identifier(++m_identifier);
+ eap_header.set_length(
+ static_cast<u16_t>(packet_length),
+ m_use_eap_expanded_type);
+ eap_header.set_type(
+ eap_type_mschapv2,
+ m_use_eap_expanded_type);
+
+ mschapv2_header_c mschapv2_header(
+ m_am_tools,
+ eap_header.get_type_data_offset(0, eap_header.get_type_data_length()),
+ eap_header.get_type_data_length());
+
+ mschapv2_header.set_opcode(mschapv2_opcode_success);
+ mschapv2_header.set_mschapv2_id(static_cast<u8_t>(++m_mschapv2id));
+ mschapv2_header.set_ms_length(static_cast<u16_t>(ms_data_length));
+
+ u8_t * success_data = mschapv2_header.get_data();
+ if (success_data == 0)
+ {
+ delete [] auth_response;
+ delete packet;
+ packet = 0;
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ // Copy auth string after headers
+ m_am_tools->memmove(
+ success_data,
+ auth_response,
+ EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE);
+
+ delete [] auth_response;
+
+ // Copy message after auth string
+ m_am_tools->memmove(
+ success_data + EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE,
+ EAP_MSCHAPV2_MESSAGE_PREFIX,
+ EAP_MSCHAPV2_MESSAGE_PREFIX_SIZE);
+
+ if (message_length != 0)
+ {
+ m_am_tools->memmove(
+ success_data + EAP_MSCHAPV2_AUTHENTICATOR_RESPONSE_SIZE + EAP_MSCHAPV2_MESSAGE_PREFIX_SIZE,
+ message,
+ message_length);
+ }
+
+ status = packet_send(packet, packet_length);
+ delete packet;
+ packet = 0;
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+
+#if defined(EAP_MSCHAPV2_SERVER)
+
+eap_status_e eap_type_mschapv2_c::rc4_decrypt(
+ const u8_t * const cypher,
+ const u32_t cypher_length,
+ const u8_t * const key,
+ const u32_t key_length,
+ u8_t * const clear)
+{
+ EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
+ if (!cypher
+ || cypher_length == 0
+ || !key
+ || key_length == 0
+ || !clear)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_process_general_error);
+ }
+
+ eap_variable_data_c v_key(m_am_tools);
+
+ eap_status_e status = v_key.set_buffer(key, key_length, false, false); // Cannot fail
+ if (status != eap_status_ok
+ || v_key.get_is_valid_data() == false)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
+ }
+
+ crypto_rc4_c rc4(m_am_tools);
+
+ status = rc4.set_key(&v_key);
+ if (status != eap_status_ok)
+ {
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+ }
+
+ status = rc4.decrypt_data(cypher, clear, cypher_length);
+
+ EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
+ return EAP_STATUS_RETURN(m_am_tools, status);
+}
+
+#endif //#if defined(EAP_MSCHAPV2_SERVER)
+
+// end