From 383a85c18b6164939e19e44e4607efd114a34650 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Tue, 4 Feb 2020 12:51:16 +0100 Subject: [PATCH] method: Merge with method_tunnel Signed-off-by: Simon Rozman --- lib/EAPBase/include/Method.h | 86 ++--------------- lib/EAPBase/src/Method.cpp | 182 +++++++++++------------------------ lib/TTLS/include/Method.h | 10 +- lib/TTLS/src/Method.cpp | 38 +++----- 4 files changed, 82 insertions(+), 234 deletions(-) diff --git a/lib/EAPBase/include/Method.h b/lib/EAPBase/include/Method.h index 6d9c0d9..91911d4 100644 --- a/lib/EAPBase/include/Method.h +++ b/lib/EAPBase/include/Method.h @@ -21,7 +21,6 @@ namespace eap { class method; - class method_tunnel; class method_eap; } @@ -58,9 +57,10 @@ namespace eap /// /// Constructs a method /// - /// \param[in] mod Module to use for global services + /// \param[in] mod Module to use for global services + /// \param[in] inner Inner method /// - method(_In_ module &mod); + method(_In_ module &mod, _In_opt_ method *inner = nullptr); /// \name Session management /// @{ @@ -105,7 +105,7 @@ namespace eap /// virtual EapPeerMethodResponseAction process_request_packet( _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize) = 0; + _In_ DWORD dwReceivedPacketSize); /// /// Obtains a response packet from the EAP method. @@ -117,7 +117,7 @@ namespace eap /// virtual void get_response_packet( _Out_ sanitizing_blob &packet, - _In_opt_ DWORD size_max = MAXDWORD) = 0; + _In_opt_ DWORD size_max = MAXDWORD); /// @} @@ -191,78 +191,8 @@ namespace eap /// @} public: - module &m_module; ///< Module for global services - method *m_outer; ///< Outer method - }; - - - /// - /// Tunnel method base class - /// - /// This is a base class for all the methods that encapsulate inner methods to provide stacking framework. - /// - class method_tunnel : public method - { - public: - /// - /// Constructs a method - /// - /// \param[in] mod Module to use for global services - /// \param[in] inner Inner method - /// - method_tunnel(_In_ module &mod, _In_ method *inner); - - /// \name Session management - /// @{ - - virtual void begin_session( - _In_ DWORD dwFlags, - _In_ const EapAttributes *pAttributeArray, - _In_ HANDLE hTokenImpersonateUser, - _In_opt_ DWORD dwMaxSendPacketSize = MAXDWORD); - - virtual void end_session(); - - /// @} - - /// \name Packet processing - /// @{ - - virtual EapPeerMethodResponseAction process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize); - - virtual void get_response_packet( - _Out_ sanitizing_blob &packet, - _In_opt_ DWORD size_max = MAXDWORD); - - /// @} - - virtual void get_result( - _In_ EapPeerMethodResultReason reason, - _Inout_ EapPeerMethodResult *pResult); - - /// \name User Interaction - /// @{ - - virtual void get_ui_context(_Out_ sanitizing_blob &context_data); - - virtual EapPeerMethodResponseAction set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize); - - /// @} - - /// \name EAP Response Attributes - /// @{ - - virtual void get_response_attributes(_Out_ EapAttributes *pAttribs); - - virtual EapPeerMethodResponseAction set_response_attributes(_In_ const EapAttributes *pAttribs); - - /// @} - - protected: + module &m_module; ///< Module for global services + method *m_outer; ///< Outer method std::unique_ptr m_inner; ///< Inner method }; @@ -272,7 +202,7 @@ namespace eap /// /// This method encapsulates inner data in EAP packets. /// - class method_eap : public method_tunnel + class method_eap : public method { public: /// diff --git a/lib/EAPBase/src/Method.cpp b/lib/EAPBase/src/Method.cpp index c9b0b4e..07670ff 100644 --- a/lib/EAPBase/src/Method.cpp +++ b/lib/EAPBase/src/Method.cpp @@ -28,10 +28,13 @@ using namespace winstd; // eap::method ////////////////////////////////////////////////////////////////////// -eap::method::method(_In_ module &mod) : +eap::method::method(_In_ module &mod, _In_opt_ method *inner) : m_module(mod), - m_outer(nullptr) + m_outer(nullptr), + m_inner(inner) { + if (m_inner) + m_inner->m_outer = this; } @@ -41,15 +44,36 @@ void eap::method::begin_session( _In_ HANDLE hTokenImpersonateUser, _In_opt_ DWORD dwMaxSendPacketSize) { - UNREFERENCED_PARAMETER(dwFlags); - UNREFERENCED_PARAMETER(pAttributeArray); - UNREFERENCED_PARAMETER(hTokenImpersonateUser); - UNREFERENCED_PARAMETER(dwMaxSendPacketSize); + if (m_inner) + m_inner->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); } void eap::method::end_session() { + if (m_inner) + m_inner->end_session(); +} + + +EapPeerMethodResponseAction eap::method::process_request_packet( + _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize) +{ + return m_inner ? + m_inner->process_request_packet(pReceivedPacket, dwReceivedPacketSize) : + EapPeerMethodResponseActionSend; +} + + +void eap::method::get_response_packet( + _Out_ sanitizing_blob &packet, + _In_opt_ DWORD size_max) +{ + if (m_inner) + m_inner->get_response_packet(packet, size_max); + else + packet.clear(); } @@ -57,15 +81,17 @@ void eap::method::get_result( _In_ EapPeerMethodResultReason reason, _Inout_ EapPeerMethodResult *pResult) { - UNREFERENCED_PARAMETER(reason); - UNREFERENCED_PARAMETER(pResult); + if (m_inner) + m_inner->get_result(reason, pResult); } void eap::method::get_ui_context(_Out_ sanitizing_blob &context_data) { - // Default implementation returns blank context data. - context_data.clear(); + if (m_inner) + m_inner->get_ui_context(context_data); + else + context_data.clear(); } @@ -73,11 +99,9 @@ EapPeerMethodResponseAction eap::method::set_ui_context( _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_ DWORD dwUIContextDataSize) { - UNREFERENCED_PARAMETER(pUIContextData); - UNREFERENCED_PARAMETER(dwUIContextDataSize); - - // Default implementation does nothing with context data. - return EapPeerMethodResponseActionNone; + return m_inner ? + m_inner->set_ui_context(pUIContextData, dwUIContextDataSize) : + EapPeerMethodResponseActionNone; } @@ -85,114 +109,20 @@ void eap::method::get_response_attributes(_Out_ EapAttributes *pAttribs) { assert(pAttribs); - // Default implementation returns no EAP attributes. - pAttribs->dwNumberOfAttributes = 0; - pAttribs->pAttribs = NULL; + if (m_inner) + m_inner->get_response_attributes(pAttribs); + else { + pAttribs->dwNumberOfAttributes = 0; + pAttribs->pAttribs = NULL; + } } EapPeerMethodResponseAction eap::method::set_response_attributes(_In_ const EapAttributes *pAttribs) { - UNREFERENCED_PARAMETER(pAttribs); - - // Default implementation does nothing with EAP attributes. - return EapPeerMethodResponseActionNone; -} - - -////////////////////////////////////////////////////////////////////// -// eap::method_tunnel -////////////////////////////////////////////////////////////////////// - -eap::method_tunnel::method_tunnel(_In_ module &mod, _In_ method *inner) : - m_inner(inner), - method(mod) -{ - assert(m_inner); - m_inner->m_outer = this; -} - - -void eap::method_tunnel::begin_session( - _In_ DWORD dwFlags, - _In_ const EapAttributes *pAttributeArray, - _In_ HANDLE hTokenImpersonateUser, - _In_opt_ DWORD dwMaxSendPacketSize) -{ - method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); - - assert(m_inner); - m_inner->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); -} - - -void eap::method_tunnel::end_session() -{ - assert(m_inner); - m_inner->end_session(); - - method::end_session(); -} - - -EapPeerMethodResponseAction eap::method_tunnel::process_request_packet( - _In_bytecount_(dwReceivedPacketSize) const void *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize) -{ - assert(m_inner); - return m_inner->process_request_packet(pReceivedPacket, dwReceivedPacketSize); -} - - -void eap::method_tunnel::get_response_packet( - _Out_ sanitizing_blob &packet, - _In_opt_ DWORD size_max) -{ - assert(m_inner); - m_inner->get_response_packet(packet, size_max); -} - - -void eap::method_tunnel::get_result( - _In_ EapPeerMethodResultReason reason, - _Inout_ EapPeerMethodResult *pResult) -{ - assert(m_inner); - m_inner->get_result(reason, pResult); -} - - -void eap::method_tunnel::get_ui_context(_Out_ sanitizing_blob &context_data) -{ - assert(m_inner); - - // Default implementation forwards UI context handling to the inner method. - m_inner->get_ui_context(context_data); -} - - -EapPeerMethodResponseAction eap::method_tunnel::set_ui_context( - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize) -{ - assert(m_inner); - - // Default implementation forwards UI context handling to the inner method. - return m_inner->set_ui_context(pUIContextData, dwUIContextDataSize); -} - - -void eap::method_tunnel::get_response_attributes(_Out_ EapAttributes *pAttribs) -{ - assert(m_inner); - m_inner->get_response_attributes(pAttribs); -} - - -EapPeerMethodResponseAction eap::method_tunnel::set_response_attributes(_In_ const EapAttributes *pAttribs) -{ - assert(m_inner); - return m_inner->set_response_attributes(pAttribs); + return m_inner ? + m_inner->set_response_attributes(pAttribs) : + EapPeerMethodResponseActionNone; } @@ -205,7 +135,7 @@ eap::method_eap::method_eap(_In_ module &mod, _In_ eap_type_t eap_method, _In_ c m_cred(cred), m_id(0), m_result(EapPeerMethodResultUnknown), - method_tunnel(mod, inner) + method(mod, inner) { } @@ -216,15 +146,11 @@ void eap::method_eap::begin_session( _In_ HANDLE hTokenImpersonateUser, _In_opt_ DWORD dwMaxSendPacketSize) { - // Initialize tunnel method session only. - method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); - // Inner method may generate packets of up to 64kB (less the EAP packet header). // Initialize inner method with appropriately less packet size maximum. if (dwMaxSendPacketSize < sizeof(EapPacket)) throw invalid_argument(string_printf(__FUNCTION__ " Maximum packet size too small (minimum: %zu, available: %u).", sizeof(EapPacket), dwMaxSendPacketSize)); - assert(m_inner); - m_inner->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, std::min(dwMaxSendPacketSize, MAXWORD) - sizeof(EapPacket)); + method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, std::min(dwMaxSendPacketSize, MAXWORD) - sizeof(EapPacket)); m_result = EapPeerMethodResultUnknown; m_packet_res.clear(); @@ -264,7 +190,7 @@ EapPeerMethodResponseAction eap::method_eap::process_request_packet( } else if ((eap_type_t)hdr->Data[0] == m_eap_method) { // Process the data with underlying method. m_packet_res.clear(); - return method_tunnel::process_request_packet(hdr->Data + 1, size_packet - sizeof(EapPacket)); + return method::process_request_packet(hdr->Data + 1, size_packet - sizeof(EapPacket)); } else { // Unsupported EAP method. Respond with Legacy Nak suggesting our EAP method to continue. make_response_packet(eap_type_t::nak, &m_eap_method, sizeof(eap_type_t)); @@ -294,7 +220,7 @@ void eap::method_eap::get_response_packet( if (m_packet_res.empty()) { // Get data from underlying method. - method_tunnel::get_response_packet(packet, size_max - sizeof(EapPacket)); + method::get_response_packet(packet, size_max - sizeof(EapPacket)); size_t size_packet = sizeof(EapPacket) + packet.size(); if (size_packet > size_max) @@ -327,8 +253,8 @@ void eap::method_eap::get_result( { switch (m_result) { case EapPeerMethodResultSuccess: - case EapPeerMethodResultFailure: return method_tunnel::get_result(m_result, pResult); - default : return method_tunnel::get_result(reason , pResult); + case EapPeerMethodResultFailure: return method::get_result(m_result, pResult); + default : return method::get_result(reason , pResult); } } diff --git a/lib/TTLS/include/Method.h b/lib/TTLS/include/Method.h index d50c46e..1409085 100644 --- a/lib/TTLS/include/Method.h +++ b/lib/TTLS/include/Method.h @@ -44,7 +44,7 @@ namespace eap /// /// EAP-(T)TLS/PEAP class defragging method tunnel /// - class method_defrag : public method_tunnel + class method_defrag : public method { public: #pragma warning(push) @@ -124,14 +124,14 @@ namespace eap /// /// Diameter EAP-Message tunnel method /// - class method_eapmsg : public method_tunnel + class method_eapmsg : public method { public: /// /// Constructs a method /// - /// \param[in] mod Module to use for global services - /// \param[in] inner Inner method + /// \param[in] mod Module to use for global services + /// \param[in] inner Inner method /// method_eapmsg(_In_ module &mod, _In_ method *inner); @@ -176,7 +176,7 @@ namespace eap /// /// TLS tunnel method /// - class method_tls_tunnel : public method_tunnel + class method_tls_tunnel : public method { public: /// diff --git a/lib/TTLS/src/Method.cpp b/lib/TTLS/src/Method.cpp index 9119c9b..a4bfbd6 100644 --- a/lib/TTLS/src/Method.cpp +++ b/lib/TTLS/src/Method.cpp @@ -34,7 +34,7 @@ eap::method_defrag::method_defrag(_In_ module &mod, _In_ unsigned char version_m m_version(version_max), m_phase(phase_t::unknown), m_send_res(false), - method_tunnel(mod, inner) + method(mod, inner) { } @@ -45,15 +45,11 @@ void eap::method_defrag::begin_session( _In_ HANDLE hTokenImpersonateUser, _In_opt_ DWORD dwMaxSendPacketSize) { - // Initialize tunnel method session only. - method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); - // Inner method may generate packets of up to 4GB. // But, we can not do the fragmentation if we have less space than flags+length. if (dwMaxSendPacketSize < 5) throw invalid_argument(string_printf(__FUNCTION__ " Maximum packet size too small (minimum: %u, available: %u).", 5, dwMaxSendPacketSize)); - assert(m_inner); - m_inner->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, MAXDWORD); + method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, MAXDWORD); m_phase = phase_t::init; } @@ -120,7 +116,7 @@ EapPeerMethodResponseAction eap::method_defrag::process_request_packet( } // Process the data with underlying method. - auto action = method_tunnel::process_request_packet(m_data_req.data(), (DWORD)m_data_req.size()); + auto action = method::process_request_packet(m_data_req.data(), (DWORD)m_data_req.size()); // Packet was processed. Clear its data since we use the absence of data to detect first of fragmented message packages. m_data_req.clear(); @@ -136,7 +132,7 @@ void eap::method_defrag::get_response_packet( if (!m_send_res) { // Get data from underlying method. - method_tunnel::get_response_packet(m_data_res, MAXDWORD); + method::get_response_packet(m_data_res, MAXDWORD); } size_t size_data = m_data_res.size(); @@ -168,7 +164,7 @@ void eap::method_defrag::get_response_packet( eap::method_eapmsg::method_eapmsg(_In_ module &mod, _In_ method *inner) : m_phase(phase_t::unknown), - method_tunnel(mod, inner) + method(mod, inner) { } @@ -179,15 +175,11 @@ void eap::method_eapmsg::begin_session( _In_ HANDLE hTokenImpersonateUser, _In_opt_ DWORD dwMaxSendPacketSize) { - // Initialize tunnel method session only. - method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); - // Inner method may generate packets of up to 16MB (less the Diameter AVP header). // Initialize inner method with appropriately less packet size maximum. if (dwMaxSendPacketSize < sizeof(diameter_avp_header)) throw invalid_argument(string_printf(__FUNCTION__ " Maximum packet size too small (minimum: %zu, available: %u).", sizeof(diameter_avp_header), dwMaxSendPacketSize)); - assert(m_inner); - m_inner->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, std::min(dwMaxSendPacketSize, 0xffffff) - sizeof(diameter_avp_header)); + method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, std::min(dwMaxSendPacketSize, 0xffffff) - sizeof(diameter_avp_header)); m_phase = phase_t::identity; } @@ -208,7 +200,7 @@ EapPeerMethodResponseAction eap::method_eapmsg::process_request_packet( m_phase = phase_t::finished; m_packet_res.clear(); - return method_tunnel::process_request_packet(&hdr_req, sizeof(EapPacket)); + return method::process_request_packet(&hdr_req, sizeof(EapPacket)); case phase_t::finished: { EapPeerMethodResponseAction action = EapPeerMethodResponseActionNone; @@ -232,7 +224,7 @@ EapPeerMethodResponseAction eap::method_eapmsg::process_request_packet( switch (code) { case 79: // EAP-Message if (!eap_message_found) { - action = method_tunnel::process_request_packet(msg, (DWORD)(msg_end - msg)); + action = method::process_request_packet(msg, (DWORD)(msg_end - msg)); eap_message_found = true; break; } @@ -267,7 +259,7 @@ void eap::method_eapmsg::get_response_packet( // Get data from underlying method. assert(size_max >= sizeof(diameter_avp_header)); // We should be able to respond with at least Diameter AVP header. - method_tunnel::get_response_packet(packet, size_max - sizeof(diameter_avp_header)); + method::get_response_packet(packet, size_max - sizeof(diameter_avp_header)); // Prepare EAP-Message Diameter AVP header. diameter_avp_header hdr; @@ -304,7 +296,7 @@ eap::method_tls_tunnel::method_tls_tunnel(_In_ module &mod, _In_ eap_type_t eap_ m_user_ctx(NULL), m_phase(phase_t::unknown), m_packet_res_inner(false), - method_tunnel(mod, inner) + method(mod, inner) { m_eap_attr_desc.dwNumberOfAttributes = 0; m_eap_attr_desc.pAttribs = NULL; @@ -320,7 +312,7 @@ void eap::method_tls_tunnel::begin_session( // In TLS, maximum packet length can precisely be calculated only after handshake is complete. // Therefore, we allow inner method same maximum packet size as this method. // Initialize tunnel and inner method session with same parameters. - method_tunnel::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); + method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); // Presume authentication will fail with generic protocol failure. (Pesimist!!!) // We will reset once we get get_result(Success) call. @@ -620,7 +612,7 @@ void eap::method_tls_tunnel::get_response_packet( // Get inner response packet. packet.reserve((size_t)sizes.cbHeader + sizes.cbMaximumMessage + sizes.cbTrailer); - method_tunnel::get_response_packet(packet, sizes.cbMaximumMessage); + method::get_response_packet(packet, sizes.cbMaximumMessage); if (!packet.empty()) { DWORD size_data = (DWORD)packet.size(); @@ -659,7 +651,7 @@ void eap::method_tls_tunnel::get_result( assert(pResult); // Get inner result. - method_tunnel::get_result(reason, pResult); + method::get_result(reason, pResult); if (reason == EapPeerMethodResultSuccess) { eap_attr a; @@ -729,7 +721,7 @@ EapPeerMethodResponseAction eap::method_tls_tunnel::decrypt_request_data() EapPeerMethodResponseAction action = EapPeerMethodResponseActionDiscard; if (m_sc_queue.empty()) { // No data for inner authentication avaliable. - action = method_tunnel::process_request_packet(NULL, 0); + action = method::process_request_packet(NULL, 0); } else { // Authenticator sent data for inner authentication. Decrypt it. @@ -746,7 +738,7 @@ EapPeerMethodResponseAction eap::method_tls_tunnel::decrypt_request_data() // Process data (only the first SECBUFFER_DATA found). for (size_t i = 0; i < _countof(buf); i++) if (buf[i].BufferType == SECBUFFER_DATA) { - action = method_tunnel::process_request_packet(buf[i].pvBuffer, buf[i].cbBuffer); + action = method::process_request_packet(buf[i].pvBuffer, buf[i].cbBuffer); break; }