eapol/eapol_framework/eapol_common/type/radius/core/eap_radius.cpp
changeset 0 c8830336c852
child 2 1c7bc153c08e
equal deleted inserted replaced
-1:000000000000 0:c8830336c852
       
     1 /*
       
     2 * Copyright (c) 2001-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  EAP and WLAN authentication protocols.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // This is enumeration of EAPOL source code.
       
    20 #if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    21 	#undef EAP_FILE_NUMBER_ENUM
       
    22 	#define EAP_FILE_NUMBER_ENUM 104 
       
    23 	#undef EAP_FILE_NUMBER_DATE 
       
    24 	#define EAP_FILE_NUMBER_DATE 1127594498 
       
    25 #endif //#if defined(USE_EAP_MINIMUM_RELEASE_TRACES)
       
    26 
       
    27 
       
    28 
       
    29 #include "eap_am_memory.h"
       
    30 #include "eap_tools.h"
       
    31 #include "eap_radius.h"
       
    32 #include "eap_radius_header.h"
       
    33 #include "eap_radius_payloads.h"
       
    34 #include "eap_radius_mac_attributes.h"
       
    35 #include "abs_eap_am_radius.h"
       
    36 #include "eap_crypto_api.h"
       
    37 #include "eap_state_notification.h"
       
    38 #include "abs_eap_am_mutex.h"
       
    39 #include "eap_automatic_variable.h"
       
    40 #include "eapol_header.h"
       
    41 #include "eap_diameter_avp_code.h"
       
    42 
       
    43 
       
    44 /// This is pseudo Ethernet and EAPOL header.
       
    45 /// This is used in trace of tunneled EAP-packet.
       
    46 const u8_t EAP_PSEUDO_ETHERNET_HEADER[] =
       
    47 {
       
    48 	0x50, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x68, 0x65,
       
    49 	0x61, 0x64, 0x65, 0x72, 0x88, 0x8e, 0x01, 0x00,
       
    50 	0x00, 0x00
       
    51 };
       
    52 
       
    53 const u32_t EAP_PSEUDO_EAPOL_HEADER_OFFSET = 14ul;
       
    54 
       
    55 //--------------------------------------------------
       
    56 
       
    57 /** @file */
       
    58 
       
    59 // 
       
    60 EAP_FUNC_EXPORT eap_radius_c::~eap_radius_c()
       
    61 {
       
    62 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    63 
       
    64 	EAP_TRACE_DEBUG(
       
    65 		m_am_tools, 
       
    66 		TRACE_FLAGS_DEFAULT, 
       
    67 		(EAPL("eap_radius_c::~eap_radius_c(): this = 0x%08x => 0x%08x\n"),
       
    68 		this,
       
    69 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
    70 
       
    71 	EAP_ASSERT(m_shutdown_was_called == true);
       
    72 
       
    73 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
    74 }
       
    75 
       
    76 //--------------------------------------------------
       
    77 
       
    78 #if defined(_WIN32) && !defined(__GNUC__)
       
    79 	#pragma warning( disable : 4355 ) // 'this' : used in base member initializer list
       
    80 #endif
       
    81 
       
    82 // 
       
    83 EAP_FUNC_EXPORT eap_radius_c::eap_radius_c(
       
    84 	abs_eap_am_tools_c * const tools,
       
    85 	abs_eap_radius_c * const partner,
       
    86 	eap_am_radius_c * const am_radius,
       
    87 	const bool free_am_radius,
       
    88 	const bool is_client_when_true)
       
    89 	: m_am_tools(tools)
       
    90 	, m_partner(partner)
       
    91 	, m_session_map(tools, this)
       
    92 	, m_pseudo_ethernet_header(tools)
       
    93 	, m_radius_header_offset(0ul)
       
    94 	, m_MTU(0ul)
       
    95 	, m_trailer_length(0ul)
       
    96 	, m_salt(0ul)
       
    97 	, m_shutdown_was_called(false)
       
    98 	, m_is_client(false)
       
    99 	, m_is_valid(false)
       
   100 {
       
   101 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   102 
       
   103 	EAP_TRACE_DEBUG(
       
   104 		m_am_tools, 
       
   105 		TRACE_FLAGS_DEFAULT, 
       
   106 		(EAPL("eap_radius_c::eap_radius_c(): this = 0x%08x => 0x%08x, partner 0x%08x\n"),
       
   107 		 this,
       
   108 		 dynamic_cast<abs_eap_base_timer_c *>(this),
       
   109 		 partner));
       
   110 
       
   111 	eap_status_e status = m_pseudo_ethernet_header.set_copy_of_buffer(
       
   112 		EAP_PSEUDO_ETHERNET_HEADER,
       
   113 		sizeof(EAP_PSEUDO_ETHERNET_HEADER));
       
   114 	if (status != eap_status_ok)
       
   115 	{
       
   116 		// Do not care of this error.
       
   117 		// User will check the validity of m_pseudo_ethernet_header.
       
   118 	}
       
   119 
       
   120 	// - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       
   121 
       
   122 	set_is_valid();
       
   123 
       
   124 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   125 }
       
   126 
       
   127 //--------------------------------------------------
       
   128 
       
   129 EAP_FUNC_EXPORT eap_const_string eap_radius_c::get_state_string(eap_radius_state_variable_e state)
       
   130 {
       
   131 
       
   132 #if defined(USE_EAP_TRACE_STRINGS)
       
   133 	EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_identity_request)
       
   134 	else EAP_IF_RETURN_STRING(state, eap_radius_state_pending_identity_query)
       
   135 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_start_request)
       
   136 	else EAP_IF_RETURN_STRING(state, eap_radius_state_imsi_waiting_for_start_request)
       
   137 	else EAP_IF_RETURN_STRING(state, eap_radius_state_pseydonym_waiting_for_start_request)
       
   138 	else EAP_IF_RETURN_STRING(state, eap_radius_state_analyse_start_request)
       
   139 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_challenge_request)
       
   140 	else EAP_IF_RETURN_STRING(state, eap_radius_state_analyses_challenge_request)
       
   141 	else EAP_IF_RETURN_STRING(state, eap_radius_state_pending_kc_sres_query)
       
   142 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_success)
       
   143 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_reauth_request)
       
   144 	else EAP_IF_RETURN_STRING(state, eap_radius_state_analyses_reauthentication_request)
       
   145 	else EAP_IF_RETURN_STRING(state, eap_radius_state_pending_pseudonym_decode_query)
       
   146 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_identity_response)
       
   147 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_start_response_with_at_permanent_identity)
       
   148 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_start_response_with_at_full_auth_identity)
       
   149 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_start_response_with_at_any_identity)
       
   150 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_start_response)
       
   151 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_challenge_response)
       
   152 	else EAP_IF_RETURN_STRING(state, eap_radius_state_pending_triplet_query)
       
   153 	else EAP_IF_RETURN_STRING(state, eap_radius_state_analyses_challenge_response)
       
   154 	else EAP_IF_RETURN_STRING(state, eap_radius_state_analyses_start_response)
       
   155 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_notification_request_success)
       
   156 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_notification_response_failure)
       
   157 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_notification_response_success)
       
   158 	else EAP_IF_RETURN_STRING(state, eap_radius_state_waiting_for_reauth_response)
       
   159 	else EAP_IF_RETURN_STRING(state, eap_radius_state_analyses_reauthentication_response)
       
   160 	else EAP_IF_RETURN_STRING(state, eap_radius_state_success)
       
   161 	else EAP_IF_RETURN_STRING(state, eap_radius_state_failure)
       
   162 	else
       
   163 #endif // #if defined(USE_EAP_TRACE_STRINGS)
       
   164 	{
       
   165 		return EAPL("Unknown RADIUS state");
       
   166 	}
       
   167 }
       
   168 
       
   169 //--------------------------------------------------
       
   170 
       
   171 #if defined(USE_EAP_RADIUS_VERIFY_STATES)
       
   172 
       
   173 /**
       
   174  * This function checks the valid states.
       
   175  */
       
   176 bool eap_radius_c::verify_states(
       
   177 	const eap_radius_state_variable_e * const valid_states,
       
   178 	const u32_t count) const
       
   179 {
       
   180 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   181 
       
   182 	for (u32_t ind = 0ul; ind < count; ind++)
       
   183 	{
       
   184 		if (m_state == valid_states[ind])
       
   185 		{
       
   186 			return true;
       
   187 		}
       
   188 	}
       
   189 
       
   190 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   191 	return false;
       
   192 }
       
   193 
       
   194 #endif //#if defined(USE_EAP_RADIUS_VERIFY_STATES)
       
   195 
       
   196 //--------------------------------------------------
       
   197 
       
   198 static const u8_t DEFAULT_CALLED_STATION_ID[] = "000000";
       
   199 static const u32_t DEFAULT_CALLED_STATION_ID_LENGTH = sizeof(DEFAULT_CALLED_STATION_ID);
       
   200 
       
   201 static const u8_t DEFAULT_CALLING_STATION_ID[] = "111111";
       
   202 static const u32_t DEFAULT_CALLING_STATION_ID_LENGTH = sizeof(DEFAULT_CALLING_STATION_ID);
       
   203 
       
   204 //
       
   205 EAP_FUNC_EXPORT eap_status_e eap_radius_c::analyse_radius_packet(
       
   206 	const eap_am_network_id_c * const receive_network_id,
       
   207 	eap_radius_header_base_c * const received_radius,
       
   208 	const u32_t radius_packet_length,
       
   209 	eap_radius_payloads_c * const p_radius_payloads)
       
   210 {
       
   211 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   212 
       
   213 	eap_status_e status(eap_status_process_general_error);
       
   214 
       
   215 	if (m_is_client == true)
       
   216 	{
       
   217 		// Not supported yet. First priority is the server functionality.
       
   218 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   219 		return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
   220 	}
       
   221 	else
       
   222 	{
       
   223 		eap_variable_data_c called_station_id(m_am_tools);
       
   224 
       
   225 		if (called_station_id.get_is_valid() == false)
       
   226 		{
       
   227 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   228 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   229 		}
       
   230 
       
   231 		if (p_radius_payloads->get_payload(eap_diameter_avp_code_called_station_id) != 0)
       
   232 		{
       
   233 			status = called_station_id.add_data(p_radius_payloads->get_payload(eap_diameter_avp_code_called_station_id)->get_payload_buffer());
       
   234 			if (status != eap_status_ok)
       
   235 			{
       
   236 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   237 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   238 			}
       
   239 		}
       
   240 		else
       
   241 		{
       
   242 			status = called_station_id.add_data(DEFAULT_CALLED_STATION_ID, DEFAULT_CALLED_STATION_ID_LENGTH);
       
   243 			if (status != eap_status_ok)
       
   244 			{
       
   245 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   246 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   247 			}
       
   248 		}
       
   249 
       
   250 		eap_variable_data_c calling_station_id(m_am_tools);
       
   251 
       
   252 		if (calling_station_id.get_is_valid() == false)
       
   253 		{
       
   254 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   255 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   256 		}
       
   257 
       
   258 		if (p_radius_payloads->get_payload(eap_diameter_avp_code_calling_station_id) != 0)
       
   259 		{
       
   260 			status = calling_station_id.add_data(p_radius_payloads->get_payload(eap_diameter_avp_code_calling_station_id)->get_payload_buffer());
       
   261 			if (status != eap_status_ok)
       
   262 			{
       
   263 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   264 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   265 			}
       
   266 		}
       
   267 		else
       
   268 		{
       
   269 			status = called_station_id.add_data(DEFAULT_CALLING_STATION_ID, DEFAULT_CALLING_STATION_ID_LENGTH);
       
   270 			if (status != eap_status_ok)
       
   271 			{
       
   272 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   273 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   274 			}
       
   275 		}
       
   276 
       
   277 
       
   278 		// Test the required attributes.
       
   279 		if (p_radius_payloads->get_payload(eap_diameter_avp_code_user_name) != 0
       
   280 			&& p_radius_payloads->get_payload(eap_diameter_avp_code_nas_ip_address) != 0
       
   281 			&& p_radius_payloads->get_payload(eap_diameter_avp_code_eap_message) != 0)
       
   282 		{
       
   283 			// Check the session.
       
   284 			eap_variable_data_c selector(m_am_tools);
       
   285 
       
   286 			if (selector.get_is_valid() == false)
       
   287 			{
       
   288 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   289 				return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   290 			}
       
   291 
       
   292 			status = selector.add_data(
       
   293 				p_radius_payloads->get_payload(
       
   294 					eap_diameter_avp_code_user_name
       
   295 					)->get_payload_buffer());
       
   296 			if (status != eap_status_ok)
       
   297 			{
       
   298 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   299 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   300 			}
       
   301 
       
   302 			status = selector.add_data(
       
   303 				p_radius_payloads->get_payload(
       
   304 					eap_diameter_avp_code_nas_ip_address
       
   305 					)->get_payload_buffer());
       
   306 			if (status != eap_status_ok)
       
   307 			{
       
   308 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   309 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   310 			}
       
   311 
       
   312 			status = selector.add_data(&called_station_id);
       
   313 			if (status != eap_status_ok)
       
   314 			{
       
   315 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   316 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   317 			}
       
   318 
       
   319 			status = selector.add_data(
       
   320 				p_radius_payloads->get_payload(
       
   321 					eap_diameter_avp_code_calling_station_id
       
   322 					)->get_payload_buffer());
       
   323 			if (status != eap_status_ok)
       
   324 			{
       
   325 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   326 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   327 			}
       
   328 
       
   329 			EAP_TRACE_DATA_DEBUG(
       
   330 				m_am_tools, 
       
   331 				TRACE_FLAGS_DEFAULT, 
       
   332 				(EAPL("RADIUS session"),
       
   333 				 selector.get_data(),
       
   334 				 selector.get_data_length()));
       
   335 
       
   336 			eap_radius_session_c * session = m_session_map.get_handler(&selector);
       
   337 
       
   338 			if (session == 0)
       
   339 			{
       
   340 				// Create a new session.
       
   341 				session = new eap_radius_session_c(
       
   342 					m_am_tools,
       
   343 					this,
       
   344 					false,
       
   345 					p_radius_payloads->get_payload(eap_diameter_avp_code_user_name),
       
   346 					p_radius_payloads->get_payload(eap_diameter_avp_code_nas_ip_address));
       
   347 
       
   348 				if (session == 0
       
   349 					|| session->get_is_valid() == false)
       
   350 				{
       
   351 					delete session;
       
   352 					session = 0;
       
   353 
       
   354 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   355 					return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   356 				}
       
   357 
       
   358 				status = session->configure();
       
   359 				if (status != eap_status_ok)
       
   360 				{
       
   361 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   362 					return EAP_STATUS_RETURN(m_am_tools, status);
       
   363 				}
       
   364 
       
   365 				status = m_session_map.add_handler(&selector, session);
       
   366 				if (status != eap_status_ok)
       
   367 				{
       
   368 					session->shutdown();
       
   369 					delete session;
       
   370 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   371 					return EAP_STATUS_RETURN(m_am_tools, status);
       
   372 				}
       
   373 			}
       
   374 
       
   375 			if (session != 0)
       
   376 			{
       
   377 				// Handle the received EAP-Response.
       
   378 
       
   379 				status = session->save_request_data(
       
   380 					received_radius->get_authenticator(),
       
   381 					received_radius->get_authenticator_length(),
       
   382 					received_radius->get_identifier());
       
   383 				if (status != eap_status_ok)
       
   384 				{
       
   385 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   386 					return EAP_STATUS_RETURN(m_am_tools, status);
       
   387 				}
       
   388 
       
   389 				eap_variable_data_c * const eap_message
       
   390 					= p_radius_payloads->get_payload(eap_diameter_avp_code_eap_message)
       
   391 					->get_payload_buffer();
       
   392 
       
   393 				eap_header_wr_c eap(
       
   394 					m_am_tools,
       
   395 					eap_message->get_data(),
       
   396 					eap_message->get_data_length());
       
   397 				
       
   398 				trace_tunneled_packet(EAPL("-> TUNNELED packet server"), &eap);
       
   399 
       
   400 				status = session->packet_process(
       
   401 					receive_network_id,
       
   402 					&eap,
       
   403 					eap_message->get_data_length());
       
   404 				if (status != eap_status_ok)
       
   405 				{
       
   406 					EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   407 					return EAP_STATUS_RETURN(m_am_tools, status);
       
   408 				}
       
   409 			}
       
   410 		}
       
   411 	}
       
   412 
       
   413 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   414 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   415 }
       
   416 
       
   417 //--------------------------------------------------
       
   418 
       
   419 //
       
   420 EAP_FUNC_EXPORT eap_status_e eap_radius_c::parse_radius_packet(
       
   421 	eap_radius_header_base_c * const radius,
       
   422 	const u32_t radius_packet_length,
       
   423 	eap_radius_payloads_c * const p_radius_payloads)
       
   424 {
       
   425 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   426 
       
   427 	if (radius->get_length() < radius->get_header_length())
       
   428 	{
       
   429 		EAP_TRACE_ERROR(
       
   430 			m_am_tools,
       
   431 			TRACE_FLAGS_RADIUS_ERROR,
       
   432 			(EAPL("ERROR: eap_radius_payloads_c::parse_radius_packet(): ")
       
   433 			 EAPL("RADIUS-header is corrupted. Buffer length and payload ")
       
   434 			 EAPL("length does not match. RADIUS-header length %lu < minimum RADIUS-header length %lu.\n"),
       
   435 			radius->get_length(),
       
   436 			radius->get_header_length()));
       
   437 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   438 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   439 	}
       
   440 
       
   441 	if (radius->get_length() > radius_packet_length)
       
   442 	{
       
   443 		EAP_TRACE_ERROR(
       
   444 			m_am_tools, 
       
   445 			TRACE_FLAGS_RADIUS_ERROR, 
       
   446 			(EAPL("ERROR: eap_radius_payloads_c::parse_radius_packet(): ")
       
   447 			 EAPL("RADIUS-header is corrupted. Buffer length and payload ")
       
   448 			 EAPL("length does not match. RADIUS-header length %lu > packet length %lu\n"),
       
   449 			radius->get_length(),
       
   450 			radius_packet_length));
       
   451 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   452 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   453 	}
       
   454 
       
   455 	u32_t buffer_length = radius->get_length() - radius->get_header_length();
       
   456 
       
   457 	if (buffer_length == 0u)
       
   458 	{
       
   459 		// No payload in this packet.
       
   460 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
   461 	}
       
   462 
       
   463 
       
   464 	eap_radius_attribute_header_c payload(
       
   465 		m_am_tools,
       
   466 		radius->get_data_offset(0ul, buffer_length),
       
   467 		buffer_length);
       
   468 
       
   469 	if (payload.get_is_valid() == false)
       
   470 	{
       
   471 		EAP_TRACE_ERROR(
       
   472 			m_am_tools, 
       
   473 			TRACE_FLAGS_RADIUS_ERROR, 
       
   474 			(EAPL("ERROR: No eap_radius_attribute_header_c.\n")));
       
   475 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   476 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   477 	}
       
   478 
       
   479 
       
   480 	eap_status_e status = p_radius_payloads->parse_radius_payload(
       
   481 		&payload,
       
   482 		&buffer_length);
       
   483 
       
   484 	if (status != eap_status_ok)
       
   485 	{
       
   486 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   487 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   488 	}
       
   489 	else if (buffer_length != 0u)
       
   490 	{
       
   491 		EAP_TRACE_ERROR(
       
   492 			m_am_tools,
       
   493 			TRACE_FLAGS_RADIUS_ERROR,
       
   494 			(EAPL("ERROR: eap_radius_payloads_c::parse_radius_packet(): ")
       
   495 			 EAPL("RADIUS-header is corrupted. Buffer length and payload ")
       
   496 			 EAPL("length does not match. Illegal byte count %lu\n"),
       
   497 			buffer_length));
       
   498 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   499 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   500 	}
       
   501 
       
   502 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   503 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   504 }
       
   505 
       
   506 //--------------------------------------------------
       
   507 
       
   508 //
       
   509 EAP_FUNC_EXPORT eap_status_e eap_radius_c::handle_radius_packet(
       
   510 	const eap_am_network_id_c * const receive_network_id,
       
   511 	eap_radius_header_base_c * const received_radius,
       
   512 	const u32_t radius_length,
       
   513 	eap_radius_payloads_c * const p_radius_payloads)
       
   514 {
       
   515 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   516 
       
   517 	eap_status_e status(eap_status_header_corrupted);
       
   518 
       
   519 	status = parse_radius_packet(received_radius, radius_length, p_radius_payloads);
       
   520 	if (status != eap_status_ok)
       
   521 	{
       
   522 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   523 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   524 	}
       
   525 
       
   526 	status = analyse_radius_packet(
       
   527 		receive_network_id,
       
   528 		received_radius,
       
   529 		radius_length,
       
   530 		p_radius_payloads);
       
   531 
       
   532 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   533 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   534 }
       
   535 
       
   536 
       
   537 //--------------------------------------------------
       
   538 
       
   539 #if defined(USE_EAP_TRACE)
       
   540 
       
   541 // 
       
   542 EAP_FUNC_EXPORT void eap_radius_c::packet_trace(
       
   543 	eap_const_string prefix,
       
   544 	const eap_am_network_id_c * const /* receive_network_id */,
       
   545 	eap_radius_header_base_c * const eap_packet,
       
   546 	const u32_t /* eap_packet_length */)
       
   547 {
       
   548 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   549 
       
   550 	EAP_UNREFERENCED_PARAMETER(prefix);
       
   551 
       
   552 	if (eap_packet->get_length() > eap_radius_header_base_c::get_header_length())
       
   553 	{
       
   554 		EAP_TRACE_DEBUG(
       
   555 			m_am_tools,
       
   556 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
   557 			(EAPL("%s EAP_type_RADIUS: %s, (0x%08x), code=0x%02x=%s, ")
       
   558 			 EAPL("identifier=0x%02x, length=0x%04x\n"),
       
   559 			prefix,
       
   560 			(m_is_client == true) ? "client": "server",
       
   561 			this,
       
   562 			eap_packet->get_code(),
       
   563 			eap_packet->get_code_string(),
       
   564 			eap_packet->get_identifier(),
       
   565 			eap_packet->get_length()));
       
   566 
       
   567 		EAP_TRACE_DEBUG(
       
   568 			m_am_tools,
       
   569 			eap_am_tools_c::eap_trace_mask_eap_messages,
       
   570 			(EAPL("\n\t%s\n\tcode       = 0x%02x   = %s\n\tidentifier = ")
       
   571 			 EAPL("0x%02x\n\tlength     = 0x%04x = %lu\n\n"),
       
   572 			(m_is_client == true) ? "client": "server",
       
   573 			eap_packet->get_code(),
       
   574 			eap_packet->get_code_string(),
       
   575 			eap_packet->get_identifier(),
       
   576 			eap_packet->get_length(),
       
   577 			eap_packet->get_length()));
       
   578 	}
       
   579 	else
       
   580 	{
       
   581 		EAP_TRACE_DEBUG(
       
   582 			m_am_tools,
       
   583 			TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
   584 			(EAPL("%s EAP_type_RADIUS: %s, (0x%08x), code=0x%02x=%s, ")
       
   585 			 EAPL("identifier=0x%02x, length=0x%04x\n"),
       
   586 			prefix,
       
   587 			(m_is_client == true) ? "client": "server",
       
   588 			this,
       
   589 			eap_packet->get_code(),
       
   590 			eap_packet->get_code_string(),
       
   591 			eap_packet->get_identifier(),
       
   592 			eap_packet->get_length()));
       
   593 
       
   594 		EAP_TRACE_DEBUG(
       
   595 			m_am_tools,
       
   596 			eap_am_tools_c::eap_trace_mask_eap_messages,
       
   597 			(EAPL("\n\t%s\n\tcode       = 0x%02x   = %s\n\tidentifier = ")
       
   598 			 EAPL("0x%02x\n\tlength     = 0x%04x = %lu\n"),
       
   599 			(m_is_client == true) ? "client": "server",
       
   600 			eap_packet->get_code(),
       
   601 			eap_packet->get_code_string(),
       
   602 			eap_packet->get_identifier(),
       
   603 			eap_packet->get_length(),
       
   604 			eap_packet->get_length()));
       
   605 	}
       
   606 
       
   607 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   608 }
       
   609 
       
   610 #endif //#if defined(USE_EAP_TRACE)
       
   611 
       
   612 //--------------------------------------------------
       
   613 
       
   614 #if defined(USE_EAP_TRACE)
       
   615 
       
   616 EAP_FUNC_EXPORT void eap_radius_c::trace_tunneled_packet(
       
   617 	eap_const_string prefix,
       
   618 	const eap_header_base_c * const eap_packet)
       
   619 {
       
   620 	if (eap_packet == 0
       
   621 		|| eap_packet->get_is_valid() == false)
       
   622 	{
       
   623 		// ERROR: Cannot trace invalid packet.
       
   624 		EAP_TRACE_ALWAYS(
       
   625 			m_am_tools,
       
   626 			TRACE_FLAGS_DEFAULT,
       
   627 			(EAPL("ERROR: %s: %s: Cannot trace invalid packet.\n"),
       
   628 			 prefix,
       
   629 			 (m_is_client == true) ? "client": "server"));
       
   630 		return;
       
   631 	}
       
   632 
       
   633 	if ((m_am_tools->get_trace_mask() & TRACE_FLAGS_DEFAULT)
       
   634 		&& m_pseudo_ethernet_header.get_is_valid_data() == true
       
   635 		&& m_pseudo_ethernet_header.get_data_length() >= sizeof(EAP_PSEUDO_ETHERNET_HEADER))
       
   636 	{
       
   637 		m_pseudo_ethernet_header.set_data_length(sizeof(EAP_PSEUDO_ETHERNET_HEADER));
       
   638 
       
   639 		u32_t eap_packet_length = eap_packet->get_length();
       
   640 		if (eap_packet->get_header_buffer_length() < eap_packet_length)
       
   641 		{
       
   642 			eap_packet_length = eap_packet->get_header_buffer_length();
       
   643 		}
       
   644 
       
   645 		eap_status_e status = m_pseudo_ethernet_header.add_data_to_offset(
       
   646 			sizeof(EAP_PSEUDO_ETHERNET_HEADER),
       
   647 			eap_packet->get_header_buffer(eap_packet_length),
       
   648 			eap_packet_length);
       
   649 
       
   650 		if (status == eap_status_ok)
       
   651 		{
       
   652 			m_pseudo_ethernet_header.set_data_length(
       
   653 				sizeof(EAP_PSEUDO_ETHERNET_HEADER) + eap_packet_length);
       
   654 
       
   655 			// Sets the EAPOL packet data length.
       
   656 			eapol_header_wr_c eapol(
       
   657 				m_am_tools,
       
   658 				m_pseudo_ethernet_header.get_data_offset(
       
   659 					EAP_PSEUDO_EAPOL_HEADER_OFFSET,
       
   660 					m_pseudo_ethernet_header.get_data_length()-EAP_PSEUDO_EAPOL_HEADER_OFFSET),
       
   661 				m_pseudo_ethernet_header.get_data_length()-EAP_PSEUDO_EAPOL_HEADER_OFFSET);
       
   662 
       
   663 			if (eapol.get_is_valid() == true)
       
   664 			{
       
   665 				eapol.set_data_length(static_cast<u16_t>(eap_packet_length));
       
   666 
       
   667 				EAP_TRACE_ALWAYS(
       
   668 					m_am_tools,
       
   669 					TRACE_FLAGS_DEFAULT,
       
   670 					(EAPL("%s: %s: type=0x%08x, packet_length 0x%04x\n"),
       
   671 					 prefix,
       
   672 					 (m_is_client == true) ? "client": "server",
       
   673 					 convert_eap_type_to_u32_t(eap_packet->get_type()),
       
   674 					 eap_packet->get_length())); // NOTE, this will trace the values from the header of the EAP-packet.
       
   675 
       
   676 				EAP_TRACE_DATA_ALWAYS(
       
   677 					m_am_tools,
       
   678 					TRACE_FLAGS_DEFAULT,
       
   679 					(prefix,
       
   680 					m_pseudo_ethernet_header.get_data(m_pseudo_ethernet_header.get_data_length()),
       
   681 					m_pseudo_ethernet_header.get_data_length()));
       
   682 			}
       
   683 		}
       
   684 	}
       
   685 }
       
   686 
       
   687 #endif //#if defined(USE_EAP_TRACE)
       
   688 
       
   689 //--------------------------------------------------
       
   690 
       
   691 // 
       
   692 EAP_FUNC_EXPORT bool eap_radius_c::get_is_client() 
       
   693 {
       
   694 	return m_is_client;
       
   695 }
       
   696 
       
   697 //--------------------------------------------------
       
   698 
       
   699 // 
       
   700 EAP_FUNC_EXPORT void eap_radius_c::set_is_valid()
       
   701 {
       
   702 	m_is_valid = true;
       
   703 }
       
   704 
       
   705 //--------------------------------------------------
       
   706 
       
   707 // 
       
   708 EAP_FUNC_EXPORT bool eap_radius_c::get_is_valid()
       
   709 {
       
   710 	return m_is_valid;
       
   711 }
       
   712 
       
   713 //--------------------------------------------------
       
   714 
       
   715 // 
       
   716 EAP_FUNC_EXPORT eap_status_e eap_radius_c::packet_process(
       
   717 	const eap_am_network_id_c * const receive_network_id,
       
   718 	eap_radius_header_base_c * const received_eap,
       
   719 	const u32_t eap_packet_length)
       
   720 {
       
   721 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   722 
       
   723 	EAP_RADIUS_PACKET_TRACE(
       
   724 		EAPL("->"),
       
   725 		receive_network_id,
       
   726 		received_eap,
       
   727 		eap_packet_length);
       
   728 
       
   729 	if (receive_network_id == 0
       
   730 		|| receive_network_id->get_is_valid_data() == false)
       
   731 	{
       
   732 		EAP_TRACE_ERROR(
       
   733 			m_am_tools, 
       
   734 			TRACE_FLAGS_RADIUS_ERROR, 
       
   735 			(EAPL("ERROR: eap_radius_c::packet_process(): receive_network_id=0x%08x is invalid.\n"),
       
   736 			receive_network_id));
       
   737 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   738 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   739 	}
       
   740 
       
   741 	if (received_eap == 0
       
   742 		|| received_eap->get_is_valid() == false)
       
   743 	{
       
   744 		EAP_TRACE_ERROR(
       
   745 			m_am_tools, 
       
   746 			TRACE_FLAGS_RADIUS_ERROR, 
       
   747 			(EAPL("ERROR: eap_radius_c::packet_process(): received_eap 0x%08x is invalid.\n"),
       
   748 			received_eap));
       
   749 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   750 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   751 	}
       
   752 
       
   753 	if (eap_packet_length < received_eap->get_length())
       
   754 	{
       
   755 		EAP_TRACE_ERROR(
       
   756 			m_am_tools, 
       
   757 			TRACE_FLAGS_RADIUS_ERROR, 
       
   758 			(EAPL("ERROR: eap_radius_c::packet_process(): ")
       
   759 			 EAPL("eap_packet_length=0x%04x < received_eap->get_length()=0x%04x.\n"),
       
   760 			eap_packet_length, received_eap->get_length()));
       
   761 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   762 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   763 	}
       
   764 
       
   765 	if (received_eap->get_length() < eap_header_base_c::get_header_length())
       
   766 	{
       
   767 		EAP_TRACE_ERROR(
       
   768 			m_am_tools, 
       
   769 			TRACE_FLAGS_RADIUS_ERROR, 
       
   770 			(EAPL("ERROR: eap_radius_c::packet_process(): received_eap->get_length() ")
       
   771 			 EAPL("< eap_header_base_c::get_header_length().\n")));
       
   772 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   773 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   774 	}
       
   775 
       
   776 
       
   777 	// NOTE: by disabling these calls throughput increases about 18%.
       
   778 	// Disabling also decreases random seeds.
       
   779 	m_am_tools->get_crypto()->add_rand_seed(
       
   780 		received_eap->get_header_buffer(eap_packet_length),
       
   781 		eap_packet_length);
       
   782 	m_am_tools->get_crypto()->add_rand_seed_hw_ticks();
       
   783 
       
   784 
       
   785 	eap_status_e status = eap_status_process_general_error;
       
   786 
       
   787 	if ((m_is_client == true
       
   788 		 && received_eap->get_code() == eap_radius_code_access_challenge)
       
   789 		|| (m_is_client == false
       
   790 			&& received_eap->get_code() == eap_radius_code_access_request))
       
   791 	{
       
   792 		eap_radius_header_base_c radius_header(
       
   793 			m_am_tools,
       
   794 			received_eap->get_header_buffer(received_eap->get_header_buffer_length()),
       
   795 			received_eap->get_header_buffer_length());
       
   796 
       
   797 		if (radius_header.get_is_valid() == false)
       
   798 		{
       
   799 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   800 			return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   801 		}
       
   802 
       
   803 		status = radius_packet_process(
       
   804 			receive_network_id,
       
   805 			&radius_header,
       
   806 			eap_packet_length,
       
   807 			m_is_client);
       
   808 
       
   809 		if (status == eap_status_ok)
       
   810 		{
       
   811 			EAP_GENERAL_HEADER_SET_ERROR_DETECTED(received_eap, false);
       
   812 		}
       
   813 
       
   814 		if (status != eap_status_ok
       
   815 			&& status != eap_status_success
       
   816 			&& status != eap_status_drop_packet_quietly
       
   817 			&& status != eap_status_pending_request)
       
   818 		{
       
   819 			eap_status_string_c status_string;
       
   820 			EAP_UNREFERENCED_PARAMETER(status_string);
       
   821 			EAP_TRACE_DEBUG(
       
   822 				m_am_tools, 
       
   823 				TRACE_FLAGS_RADIUS_ERROR, 
       
   824 				(EAPL("ERROR: %s=%d eap_radius_c::radius_packet_process() failed\n"),
       
   825 				 status_string.get_status_string(status), status));
       
   826 
       
   827 			if (status != eap_status_ok)
       
   828 			{
       
   829 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   830 				return EAP_STATUS_RETURN(m_am_tools, status);
       
   831 			}
       
   832 		}
       
   833 	}
       
   834 	else if (m_is_client == true
       
   835 		&& (received_eap->get_code() == eap_radius_code_access_accept
       
   836 		|| received_eap->get_code() == eap_radius_code_access_reject))
       
   837 	{
       
   838 		// Here we swap the addresses.
       
   839 		eap_am_network_id_c send_network_id(m_am_tools,
       
   840 			receive_network_id->get_destination_id(),
       
   841 			receive_network_id->get_source_id(),
       
   842 			receive_network_id->get_type());
       
   843 
       
   844 		if (received_eap->get_code() == eap_radius_code_access_accept)
       
   845 		{
       
   846 		}
       
   847 		else if (received_eap->get_code() == eap_radius_code_access_reject)
       
   848 		{
       
   849 			// EAP is quite sloppy protocol.
       
   850 			// Somebody just send a EAP-failure message and authentication is terminated.
       
   851 
       
   852 			// Save received failure. We do not change our state yet.
       
   853 			// The real correct EAP message could be received later if this failure was
       
   854 			// send by nasty attacker.
       
   855 			// We handle the EAP-Request/Failure message after a timeout.
       
   856 
       
   857 			status = eap_status_ok;
       
   858 		}
       
   859 		else
       
   860 		{
       
   861 			EAP_TRACE_ERROR(
       
   862 				m_am_tools, 
       
   863 				TRACE_FLAGS_DEFAULT, 
       
   864 				(EAPL("dropped EAP code unknown: code=0x%02x, ")
       
   865 				 EAPL("identifier=0x%02x, length=0x%04x, is client %d\n"),
       
   866 				 received_eap->get_code(), received_eap->get_identifier(), 
       
   867 				 received_eap->get_length(), (m_is_client == true)));
       
   868 			status = eap_status_illegal_eap_code;
       
   869 		}
       
   870 	}
       
   871 	else
       
   872 	{
       
   873 		EAP_TRACE_ERROR(
       
   874 			m_am_tools, 
       
   875 			TRACE_FLAGS_DEFAULT, 
       
   876 			(EAPL("dropped EAP code unknown: code=0x%02x, ")
       
   877 			 EAPL("identifier=0x%02x, length=0x%04x, is client %d\n"),
       
   878 			 received_eap->get_code(), received_eap->get_identifier(), 
       
   879 			 received_eap->get_length(), (m_is_client == true)));
       
   880 		status = eap_status_illegal_eap_code;
       
   881 	}
       
   882 
       
   883 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   884 	return EAP_STATUS_RETURN(m_am_tools, status);
       
   885 }
       
   886 
       
   887 //--------------------------------------------------
       
   888 
       
   889 //
       
   890 EAP_FUNC_EXPORT eap_status_e eap_radius_c::radius_packet_process(
       
   891 	const eap_am_network_id_c * const receive_network_id,
       
   892 	eap_radius_header_base_c * const received_radius,
       
   893 	const u32_t radius_packet_length,
       
   894 	const bool is_client_when_true)
       
   895 {
       
   896 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   897 
       
   898 	if (receive_network_id == 0
       
   899 		|| receive_network_id->get_is_valid_data() == false)
       
   900 	{
       
   901 		EAP_TRACE_ERROR(
       
   902 			m_am_tools, 
       
   903 			TRACE_FLAGS_RADIUS_ERROR, 
       
   904 			(EAPL("ERROR: eap_radius_c::radius_packet_process(): ")
       
   905 			 EAPL("receive_network_id=0x%08x is invalid.\n"),
       
   906 			receive_network_id));
       
   907 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   908 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   909 	}
       
   910 
       
   911 	if (received_radius == 0
       
   912 		|| received_radius->get_is_valid() == false)
       
   913 	{
       
   914 		EAP_TRACE_ERROR(
       
   915 			m_am_tools, 
       
   916 			TRACE_FLAGS_RADIUS_ERROR, 
       
   917 			(EAPL("ERROR: eap_radius_c::radius_packet_process(): ")
       
   918 			 EAPL("received_radius 0x%08x is invalid.\n"),
       
   919 			received_radius));
       
   920 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   921 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
   922 	}
       
   923 
       
   924 	if (radius_packet_length < received_radius->get_length())
       
   925 	{
       
   926 		EAP_TRACE_ERROR(
       
   927 			m_am_tools, 
       
   928 			TRACE_FLAGS_RADIUS_ERROR, 
       
   929 			(EAPL("ERROR: eap_radius_c::radius_packet_process(): ")
       
   930 			 EAPL("radius_packet_length < received_radius->get_length().\n")));
       
   931 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   932 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
   933 	}
       
   934 
       
   935 	eap_status_e status = eap_status_process_general_error;
       
   936 
       
   937 	// Here we swap the addresses.
       
   938 	eap_am_network_id_c send_network_id(m_am_tools,
       
   939 		receive_network_id->get_destination_id(),
       
   940 		receive_network_id->get_source_id(),
       
   941 		receive_network_id->get_type());
       
   942 
       
   943 	EAP_TRACE_DATA_DEBUG(
       
   944 		m_am_tools, 
       
   945 		TRACE_FLAGS_DEFAULT, 
       
   946 		(EAPL("received: RADIUS packet"),
       
   947 		 received_radius->get_header_buffer(
       
   948 			 received_radius->get_header_length()+received_radius->get_data_length()),
       
   949 		 received_radius->get_header_length()+received_radius->get_data_length()));
       
   950 
       
   951 
       
   952 	if (radius_packet_length < eap_radius_header_base_c::get_header_length())
       
   953 	{
       
   954 		EAP_TRACE_ERROR(
       
   955 			m_am_tools,
       
   956 			TRACE_FLAGS_RADIUS_ERROR,
       
   957 			(EAPL("ERROR: eap_radius_c::radius_packet_process(): ")
       
   958 			 EAPL("radius_packet_length < eap_radius_header_base_c::get_header_length().\n")));
       
   959 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   960 		return EAP_STATUS_RETURN(m_am_tools, eap_status_header_corrupted);
       
   961 	}
       
   962 
       
   963 	status = received_radius->check_header();
       
   964 	if (status != eap_status_ok)
       
   965 	{
       
   966 		eap_status_string_c status_string;
       
   967 		EAP_TRACE_ERROR(
       
   968 			m_am_tools,
       
   969 			TRACE_FLAGS_RADIUS_ERROR,
       
   970 			(EAPL("ERROR: %s=%d eap_radius_c::radius_packet_process(): ")
       
   971 			 EAPL("corrupted RADIUS-header.\n"),
       
   972 			status_string.get_status_string(status), status));
       
   973 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   974 		return EAP_STATUS_RETURN(m_am_tools, status);
       
   975 	}
       
   976 
       
   977 	eap_radius_payloads_c * const l_radius_payloads = new eap_radius_payloads_c(m_am_tools);
       
   978 	eap_automatic_variable_c<eap_radius_payloads_c> l_radius_payloads_automatic(
       
   979 		m_am_tools,
       
   980 		l_radius_payloads);
       
   981 
       
   982 	if (l_radius_payloads == 0
       
   983 		|| l_radius_payloads->get_is_valid() == false)
       
   984 	{
       
   985 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
   986 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
   987 	}
       
   988 
       
   989 	status = handle_radius_packet(
       
   990 		receive_network_id,
       
   991 		received_radius,
       
   992 		radius_packet_length,
       
   993 		l_radius_payloads);
       
   994 
       
   995 	if (status != eap_status_ok
       
   996 		&& status != eap_status_success
       
   997 		&& status != eap_status_drop_packet_quietly
       
   998 		&& status != eap_status_pending_request)
       
   999 	{
       
  1000 		eap_status_string_c status_string;
       
  1001 		EAP_UNREFERENCED_PARAMETER(status_string);
       
  1002 		EAP_TRACE_DEBUG(
       
  1003 			m_am_tools, 
       
  1004 			TRACE_FLAGS_RADIUS_ERROR, 
       
  1005 			(EAPL("ERROR: %s=%d eap_radius_c::radius_packet_process(): ")
       
  1006 			 EAPL("handle_radius_packet().\n"),
       
  1007 			status_string.get_status_string(status), status));
       
  1008 	}
       
  1009 
       
  1010 	if (status == eap_status_ok)
       
  1011 	{
       
  1012 		// Do nothing special.
       
  1013 	}
       
  1014 	else if (status == eap_status_drop_packet_quietly)
       
  1015 	{
       
  1016 		// We will drop this message quietly.
       
  1017 	}
       
  1018 	else if (status != eap_status_ok)
       
  1019 	{
       
  1020 		// EAP-Failure will be sent from shutdown().
       
  1021 	}
       
  1022 
       
  1023 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1024 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1025 }
       
  1026 
       
  1027 //--------------------------------------------------
       
  1028 
       
  1029 //
       
  1030 EAP_FUNC_EXPORT u32_t eap_radius_c::get_header_offset(
       
  1031 	u32_t * const MTU,
       
  1032 	u32_t * const trailer_length)
       
  1033 {
       
  1034 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1035 
       
  1036 	*MTU = 1020;
       
  1037 	*trailer_length = 0ul;
       
  1038 
       
  1039 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1040 	return 0ul;
       
  1041 }
       
  1042 
       
  1043 //--------------------------------------------------
       
  1044 
       
  1045 //
       
  1046 EAP_FUNC_EXPORT eap_status_e eap_radius_c::timer_expired(
       
  1047 	const u32_t id, void *data)
       
  1048 {
       
  1049 	EAP_UNREFERENCED_PARAMETER(id);
       
  1050 	EAP_UNREFERENCED_PARAMETER(data);
       
  1051 
       
  1052 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1053 
       
  1054 	EAP_TRACE_DEBUG(
       
  1055 		m_am_tools, 
       
  1056 		TRACE_FLAGS_DEFAULT, 
       
  1057 		(EAPL("TIMER: [0x%08x]->eap_radius_c::timer_expired(id 0x%02x, data 0x%08x).\n"),
       
  1058 		this, id, data));
       
  1059 
       
  1060 	eap_status_e status = eap_status_process_general_error;
       
  1061 
       
  1062 	if (id == EAP_TYPE_RADIUS_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID)
       
  1063 	{
       
  1064 		EAP_TRACE_DEBUG(
       
  1065 			m_am_tools, 
       
  1066 			TRACE_FLAGS_DEFAULT, 
       
  1067 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID elapsed.\n"),
       
  1068 			 (m_is_client == true) ? "client": "server"));
       
  1069 	}
       
  1070 	else if (id == EAP_TYPE_RADIUS_TIMER_DELAY_NOTIFICATION_MESSAGE_ID)
       
  1071 	{
       
  1072 		EAP_TRACE_DEBUG(
       
  1073 			m_am_tools, 
       
  1074 			TRACE_FLAGS_DEFAULT, 
       
  1075 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_NOTIFICATION_MESSAGE_ID elapsed.\n"),
       
  1076 			 (m_is_client == true) ? "client": "server"));
       
  1077 	}
       
  1078 
       
  1079 
       
  1080 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1081 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1082 }
       
  1083 
       
  1084 //--------------------------------------------------
       
  1085 
       
  1086 //
       
  1087 EAP_FUNC_EXPORT eap_status_e eap_radius_c::timer_delete_data(
       
  1088 	const u32_t id, void *data)
       
  1089 {
       
  1090 	EAP_UNREFERENCED_PARAMETER(id);
       
  1091 	EAP_UNREFERENCED_PARAMETER(data);
       
  1092 
       
  1093 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1094 
       
  1095 	EAP_TRACE_DEBUG(
       
  1096 		m_am_tools, 
       
  1097 		TRACE_FLAGS_DEFAULT, 
       
  1098 		(EAPL("TIMER: [0x%08x]->eap_radius_c::timer_delete_data(id 0x%02x, data 0x%08x).\n"),
       
  1099 		this, id, data));
       
  1100 
       
  1101 	if (id == EAP_TYPE_RADIUS_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID)
       
  1102 	{
       
  1103 		EAP_TRACE_DEBUG(
       
  1104 			m_am_tools, 
       
  1105 			TRACE_FLAGS_DEFAULT, 
       
  1106 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_FAILURE_MESSAGE_SENT_ID delete data.\n"),
       
  1107 			 (m_is_client == true) ? "client": "server"));
       
  1108 	}
       
  1109 	else if (id == EAP_TYPE_RADIUS_TIMER_DELAY_NOTIFICATION_MESSAGE_ID)
       
  1110 	{
       
  1111 		EAP_TRACE_DEBUG(
       
  1112 			m_am_tools, 
       
  1113 			TRACE_FLAGS_DEFAULT, 
       
  1114 			(EAPL("TIMER: %s: EAP_TYPE_TIMER_DELAY_NOTIFICATION_MESSAGE_ID delete data.\n"),
       
  1115 			 (m_is_client == true) ? "client": "server"));
       
  1116 	}
       
  1117 
       
  1118 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1119 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1120 }
       
  1121 
       
  1122 //--------------------------------------------------
       
  1123 
       
  1124 //
       
  1125 EAP_FUNC_EXPORT eap_status_e eap_radius_c::add_user_name_attribute(
       
  1126 	const eap_radius_variable_data_c * const user_name,
       
  1127 	eap_radius_header_base_c * const radius_header,
       
  1128 	u32_t * const radius_attribute_offset,
       
  1129 	crypto_hmac_c * const hmac_message_auth,
       
  1130 	crypto_md5_c * const md5_response_auth)
       
  1131 {
       
  1132 	const u32_t user_name_length
       
  1133 		= eap_radius_attribute_header_c::get_header_length()
       
  1134 		+ user_name->get_data_length();
       
  1135 
       
  1136 	eap_radius_attribute_header_c user_name_attribute(
       
  1137 		m_am_tools,
       
  1138 		radius_header->get_data_offset(
       
  1139 			*radius_attribute_offset,
       
  1140 			user_name_length),
       
  1141 		user_name_length);
       
  1142 	if (user_name_attribute.get_is_valid() == false)
       
  1143 	{
       
  1144 		EAP_TRACE_ERROR(
       
  1145 			m_am_tools,
       
  1146 			TRACE_FLAGS_DEFAULT,
       
  1147 			(EAPL("packet buffer corrupted.\n")));
       
  1148 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1149 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1150 	}
       
  1151 	
       
  1152 	user_name_attribute.reset_header(
       
  1153 		static_cast<u16_t>(user_name_length
       
  1154 			-eap_radius_attribute_header_c::get_header_length()));
       
  1155 
       
  1156 	user_name_attribute.set_current_payload(eap_diameter_avp_code_user_name);
       
  1157 
       
  1158 	u8_t * const data = user_name_attribute.get_data_offset(
       
  1159 		0ul,
       
  1160 		user_name->get_data_length());
       
  1161 	if (data == 0)
       
  1162 	{
       
  1163 		EAP_TRACE_ERROR(
       
  1164 			m_am_tools,
       
  1165 			TRACE_FLAGS_DEFAULT,
       
  1166 			(EAPL("packet buffer corrupted.\n")));
       
  1167 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1168 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1169 	}
       
  1170 
       
  1171 	m_am_tools->memmove(
       
  1172 		data,
       
  1173 		user_name->get_data(user_name->get_data_length()),
       
  1174 		user_name->get_data_length());
       
  1175 
       
  1176 	eap_status_e status = hmac_message_auth->hmac_update(
       
  1177 		user_name_attribute.get_header_buffer(
       
  1178 			user_name_attribute.get_header_buffer_length()),
       
  1179 		user_name_attribute.get_header_buffer_length());
       
  1180 	if (status != eap_status_ok)
       
  1181 	{
       
  1182 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1183 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1184 	}
       
  1185 
       
  1186 	status = md5_response_auth->hash_update(
       
  1187 		user_name_attribute.get_header_buffer(
       
  1188 			user_name_attribute.get_header_buffer_length()),
       
  1189 		user_name_attribute.get_header_buffer_length());
       
  1190 	if (status != eap_status_ok)
       
  1191 	{
       
  1192 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1193 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1194 	}
       
  1195 
       
  1196 	EAP_TRACE_DATA_DEBUG(
       
  1197 		m_am_tools,
       
  1198 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  1199 		(EAPL("User-Name"),
       
  1200 		 user_name_attribute.get_header_buffer(
       
  1201 			 user_name_attribute.get_header_buffer_length()),
       
  1202 		 user_name_attribute.get_header_buffer_length()));
       
  1203 
       
  1204 	*radius_attribute_offset += user_name_length;
       
  1205 
       
  1206 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1207 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1208 }
       
  1209 
       
  1210 //--------------------------------------------------
       
  1211 
       
  1212 EAP_FUNC_EXPORT eap_status_e eap_radius_c::xor_values(
       
  1213 	u8_t * const plaintext,
       
  1214 	const u32_t plaintext_length,
       
  1215 	const eap_variable_data_c * const intermediate_value)
       
  1216 {
       
  1217 	u8_t * const intermediate_value_data = intermediate_value->get_data(plaintext_length);
       
  1218 
       
  1219 	if (intermediate_value_data == 0)
       
  1220 	{
       
  1221 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1222 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1223 	}
       
  1224 
       
  1225 	for (u32_t ind = 0ul; ind < plaintext_length; ind++)
       
  1226 	{
       
  1227 		plaintext[ind] = plaintext[ind] ^ intermediate_value_data[ind];
       
  1228 	}
       
  1229 
       
  1230 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1231 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1232 }
       
  1233 
       
  1234 //--------------------------------------------------
       
  1235 
       
  1236 //
       
  1237 EAP_FUNC_EXPORT eap_status_e eap_radius_c::encrypt_ms_mppe_key_attribute(
       
  1238 	const eap_variable_data_c * const shared_secret,
       
  1239 	const eap_variable_data_c * const request_authenticator,
       
  1240 	const u8_t * salt,
       
  1241 	const u32_t salt_length,
       
  1242 	u8_t * const data,
       
  1243 	const u32_t data_length)
       
  1244 {
       
  1245 	crypto_md5_c md5(
       
  1246 		m_am_tools);
       
  1247 
       
  1248 	eap_status_e status = md5.hash_init();
       
  1249 	if (status != eap_status_ok)
       
  1250 	{
       
  1251 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1252 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1253 	}
       
  1254 
       
  1255 	status = md5.hash_update(
       
  1256 		shared_secret->get_data(),
       
  1257 		shared_secret->get_data_length());
       
  1258 	if (status != eap_status_ok)
       
  1259 	{
       
  1260 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1261 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1262 	}
       
  1263 
       
  1264 	status = md5.hash_update(
       
  1265 		request_authenticator->get_data(),
       
  1266 		request_authenticator->get_data_length());
       
  1267 	if (status != eap_status_ok)
       
  1268 	{
       
  1269 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1270 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1271 	}
       
  1272 
       
  1273 	status = md5.hash_update(
       
  1274 		salt,
       
  1275 		salt_length);
       
  1276 	if (status != eap_status_ok)
       
  1277 	{
       
  1278 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1279 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1280 	}
       
  1281 
       
  1282 
       
  1283 	const u32_t block_size = md5.get_digest_length();
       
  1284 	const u32_t chunks_count = data_length/block_size;
       
  1285 
       
  1286 	if ((data_length % block_size) != 0)
       
  1287 	{
       
  1288 		// ERROR
       
  1289 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1290 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_parameter);
       
  1291 	}
       
  1292 
       
  1293 
       
  1294 	eap_variable_data_c intermediate_value(m_am_tools);
       
  1295 
       
  1296 	status = intermediate_value.init(block_size);
       
  1297 	if (status != eap_status_ok)
       
  1298 	{
       
  1299 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1300 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1301 	}
       
  1302 
       
  1303 	status = intermediate_value.set_data_length(block_size);
       
  1304 	if (status != eap_status_ok)
       
  1305 	{
       
  1306 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1307 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1308 	}
       
  1309 
       
  1310 	for (u32_t ind = 0ul; ind < chunks_count; ind++)
       
  1311 	{
       
  1312 		status = md5.hash_final(
       
  1313 			intermediate_value.get_data(block_size),
       
  1314 			0);
       
  1315 		if (status != eap_status_ok)
       
  1316 		{
       
  1317 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1318 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1319 		}
       
  1320 
       
  1321 		xor_values(
       
  1322 			data+(ind*block_size),
       
  1323 			block_size,
       
  1324 			&intermediate_value);
       
  1325 
       
  1326 		status = md5.hash_init();
       
  1327 		if (status != eap_status_ok)
       
  1328 		{
       
  1329 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1330 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1331 		}
       
  1332 
       
  1333 		status = md5.hash_update(
       
  1334 			shared_secret->get_data(),
       
  1335 			shared_secret->get_data_length());
       
  1336 		if (status != eap_status_ok)
       
  1337 		{
       
  1338 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1339 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1340 		}
       
  1341 
       
  1342 
       
  1343 		status = md5.hash_update(
       
  1344 			data+(ind*block_size),
       
  1345 			block_size);
       
  1346 		if (status != eap_status_ok)
       
  1347 		{
       
  1348 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1349 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1350 		}
       
  1351 
       
  1352 	} // for()
       
  1353 
       
  1354 	
       
  1355 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1356 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  1357 }
       
  1358 
       
  1359 //--------------------------------------------------
       
  1360 
       
  1361 //
       
  1362 EAP_FUNC_EXPORT eap_status_e eap_radius_c::add_one_ms_mppe_key_attribute(
       
  1363 	const eap_variable_data_c * const shared_secret,
       
  1364 	const eap_variable_data_c * const request_authenticator,
       
  1365 	eap_radius_header_base_c * const radius_header,
       
  1366 	u32_t * const radius_attribute_offset,
       
  1367 	const u8_t * const key,
       
  1368 	const u32_t key_length,
       
  1369 	const eap_diameter_avp_code_c mppe_key_type,
       
  1370 	crypto_hmac_c * const hmac_message_auth,
       
  1371 	crypto_md5_c * const md5_response_auth)
       
  1372 {
       
  1373 	const u32_t vendor_specific_length
       
  1374 		= eap_radius_attribute_header_c::get_header_length()
       
  1375 		+ EAP_RADIUS_VENDOR_ID_LENGTH;
       
  1376 
       
  1377 	const u32_t mppe_key_length
       
  1378 		= eap_radius_attribute_header_c::get_header_length()
       
  1379 		+ EAP_RADIUS_MS_MPPE_KEY_DATA_LENGTH;
       
  1380 
       
  1381 	const u32_t attribute_length
       
  1382 		= vendor_specific_length
       
  1383 		+ mppe_key_length;
       
  1384 
       
  1385 	eap_radius_attribute_header_c vendor_specific(
       
  1386 		m_am_tools,
       
  1387 		radius_header->get_data_offset(
       
  1388 			*radius_attribute_offset,
       
  1389 			attribute_length),
       
  1390 		attribute_length);
       
  1391 	if (vendor_specific.get_is_valid() == false)
       
  1392 	{
       
  1393 		EAP_TRACE_ERROR(
       
  1394 			m_am_tools,
       
  1395 			TRACE_FLAGS_DEFAULT,
       
  1396 			(EAPL("packet buffer corrupted.\n")));
       
  1397 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1398 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1399 	}
       
  1400 
       
  1401 	vendor_specific.reset_header(
       
  1402 		static_cast<u16_t>(attribute_length
       
  1403 			-eap_radius_attribute_header_c::get_header_length()));
       
  1404 
       
  1405 	vendor_specific.set_current_payload(eap_diameter_avp_code_vendor_specific);
       
  1406 
       
  1407 	u8_t * const vendor_id = vendor_specific.get_data_offset(0ul, sizeof(u32_t));
       
  1408 	if (vendor_id == 0)
       
  1409 	{
       
  1410 		EAP_TRACE_ERROR(
       
  1411 			m_am_tools,
       
  1412 			TRACE_FLAGS_DEFAULT,
       
  1413 			(EAPL("packet buffer corrupted.\n")));
       
  1414 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1415 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1416 	}
       
  1417 
       
  1418 	u32_t vendor_id_data_offset = 0ul;
       
  1419 
       
  1420 	eap_write_u32_t_network_order(
       
  1421 		vendor_id,
       
  1422 		sizeof(u32_t),
       
  1423 		eap_diameter_vendor_id_of_microsoft);
       
  1424 
       
  1425 	vendor_id_data_offset += sizeof(u32_t);
       
  1426 
       
  1427 	*radius_attribute_offset += vendor_specific_length;
       
  1428 
       
  1429 
       
  1430 	eap_radius_attribute_header_c mppe_key(
       
  1431 		m_am_tools,
       
  1432 		vendor_specific.get_data_offset(
       
  1433 			vendor_id_data_offset,
       
  1434 			mppe_key_length),
       
  1435 		mppe_key_length);
       
  1436 	if (mppe_key.get_is_valid() == false)
       
  1437 	{
       
  1438 		EAP_TRACE_ERROR(
       
  1439 			m_am_tools,
       
  1440 			TRACE_FLAGS_DEFAULT,
       
  1441 			(EAPL("packet buffer corrupted.\n")));
       
  1442 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1443 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1444 	}
       
  1445 
       
  1446 	mppe_key.reset_header(
       
  1447 		static_cast<u16_t>(mppe_key_length
       
  1448 			-eap_radius_attribute_header_c::get_header_length()));
       
  1449 	mppe_key.set_current_payload(mppe_key_type);
       
  1450 
       
  1451 	u8_t * const key_data = mppe_key.get_data_offset(0ul, EAP_RADIUS_MS_MPPE_KEY_DATA_LENGTH);
       
  1452 	if (key_data == 0)
       
  1453 	{
       
  1454 		EAP_TRACE_ERROR(
       
  1455 			m_am_tools,
       
  1456 			TRACE_FLAGS_DEFAULT,
       
  1457 			(EAPL("packet buffer corrupted.\n")));
       
  1458 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1459 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1460 	}
       
  1461 
       
  1462 	u32_t key_offset = 0ul;
       
  1463 
       
  1464 	u16_t salt_field = 0x8000 | m_salt++;
       
  1465 
       
  1466 	eap_write_u16_t_network_order(
       
  1467 		key_data+key_offset,
       
  1468 		sizeof(u16_t),
       
  1469 		salt_field);
       
  1470 	key_offset += sizeof(u16_t);
       
  1471 
       
  1472 	u8_t * const encrypted_data = key_data+key_offset;
       
  1473 	*(key_data+key_offset) = static_cast<u8_t>(key_length);
       
  1474 	key_offset += sizeof(u8_t);
       
  1475 
       
  1476 	m_am_tools->memmove(key_data+key_offset, key, key_length);
       
  1477 	key_offset += key_length;
       
  1478 
       
  1479 	u32_t encrypted_data_length = EAP_RADIUS_MS_MPPE_KEY_DATA_LENGTH-(sizeof(u16_t));
       
  1480 
       
  1481 	m_am_tools->memset(key_data+key_offset, 0, EAP_RADIUS_MS_MPPE_KEY_DATA_LENGTH-key_length);
       
  1482 
       
  1483 	EAP_TRACE_DATA_DEBUG(
       
  1484 		m_am_tools,
       
  1485 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  1486 		(EAPL("Plain text MPPE key"),
       
  1487 		 vendor_specific.get_header_buffer(vendor_specific.get_header_buffer_length()),
       
  1488 		 vendor_specific.get_header_buffer_length()));
       
  1489 
       
  1490 	eap_status_e status = encrypt_ms_mppe_key_attribute(
       
  1491 		shared_secret,
       
  1492 		request_authenticator,
       
  1493 		key_data, //salt
       
  1494 		sizeof(u16_t), // salt_length,
       
  1495 		encrypted_data,
       
  1496 		encrypted_data_length);
       
  1497 
       
  1498 	*radius_attribute_offset += mppe_key_length;
       
  1499 
       
  1500 	status = hmac_message_auth->hmac_update(
       
  1501 		vendor_specific.get_header_buffer(
       
  1502 			vendor_specific.get_header_buffer_length()),
       
  1503 		vendor_specific.get_header_buffer_length());
       
  1504 	if (status != eap_status_ok)
       
  1505 	{
       
  1506 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1507 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1508 	}
       
  1509 
       
  1510 	status = md5_response_auth->hash_update(
       
  1511 		vendor_specific.get_header_buffer(
       
  1512 			vendor_specific.get_header_buffer_length()),
       
  1513 		vendor_specific.get_header_buffer_length());
       
  1514 	if (status != eap_status_ok)
       
  1515 	{
       
  1516 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1517 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1518 	}
       
  1519 
       
  1520 	EAP_TRACE_DATA_DEBUG(
       
  1521 		m_am_tools,
       
  1522 		TRACE_FLAGS_DEFAULT|TRACE_TEST_VECTORS,
       
  1523 		(EAPL("Encrypted MPPE key"),
       
  1524 		 vendor_specific.get_header_buffer(vendor_specific.get_header_buffer_length()),
       
  1525 		 vendor_specific.get_header_buffer_length()));
       
  1526 
       
  1527 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1528 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1529 }
       
  1530 
       
  1531 //--------------------------------------------------
       
  1532 
       
  1533 //
       
  1534 EAP_FUNC_EXPORT eap_status_e eap_radius_c::add_ms_mppe_key_attributes(
       
  1535 	const eap_variable_data_c * const shared_secret,
       
  1536 	const eap_variable_data_c * const master_session_key,
       
  1537 	const eap_variable_data_c * const request_authenticator,
       
  1538 	eap_radius_header_base_c * const radius_header,
       
  1539 	u32_t * const radius_attribute_offset,
       
  1540 	crypto_hmac_c * const hmac_message_auth,
       
  1541 	crypto_md5_c * const md5_response_auth)
       
  1542 {
       
  1543 	eap_status_e status = add_one_ms_mppe_key_attribute(
       
  1544 		shared_secret,
       
  1545 		request_authenticator,
       
  1546 		radius_header,
       
  1547 		radius_attribute_offset,
       
  1548 		master_session_key->get_data(EAP_RADIUS_MS_MPPE_KEY_LENGTH),
       
  1549 		EAP_RADIUS_MS_MPPE_KEY_LENGTH,
       
  1550 		eap_diameter_vendor_code_of_microsoft_ms_mppe_recv_key.get_code(),
       
  1551 		hmac_message_auth,
       
  1552 		md5_response_auth);
       
  1553 	if (status != eap_status_ok)
       
  1554 	{
       
  1555 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1556 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1557 	}
       
  1558 
       
  1559 	status = add_one_ms_mppe_key_attribute(
       
  1560 		shared_secret,
       
  1561 		request_authenticator,
       
  1562 		radius_header,
       
  1563 		radius_attribute_offset,
       
  1564 		master_session_key->get_data_offset(
       
  1565 			EAP_RADIUS_MS_MPPE_KEY_LENGTH,
       
  1566 			EAP_RADIUS_MS_MPPE_KEY_LENGTH),
       
  1567 		EAP_RADIUS_MS_MPPE_KEY_LENGTH,
       
  1568 		eap_diameter_vendor_code_of_microsoft_ms_mppe_send_key.get_code(),
       
  1569 		hmac_message_auth,
       
  1570 		md5_response_auth);
       
  1571 
       
  1572 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1573 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1574 }
       
  1575 
       
  1576 //--------------------------------------------------
       
  1577 
       
  1578 //
       
  1579 EAP_FUNC_EXPORT eap_status_e eap_radius_c::packet_send(
       
  1580 	const eap_am_network_id_c * const network_id,
       
  1581 	eap_buf_chain_wr_c * const sent_packet,
       
  1582 	const u32_t header_offset,
       
  1583 	const u32_t data_length,
       
  1584 	const u32_t buffer_length,
       
  1585 	eap_radius_session_c * const session)
       
  1586 {
       
  1587 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1588 	EAP_TRACE_DEBUG(
       
  1589 		m_am_tools, 
       
  1590 		TRACE_FLAGS_DEFAULT, 
       
  1591 		(EAPL("eap_radius_c::packet_send().\n")));
       
  1592 
       
  1593 	eap_header_rd_c eap(
       
  1594 		m_am_tools,
       
  1595 		sent_packet->get_data_offset(
       
  1596 			header_offset, data_length),
       
  1597 		data_length);
       
  1598 	if (eap.get_is_valid() == false)
       
  1599 	{
       
  1600 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1601 		return EAP_STATUS_RETURN(m_am_tools, eap_status_process_illegal_packet_error);
       
  1602 	}
       
  1603 
       
  1604 	trace_tunneled_packet(EAPL("<- TUNNELED packet server"), &eap);
       
  1605 
       
  1606 	crypto_md5_c md5_message_auth(
       
  1607 		m_am_tools);
       
  1608 
       
  1609 	crypto_hmac_c hmac_message_auth(
       
  1610 		m_am_tools,
       
  1611 		&md5_message_auth,
       
  1612 		false);
       
  1613 	if (hmac_message_auth.get_is_valid() == false)
       
  1614 	{
       
  1615 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1616 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1617 	}
       
  1618 
       
  1619 	eap_status_e status = hmac_message_auth.hmac_set_key(session->get_shared_secret());
       
  1620 	if (status != eap_status_ok)
       
  1621 	{
       
  1622 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1623 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1624 	}
       
  1625 
       
  1626 	crypto_md5_c md5_response_auth(
       
  1627 		m_am_tools);
       
  1628 
       
  1629 	status = md5_response_auth.hash_init();
       
  1630 	if (status != eap_status_ok)
       
  1631 	{
       
  1632 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1633 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  1634 	}
       
  1635 
       
  1636 
       
  1637 	u32_t fragment_count
       
  1638 		= (1ul
       
  1639 		   + eap.get_length()
       
  1640 		   / eap_radius_attribute_header_c::get_max_attribute_data_length());
       
  1641 
       
  1642 	u32_t eap_payload_length
       
  1643 		= eap.get_length()
       
  1644 		+ eap_radius_attribute_header_c::get_header_length() * fragment_count;
       
  1645 
       
  1646 	u32_t packet_data_length
       
  1647 		= eap_radius_header_base_c::get_header_length()
       
  1648 		+ eap_payload_length
       
  1649 		+ eap_radius_attribute_header_c::get_header_length()
       
  1650 		+ hmac_message_auth.get_digest_length();
       
  1651 
       
  1652 	if (session->get_state() == eap_state_authentication_finished_successfully)
       
  1653 	{
       
  1654 		// Successfully finished authentication.
       
  1655 		// The keys must be added.
       
  1656 		packet_data_length
       
  1657 			+= 2ul * (2ul * eap_radius_attribute_header_c::get_header_length()
       
  1658 					  + EAP_RADIUS_VENDOR_ID_LENGTH
       
  1659 					  + EAP_RADIUS_MS_MPPE_KEY_DATA_LENGTH)
       
  1660 			+ eap_radius_attribute_header_c::get_header_length()
       
  1661 			+ session->get_user_name()->get_data_length();
       
  1662 	}
       
  1663 
       
  1664 	eap_buf_chain_wr_c challenge(
       
  1665 		eap_write_buffer, 
       
  1666 		m_am_tools, 
       
  1667 		packet_data_length);
       
  1668 
       
  1669 	if (challenge.get_is_valid() == false)
       
  1670 	{
       
  1671 		EAP_TRACE_ERROR(
       
  1672 			m_am_tools,
       
  1673 			TRACE_FLAGS_DEFAULT,
       
  1674 			(EAPL("packet buffer corrupted.\n")));
       
  1675 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1676 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1677 	}
       
  1678 
       
  1679 
       
  1680 	eap_radius_header_base_c radius_header(
       
  1681 		m_am_tools,
       
  1682 		reinterpret_cast<eap_radius_header_base_c *>(
       
  1683 			challenge.get_data_offset(0ul, packet_data_length)),
       
  1684 		packet_data_length);
       
  1685 	if (radius_header.get_is_valid() == false)
       
  1686 	{
       
  1687 		EAP_TRACE_ERROR(
       
  1688 			m_am_tools,
       
  1689 			TRACE_FLAGS_DEFAULT,
       
  1690 			(EAPL("packet buffer corrupted.\n")));
       
  1691 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1692 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1693 	}
       
  1694 
       
  1695 	radius_header.reset_header(static_cast<u16_t>(packet_data_length));
       
  1696 
       
  1697 	radius_header.set_identifier(session->get_identifier());
       
  1698 
       
  1699 	if (session->get_state() == eap_state_authentication_finished_successfully
       
  1700 		/* && eap.get_code() == eap_code_success */)
       
  1701 	{
       
  1702 		// Successfully finished authentication.
       
  1703 		radius_header.set_code(eap_radius_code_access_accept);
       
  1704 	}
       
  1705 	else if (session->get_state() == eap_state_authentication_terminated_unsuccessfully
       
  1706 		&& eap.get_code() == eap_code_failure)
       
  1707 	{
       
  1708 		// Failed authentication.
       
  1709 		radius_header.set_code(eap_radius_code_access_reject);
       
  1710 	}
       
  1711 	else if (eap.get_code() == eap_code_request
       
  1712 			 || eap.get_code() == eap_code_response
       
  1713 			 || eap.get_code() == eap_code_success)
       
  1714 	{
       
  1715 		radius_header.set_code(eap_radius_code_access_challenge);
       
  1716 	}
       
  1717 	else
       
  1718 	{
       
  1719 		// Illegal combination.
       
  1720 		EAP_TRACE_ERROR(
       
  1721 			m_am_tools,
       
  1722 			TRACE_FLAGS_DEFAULT,
       
  1723 			(EAPL("Illegal combination eap.code %d, session.state %d.\n"),
       
  1724 			 eap.get_code(),
       
  1725 			 session->get_state()));
       
  1726 		EAP_ASSERT_ANYWAY_TOOLS(m_am_tools);
       
  1727 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1728 		return EAP_STATUS_RETURN(m_am_tools, eap_status_illegal_eap_code);
       
  1729 	}
       
  1730 
       
  1731 
       
  1732 	{
       
  1733 		// Type, Identifier and Length fields.
       
  1734 		const u32_t hmac_fields_length = 4ul;
       
  1735 
       
  1736 		{
       
  1737 			status = hmac_message_auth.hmac_update(
       
  1738 				radius_header.get_header_buffer(hmac_fields_length),
       
  1739 				hmac_fields_length);
       
  1740 			if (status != eap_status_ok)
       
  1741 			{
       
  1742 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1743 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1744 			}
       
  1745 			
       
  1746 			status = hmac_message_auth.hmac_update(
       
  1747 				session->get_request_authenticator()->get_data(),
       
  1748 				session->get_request_authenticator()->get_data_length());
       
  1749 			if (status != eap_status_ok)
       
  1750 			{
       
  1751 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1752 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1753 			}
       
  1754 
       
  1755 		}
       
  1756 
       
  1757 		{
       
  1758 			status = md5_response_auth.hash_update(
       
  1759 				radius_header.get_header_buffer(hmac_fields_length),
       
  1760 				hmac_fields_length);
       
  1761 			if (status != eap_status_ok)
       
  1762 			{
       
  1763 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1764 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1765 			}
       
  1766 			
       
  1767 			status = md5_response_auth.hash_update(
       
  1768 				session->get_request_authenticator()->get_data(),
       
  1769 				session->get_request_authenticator()->get_data_length());
       
  1770 			if (status != eap_status_ok)
       
  1771 			{
       
  1772 				EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1773 				return EAP_STATUS_RETURN(m_am_tools, status);
       
  1774 			}
       
  1775 		}
       
  1776 	}
       
  1777 
       
  1778 	u32_t radius_attribute_offset(0ul);
       
  1779 
       
  1780 	if (session->get_state() == eap_state_authentication_finished_successfully)
       
  1781 	{
       
  1782 		// Successfully finished authentication.
       
  1783 		// The MPPE keys and User-Name must be added.
       
  1784 		status = add_ms_mppe_key_attributes(
       
  1785 			session->get_shared_secret(),
       
  1786 			session->get_master_session_key(),
       
  1787 			session->get_request_authenticator(),
       
  1788 			&radius_header,
       
  1789 			&radius_attribute_offset,
       
  1790 			&hmac_message_auth,
       
  1791 			&md5_response_auth);
       
  1792 		if (status != eap_status_ok)
       
  1793 		{
       
  1794 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1795 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1796 		}
       
  1797 
       
  1798 		status = add_user_name_attribute(
       
  1799 			session->get_user_name(),
       
  1800 			&radius_header,
       
  1801 			&radius_attribute_offset,
       
  1802 			&hmac_message_auth,
       
  1803 			&md5_response_auth);
       
  1804 		if (status != eap_status_ok)
       
  1805 		{
       
  1806 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1807 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1808 		}
       
  1809 	}
       
  1810 
       
  1811 	u32_t remaining_eap_data_length = eap.get_length();
       
  1812 	u8_t * eap_data = eap.get_header_buffer(remaining_eap_data_length);
       
  1813 	if (eap_data == 0)
       
  1814 	{
       
  1815 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  1816 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1817 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1818 	}
       
  1819 
       
  1820 	u32_t max_data_length
       
  1821 		= eap_radius_attribute_header_c::get_max_attribute_data_length()
       
  1822 		- eap_radius_attribute_header_c::get_header_length();
       
  1823 
       
  1824 	for (u32_t ind = 0ul; ind < fragment_count; ind++)
       
  1825 	{
       
  1826 		u32_t fragment_length = remaining_eap_data_length;
       
  1827 		if (fragment_length > max_data_length)
       
  1828 		{
       
  1829 			fragment_length = max_data_length;
       
  1830 		}
       
  1831 
       
  1832 		eap_radius_attribute_header_c fragment(
       
  1833 			m_am_tools,
       
  1834 			radius_header.get_data_offset(
       
  1835 				radius_attribute_offset
       
  1836 				+ ind * eap_radius_attribute_header_c::get_max_attribute_data_length(),
       
  1837 				fragment_length),
       
  1838 			eap_radius_attribute_header_c::get_header_length()+fragment_length);
       
  1839 		if (fragment.get_is_valid() == false)
       
  1840 		{
       
  1841 			EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  1842 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1843 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1844 		}
       
  1845 
       
  1846 		fragment.reset_header(static_cast<u16_t>(fragment_length));
       
  1847 		fragment.set_current_payload(eap_diameter_avp_code_eap_message);
       
  1848 
       
  1849 		u8_t * const data = fragment.get_data_offset(0ul, fragment_length);
       
  1850 		if (data == 0)
       
  1851 		{
       
  1852 			EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  1853 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1854 			return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1855 		}
       
  1856 
       
  1857 		m_am_tools->memmove(data, eap_data, fragment_length);
       
  1858 
       
  1859 		status = hmac_message_auth.hmac_update(
       
  1860 			fragment.get_header_buffer(fragment.get_length()),
       
  1861 			fragment.get_length());
       
  1862 		if (status != eap_status_ok)
       
  1863 		{
       
  1864 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1865 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1866 		}
       
  1867 
       
  1868 		status = md5_response_auth.hash_update(
       
  1869 			fragment.get_header_buffer(fragment.get_length()),
       
  1870 			fragment.get_length());
       
  1871 		if (status != eap_status_ok)
       
  1872 		{
       
  1873 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1874 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1875 		}
       
  1876 
       
  1877 		remaining_eap_data_length -= fragment_length;
       
  1878 		eap_data += fragment_length;
       
  1879 
       
  1880 	} // for()
       
  1881 
       
  1882 
       
  1883 	radius_attribute_offset += eap_payload_length;
       
  1884 
       
  1885 	u32_t authenticator_length
       
  1886 		= eap_radius_attribute_header_c::get_header_length()
       
  1887 		+ hmac_message_auth.get_digest_length();
       
  1888 
       
  1889 	eap_radius_attribute_header_c authenticator(
       
  1890 		m_am_tools,
       
  1891 		radius_header.get_data_offset(
       
  1892 			radius_attribute_offset,
       
  1893 			authenticator_length),
       
  1894 		authenticator_length);
       
  1895 	if (authenticator.get_is_valid() == false)
       
  1896 	{
       
  1897 		EAP_TRACE_ERROR(m_am_tools, TRACE_FLAGS_DEFAULT, (EAPL("packet buffer corrupted.\n")));
       
  1898 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1899 		return EAP_STATUS_RETURN(m_am_tools, eap_status_allocation_error);
       
  1900 	}
       
  1901 
       
  1902 	authenticator.reset_header(static_cast<u16_t>(hmac_message_auth.get_digest_length()));
       
  1903 	authenticator.set_current_payload(eap_diameter_avp_code_message_authenticator);
       
  1904 
       
  1905 	{
       
  1906 		u8_t * const signature
       
  1907 			= authenticator.get_data_offset(
       
  1908 				0ul,
       
  1909 				authenticator.get_data_length());
       
  1910 
       
  1911 		m_am_tools->memset(signature, 0, authenticator.get_data_length());
       
  1912 
       
  1913 		status = hmac_message_auth.hmac_update(
       
  1914 			authenticator.get_header_buffer(authenticator.get_length()),
       
  1915 			authenticator.get_length());
       
  1916 		if (status != eap_status_ok)
       
  1917 		{
       
  1918 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1919 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1920 		}
       
  1921 
       
  1922 		status = hmac_message_auth.hmac_final(
       
  1923 			signature,
       
  1924 			0);
       
  1925 		if (status != eap_status_ok)
       
  1926 		{
       
  1927 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1928 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1929 		}
       
  1930 
       
  1931 		status = md5_response_auth.hash_update(
       
  1932 			authenticator.get_header_buffer(authenticator.get_length()),
       
  1933 			authenticator.get_length());
       
  1934 		if (status != eap_status_ok)
       
  1935 		{
       
  1936 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1937 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1938 		}
       
  1939 	}
       
  1940 
       
  1941 	{
       
  1942 		status = md5_response_auth.hash_update(
       
  1943 			session->get_shared_secret()->get_data(),
       
  1944 			session->get_shared_secret()->get_data_length());
       
  1945 		if (status != eap_status_ok)
       
  1946 		{
       
  1947 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1948 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1949 		}
       
  1950 				
       
  1951 		status = md5_response_auth.hash_final(
       
  1952 			radius_header.get_authenticator(),
       
  1953 			0);
       
  1954 		if (status != eap_status_ok)
       
  1955 		{
       
  1956 			EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1957 			return EAP_STATUS_RETURN(m_am_tools, status);
       
  1958 		}
       
  1959 	}
       
  1960 
       
  1961 	challenge.set_data_length(packet_data_length);
       
  1962 
       
  1963 	EAP_RADIUS_PACKET_TRACE(
       
  1964 		EAPL("<-"),
       
  1965 		network_id,
       
  1966 		&radius_header,
       
  1967 		packet_data_length);
       
  1968 
       
  1969 	status = m_partner->packet_send(
       
  1970 		network_id, 
       
  1971 		&challenge, 
       
  1972 		header_offset, 
       
  1973 		packet_data_length,
       
  1974 		challenge.get_buffer_length()
       
  1975 		);
       
  1976 
       
  1977 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1978 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  1979 }
       
  1980 
       
  1981 //--------------------------------------------------
       
  1982 
       
  1983 EAP_FUNC_EXPORT eap_status_e eap_radius_c::read_configure(
       
  1984 	const eap_configuration_field_c * const field,
       
  1985 	eap_variable_data_c * const data)
       
  1986 {
       
  1987 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  1988 
       
  1989 	if (cf_str_EAP_CORE_send_eap_success_after_notification.get_field()->compare(
       
  1990 			m_am_tools,
       
  1991 			field) == true)
       
  1992 	{
       
  1993 		// In Radius server EAP-Success must be send after state notification.
       
  1994 		u32_t send_eap_success_after_notification(true);
       
  1995 		
       
  1996 		const eap_status_e status = data->set_copy_of_buffer(
       
  1997 			&send_eap_success_after_notification,
       
  1998 			sizeof(send_eap_success_after_notification));
       
  1999 
       
  2000 		EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2001 		return EAP_STATUS_RETURN(m_am_tools, status);
       
  2002 	}
       
  2003 
       
  2004 	const eap_status_e status = m_partner->read_configure(field, data);
       
  2005 
       
  2006 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2007 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2008 }
       
  2009 
       
  2010 //--------------------------------------------------
       
  2011 
       
  2012 EAP_FUNC_EXPORT eap_status_e eap_radius_c::write_configure(
       
  2013 	const eap_configuration_field_c * const field,
       
  2014 	eap_variable_data_c * const data)
       
  2015 {
       
  2016 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2017 
       
  2018 	const eap_status_e status = m_partner->write_configure(field, data);
       
  2019 
       
  2020 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2021 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2022 }
       
  2023 
       
  2024 //--------------------------------------------------
       
  2025 
       
  2026 // This is commented in eap_base_type_c::configure().
       
  2027 EAP_FUNC_EXPORT eap_status_e eap_radius_c::configure()
       
  2028 {
       
  2029 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2030 
       
  2031 	EAP_TRACE_DEBUG(
       
  2032 		m_am_tools, 
       
  2033 		TRACE_FLAGS_DEFAULT, 
       
  2034 		(EAPL("eap_radius_c::configure(): this = 0x%08x => 0x%08x\n"),
       
  2035 		this,
       
  2036 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
  2037 
       
  2038 	m_radius_header_offset = m_partner->get_header_offset(
       
  2039 		&m_MTU, &m_trailer_length);
       
  2040 
       
  2041 	if (m_radius_header_offset+m_MTU+m_trailer_length
       
  2042 		> EAP_TYPE_RADIUS_LOCAL_PACKET_BUFFER_LENGTH)
       
  2043 	{
       
  2044 		EAP_ASSERT_ALWAYS(EAP_TYPE_RADIUS_LOCAL_PACKET_BUFFER_LENGTH
       
  2045 						  >= (m_radius_header_offset+m_trailer_length));
       
  2046 
       
  2047 		m_MTU = EAP_TYPE_RADIUS_LOCAL_PACKET_BUFFER_LENGTH
       
  2048 			- (m_radius_header_offset+m_trailer_length);
       
  2049 	}
       
  2050 
       
  2051 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2052 	return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2053 }
       
  2054 
       
  2055 //--------------------------------------------------
       
  2056 
       
  2057 //
       
  2058 EAP_FUNC_EXPORT eap_status_e eap_radius_c::shutdown_operation(
       
  2059 	eap_radius_session_c * const session,
       
  2060 	abs_eap_am_tools_c * const m_am_tools)
       
  2061 {
       
  2062 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2063 
       
  2064 	eap_status_e status = session->shutdown();
       
  2065 
       
  2066 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2067 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2068 }
       
  2069 
       
  2070 //--------------------------------------------------
       
  2071 
       
  2072 // This is commented in eap_base_type_c::shutdown().
       
  2073 EAP_FUNC_EXPORT eap_status_e eap_radius_c::shutdown()
       
  2074 {
       
  2075 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2076 
       
  2077 	EAP_TRACE_DEBUG(
       
  2078 		m_am_tools, 
       
  2079 		TRACE_FLAGS_DEFAULT, 
       
  2080 		(EAPL("eap_radius_c::shutdown(): this = 0x%08x => 0x%08x\n"),
       
  2081 		this,
       
  2082 		dynamic_cast<abs_eap_base_timer_c *>(this)));
       
  2083 
       
  2084 	if (m_shutdown_was_called == true)
       
  2085 	{
       
  2086 		// Shutdown function was called already.
       
  2087 		return EAP_STATUS_RETURN(m_am_tools, eap_status_ok);
       
  2088 	}
       
  2089 	m_shutdown_was_called = true;
       
  2090 
       
  2091 	eap_status_e status = m_session_map.for_each(shutdown_operation, true);
       
  2092 
       
  2093 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2094 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2095 }
       
  2096 
       
  2097 //--------------------------------------------------
       
  2098 
       
  2099 // This function is to allow reuse of this object.
       
  2100 // The whole object state must be reset.
       
  2101 EAP_FUNC_EXPORT eap_status_e eap_radius_c::reset()
       
  2102 {
       
  2103 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2104 
       
  2105 	EAP_TRACE_DEBUG(
       
  2106 		m_am_tools,
       
  2107 		TRACE_FLAGS_DEFAULT,
       
  2108 		(EAPL("RADIUS: %s: function: eap_radius_c::reset(): this = 0x%08x\n"),
       
  2109 		(m_is_client == true ? "client": "server"),
       
  2110 		this));
       
  2111 
       
  2112 	eap_status_e status = eap_status_not_supported;
       
  2113 
       
  2114 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2115 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2116 }
       
  2117 
       
  2118 //--------------------------------------------------
       
  2119 
       
  2120 //
       
  2121 EAP_FUNC_EXPORT eap_status_e eap_radius_c::load_module(
       
  2122 	const eap_type_value_e type,
       
  2123 	const eap_type_value_e tunneling_type,
       
  2124 	abs_eap_base_type_c * const partner,
       
  2125 	eap_base_type_c ** const eap_type,
       
  2126 	const bool is_client_when_true,
       
  2127 	const eap_am_network_id_c * const receive_network_id)
       
  2128 {
       
  2129 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2130 
       
  2131 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2132 
       
  2133 	eap_status_e status = m_partner->load_module(
       
  2134 		type,
       
  2135 		tunneling_type,
       
  2136 		partner,
       
  2137 		eap_type,
       
  2138 		is_client_when_true,
       
  2139 		receive_network_id);
       
  2140 
       
  2141 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2142 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2143 }
       
  2144 
       
  2145 //--------------------------------------------------
       
  2146 
       
  2147 //
       
  2148 EAP_FUNC_EXPORT eap_status_e eap_radius_c::unload_module(const eap_type_value_e type)
       
  2149 {
       
  2150 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2151 
       
  2152 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2153 
       
  2154 	const eap_status_e status = m_partner->unload_module(type);
       
  2155 
       
  2156 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2157 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2158 }
       
  2159 
       
  2160 //--------------------------------------------------
       
  2161 
       
  2162 //
       
  2163 EAP_FUNC_EXPORT eap_status_e eap_radius_c::restart_authentication(
       
  2164 	const eap_am_network_id_c * const send_network_id,
       
  2165 	const bool is_client_when_true,
       
  2166 		const bool force_clean_restart,
       
  2167 		const bool from_timer)
       
  2168 {
       
  2169 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2170 
       
  2171 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2172 
       
  2173 	eap_status_e status = eap_status_process_general_error;
       
  2174 
       
  2175 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2176 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2177 }
       
  2178 
       
  2179 //--------------------------------------------------
       
  2180 
       
  2181 //
       
  2182 eap_status_e eap_radius_c::asynchronous_init_remove_eap_session(
       
  2183 	const eap_am_network_id_c * const send_network_id)
       
  2184 {
       
  2185 	EAP_TRACE_DEBUG(
       
  2186 		m_am_tools, 
       
  2187 		TRACE_FLAGS_DEFAULT, 
       
  2188 		(EAPL("eap_session_core_c::asynchronous_init_remove_eap_session(): %s.\n"),
       
  2189 		 (m_is_client == true) ? "client": "server"));
       
  2190 
       
  2191 	eap_status_e status = eap_status_process_general_error;
       
  2192 
       
  2193 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2194 }
       
  2195 
       
  2196 //--------------------------------------------------
       
  2197 
       
  2198 EAP_FUNC_EXPORT eap_status_e eap_radius_c::check_is_valid_eap_type(
       
  2199 	const eap_type_value_e eap_type)
       
  2200 {
       
  2201 	eap_status_e status = m_partner->check_is_valid_eap_type(eap_type);
       
  2202 
       
  2203 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2204 }
       
  2205 
       
  2206 //--------------------------------------------------
       
  2207 
       
  2208 EAP_FUNC_EXPORT eap_status_e eap_radius_c::get_eap_type_list(
       
  2209 	eap_array_c<eap_type_value_e> * const eap_type_list)
       
  2210 {
       
  2211 	eap_status_e status = m_partner->get_eap_type_list(eap_type_list);
       
  2212 
       
  2213 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2214 }
       
  2215 
       
  2216 //--------------------------------------------------
       
  2217 
       
  2218 EAP_FUNC_EXPORT eap_status_e eap_radius_c::add_rogue_ap(
       
  2219 	eap_array_c<eap_rogue_ap_entry_c> & rogue_ap_list)
       
  2220 {
       
  2221 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2222 
       
  2223 	const eap_status_e status = m_partner->add_rogue_ap(rogue_ap_list);
       
  2224 
       
  2225 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2226 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2227 }
       
  2228 
       
  2229 //--------------------------------------------------
       
  2230 
       
  2231 //
       
  2232 EAP_FUNC_EXPORT eap_status_e eap_radius_c::set_session_timeout(
       
  2233 	const u32_t /* session_timeout_ms */)
       
  2234 {
       
  2235 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2236 
       
  2237 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2238 
       
  2239 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2240 	return EAP_STATUS_RETURN(m_am_tools, eap_status_not_supported);
       
  2241 }
       
  2242 
       
  2243 //--------------------------------------------------
       
  2244 
       
  2245 //
       
  2246 EAP_FUNC_EXPORT eap_status_e eap_radius_c::set_timer(
       
  2247 	abs_eap_base_timer_c * const p_initializer, 
       
  2248 	const u32_t p_id, 
       
  2249 	void * const p_data,
       
  2250 	const u32_t p_time_ms)
       
  2251 {
       
  2252 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2253 
       
  2254 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2255 
       
  2256 	const eap_status_e status = m_partner->set_timer(
       
  2257 		p_initializer, 
       
  2258 		p_id, 
       
  2259 		p_data,
       
  2260 		p_time_ms);
       
  2261 
       
  2262 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2263 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2264 }
       
  2265 
       
  2266 //--------------------------------------------------
       
  2267 
       
  2268 //
       
  2269 EAP_FUNC_EXPORT eap_status_e eap_radius_c::cancel_timer(
       
  2270 	abs_eap_base_timer_c * const p_initializer, 
       
  2271 	const u32_t p_id)
       
  2272 {
       
  2273 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2274 
       
  2275 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2276 
       
  2277 	const eap_status_e status = m_partner->cancel_timer(
       
  2278 		p_initializer, 
       
  2279 		p_id);
       
  2280 
       
  2281 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2282 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2283 }
       
  2284 
       
  2285 //--------------------------------------------------
       
  2286 
       
  2287 //
       
  2288 EAP_FUNC_EXPORT eap_status_e eap_radius_c::cancel_all_timers()
       
  2289 {
       
  2290 	EAP_TRACE_BEGIN(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2291 
       
  2292 	EAP_ASSERT(m_am_tools->get_global_mutex()->get_is_reserved() == true);
       
  2293 
       
  2294 	const eap_status_e status = m_partner->cancel_all_timers();
       
  2295 
       
  2296 	EAP_TRACE_END(m_am_tools, TRACE_FLAGS_DEFAULT);
       
  2297 	return EAP_STATUS_RETURN(m_am_tools, status);
       
  2298 }
       
  2299 
       
  2300 //--------------------------------------------------
       
  2301 
       
  2302 
       
  2303 
       
  2304 // End.