diff --git a/EAPMethods/src/Main.cpp b/EAPMethods/src/Main.cpp index 8678ec2..602d61b 100644 --- a/EAPMethods/src/Main.cpp +++ b/EAPMethods/src/Main.cpp @@ -376,11 +376,12 @@ DWORD APIENTRY EapPeerProcessRequestPacket( if (!hSession) g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" hSession is NULL."))); - else if (!pReceivedPacket && dwReceivedPacketSize) - g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pReceivedPacket is NULL."))); + else if (!pReceivedPacket || dwReceivedPacketSize < 4) + g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pReceivedPacket is NULL or too short."))); else if (!pEapOutput) g_peer.log_error(*ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" pEapOutput is NULL."))); else { + assert(dwReceivedPacketSize == ntohs(*(WORD*)pReceivedPacket->Length)); if (!static_cast<_EAPMETHOD_SESSION*>(hSession)->process_request_packet(dwReceivedPacketSize, pReceivedPacket, pEapOutput, ppEapError)) { if (*ppEapError) { g_peer.log_error(*ppEapError); diff --git a/lib/EAPBase/include/Module.h b/lib/EAPBase/include/Module.h index abbac2d..3642150 100644 --- a/lib/EAPBase/include/Module.h +++ b/lib/EAPBase/include/Module.h @@ -622,7 +622,7 @@ namespace eap *pdwDataOutSize = (DWORD)data_enc.size(); *ppDataOut = alloc_memory(*pdwDataOutSize); if (!*ppDataOut) { - log_error(*ppEapError = g_peer.make_error(ERROR_OUTOFMEMORY, tstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for BLOB (%uB)."), *pdwDataOutSize).c_str())); + log_error(*ppEapError = g_peer.make_error(ERROR_OUTOFMEMORY, wstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for BLOB (%uB)."), *pdwDataOutSize).c_str())); return false; } memcpy(*ppDataOut, data_enc.data(), *pdwDataOutSize); @@ -631,7 +631,7 @@ namespace eap *pdwDataOutSize = (DWORD)pksizeof(record); *ppDataOut = alloc_memory(*pdwDataOutSize); if (!*ppDataOut) { - log_error(*ppEapError = g_peer.make_error(ERROR_OUTOFMEMORY, tstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for BLOB (%uB)."), *pdwDataOutSize).c_str())); + log_error(*ppEapError = g_peer.make_error(ERROR_OUTOFMEMORY, wstring_printf(_T(__FUNCTION__) _T(" Error allocating memory for BLOB (%uB)."), *pdwDataOutSize).c_str())); return false; } diff --git a/lib/EAPBase/include/Session.h b/lib/EAPBase/include/Session.h index e685afb..4d5ea29 100644 --- a/lib/EAPBase/include/Session.h +++ b/lib/EAPBase/include/Session.h @@ -224,7 +224,6 @@ namespace eap _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) = 0; - /// /// Obtains a response packet from the EAP method. /// @@ -237,23 +236,7 @@ namespace eap virtual bool get_response_packet( _Inout_ DWORD *pdwSendPacketSize, _Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket, - _Out_ EAP_ERROR **ppEapError) - { - assert(pdwSendPacketSize); - assert(pSendPacket); - assert(ppEapError); - - WORD size = m_packet.size(); - if (size > *pdwSendPacketSize) { - *ppEapError = m_module.make_error(ERROR_INSUFFICIENT_BUFFER, winstd::string_printf(_T(__FUNCTION__) _T(" Packet buffer is too small (%uB required, %uB provided)."), m_packet.size(), *pdwSendPacketSize).c_str()); - return false; - } - memcpy(pSendPacket, (const EapPacket*)m_packet, size); - *pdwSendPacketSize = size; - - return true; - } - + _Out_ EAP_ERROR **ppEapError) = 0; /// /// Obtains the result of an authentication session from the EAP method. @@ -366,13 +349,12 @@ namespace eap /// @} public: - module &m_module; ///< Reference of the EAP module - config_providers m_cfg; ///< Session configuration - credentials_type m_cred; ///< User credentials - winstd::eap_packet m_packet; ///< Response packet - interactive_request_type m_intreq; ///< Interactive UI request data - DWORD m_eap_flags; ///< A combination of EAP flags that describe the new EAP authentication session behavior - HANDLE m_token; ///< Specifies a handle to the user impersonation token to use in this session - DWORD m_send_packet_size_max; ///< Specifies the maximum size in bytes of an EAP packet sent during the session. If the method needs to send a packet larger than the maximum size, the method must accommodate fragmentation and reassembly. + module &m_module; ///< Reference of the EAP module + config_providers m_cfg; ///< Session configuration + credentials_type m_cred; ///< User credentials + interactive_request_type m_intreq; ///< Interactive UI request data + DWORD m_eap_flags; ///< A combination of EAP flags that describe the new EAP authentication session behavior + HANDLE m_token; ///< Specifies a handle to the user impersonation token to use in this session + DWORD m_send_packet_size_max; ///< Specifies the maximum size in bytes of an EAP packet sent during the session. If the method needs to send a packet larger than the maximum size, the method must accommodate fragmentation and reassembly. }; } diff --git a/lib/Events/build/Events.vcxproj b/lib/Events/build/Events.vcxproj index 06c569f..317767e 100644 --- a/lib/Events/build/Events.vcxproj +++ b/lib/Events/build/Events.vcxproj @@ -93,6 +93,7 @@ $(IntDir)EventsETW.h;$(IntDir)EventsETW.rc;$(IntDir)EventsETW_MSG00001.bin;$(IntDir)EventsETWTEMP.BIN;%(Outputs) $(IntDir)EventsETW.h;$(IntDir)EventsETW.rc;$(IntDir)EventsETW_MSG00001.bin;$(IntDir)EventsETWTEMP.BIN;%(Outputs) $(IntDir)EventsETW.h;$(IntDir)EventsETW.rc;$(IntDir)EventsETW_MSG00001.bin;$(IntDir)EventsETWTEMP.BIN;%(Outputs) + Designer diff --git a/lib/Events/res/EventsETW.man b/lib/Events/res/EventsETW.man index 1a2fbf1..2578a70 100644 Binary files a/lib/Events/res/EventsETW.man and b/lib/Events/res/EventsETW.man differ diff --git a/lib/TLS/build/TLS.vcxproj b/lib/TLS/build/TLS.vcxproj index 15f4e4c..85b4ca7 100644 --- a/lib/TLS/build/TLS.vcxproj +++ b/lib/TLS/build/TLS.vcxproj @@ -81,10 +81,12 @@ + + Create Create diff --git a/lib/TLS/build/TLS.vcxproj.filters b/lib/TLS/build/TLS.vcxproj.filters index 3761eec..587889a 100644 --- a/lib/TLS/build/TLS.vcxproj.filters +++ b/lib/TLS/build/TLS.vcxproj.filters @@ -20,6 +20,9 @@ Header Files + + Header Files + @@ -31,5 +34,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/lib/TLS/include/Session.h b/lib/TLS/include/Session.h new file mode 100644 index 0000000..056f17f --- /dev/null +++ b/lib/TLS/include/Session.h @@ -0,0 +1,141 @@ +/* + Copyright 2015-2016 Amebis + Copyright 2016 GÉANT + + This file is part of GÉANTLink. + + GÉANTLink is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + GÉANTLink is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GÉANTLink. If not, see . +*/ + +namespace eap +{ + /// + /// TLS session + /// + class session_tls; +} + +#pragma once + +#include "../include/Config.h" +#include "../include/Credentials.h" + +#include "../../EAPBase/include/Session.h" + +#include + + +namespace eap +{ + class session_tls : public session + { + public: + /// + /// Constructor + /// + /// \param[in] mod Reference of the EAP module to use for global services + /// + session_tls(_In_ module &mod); + + /// + /// Copies TLS session + /// + /// \param[in] other Session to copy from + /// + session_tls(_In_ const session_tls &other); + + /// + /// Moves TLS session + /// + /// \param[in] other Session to move from + /// + session_tls(_Inout_ session_tls &&other); + + /// + /// Copies TLS session + /// + /// \param[in] other Session to copy from + /// + /// \returns Reference to this object + /// + session_tls& operator=(_In_ const session_tls &other); + + /// + /// Moves TLS session + /// + /// \param[in] other Session to move from + /// + /// \returns Reference to this object + /// + session_tls& operator=(_Inout_ session_tls &&other); + + /// \name Session start/end + /// @{ + + /// + /// Starts an EAP authentication session on the peer EAPHost using the EAP method. + /// + /// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx) + /// + /// \returns + /// - \c true if succeeded + /// - \c false otherwise. See \p ppEapError for details. + /// + //virtual bool begin( + // _In_ DWORD dwFlags, + // _In_ const EapAttributes *pAttributeArray, + // _In_ HANDLE hTokenImpersonateUser, + // _In_ DWORD dwMaxSendPacketSize, + // _Out_ EAP_ERROR **ppEapError); + + /// @} + + /// \name Packet processing + /// @{ + + /// + /// Processes a packet received by EAPHost from a supplicant. + /// + /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) + /// + /// \returns + /// - \c true if succeeded + /// - \c false otherwise. See \p ppEapError for details. + /// + virtual bool process_request_packet( + _In_ DWORD dwReceivedPacketSize, + _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, + _Out_ EapPeerMethodOutput *pEapOutput, + _Out_ EAP_ERROR **ppEapError); + + /// + /// Obtains the result of an authentication session from the EAP method. + /// + /// \sa [EapPeerGetResult function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363611.aspx) + /// + /// \returns + /// - \c true if succeeded + /// - \c false otherwise. See \p ppEapError for details. + /// + virtual bool get_result( + _In_ EapPeerMethodResultReason reason, + _Out_ EapPeerMethodResult *ppResult, + _Out_ EAP_ERROR **ppEapError); + + /// @} + + public: + winstd::crypt_prov m_cp; ///< Cryptography provider + }; +} diff --git a/lib/TLS/src/Session.cpp b/lib/TLS/src/Session.cpp new file mode 100644 index 0000000..6328c13 --- /dev/null +++ b/lib/TLS/src/Session.cpp @@ -0,0 +1,109 @@ +/* + Copyright 2015-2016 Amebis + Copyright 2016 GÉANT + + This file is part of GÉANTLink. + + GÉANTLink is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + GÉANTLink is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GÉANTLink. If not, see . +*/ + +#include "StdAfx.h" + +using namespace std; +using namespace winstd; + + +////////////////////////////////////////////////////////////////////// +// eap::session_tls +////////////////////////////////////////////////////////////////////// + +eap::session_tls::session_tls(_In_ module &mod) : session(mod) +{ +} + + +eap::session_tls::session_tls(_In_ const session_tls &other) : + session(other) +{ +} + + +eap::session_tls::session_tls(_Inout_ session_tls &&other) : + session(std::move(other)) +{ +} + + +eap::session_tls& eap::session_tls::operator=(_In_ const session_tls &other) +{ + if (this != &other) + (session&)*this = other; + + return *this; +} + + +eap::session_tls& eap::session_tls::operator=(_Inout_ session_tls &&other) +{ + if (this != &other) + (session&)*this = std::move(other); + + return *this; +} + + +//bool eap::session_tls::begin( +// _In_ DWORD dwFlags, +// _In_ const EapAttributes *pAttributeArray, +// _In_ HANDLE hTokenImpersonateUser, +// _In_ DWORD dwMaxSendPacketSize, +// _Out_ EAP_ERROR **ppEapError) +//{ +// if (!session::begin(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize, ppEapError)) +// return false; +// +// +// +// return true; +//} + + +bool eap::session_tls::process_request_packet( + _In_ DWORD dwReceivedPacketSize, + _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, + _Out_ EapPeerMethodOutput *pEapOutput, + _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(dwReceivedPacketSize); + UNREFERENCED_PARAMETER(pReceivedPacket); + UNREFERENCED_PARAMETER(pEapOutput); + assert(ppEapError); + + *ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, _T(__FUNCTION__) _T(" Not supported.")); + return false; +} + + +bool eap::session_tls::get_result( + _In_ EapPeerMethodResultReason reason, + _Out_ EapPeerMethodResult *ppResult, + _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(reason); + UNREFERENCED_PARAMETER(ppResult); + assert(ppEapError); + + *ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, _T(__FUNCTION__) _T(" Not supported.")); + return false; +} diff --git a/lib/TLS/src/StdAfx.h b/lib/TLS/src/StdAfx.h index 81cf762..92f3151 100644 --- a/lib/TLS/src/StdAfx.h +++ b/lib/TLS/src/StdAfx.h @@ -22,6 +22,7 @@ #include "../include/Config.h" #include "../include/Credentials.h" +#include "../include/Session.h" #include "../../EAPBase/include/EAPXML.h" diff --git a/lib/TTLS/include/Session.h b/lib/TTLS/include/Session.h index 40d6225..50863b7 100644 --- a/lib/TTLS/include/Session.h +++ b/lib/TTLS/include/Session.h @@ -24,6 +24,14 @@ namespace eap /// TTLS session /// class session_ttls; + + + /// + /// EAP-TTLS packet flags + /// + /// \sa [Extensible Authentication Protocol Tunneled Transport Layer Security Authenticated Protocol Version 0 (EAP-TTLSv0) (Chapter: 9.1 Packet Format)](https://tools.ietf.org/html/rfc5281#section-9.1) + /// + enum ttls_flags_t; } #pragma once @@ -33,6 +41,14 @@ namespace eap namespace eap { + enum ttls_flags_t { + ttls_flags_length_incl = 0x80, ///< Length included + ttls_flags_more_frag = 0x40, ///< More fragments + ttls_flags_start = 0x20, ///< Start + ttls_flags_ver_mask = 0x07, ///< Version mask + }; + + class session_ttls : public session { public: @@ -75,6 +91,27 @@ namespace eap /// session_ttls& operator=(_Inout_ session_ttls &&other); + /// \name Session start/end + /// @{ + + /// + /// Starts an EAP authentication session on the peer EAPHost using the EAP method. + /// + /// \sa [EapPeerBeginSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363600.aspx) + /// + /// \returns + /// - \c true if succeeded + /// - \c false otherwise. See \p ppEapError for details. + /// + virtual bool begin( + _In_ DWORD dwFlags, + _In_ const EapAttributes *pAttributeArray, + _In_ HANDLE hTokenImpersonateUser, + _In_ DWORD dwMaxSendPacketSize, + _Out_ EAP_ERROR **ppEapError); + + /// @} + /// \name Packet processing /// @{ @@ -93,6 +130,20 @@ namespace eap _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError); + /// + /// Obtains a response packet from the EAP method. + /// + /// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx) + /// + /// \returns + /// - \c true if succeeded + /// - \c false otherwise. See \p ppEapError for details. + /// + virtual bool get_response_packet( + _Inout_ DWORD *pdwSendPacketSize, + _Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket, + _Out_ EAP_ERROR **ppEapError); + /// /// Obtains the result of an authentication session from the EAP method. /// @@ -108,5 +159,23 @@ namespace eap _Out_ EAP_ERROR **ppEapError); /// @} + + public: + enum phase_t { + phase_handshake_start = 0, + } m_phase; ///< Session phase + + enum version_t { + version_0 = 0, ///< EAP-TTLS v0 + } m_version; ///< EAP-TTLS version + + struct { + EapCode m_code; ///< Packet code + BYTE m_id; ///< Packet ID + BYTE m_flags; ///< Packet flags + std::vector m_data; ///< Packet data + } + m_packet_req, ///< Request packet + m_packet_res; ///< Response packet }; } diff --git a/lib/TTLS/src/Session.cpp b/lib/TTLS/src/Session.cpp index b6cc36c..83f7754 100644 --- a/lib/TTLS/src/Session.cpp +++ b/lib/TTLS/src/Session.cpp @@ -28,27 +28,72 @@ using namespace winstd; // eap::session_ttls ////////////////////////////////////////////////////////////////////// -eap::session_ttls::session_ttls(_In_ module &mod) : session(mod) +eap::session_ttls::session_ttls(_In_ module &mod) : + m_phase(phase_handshake_start), + m_version(version_0), + session(mod) { + m_packet_req.m_code = (EapCode)0; + m_packet_req.m_id = 0; + m_packet_req.m_flags = version_0; + + m_packet_res.m_code = (EapCode)0; + m_packet_res.m_id = 0; + m_packet_res.m_flags = version_0; } eap::session_ttls::session_ttls(_In_ const session_ttls &other) : + m_phase(other.m_phase), + m_version(other.m_version), session(other) { + m_packet_req.m_code = other.m_packet_req.m_code ; + m_packet_req.m_id = other.m_packet_req.m_id ; + m_packet_req.m_flags = other.m_packet_req.m_flags; + m_packet_req.m_data = other.m_packet_req.m_data ; + + m_packet_res.m_code = other.m_packet_res.m_code ; + m_packet_res.m_id = other.m_packet_res.m_id ; + m_packet_res.m_flags = other.m_packet_res.m_flags; + m_packet_res.m_data = other.m_packet_res.m_data ; } eap::session_ttls::session_ttls(_Inout_ session_ttls &&other) : + m_phase(std::move(other.m_phase)), + m_version(std::move(other.m_version)), session(std::move(other)) { + m_packet_req.m_code = std::move(other.m_packet_req.m_code ); + m_packet_req.m_id = std::move(other.m_packet_req.m_id ); + m_packet_req.m_flags = std::move(other.m_packet_req.m_flags); + m_packet_req.m_data = std::move(other.m_packet_req.m_data ); + + m_packet_res.m_code = std::move(other.m_packet_res.m_code ); + m_packet_res.m_id = std::move(other.m_packet_res.m_id ); + m_packet_res.m_flags = std::move(other.m_packet_res.m_flags); + m_packet_res.m_data = std::move(other.m_packet_res.m_data ); } eap::session_ttls& eap::session_ttls::operator=(_In_ const session_ttls &other) { - if (this != &other) + if (this != &other) { (session&)*this = other; + m_phase = other.m_phase; + m_version = other.m_version; + + m_packet_req.m_code = other.m_packet_req.m_code ; + m_packet_req.m_id = other.m_packet_req.m_id ; + m_packet_req.m_flags = other.m_packet_req.m_flags; + m_packet_req.m_data = other.m_packet_req.m_data ; + + m_packet_res.m_code = other.m_packet_res.m_code ; + m_packet_res.m_id = other.m_packet_res.m_id ; + m_packet_res.m_flags = other.m_packet_res.m_flags; + m_packet_res.m_data = other.m_packet_res.m_data ; + } return *this; } @@ -56,26 +101,193 @@ eap::session_ttls& eap::session_ttls::operator=(_In_ const session_ttls &other) eap::session_ttls& eap::session_ttls::operator=(_Inout_ session_ttls &&other) { - if (this != &other) + if (this != &other) { (session&)*this = std::move(other); + m_phase = std::move(other.m_phase); + m_version = std::move(other.m_version); + + m_packet_req.m_code = std::move(other.m_packet_req.m_code ); + m_packet_req.m_id = std::move(other.m_packet_req.m_id ); + m_packet_req.m_flags = std::move(other.m_packet_req.m_flags); + m_packet_req.m_data = std::move(other.m_packet_req.m_data ); + + m_packet_res.m_code = std::move(other.m_packet_res.m_code ); + m_packet_res.m_id = std::move(other.m_packet_res.m_id ); + m_packet_res.m_flags = std::move(other.m_packet_res.m_flags); + m_packet_res.m_data = std::move(other.m_packet_res.m_data ); + } return *this; } +bool eap::session_ttls::begin( + _In_ DWORD dwFlags, + _In_ const EapAttributes *pAttributeArray, + _In_ HANDLE hTokenImpersonateUser, + _In_ DWORD dwMaxSendPacketSize, + _Out_ EAP_ERROR **ppEapError) +{ + if (dwMaxSendPacketSize <= 10) { + *ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, wstring_printf(_T(__FUNCTION__) _T(" Maximum send packet size too small (expected: >%u, received: %u)."), 10, dwMaxSendPacketSize).c_str()); + return false; + } + + return session::begin(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize, ppEapError); +} + + bool eap::session_ttls::process_request_packet( _In_ DWORD dwReceivedPacketSize, _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) { - UNREFERENCED_PARAMETER(dwReceivedPacketSize); - UNREFERENCED_PARAMETER(pReceivedPacket); - UNREFERENCED_PARAMETER(pEapOutput); + assert(pReceivedPacket && dwReceivedPacketSize >= 4); + assert(pEapOutput); assert(ppEapError); - *ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, _T(__FUNCTION__) _T(" Not supported.")); - return false; + // Initialize output. + pEapOutput->fAllowNotifications = TRUE; + pEapOutput->action = EapPeerMethodResponseActionDiscard; + + // Is this a valid EAP-TTLS packet? + if (dwReceivedPacketSize < 6) { + *ppEapError = m_module.make_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, _T(__FUNCTION__) _T(" Packet is too small. EAP-TTLS packets should be at least 6B.")); + return false; + } else if (pReceivedPacket->Data[0] != eap_type_ttls) { + *ppEapError = m_module.make_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, wstring_printf(_T(__FUNCTION__) _T(" Packet is not EAP-TTLS (expected: %u, received: %u)."), eap_type_ttls, pReceivedPacket->Data[0]).c_str()); + return false; + } + + if (pReceivedPacket->Data[1] & ttls_flags_more_frag) { + if (pReceivedPacket->Data[1] & ttls_flags_length_incl) { + // First fragment received. + if (dwReceivedPacketSize < 10) { + *ppEapError = m_module.make_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, _T(__FUNCTION__) _T(" Packet is too small. EAP-TTLS first fragmented packet should be at least 10B.")); + return false; + } + + // Start a new packet. + m_packet_req.m_code = (EapCode)pReceivedPacket->Code; + m_packet_req.m_id = pReceivedPacket->Id; + m_packet_req.m_flags = pReceivedPacket->Data[1]; + m_packet_req.m_data.reserve(*(DWORD*)(pReceivedPacket->Data + 2)); + m_packet_req.m_data.assign(pReceivedPacket->Data + 6, pReceivedPacket->Data + dwReceivedPacketSize - 4); + } else { + // Mid fragment received. Append data. + m_packet_req.m_data.insert(m_packet_req.m_data.end(), pReceivedPacket->Data + 2, pReceivedPacket->Data + dwReceivedPacketSize - 4); + } + + // Reply with Acknowledgement packet. + m_packet_res.m_code = EapCodeResponse; + m_packet_res.m_id = m_packet_req.m_id; + m_packet_res.m_flags = 0; + m_packet_res.m_data.clear(); + pEapOutput->action = EapPeerMethodResponseActionSend; + return true; + } else if (!m_packet_req.m_data.empty()) { + // Last fragment received. Append data. + m_packet_req.m_data.insert(m_packet_req.m_data.end(), + pReceivedPacket->Data + (!(pReceivedPacket->Data[1] & ttls_flags_length_incl) ? 2 : 6), // Should not include "Length" field (by RFC 5281: https://tools.ietf.org/html/rfc5281#section-9.2.2). Tolerate. + pReceivedPacket->Data + dwReceivedPacketSize - 4); + } + + if ( m_packet_req.m_code == EapCodeResponse && + m_packet_req.m_id == m_packet_res.m_id && + !(m_packet_req.m_flags & (ttls_flags_length_incl | ttls_flags_more_frag | ttls_flags_start)) && + (m_packet_res.m_flags & ttls_flags_more_frag )) + { + // This is an Acknowledgement of our fragmented packet response. Send the next fragment. + pEapOutput->action = EapPeerMethodResponseActionSend; + return true; + } + + switch (m_phase) { + case phase_handshake_start: { + // Is this an EAP-TTLS Start packet? + if (m_packet_req.m_code != EapCodeRequest) { + *ppEapError = m_module.make_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, wstring_printf(_T(__FUNCTION__) _T(" Packet is not a request (expected: %x, received: %x)."), EapCodeRequest, m_packet_req.m_code).c_str()); + return false; + } else if (!(m_packet_req.m_flags & ttls_flags_start)) { + *ppEapError = m_module.make_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, wstring_printf(_T(__FUNCTION__) _T(" Packet is not EAP-TTLS Start (expected: %x, received: %x)."), ttls_flags_start, m_packet_req.m_flags).c_str()); + return false; + } + + // Determine minimum EAP-TTLS version supported by server and us. + version_t ver_remote = (version_t)(m_packet_req.m_flags & ttls_flags_ver_mask); + m_version = std::min(ver_remote, version_0); + m_module.log_event(&EAPMETHOD_HANDSHAKE_START, event_data(m_cred.target_suffix()), event_data((unsigned char)m_version), event_data((unsigned char)ver_remote), event_data::blank); + + // Build response packet. + //if (!m_packet_res.create(EapCodeResponse, pReceivedPacket->Id, eap_type_ttls, (BYTE)m_version)) { + // *ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error creating packet.")); + // return false; + //} + break; + } + + default: + *ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, _T(__FUNCTION__) _T(" Not supported.")); + return false; + } + + return true; +} + + +bool eap::session_ttls::get_response_packet( + _Inout_ DWORD *pdwSendPacketSize, + _Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket, + _Out_ EAP_ERROR **ppEapError) +{ + assert(pdwSendPacketSize); + assert(pSendPacket); + UNREFERENCED_PARAMETER(ppEapError); + + DWORD + size_data = (DWORD)m_packet_res.m_data.size(), + size_packet = size_data + 6; + WORD size_packet_limit = (WORD)std::min(m_send_packet_size_max, (WORD)-1); + BYTE *data_dst; + + if (!(m_packet_res.m_flags & ttls_flags_more_frag)) { + // Not fragmented. + if (size_packet <= size_packet_limit) { + // No need to fragment the packet. + m_packet_res.m_flags &= ~ttls_flags_length_incl; // No need to explicitly include the Length field either. + data_dst = pSendPacket->Data + 2; + } else { + // But it should be fragmented. + m_packet_res.m_flags |= ttls_flags_length_incl | ttls_flags_more_frag; + *(DWORD*)(pSendPacket->Data + 2) = (DWORD)size_packet; + data_dst = pSendPacket->Data + 6; + size_data = size_packet_limit - 10; + size_packet = size_packet_limit; + } + } else { + // Continuing the fragmented packet... + if (size_packet <= size_packet_limit) { + // This is the last fragment. + m_packet_res.m_flags &= ~(ttls_flags_length_incl | ttls_flags_more_frag); + } else { + // This is a mid fragment. + m_packet_res.m_flags &= ~ttls_flags_length_incl; + size_data = size_packet_limit - 6; + size_packet = size_packet_limit; + } + data_dst = pSendPacket->Data + 2; + } + + pSendPacket->Code = (BYTE)m_packet_res.m_code; + pSendPacket->Id = m_packet_res.m_id; + *(WORD*)pSendPacket->Length = htons((WORD)size_packet); + pSendPacket->Data[0] = (BYTE)eap_type_ttls; + pSendPacket->Data[1] = m_packet_res.m_flags | (BYTE)m_version; + memcpy(data_dst, m_packet_res.m_data.data(), size_data); + m_packet_res.m_data.erase(m_packet_res.m_data.begin(), m_packet_res.m_data.begin() + size_data); + *pdwSendPacketSize = size_packet; + return true; } diff --git a/lib/TTLS/src/StdAfx.h b/lib/TTLS/src/StdAfx.h index c396688..012310e 100644 --- a/lib/TTLS/src/StdAfx.h +++ b/lib/TTLS/src/StdAfx.h @@ -28,3 +28,5 @@ #include "../../EAPBase/include/EAPXML.h" #include + +#include diff --git a/lib/WinStd b/lib/WinStd index 4b63d60..d82a31e 160000 --- a/lib/WinStd +++ b/lib/WinStd @@ -1 +1 @@ -Subproject commit 4b63d60b01c7f579f4da2d5d61bb766813884a9f +Subproject commit d82a31e543b86505380719f7dca478e20a66d294