From 654c965851e72392230ef6b91dc6a7e238149a0c Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Thu, 27 Oct 2016 10:00:18 +0200 Subject: [PATCH] Support for various peer action request extended --- lib/EAPBase/include/Method.h | 18 +++----- lib/EAPBase/src/Method.cpp | 19 +++----- lib/EapHost/include/Method.h | 42 ++++++++--------- lib/EapHost/src/Method.cpp | 27 ++++------- lib/MSCHAPv2/include/Method.h | 7 ++- lib/MSCHAPv2/src/Method.cpp | 20 ++++---- lib/PAP/include/Method.h | 7 ++- lib/PAP/src/Method.cpp | 18 ++++---- lib/TLS/include/Method.h | 13 +++--- lib/TLS/src/Method.cpp | 86 +++++++++++++++++++++++------------ lib/TTLS/include/Method.h | 20 ++++---- lib/TTLS/src/Method.cpp | 37 +++++++-------- lib/TTLS/src/Module.cpp | 12 +++-- 13 files changed, 160 insertions(+), 166 deletions(-) diff --git a/lib/EAPBase/include/Method.h b/lib/EAPBase/include/Method.h index ed28c35..67ab0a0 100644 --- a/lib/EAPBase/include/Method.h +++ b/lib/EAPBase/include/Method.h @@ -105,10 +105,9 @@ namespace eap /// /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// - virtual void process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) = 0; + virtual EapPeerMethodResponseAction process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) = 0; /// /// Obtains a response packet from the EAP method. @@ -151,10 +150,9 @@ namespace eap /// /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) /// - virtual void set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction set_ui_context( + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize); /// @} @@ -173,9 +171,7 @@ namespace eap /// /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) /// - virtual void set_response_attributes( - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs); /// @} diff --git a/lib/EAPBase/src/Method.cpp b/lib/EAPBase/src/Method.cpp index 87eea25..1552585 100644 --- a/lib/EAPBase/src/Method.cpp +++ b/lib/EAPBase/src/Method.cpp @@ -122,16 +122,15 @@ void eap::method::get_ui_context( } -void eap::method::set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method::set_ui_context( + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize) { UNREFERENCED_PARAMETER(pUIContextData); UNREFERENCED_PARAMETER(dwUIContextDataSize); - UNREFERENCED_PARAMETER(pEapOutput); // Default implementation does nothing with context data. + return EapPeerMethodResponseActionNone; } @@ -145,16 +144,12 @@ void eap::method::get_response_attributes(_Inout_ EapAttributes *pAttribs) } -void eap::method::set_response_attributes( - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method::set_response_attributes(_In_ const EapAttributes *pAttribs) { UNREFERENCED_PARAMETER(pAttribs); - assert(pEapOutput); - // Default implementation discards the EAP attributes. - pEapOutput->action = EapPeerMethodResponseActionDiscard; - pEapOutput->fAllowNotifications = FALSE; + // Default implementation does nothing with EAP attributes. + return EapPeerMethodResponseActionNone; } diff --git a/lib/EapHost/include/Method.h b/lib/EapHost/include/Method.h index c510983..e7fa405 100644 --- a/lib/EapHost/include/Method.h +++ b/lib/EapHost/include/Method.h @@ -93,10 +93,9 @@ namespace eap /// /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// - virtual void process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize); /// /// Obtains a response packet from the EAP method. @@ -139,10 +138,9 @@ namespace eap /// /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) /// - virtual void set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction set_ui_context( + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize); /// @} @@ -161,9 +159,7 @@ namespace eap /// /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) /// - virtual void set_response_attributes( - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs); /// @} @@ -171,24 +167,22 @@ namespace eap /// /// Converts EapHost peer action to output structure. /// - /// \param[in ] action EapHost peer action - /// \param[out] pEapOutput EAP method output structure + /// \param[in] action EapHost peer action /// - inline void action_to_output( - _In_ EapHostPeerResponseAction action, - _Out_ EapPeerMethodOutput *pEapOutput) + /// \returns EAP method output action + /// + inline EapPeerMethodResponseAction action_h2p(_In_ EapHostPeerResponseAction action) { switch (action) { - case EapHostPeerResponseDiscard : pEapOutput->action = EapPeerMethodResponseActionDiscard ; break; - case EapHostPeerResponseSend : pEapOutput->action = EapPeerMethodResponseActionSend ; break; - case EapHostPeerResponseResult : pEapOutput->action = EapPeerMethodResponseActionResult ; break; - case EapHostPeerResponseInvokeUi : pEapOutput->action = EapPeerMethodResponseActionInvokeUI; break; - case EapHostPeerResponseRespond : pEapOutput->action = EapPeerMethodResponseActionRespond ; break; - case EapHostPeerResponseStartAuthentication: pEapOutput->action = EapPeerMethodResponseActionDiscard ; break; // The session could not be found. So the supplicant either needs to start session again with the same packet or discard the packet. - case EapHostPeerResponseNone : pEapOutput->action = EapPeerMethodResponseActionNone ; break; + case EapHostPeerResponseDiscard : return EapPeerMethodResponseActionDiscard ; + case EapHostPeerResponseSend : return EapPeerMethodResponseActionSend ; + case EapHostPeerResponseResult : return EapPeerMethodResponseActionResult ; + case EapHostPeerResponseInvokeUi : return EapPeerMethodResponseActionInvokeUI; + case EapHostPeerResponseRespond : return EapPeerMethodResponseActionRespond ; + case EapHostPeerResponseStartAuthentication: return EapPeerMethodResponseActionDiscard ; // The session could not be found. So the supplicant either needs to start session again with the same packet or discard the packet. + case EapHostPeerResponseNone : return EapPeerMethodResponseActionNone ; default : throw std::invalid_argument(winstd::string_printf(__FUNCTION__ " Unknown action (%u).", action).c_str()); } - pEapOutput->fAllowNotifications = TRUE; } protected: diff --git a/lib/EapHost/src/Method.cpp b/lib/EapHost/src/Method.cpp index 6ca54a4..a79aaa4 100644 --- a/lib/EapHost/src/Method.cpp +++ b/lib/EapHost/src/Method.cpp @@ -102,13 +102,11 @@ void eap::method_eaphost::end_session() } -void eap::method_eaphost::process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_eaphost::process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) { assert(pReceivedPacket || dwReceivedPacketSize == 0); - assert(pEapOutput); m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)m_cfg.get_method_id()), event_data((unsigned int)dwReceivedPacketSize), event_data::blank); @@ -123,7 +121,7 @@ void eap::method_eaphost::process_request_packet( &error._Myptr); if (dwResult == ERROR_SUCCESS) { // Packet successfuly processed. - action_to_output(action, pEapOutput); + return action_h2p(action); } else if (error) throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerProcessReceivedPacket failed."); else @@ -212,13 +210,10 @@ void eap::method_eaphost::get_ui_context( } -void eap::method_eaphost::set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_eaphost::set_ui_context( + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize) { - assert(pEapOutput); - // Set EapHost peer UI context data. EapHostPeerResponseAction action; eap_error_runtime error; @@ -230,7 +225,7 @@ void eap::method_eaphost::set_ui_context( &error._Myptr); if (dwResult == ERROR_SUCCESS) { // UI context data successfuly returned. - action_to_output(action, pEapOutput); + return action_h2p(action); } else if (error) throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerSetUIContext failed."); else @@ -255,9 +250,7 @@ void eap::method_eaphost::get_response_attributes(_Inout_ EapAttributes *pAttrib } -void eap::method_eaphost::set_response_attributes( - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_eaphost::set_response_attributes(_In_ const EapAttributes *pAttribs) { // Set response attributes for EapHost peer. EapHostPeerResponseAction action; @@ -269,7 +262,7 @@ void eap::method_eaphost::set_response_attributes( &error._Myptr); if (dwResult == ERROR_SUCCESS) { // Response attributes successfuly set. - action_to_output(action, pEapOutput); + return action_h2p(action); } else if (error) throw eap_runtime_error(*error , __FUNCTION__ " EapHostPeerGetResponseAttributes failed."); else diff --git a/lib/MSCHAPv2/include/Method.h b/lib/MSCHAPv2/include/Method.h index 239daf4..2f158f8 100644 --- a/lib/MSCHAPv2/include/Method.h +++ b/lib/MSCHAPv2/include/Method.h @@ -87,10 +87,9 @@ namespace eap /// /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// - virtual void process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize); /// @} diff --git a/lib/MSCHAPv2/src/Method.cpp b/lib/MSCHAPv2/src/Method.cpp index 15005f7..c1dcc62 100644 --- a/lib/MSCHAPv2/src/Method.cpp +++ b/lib/MSCHAPv2/src/Method.cpp @@ -87,13 +87,11 @@ void eap::method_mschapv2::begin_session( } -void eap::method_mschapv2::process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_mschapv2::process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) { assert(pReceivedPacket || dwReceivedPacketSize == 0); - assert(pEapOutput); m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)eap_type_legacy_mschapv2), event_data((unsigned int)dwReceivedPacketSize), event_data::blank); @@ -130,22 +128,22 @@ void eap::method_mschapv2::process_request_packet( m_phase = phase_challenge_server; m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. - break; + return EapPeerMethodResponseActionSend; } case phase_challenge_server: { process_packet(pReceivedPacket, dwReceivedPacketSize); if (m_success) m_phase = phase_finished; - break; + return EapPeerMethodResponseActionNone; } case phase_finished: - break; - } + return EapPeerMethodResponseActionNone; - pEapOutput->fAllowNotifications = TRUE; - pEapOutput->action = EapPeerMethodResponseActionSend; + default: + throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str()); + } } diff --git a/lib/PAP/include/Method.h b/lib/PAP/include/Method.h index 0f47c1c..8137d07 100644 --- a/lib/PAP/include/Method.h +++ b/lib/PAP/include/Method.h @@ -85,10 +85,9 @@ namespace eap /// /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// - virtual void process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize); /// @} diff --git a/lib/PAP/src/Method.cpp b/lib/PAP/src/Method.cpp index 1a602f7..124536e 100644 --- a/lib/PAP/src/Method.cpp +++ b/lib/PAP/src/Method.cpp @@ -69,14 +69,12 @@ void eap::method_pap::begin_session( } -void eap::method_pap::process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_pap::process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) { UNREFERENCED_PARAMETER(pReceivedPacket); assert(pReceivedPacket || dwReceivedPacketSize == 0); - assert(pEapOutput); m_module.log_event(&EAPMETHOD_PACKET_RECV, event_data((unsigned int)eap_type_legacy_pap), event_data((unsigned int)dwReceivedPacketSize), event_data::blank); @@ -99,13 +97,13 @@ void eap::method_pap::process_request_packet( m_phase = phase_finished; m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. - break; + return EapPeerMethodResponseActionSend; } case phase_finished: - break; - } + return EapPeerMethodResponseActionNone; - pEapOutput->fAllowNotifications = TRUE; - pEapOutput->action = EapPeerMethodResponseActionSend; + default: + throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str()); + } } diff --git a/lib/TLS/include/Method.h b/lib/TLS/include/Method.h index d473e9c..bf4a413 100644 --- a/lib/TLS/include/Method.h +++ b/lib/TLS/include/Method.h @@ -107,10 +107,9 @@ namespace eap /// /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// - virtual void process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize); /// /// Obtains a response packet from the EAP method. @@ -291,13 +290,13 @@ namespace eap /// /// Process handshake /// - void process_handshake(); + EapPeerMethodResponseAction process_handshake(); #endif /// /// Process application data /// - void process_application_data(); + EapPeerMethodResponseAction process_application_data(); /// /// Processes a TLS application_data message @@ -307,7 +306,7 @@ namespace eap /// \param[in] msg TLS application_data message data /// \param[in] size_msg TLS application_data message data size /// - virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); + virtual EapPeerMethodResponseAction process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); /// @} diff --git a/lib/TLS/src/Method.cpp b/lib/TLS/src/Method.cpp index 683da01..2aa7120 100644 --- a/lib/TLS/src/Method.cpp +++ b/lib/TLS/src/Method.cpp @@ -246,13 +246,11 @@ void eap::method_tls::begin_session( } -void eap::method_tls::process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_tls::process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) { assert(pReceivedPacket && dwReceivedPacketSize >= 4); - assert(pEapOutput); // Is this a valid EAP-TLS packet? if (dwReceivedPacketSize < 6) @@ -265,9 +263,7 @@ void eap::method_tls::process_request_packet( m_packet_res.m_id = ((const EapPacket*)pReceivedPacket)->Id; m_packet_res.m_flags = 0; m_packet_res.m_data.clear(); - pEapOutput->fAllowNotifications = FALSE; - pEapOutput->action = EapPeerMethodResponseActionSend; - return; + return EapPeerMethodResponseActionSend; } if (m_packet_res.m_flags & packet_tls::flags_res_more_frag) { @@ -275,9 +271,7 @@ void eap::method_tls::process_request_packet( if (m_packet_req.is_ack(m_packet_res.m_id)) { // This is the ACK of our fragmented message packet. Send the next fragment. m_packet_res.m_id++; - pEapOutput->fAllowNotifications = FALSE; - pEapOutput->action = EapPeerMethodResponseActionSend; - return; + return EapPeerMethodResponseActionSend; } else throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " ACK expected, received %u-%u-%x.", m_packet_req.m_code, m_packet_req.m_id, m_packet_req.m_flags)); } @@ -286,6 +280,7 @@ void eap::method_tls::process_request_packet( m_packet_res.m_id = m_packet_req.m_id; m_packet_res.m_flags = 0; + EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone; user_impersonator impersonating(m_user_ctx); #if EAP_TLS < EAP_TLS_SCHANNEL @@ -325,6 +320,7 @@ void eap::method_tls::process_request_packet( m_packet_res.m_data.insert(m_packet_res.m_data.end(), msg_client_hello.begin(), msg_client_hello.end()); m_phase = phase_server_hello; + action = EapPeerMethodResponseActionSend; break; } @@ -427,12 +423,14 @@ void eap::method_tls::process_request_packet( // Go to application data phase. And allow piggybacking of the first data message. m_phase = phase_application_data; m_session_resumed = true; - process_application_data(NULL, 0); + action = process_application_data(NULL, 0); } else { m_session_resumed = false; m_phase = phase_change_cipher_spec; m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. + action = EapPeerMethodResponseActionSend; } + break; } @@ -440,13 +438,20 @@ void eap::method_tls::process_request_packet( // Wait in this phase until server sends change cipher spec and finish. if (m_state_server.m_alg_encrypt && m_handshake[tls_handshake_type_finished]) { m_phase = phase_application_data; - process_application_data(NULL, 0); + action = process_application_data(NULL, 0); + } else { + // Ignore content of the message and keep replying with ACK packet until change cipher spec is delivered. + action = EapPeerMethodResponseActionSend; } break; case phase_application_data: if (m_handshake[tls_handshake_type_hello_request]) m_phase = phase_client_hello; + break; + + default: + throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str()); } #else if (((const EapPacket*)pReceivedPacket)->Code == EapCodeRequest && (m_packet_req.m_flags & packet_tls::flags_req_start)) { @@ -462,20 +467,21 @@ void eap::method_tls::process_request_packet( switch (m_phase) { case phase_handshake_init: case phase_handshake_cont: - process_handshake(); + action = process_handshake(); break; case phase_application_data: - process_application_data(); + action = process_application_data(); break; + + default: + throw invalid_argument(string_printf(__FUNCTION__ " Unknown phase (phase %u).", m_phase).c_str()); } #endif - pEapOutput->fAllowNotifications = TRUE; - pEapOutput->action = EapPeerMethodResponseActionSend; - // EAP-Request packet was processed. Clear its data since we use the absence of data to detect first of fragmented message packages. m_packet_req.m_data.clear(); + return action; } @@ -1105,7 +1111,7 @@ void eap::method_tls::process_handshake(_In_bytecount_(size_msg) const void *_ms #else -void eap::method_tls::process_handshake() +EapPeerMethodResponseAction eap::method_tls::process_handshake() { // Prepare input buffer(s). SecBuffer buf_in[] = { @@ -1193,32 +1199,35 @@ void eap::method_tls::process_handshake() derive_challenge(); m_phase = phase_application_data; - process_application_data(m_sc_queue.data(), m_sc_queue.size()); + return process_application_data(m_sc_queue.data(), m_sc_queue.size()); } else { m_phase = phase_handshake_cont; m_cfg.m_last_status = config_method::status_cred_invalid; // Blame credentials if we fail beyond this point. + return EapPeerMethodResponseActionSend; } } else if (status == SEC_E_INCOMPLETE_MESSAGE) { // Schannel neeeds more data. Send ACK packet to server to send more. + return EapPeerMethodResponseActionSend; } else if (FAILED(status)) { if (m_sc_ctx.m_attrib & ISC_RET_EXTENDED_ERROR) { - // Send alert via EAP. Not that EAP will transmit it once we throw this is an error... + // Send alert. assert(buf_out[1].BufferType == SECBUFFER_ALERT); assert(m_sc_ctx.m_attrib & ISC_RET_ALLOCATED_MEMORY); m_packet_res.m_data.assign(reinterpret_cast(buf_out[1].pvBuffer), reinterpret_cast(buf_out[1].pvBuffer) + buf_out[1].cbBuffer); - } - - throw sec_runtime_error(status, __FUNCTION__ " Schannel error."); + return EapPeerMethodResponseActionSend; + } else + throw sec_runtime_error(status, __FUNCTION__ " Schannel error."); } + + return EapPeerMethodResponseActionNone; } -void eap::method_tls::process_application_data() +EapPeerMethodResponseAction eap::method_tls::process_application_data() { if (m_sc_queue.empty()) { // An ACK packet received. Nothing to unencrypt. - process_application_data(NULL, 0); - return; + return process_application_data(NULL, 0); } if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY)) @@ -1244,10 +1253,18 @@ void eap::method_tls::process_application_data() // Decrypt the message. SECURITY_STATUS status = DecryptMessage(m_sc_ctx, &buf_desc, 0, NULL); if (status == SEC_E_OK) { + EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone; + // Find SECBUFFER_DATA buffer(s) and process data. for (size_t i = 0; i < _countof(buf); i++) - if (buf[i].BufferType == SECBUFFER_DATA) - process_application_data(buf[i].pvBuffer, buf[i].cbBuffer); + if (buf[i].BufferType == SECBUFFER_DATA) { + action = process_application_data(buf[i].pvBuffer, buf[i].cbBuffer); + if (action == EapPeerMethodResponseActionDiscard) { + // Request is to be discarded as a whole. + m_sc_queue.clear(); + return EapPeerMethodResponseActionDiscard; + } + } // Find SECBUFFER_EXTRA buffer(s) and queue data for the next time. std::vector extra; @@ -1255,28 +1272,37 @@ void eap::method_tls::process_application_data() if (buf[i].BufferType == SECBUFFER_EXTRA) extra.insert(extra.end(), reinterpret_cast(buf[i].pvBuffer), reinterpret_cast(buf[i].pvBuffer) + buf[i].cbBuffer); m_sc_queue = std::move(extra); + + return action; } else if (status == SEC_E_INCOMPLETE_MESSAGE) { // Schannel neeeds more data. Send ACK packet to server to send more. + return EapPeerMethodResponseActionSend; } else if (status == SEC_I_CONTEXT_EXPIRED) { // Server initiated connection shutdown. m_sc_queue.clear(); m_phase = phase_shutdown; + return EapPeerMethodResponseActionNone; } else if (status == SEC_I_RENEGOTIATE) { // Re-negotiation required. m_sc_queue.clear(); m_phase = phase_handshake_init; process_handshake(); + return EapPeerMethodResponseActionSend; } else if (FAILED(status)) throw sec_runtime_error(status, __FUNCTION__ " Schannel error."); + + return EapPeerMethodResponseActionNone; } #endif -void eap::method_tls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) +EapPeerMethodResponseAction eap::method_tls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) { UNREFERENCED_PARAMETER(msg); UNREFERENCED_PARAMETER(size_msg); + + return EapPeerMethodResponseActionNone; } diff --git a/lib/TTLS/include/Method.h b/lib/TTLS/include/Method.h index f5c66af..c061d9c 100644 --- a/lib/TTLS/include/Method.h +++ b/lib/TTLS/include/Method.h @@ -94,10 +94,9 @@ namespace eap /// /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) /// - virtual void process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize); /// /// Obtains a response packet from the EAP method. @@ -140,10 +139,9 @@ namespace eap /// /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) /// - virtual void set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction set_ui_context( + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize); /// @} @@ -162,9 +160,7 @@ namespace eap /// /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) /// - virtual void set_response_attributes( - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput); + virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs); /// @} @@ -187,7 +183,7 @@ namespace eap /// \param[in] msg Application message data /// \param[in] size_msg Application message data size /// - virtual void process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); + virtual EapPeerMethodResponseAction process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg); protected: #pragma warning(suppress: 4480) diff --git a/lib/TTLS/src/Method.cpp b/lib/TTLS/src/Method.cpp index c26b68f..6029e99 100644 --- a/lib/TTLS/src/Method.cpp +++ b/lib/TTLS/src/Method.cpp @@ -89,10 +89,9 @@ void eap::method_ttls::end_session() } -void eap::method_ttls::process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_ttls::process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) { if (((const EapPacket*)pReceivedPacket)->Code == EapCodeRequest && (((const EapPacket*)pReceivedPacket)->Data[1] & packet_ttls::flags_start)) { // This is a start EAP-TTLS packet. @@ -104,7 +103,7 @@ void eap::method_ttls::process_request_packet( } // Do the TLS. - method_tls::process_request_packet(pReceivedPacket, dwReceivedPacketSize, pEapOutput); + return method_tls::process_request_packet(pReceivedPacket, dwReceivedPacketSize); } @@ -155,14 +154,12 @@ void eap::method_ttls::get_ui_context( } -void eap::method_ttls::set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_ttls::set_ui_context( + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize) { UNREFERENCED_PARAMETER(pUIContextData); UNREFERENCED_PARAMETER(dwUIContextDataSize); - UNREFERENCED_PARAMETER(pEapOutput); throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); } @@ -176,12 +173,9 @@ void eap::method_ttls::get_response_attributes(_Inout_ EapAttributes *pAttribs) } -void eap::method_ttls::set_response_attributes( - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput) +EapPeerMethodResponseAction eap::method_ttls::set_response_attributes(_In_ const EapAttributes *pAttribs) { UNREFERENCED_PARAMETER(pAttribs); - UNREFERENCED_PARAMETER(pEapOutput); throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); } @@ -273,7 +267,7 @@ void eap::method_ttls::derive_challenge() } -void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) +EapPeerMethodResponseAction eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const void *msg, _In_ size_t size_msg) { // Prepare inner authentication. #if EAP_TLS < EAP_TLS_SCHANNEL @@ -282,7 +276,7 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v if (m_session_resumed) { // On reconnect we do not need to do inner re-authentication. - return; + return EapPeerMethodResponseActionNone; } #else if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY)) @@ -292,13 +286,12 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v if (SUCCEEDED(QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_SESSION_INFO, &session_info)) && (session_info.dwFlags & SSL_SESSION_RECONNECT)) { // On reconnect we do not need to do inner re-authentication. // According to MSDN QueryContextAttributes(SECPKG_ATTR_SESSION_INFO) works from Windows 7 on. Therefore behaviour might vary. - return; + return EapPeerMethodResponseActionNone; } #endif - EapPeerMethodOutput eap_output = {}; - m_inner->process_request_packet(msg, (DWORD)size_msg, &eap_output); - switch (eap_output.action) { + EapPeerMethodResponseAction action = m_inner->process_request_packet(msg, (DWORD)size_msg); + switch (action) { case EapPeerMethodResponseActionSend: { // Retrieve inner packet and send it. @@ -356,6 +349,8 @@ void eap::method_ttls::process_application_data(_In_bytecount_(size_msg) const v } default: - throw invalid_argument(string_printf(__FUNCTION__ " Inner method returned an unsupported action (action %u).", eap_output.action).c_str()); + throw invalid_argument(string_printf(__FUNCTION__ " Inner method returned an unsupported action (action %u).", action).c_str()); } + + return action; } diff --git a/lib/TTLS/src/Module.cpp b/lib/TTLS/src/Module.cpp index 6a44cc6..d5045a8 100644 --- a/lib/TTLS/src/Module.cpp +++ b/lib/TTLS/src/Module.cpp @@ -254,7 +254,9 @@ void eap::peer_ttls::process_request_packet( _Out_ EapPeerMethodOutput *pEapOutput) { assert(dwReceivedPacketSize == ntohs(*(WORD*)pReceivedPacket->Length)); - static_cast(hSession)->m_method->process_request_packet(pReceivedPacket, dwReceivedPacketSize, pEapOutput); + assert(pEapOutput); + pEapOutput->action = static_cast(hSession)->m_method->process_request_packet(pReceivedPacket, dwReceivedPacketSize); + pEapOutput->fAllowNotifications = TRUE; } @@ -318,7 +320,9 @@ void eap::peer_ttls::set_ui_context( _In_ DWORD dwUIContextDataSize, _Out_ EapPeerMethodOutput *pEapOutput) { - static_cast(hSession)->m_method->set_ui_context(pUIContextData, dwUIContextDataSize, pEapOutput); + assert(pEapOutput); + pEapOutput->action = static_cast(hSession)->m_method->set_ui_context(pUIContextData, dwUIContextDataSize); + pEapOutput->fAllowNotifications = TRUE; } @@ -335,7 +339,9 @@ void eap::peer_ttls::set_response_attributes( _In_ const EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput) { - static_cast(hSession)->m_method->set_response_attributes(pAttribs, pEapOutput); + assert(pEapOutput); + pEapOutput->action = static_cast(hSession)->m_method->set_response_attributes(pAttribs); + pEapOutput->fAllowNotifications = TRUE; }