--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/core_eapol_handler.cpp Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,1082 @@
+/*
+* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: handler to EAPOL callbacks.
+*
+*/
+
+
+#include "core_eapol_handler.h"
+#include "core_server.h"
+#include "core_tools.h"
+#include "core_tools_parser.h"
+#include "abs_core_protected_setup_handler.h"
+#include "am_debug.h"
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_eapol_handler_c::core_eapol_handler_c(
+ core_server_c* server,
+ abs_core_driverif_c* drivers,
+ abs_core_server_callback_c* adaptation ) :
+ abs_wlan_eapol_callback_interface_c(),
+ server_m( server ),
+ drivers_m( drivers ),
+ adaptation_m( adaptation ),
+ handler_m( NULL ),
+ protected_setup_handler_m( NULL )
+ {
+ DEBUG( "core_eapol_handler_c::core_eapol_handler_c()" );
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_eapol_handler_c::~core_eapol_handler_c()
+ {
+ DEBUG( "core_eapol_handler_c::~core_eapol_handler_c()" );
+ server_m = NULL;
+ drivers_m = NULL;
+ adaptation_m = NULL;
+ handler_m = NULL;
+ protected_setup_handler_m = NULL;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+abs_wlan_eapol_callback_interface_c* core_eapol_handler_c::eapol_handler()
+ {
+ return handler_m;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void core_eapol_handler_c::set_eapol_handler(
+ abs_wlan_eapol_callback_interface_c* handler )
+ {
+ handler_m = handler;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void core_eapol_handler_c::set_protected_setup_handler(
+ abs_core_protected_setup_handler_c* handler )
+ {
+ protected_setup_handler_m = handler;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::packet_send(
+ network_id_c * send_network_id,
+ u8_t * packet_data,
+ u32_t packet_data_length,
+ bool_t send_unencrypted )
+ {
+ DEBUG( "core_eapol_handler_c::packet_send()" );
+
+ ASSERT ( server_m != NULL );
+ if ( !server_m->get_core_settings().is_connected() )
+ {
+ DEBUG( "core_eapol_handler_c::packet_send() - not connected or attempting connection, ignoring" );
+
+ return core_error_ok;
+ }
+
+ if ( handler_m )
+ {
+ return handler_m->packet_send(
+ send_network_id,
+ packet_data,
+ packet_data_length,
+ send_unencrypted );
+ }
+
+ server_m->send_data_frame(
+ *server_m->get_connection_data()->current_ap_data(),
+ core_frame_type_ethernet,
+ static_cast<u16_t>( packet_data_length ),
+ packet_data,
+ core_access_class_voice,
+ send_network_id->destination(),
+ send_unencrypted );
+
+ return core_error_ok;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::associate(
+ wlan_eapol_if_eapol_key_authentication_mode_e authentication_mode )
+ {
+ DEBUG( "core_eapol_handler_c::associate()" );
+
+ ASSERT ( handler_m );
+ if ( handler_m )
+ {
+ return handler_m->associate(
+ authentication_mode );
+ }
+ return core_error_ok;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::disassociate(
+ network_id_c * receive_network_id,
+ const bool_t self_disassociation )
+ {
+ DEBUG( "core_eapol_handler_c::disassociate()" );
+
+ ASSERT ( handler_m );
+ if ( handler_m )
+ {
+ return handler_m->disassociate(
+ receive_network_id,
+ self_disassociation );
+ }
+ return core_error_ok;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::packet_data_session_key(
+ network_id_c * send_network_id,
+ session_key_c * key )
+ {
+ DEBUG( "core_eapol_handler_c::packet_data_session_key()" );
+ ASSERT( key != NULL);
+ ASSERT( send_network_id != NULL);
+
+ if ( !handler_m )
+ {
+ ASSERT ( server_m != NULL );
+ core_cipher_key_type_e type =
+ core_tools_c::cipher_key_type(
+ key->eapol_key_type,
+ server_m->get_connection_data()->current_ap_data()->best_pairwise_cipher(),
+ server_m->get_connection_data()->current_ap_data()->best_group_cipher() );
+
+ core_mac_address_s mac( BROADCAST_MAC_ADDR );
+ if ( key->eapol_key_type == wlan_eapol_if_eapol_key_type_unicast )
+ {
+ mac = send_network_id->destination();
+ }
+
+ ASSERT ( drivers_m != NULL );
+ drivers_m->add_cipher_key(
+ type,
+ static_cast<u8_t>( key->key_index ),
+ static_cast<u16_t>( key->key_length ),
+ key->key,
+ mac,
+ true_t );
+
+ return core_error_ok;
+ }
+
+ return handler_m->packet_data_session_key(
+ send_network_id,
+ key );
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void core_eapol_handler_c::state_notification(
+ state_notification_c * state )
+ {
+ DEBUG( "core_eapol_handler_c::state_notification()" );
+
+ const u32_t eap_type_vendor_id_ietf = 0;
+ const u32_t eap_type_vendor_id_WFA = 0x00372A;
+
+ ASSERT ( server_m != NULL );
+ if ( !server_m->get_core_settings().is_connected() )
+ {
+ DEBUG( "core_eapol_handler_c::state_notification() - not connected or attempting connection, ignoring" );
+
+ return;
+ }
+
+ ASSERT ( state != NULL );
+
+ if ( state->protocol_layer == wlan_eapol_if_eap_protocol_layer_wlan_authentication ||
+ state->protocol_layer == wlan_eapol_if_eap_protocol_layer_wapi )
+ {
+ if ( state->current_state == wlan_eapol_if_eapol_wlan_authentication_state_authentication_cancelled )
+ {
+ if ( server_m->get_connection_data()->last_failed_eap_type() == EAP_TYPE_NONE )
+ {
+ // We know that vendor_type values (in ietf and WFA) are not overlapping
+ // and thus there is no need for storing vendor_id's.
+ if ( state->eap_type_vendor_id == eap_type_vendor_id_ietf
+ || state->eap_type_vendor_id == eap_type_vendor_id_WFA )
+ {
+ server_m->get_connection_data()->set_last_failed_eap_type(
+ state->eap_type_vendor_type );
+ server_m->get_connection_data()->set_last_eap_error(
+ state->authentication_error );
+ }
+ else
+ {
+ DEBUG1( "core_eapol_handler_c::state_notification() - Unknown vendor_id %i in EAP-type. Type not stored.",
+ state->eap_type_vendor_id );
+ }
+ }
+ }
+
+ handle_wlan_authentication_state(
+ state->current_state,
+ state->network_id.destination() );
+ }
+ else
+ {
+ if ( state->protocol_layer == wlan_eapol_if_eap_protocol_layer_general &&
+ state->current_state == wlan_eapol_if_eap_state_general_authentication_error )
+ {
+ DEBUG( "core_eapol_handler_c::state_notification() - EAP-specific authentication error:" );
+ }
+ else if ( state->protocol_layer == wlan_eapol_if_eap_protocol_layer_eap &&
+ state->current_state == wlan_eapol_if_eap_state_authentication_terminated_unsuccessfully )
+ {
+ DEBUG( "core_eapol_handler_c::state_notification() - EAP-layer error:" );
+ }
+
+ if ( ( state->protocol_layer == wlan_eapol_if_eap_protocol_layer_general &&
+ state->current_state == wlan_eapol_if_eap_state_general_authentication_error ) ||
+ ( state->protocol_layer == wlan_eapol_if_eap_protocol_layer_eap &&
+ state->current_state == wlan_eapol_if_eap_state_authentication_terminated_unsuccessfully ) )
+ {
+ DEBUG2( "core_eapol_handler_c::state_notification() - type: vendor_id: %u, vendor_type: %u",
+ state->eap_type_vendor_id,
+ state->eap_type_vendor_type );
+ DEBUG1( "core_eapol_handler_c::state_notification() - error: %u",
+ state->authentication_error );
+ DEBUG1( "core_eapol_handler_c::state_notification() - previous type: %u",
+ server_m->get_connection_data()->last_failed_eap_type() );
+ DEBUG1( "core_eapol_handler_c::state_notification() - previous error: %u",
+ server_m->get_connection_data()->last_eap_error() );
+
+ if ( server_m->get_connection_data()->last_failed_eap_type() == EAP_TYPE_NONE )
+ {
+ // We know that vendor_type values (in ietf and WFA) are not overlapping
+ // and thus there is no need for storing vendor_id's.
+ if ( state->eap_type_vendor_id == eap_type_vendor_id_ietf
+ || state->eap_type_vendor_id == eap_type_vendor_id_WFA )
+ {
+ server_m->get_connection_data()->set_last_failed_eap_type(
+ state->eap_type_vendor_type );
+ server_m->get_connection_data()->set_last_eap_error(
+ state->authentication_error );
+ }
+ else
+ {
+ DEBUG1( "core_eapol_handler_c::state_notification() - Unknown vendor_id %i in EAP-type. Type not stored.",
+ state->eap_type_vendor_id );
+ }
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::reassociate(
+ network_id_c * send_network_id,
+ const wlan_eapol_if_eapol_key_authentication_type_e authentication_type,
+ u8_t * PMKID,
+ u32_t PMKID_length )
+ {
+ DEBUG( "core_eapol_handler_c::reassociate()" );
+
+ ASSERT ( handler_m );
+ if ( handler_m )
+ {
+ return handler_m->reassociate(
+ send_network_id,
+ authentication_type,
+ PMKID,
+ PMKID_length );
+ }
+ return core_error_ok;
+ }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+u32_t core_eapol_handler_c::convert_core_error_to_if_status(
+ core_error_e core_error )
+ {
+ DEBUG1( "core_eapol_handler_c::convert_core_error_to_if_status( %i )", core_error );
+ switch ( core_error )
+ {
+ case core_error_ok:
+ return wlan_eapol_if_error_ok;
+ case core_error_request_pending:
+ return wlan_eapol_if_error_pending_request;
+ case core_error_no_memory:
+ return wlan_eapol_if_error_allocation_error;
+ case core_error_illegal_argument:
+ return wlan_eapol_if_error_illegal_parameter;
+ case core_error_general:
+ return wlan_eapol_if_error_process_general_error;
+ default:
+ DEBUG( "core_eapol_handler_c::convert_core_error_to_if_status - Error: No special conversion to given status" );
+ return wlan_eapol_if_error_process_general_error;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+u32_t core_eapol_handler_c::send_data(
+ const void * const data,
+ const u32_t length )
+ {
+ DEBUG2( "core_eapol_handler_c::send_data(data=0x%08X, length=%i)", data, length );
+
+ if ( !data || length == 0 )
+ {
+ DEBUG( "core_eapol_handler_c::send_data() - Parameters not valid. Ignoring." );
+
+ core_wlan_eapol_if_function_c function;
+ if ( function.generate_error( wlan_eapol_if_error_illegal_parameter, wlan_eapol_if_message_type_function_none )
+ == core_error_ok )
+ {
+ adaptation_m->process_data( function.get_data(), function.size() );
+ }
+ return wlan_eapol_if_error_illegal_parameter;
+ }
+
+ core_wlan_eapol_if_function_c function( static_cast<u8_t *>( const_cast<void *>( data ) ), length );
+
+ function.debug_print();
+
+ core_error_e error( core_error_ok );
+
+ // 1. Get function
+ // 2. Parse it's parameters
+ // 3. Call actual function
+
+ // Check error case here.
+ wlan_eapol_if_message_type_e type = function.get_type();
+ if ( type == wlan_eapol_if_message_type_error )
+ {
+ DEBUG( "core_eapol_handler_c::send_data() - Error received." );
+
+ wlan_eapol_if_error_e parsed_errorcode;
+ wlan_eapol_if_message_type_function_e parsed_function;
+
+ error = function.parse_error( &parsed_errorcode, &parsed_function );
+ if ( error != core_error_ok )
+ {
+ DEBUG1( "core_eapol_handler_c::send_data() - Could not parse error message (parsing error=%i)", error );
+ // Do not send Error message when error message parsing fails...
+ }
+ else
+ {
+ handle_error( parsed_errorcode, parsed_function );
+ }
+ return wlan_eapol_if_error_ok;
+ }
+ else if ( type != wlan_eapol_if_message_type_function )
+ {
+ DEBUG( "core_eapol_handler_c::send_data() - Type parameter is not valid. Ignoring." );
+
+ if ( function.generate_error( wlan_eapol_if_error_illegal_parameter, wlan_eapol_if_message_type_function_none )
+ == core_error_ok )
+ {
+ adaptation_m->process_data( function.get_data(), function.size() );
+ }
+ return wlan_eapol_if_error_illegal_parameter;
+ }
+
+ wlan_eapol_if_message_type_function_e func = function.get_function();
+
+ switch ( func )
+ {
+ // These functions are used only from WLAN Engine to EAPOL. So, no need to parse and handle...
+ case wlan_eapol_if_message_type_function_check_pmksa_cache:
+ case wlan_eapol_if_message_type_function_start_authentication:
+ case wlan_eapol_if_message_type_function_complete_association:
+ case wlan_eapol_if_message_type_function_disassociation:
+ case wlan_eapol_if_message_type_function_start_preauthentication:
+ case wlan_eapol_if_message_type_function_start_reassociation:
+ case wlan_eapol_if_message_type_function_complete_reassociation:
+ case wlan_eapol_if_message_type_function_start_wpx_fast_roam_reassociation:
+ case wlan_eapol_if_message_type_function_complete_wpx_fast_roam_reassociation:
+ case wlan_eapol_if_message_type_function_packet_process:
+ case wlan_eapol_if_message_type_function_tkip_mic_failure:
+ case wlan_eapol_if_message_type_function_eap_acknowledge:
+ case wlan_eapol_if_message_type_function_update_header_offset:
+ case wlan_eapol_if_message_type_function_update_wlan_database_reference_values:
+ DEBUG1( "core_eapol_handler_c::send_data() - Error: Message %i coming to from EAPOL to Engine (wrong direction...)", func );
+ return wlan_eapol_if_error_illegal_parameter;
+
+ // These functions are handled in WLAN Engine.
+ case wlan_eapol_if_message_type_function_complete_check_pmksa_cache:
+ {
+ core_type_list_c<network_id_c> network_id_list;
+
+ error = function.parse_complete_check_pmksa_cache(
+ network_id_list );
+ if ( error == core_error_ok )
+ {
+ error = complete_check_pmksa_cache( network_id_list );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_packet_send:
+ {
+ network_id_c network_id( NULL, 0, NULL, 0, 0 );
+ u8_t * packet( NULL );
+ u32_t packet_length( 0 );
+
+ wlan_eapol_if_eapol_key_authentication_type_e type(
+ server_m->get_eapol_instance().authentication_type() );
+ bool_t send_unecrypted( false_t );
+ if( type == wlan_eapol_if_eapol_key_authentication_type_wapi ||
+ type == wlan_eapol_if_eapol_key_authentication_type_wapi_psk )
+ {
+ send_unecrypted = true_t;
+ }
+
+ error = function.parse_packet_send(
+ &network_id,
+ &packet, &packet_length );
+ if ( error == core_error_ok )
+ {
+ error = packet_send( &network_id, packet, packet_length, send_unecrypted );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_associate:
+ {
+ wlan_eapol_if_eapol_key_authentication_mode_e auth_mode( wlan_eapol_if_eapol_key_authentication_mode_none );
+
+ error = function.parse_associate(
+ &auth_mode );
+ if ( error == core_error_ok )
+ {
+ error = associate( auth_mode );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_disassociate:
+ {
+ network_id_c network_id( NULL, 0, NULL, 0, 0 );
+ bool_t self_disassociation( false_t );
+
+ error = function.parse_disassociate(
+ &network_id,
+ &self_disassociation );
+ if ( error == core_error_ok )
+ {
+ error = disassociate( &network_id, self_disassociation );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_packet_data_session_key:
+ {
+ network_id_c network_id( NULL, 0, NULL, 0, 0 );
+ session_key_c session_key( NULL, 0, NULL, 0, wlan_eapol_if_eapol_key_type_broadcast, 0, false_t );
+
+ error = function.parse_packet_data_session_key(
+ &network_id,
+ &session_key );
+ if ( error == core_error_ok )
+ {
+ error = packet_data_session_key( &network_id, &session_key );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_state_notification:
+ {
+ network_id_c network_id( NULL, 0, NULL, 0, 0 );
+ state_notification_c state_notif( &network_id, wlan_eapol_if_eap_protocol_layer_none, 0, 0, 0, 0, false_t, wlan_eapol_if_eap_status_none );
+
+ error = function.parse_state_notification(
+ &state_notif );
+ if ( error == core_error_ok )
+ {
+ state_notification( &state_notif );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_reassociate:
+ {
+ network_id_c network_id( NULL, 0, NULL, 0, 0 );
+ wlan_eapol_if_eapol_key_authentication_type_e authentication_type( wlan_eapol_if_eapol_key_authentication_type_none );
+ u8_t * pmkid( NULL );
+ u32_t pmkid_length( 0 );
+
+ error = function.parse_reassociate(
+ &network_id,
+ &authentication_type,
+ &pmkid,
+ &pmkid_length );
+ if ( error == core_error_ok )
+ {
+ error = reassociate(
+ &network_id,
+ authentication_type,
+ pmkid,
+ pmkid_length );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_complete_start_wpx_fast_roam_reassociation:
+ {
+ network_id_c network_id( NULL, 0, NULL, 0, 0 );
+ u8_t * reassociation_request_ie( NULL );
+ u32_t reassociation_request_ie_length( 0 );
+
+ error = function.parse_complete_start_wpx_fast_roam_reassociation(
+ &network_id,
+ &reassociation_request_ie,
+ &reassociation_request_ie_length );
+ if ( error == core_error_ok )
+ {
+ error = complete_start_wpx_fast_roam_reassociation(
+ &network_id,
+ reassociation_request_ie,
+ reassociation_request_ie_length );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_new_protected_setup_credentials:
+ {
+ core_type_list_c< protected_setup_credential_c > credential_list;
+
+ error = function.parse_new_protected_setup_credentials(
+ credential_list );
+ if ( error == core_error_ok )
+ {
+ error = new_protected_setup_credentials(
+ credential_list );
+ }
+ break;
+ }
+ case wlan_eapol_if_message_type_function_none:
+ default:
+ DEBUG1( "core_eapol_handler_c::send_data() - Error: unknown function %i", func );
+ }
+
+ // Check if error message should be sent
+ if ( error != core_error_ok
+ && error != core_error_request_pending )
+ {
+ // send error message
+ core_error_e ret_val = function.generate_error(
+ static_cast<wlan_eapol_if_error_e>( core_eapol_handler_c::convert_core_error_to_if_status( error ) ),
+ func );
+ if ( ret_val == core_error_ok )
+ {
+ adaptation_m->process_data( function.get_data(), function.size() );
+ }
+ }
+ return core_eapol_handler_c::convert_core_error_to_if_status( error );
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::complete_check_pmksa_cache(
+ core_type_list_c<network_id_c> & network_id_list )
+ {
+ DEBUG( "core_eapol_handler_c::complete_check_pmksa_cache()" );
+
+ return server_m->get_eapol_instance().update_completed_check_pmksa_cache_list( network_id_list );
+ }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::complete_start_wpx_fast_roam_reassociation(
+ network_id_c * receive_network_id,
+ u8_t * reassociation_request_ie,
+ u32_t reassociation_request_ie_length )
+ {
+ DEBUG( "core_eapol_handler_c::complete_start_wpx_fast_roam_reassociation()" );
+
+ if ( handler_m )
+ {
+ return handler_m->complete_start_wpx_fast_roam_reassociation(
+ receive_network_id,
+ reassociation_request_ie,
+ reassociation_request_ie_length );
+ }
+ return core_error_ok;
+ }
+
+
+enum protected_setup_authentication_type_e
+{
+ protected_setup_authentication_type_None = 0x0000,
+ protected_setup_authentication_type_Open = 0x0001,
+ protected_setup_authentication_type_WPAPSK = 0x0002,
+ protected_setup_authentication_type_Shared = 0x0004,
+ protected_setup_authentication_type_WPA = 0x0008,
+ protected_setup_authentication_type_WPA2 = 0x0010,
+ protected_setup_authentication_type_WPA2PSK = 0x0020,
+};
+
+enum protected_setup_encryption_type_e
+{
+ protected_setup_encryption_type_None = 0x0001,
+ protected_setup_encryption_type_WEP = 0x0002,
+ protected_setup_encryption_type_TKIP = 0x0004,
+ protected_setup_encryption_type_AES = 0x0008,
+};
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::new_protected_setup_credentials(
+ core_type_list_c< protected_setup_credential_c > & credential_list )
+ {
+ DEBUG( "core_eapol_handler_c::new_protected_setup_credentials()" );
+
+ ASSERT( protected_setup_handler_m );
+
+ for ( protected_setup_credential_c* credential = credential_list.first(); credential; credential = credential_list.next() )
+ {
+ core_iap_data_s iap_data;
+ core_tools_c::fillz(
+ &iap_data,
+ sizeof ( iap_data ) );
+
+ iap_data.id = 0;
+ iap_data.op_mode = core_operating_mode_infrastructure;
+ iap_data.is_hidden = false_t;
+ iap_data.authentication_mode = core_authentication_mode_open;
+ iap_data.wpa_preshared_key_in_use = false_t;
+ iap_data.is_wpa_overriden = false_t;
+ iap_data.used_adhoc_channel = 0;
+ iap_data.is_dynamic_ip_addr = true_t;
+ iap_data.is_roaming_allowed = true_t;
+
+ // SSID
+ if ( credential->ssid_length > MAX_SSID_LEN )
+ {
+ DEBUG1( "core_eapol_handler_c::new_protected_setup_credentials() - Error: Too long SSID (%d bytes). Ignoring credentials.",
+ credential->ssid_length );
+ }
+ else
+ {
+ iap_data.ssid.length =
+ credential->ssid_length;
+ core_tools_c::copy(
+ &iap_data.ssid.ssid[0],
+ credential->ssid,
+ iap_data.ssid.length );
+
+ // Security mode
+ switch ( credential->authentication_type )
+ {
+ case protected_setup_authentication_type_WPAPSK:
+ iap_data.security_mode = core_security_mode_wpa;
+ iap_data.wpa_preshared_key_in_use = true_t;
+ break;
+ case protected_setup_authentication_type_WPA2PSK:
+ iap_data.security_mode = core_security_mode_wpa2only;
+ iap_data.wpa_preshared_key_in_use = true_t;
+ break;
+ case protected_setup_authentication_type_WPA:
+ iap_data.security_mode = core_security_mode_wpa;
+ break;
+ case protected_setup_authentication_type_WPA2:
+ iap_data.security_mode = core_security_mode_wpa2only;
+ break;
+ case protected_setup_authentication_type_Shared:
+ iap_data.security_mode = core_security_mode_wep;
+ iap_data.authentication_mode = core_authentication_mode_shared;
+ break;
+ case protected_setup_authentication_type_Open:
+ if ( credential->encryption_type == protected_setup_encryption_type_WEP )
+ {
+ iap_data.security_mode = core_security_mode_wep;
+ }
+ else
+ {
+ iap_data.security_mode = core_security_mode_allow_unsecure;
+ }
+ break;
+ case protected_setup_authentication_type_None:
+ /** Falls through on purpose. */
+ default:
+ iap_data.security_mode = core_security_mode_allow_unsecure;
+ break;
+ }
+
+ bool_t ignore_current_credential( false_t );
+ // Encryption keys
+ switch ( iap_data.security_mode )
+ {
+ case core_security_mode_wpa:
+ /** Falls through on purpose. */
+ case core_security_mode_wpa2only:
+ if ( iap_data.wpa_preshared_key_in_use &&
+ credential->network_key_list.first() )
+ {
+ network_key_c* key = credential->network_key_list.current();
+ if ( key->network_key_length > MAX_WPA_PSK_LENGTH )
+ {
+ DEBUG1( "core_eapol_handler_c::new_protected_setup_credentials() - Error: Too long WPA Passphrase (%d bytes). Ignoring credentials.",
+ key->network_key_length );
+ ignore_current_credential = true_t;
+ }
+ else
+ {
+ iap_data.wpa_preshared_key.key_length = key->network_key_length;
+ core_tools_c::copy(
+ &iap_data.wpa_preshared_key.key_data[0],
+ key->network_key,
+ iap_data.wpa_preshared_key.key_length );
+ }
+ }
+ break;
+ case core_security_mode_wep:
+ {
+ for ( network_key_c* key = credential->network_key_list.first(); key; key = credential->network_key_list.next())
+ {
+ core_wep_key_s wep_key;
+ if ( key->network_key_length > MAX_WEP_KEY_LENGTH)
+ {
+ // WEP key is ignored if its key_length is too long.
+ DEBUG2( "core_eapol_handler_c::new_protected_setup_credentials() - Error: Too long WEP key for key index %d (%d bytes). Ignoring WEP key.",
+ key->network_key_index,
+ key->network_key_length );
+ }
+ else
+ {
+ wep_key.key_index = key->network_key_index;
+ wep_key.key_length = key->network_key_length;
+ core_tools_c::copy(
+ &wep_key.key_data[0],
+ key->network_key,
+ wep_key.key_length );
+
+ if ( wep_key.key_index == 1 )
+ {
+ iap_data.wep_key1 = wep_key;
+ }
+ else if ( wep_key.key_index == 2 )
+ {
+ iap_data.wep_key2 = wep_key;
+ }
+ else if ( wep_key.key_index == 3 )
+ {
+ iap_data.wep_key3 = wep_key;
+ }
+ else if ( wep_key.key_index == 4 )
+ {
+ iap_data.wep_key4 = wep_key;
+ }
+ else
+ {
+ // WEP key is ignored if its key_index is not valid.
+ DEBUG1( "core_eapol_handler_c::new_protected_setup_credentials() - Error: WEP key index is not valid (it was %d). Ignoring WEP key.",
+ wep_key.key_index );
+ }
+ }
+ }
+
+ /** Use the first defined key as the default key. */
+ if ( iap_data.wep_key1.key_length )
+ {
+ iap_data.default_wep_key = 0;
+ }
+ else if ( iap_data.wep_key2.key_length )
+ {
+ iap_data.default_wep_key = 1;
+ }
+ else if ( iap_data.wep_key3.key_length )
+ {
+ iap_data.default_wep_key = 2;
+ }
+ else if ( iap_data.wep_key4.key_length )
+ {
+ iap_data.default_wep_key = 3;
+ }
+ else
+ {
+ // Credentials are ignored if there was no valid keys.
+ DEBUG( "core_eapol_handler_c::new_protected_setup_credentials() - Error: No valid WEP keys defined. Could not set default wep key. Ignoring credentials." );
+ ignore_current_credential = true_t;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if ( !ignore_current_credential )
+ {
+ protected_setup_handler_m->handle_protected_setup_network( iap_data );
+ }
+ }
+ }
+
+ return core_error_ok;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void core_eapol_handler_c::handle_error(
+ wlan_eapol_if_error_e errorcode,
+ wlan_eapol_if_message_type_function_e function )
+ {
+ DEBUG2( "core_eapol_handler_c::handle_error() - Received error message: errorcode=%i, function=%i", errorcode, function );
+
+ if ( handler_m )
+ {
+ handler_m->handle_error(
+ errorcode,
+ function );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+void core_eapol_handler_c::handle_wlan_authentication_state(
+ u32_t state,
+ const core_mac_address_s& bssid )
+ {
+#ifdef _DEBUG
+ switch ( state )
+ {
+ case wlan_eapol_if_eapol_wlan_authentication_state_no_response:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_no_response" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_this_ap_failed:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_this_ap_failed" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_failed_completely:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_failed_completely" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_authentication_cancelled:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_authentication_cancelled" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_authentication_successfull:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_authentication_successfull" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_association_ok:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_association_ok" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_802_11_auth_algorithm_not_supported:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_802_11_auth_algorithm_not_supported" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_eap_authentication_running:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_eap_authentication_running" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_4_way_handshake_running:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_4_way_handshake_running" );
+ break;
+ case wlan_eapol_if_eapol_wlan_authentication_state_wapi_authentication_running:
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - wlan_eapol_if_eapol_wlan_authentication_state_wapi_authentication_running" );
+ break;
+ }
+#endif // _DEBUG
+
+ const core_mac_address_s cur_bssid(
+ server_m->get_connection_data()->eapol_auth_bssid() );
+
+ DEBUG6( "core_eapol_handler_c::handle_wlan_authentication_state() - notification BSSID is %02X:%02X:%02X:%02X:%02X:%02X",
+ bssid.addr[0], bssid.addr[1], bssid.addr[2],
+ bssid.addr[3], bssid.addr[4], bssid.addr[5] );
+ DEBUG6( "core_eapol_handler_c::handle_wlan_authentication_state() - current BSSID is %02X:%02X:%02X:%02X:%02X:%02X",
+ cur_bssid.addr[0], cur_bssid.addr[1], cur_bssid.addr[2],
+ cur_bssid.addr[3], cur_bssid.addr[4], cur_bssid.addr[5] );
+
+ if ( state == wlan_eapol_if_eapol_wlan_authentication_state_eap_authentication_running ||
+ state == wlan_eapol_if_eapol_wlan_authentication_state_4_way_handshake_running ||
+ state == wlan_eapol_if_eapol_wlan_authentication_state_wapi_authentication_running )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - marking is_eapol_authenticating as true" );
+
+ /**
+ * EAPOL has started authenticating, reset the previous
+ * failures.
+ */
+ ASSERT ( server_m != NULL );
+
+ server_m->get_connection_data()->set_eapol_authenticating(
+ true_t );
+ server_m->get_connection_data()->set_last_failed_eap_type(
+ EAP_TYPE_NONE );
+ server_m->get_connection_data()->set_last_eap_error(
+ EAP_ERROR_NONE );
+
+ return;
+ }
+
+ // EAP-FAST will fail after PAC provisioning. With this state EAPOL requires wlan engine to reconnect again.
+ if ( state == wlan_eapol_if_eapol_wlan_authentication_state_immediate_reconnect )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - immediate reconnect required" );
+
+ server_m->get_connection_data()->set_eapol_require_immediate_reconnect( true_t );
+
+ return;
+ }
+
+ if ( !is_eapol_wlan_authentication_state_success( state ) &&
+ !is_eapol_wlan_authentication_state_failure( state ) )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - neither a failure nor a success, ignoring notification" );
+
+ return;
+ }
+ else if ( !server_m->get_connection_data()->is_eapol_authenticating() &&
+ !server_m->get_connection_data()->is_eapol_authentication_started() )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - failure or success received while not authenticating, ignoring notification" );
+
+ return;
+ }
+ else if ( bssid != ZERO_MAC_ADDR &&
+ bssid != cur_bssid )
+ {
+ DEBUG( "core_ap_data_c::instance() - notification doesn't match the current BSSID, ignoring notification" );
+
+ return;
+ }
+
+ bool_t is_authentication_started( server_m->get_connection_data()->is_eapol_authenticating() );
+
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - marking is_eapol_authenticating as false" );
+ server_m->get_connection_data()->set_eapol_authenticating(
+ false_t );
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - marking is_eapol_authentication_started as false" );
+ server_m->get_connection_data()->set_eapol_authentication_started(
+ false_t );
+
+ if ( handler_m )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - eapol handler registered" );
+
+ // Check whether authentication ended without getting even first message from AP.
+ if ( is_authentication_started
+ || state == wlan_eapol_if_eapol_wlan_authentication_state_failed_completely
+ || state == wlan_eapol_if_eapol_wlan_authentication_state_authentication_cancelled
+ || state == wlan_eapol_if_eapol_wlan_authentication_state_authentication_successfull )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - completing request" );
+ server_m->request_complete(
+ REQUEST_ID_CORE_INTERNAL,
+ eapol_wlan_authentication_state_to_error( state ) );
+ }
+ else
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - completing request (authentication not yet started)" );
+ server_m->request_complete(
+ REQUEST_ID_CORE_INTERNAL,
+ core_error_eapol_auth_start_timeout );
+ }
+ }
+ else
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - no eapol handler registered" );
+
+ /**
+ * Since we have no operation to complete, it means this indication is
+ * about a reauthentication.
+ */
+ if ( is_eapol_wlan_authentication_state_failure( state ) )
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - reauthentication has failed, scheduling a roam" );
+ server_m->schedule_roam(
+ core_operation_handle_bss_lost_c::core_bss_lost_reason_failed_reauthentication );
+ }
+ else
+ {
+ DEBUG( "core_eapol_handler_c::handle_wlan_authentication_state() - reauthentication has succeeded" );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+core_error_e core_eapol_handler_c::eapol_wlan_authentication_state_to_error(
+ u32_t state ) const
+ {
+ switch ( state )
+ {
+ case wlan_eapol_if_eapol_wlan_authentication_state_no_response:
+ /** Falls through on purpose. */
+ case wlan_eapol_if_eapol_wlan_authentication_state_this_ap_failed:
+ return core_error_eapol_failure;
+ case wlan_eapol_if_eapol_wlan_authentication_state_failed_completely:
+ /** Falls through on purpose. */
+ case wlan_eapol_if_eapol_wlan_authentication_state_authentication_cancelled:
+ return core_error_eapol_total_failure;
+ case wlan_eapol_if_eapol_wlan_authentication_state_authentication_successfull:
+ /** Falls through on purpose. */
+ default:
+ return core_error_ok;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+bool_t core_eapol_handler_c::is_eapol_wlan_authentication_state_failure(
+ u32_t state ) const
+ {
+ if ( state == wlan_eapol_if_eapol_wlan_authentication_state_no_response ||
+ state == wlan_eapol_if_eapol_wlan_authentication_state_this_ap_failed ||
+ state == wlan_eapol_if_eapol_wlan_authentication_state_failed_completely ||
+ state == wlan_eapol_if_eapol_wlan_authentication_state_authentication_cancelled )
+ {
+ return true_t;
+ }
+
+ return false_t;
+ }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+bool_t core_eapol_handler_c::is_eapol_wlan_authentication_state_success(
+ u32_t state ) const
+ {
+ if ( state == wlan_eapol_if_eapol_wlan_authentication_state_authentication_successfull )
+ {
+ return true_t;
+ }
+
+ return false_t;
+ }