diff --git a/EAPMethods/build/EAPTTLS.vcxproj b/EAPMethods/build/EAPTTLS.vcxproj index 2b4778e..cde66e1 100644 --- a/EAPMethods/build/EAPTTLS.vcxproj +++ b/EAPMethods/build/EAPTTLS.vcxproj @@ -79,9 +79,13 @@ + + + + Create diff --git a/EAPMethods/build/EAPTTLS.vcxproj.filters b/EAPMethods/build/EAPTTLS.vcxproj.filters index 1c80dcd..be1489a 100644 --- a/EAPMethods/build/EAPTTLS.vcxproj.filters +++ b/EAPMethods/build/EAPTTLS.vcxproj.filters @@ -18,6 +18,12 @@ Header Files + + Header Files + + + Header Files + @@ -26,6 +32,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/EAPMethods/include/EAPMethods.h b/EAPMethods/include/EAPMethods.h new file mode 100644 index 0000000..bf821d2 --- /dev/null +++ b/EAPMethods/include/EAPMethods.h @@ -0,0 +1,454 @@ +/* + Copyright 2015-2016 Amebis + Copyright 2016 GÉANT + + This file is part of GEANTLink. + + GEANTLink 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. + + GEANTLink 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 GEANTLink. If not, see . +*/ + +#include +#include + +#include +extern "C" { +#include +} + +#include + +#include + + +namespace eap +{ + class session_base; + template class peer; +}; + +#pragma once + + +#define ETW_ERROR(kw, f, ...) m_ep.write(TRACE_LEVEL_ERROR , kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define ETW_WARNING(kw, f, ...) m_ep.write(TRACE_LEVEL_WARNING , kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define ETW_INFO(kw, f, ...) m_ep.write(TRACE_LEVEL_INFORMATION, kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define ETW_VERBOSE(kw, f, ...) m_ep.write(TRACE_LEVEL_VERBOSE , kw, _T(__FUNCTION__) _T(" ") f, ##__VA_ARGS__) +#define ETW_FN_VOID winstd::event_fn_auto < &EAPMETHOD_TRACE_EVT_FN_CALL, &EAPMETHOD_TRACE_EVT_FN_RETURN > _event_auto(m_ep, __FUNCTION__) +#define ETW_FN_DWORD(res) winstd::event_fn_auto_ret _event_auto(m_ep, __FUNCTION__, res) +#define ETW_FN_HRESULT(res) winstd::event_fn_auto_ret _event_auto(m_ep, __FUNCTION__, res) + + +namespace eap +{ + /// + /// EAP session + /// + class session_base + { + public: + /// + /// Constructor + /// + session_base(); + + /// + /// 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) + /// + virtual DWORD begin(_In_ DWORD dwFlags, _In_ const EapAttributes *pAttributeArray, _In_ HANDLE hTokenImpersonateUser, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) BYTE *pUserData, _In_ DWORD dwMaxSendPacketSize, _Out_ EAP_ERROR **ppEapError); + + /// + /// Ends an EAP authentication session for the EAP method. + /// + /// \sa [EapPeerEndSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363604.aspx) + /// + virtual DWORD end(_Out_ EAP_ERROR **ppEapError); + + /// + /// Processes a packet received by EAPHost from a supplicant. + /// + /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) + /// + virtual DWORD process_request_packet(_In_ DWORD dwSizeofReceivePacket, _In_bytecount_(dwSizeofReceivePacket) EapPacket *pReceivePacket, _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) + /// + virtual DWORD get_response_packet(_Inout_ DWORD *pcbSendPacket, _Out_cap_(*pcbSendPacket) EapPacket *pSendPacket, _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) + /// + virtual DWORD get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError); + + /// + /// Obtains the user interface context from the EAP method. + /// + /// \note This function is always followed by the `EapPeerInvokeInteractiveUI()` function, which is followed by the `EapPeerSetUIContext()` function. + /// + /// \sa [EapPeerGetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363612.aspx) + /// + virtual DWORD get_ui_context(_Out_ DWORD *dwSizeOfUIContextData, _Out_cap_(*dwSizeOfUIContextData) BYTE **pUIContextData, _Out_ EAP_ERROR **ppEapError); + + /// + /// Provides a user interface context to the EAP method. + /// + /// \note This function is called after the UI has been raised through the `EapPeerGetUIContext()` function. + /// + /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) + /// + virtual DWORD set_ui_context(_In_ DWORD dwSizeOfUIContextData, _In_count_(dwSizeOfUIContextData) const BYTE *pUIContextData, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError); + + /// + /// Obtains an array of EAP response attributes from the EAP method. + /// + /// \sa [EapPeerGetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363609.aspx) + /// + virtual DWORD get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError); + + /// + /// Provides an updated array of EAP response attributes to the EAP method. + /// + /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) + /// + virtual DWORD set_response_attributes(_In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError); + }; + + + /// + /// EAP peer base class + /// + template + class peer + { + public: + inline DWORD create() + { + m_ep.create(&EAPMETHOD_TRACE_EVENT_PROVIDER); + m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, winstd::event_data((BYTE)EAPMETHOD_TYPE), winstd::event_data::blank); + + if (!m_heap.create(0, 0, 0)) + return ERROR_OUTOFMEMORY; + + return ERROR_SUCCESS; + } + + + virtual ~peer() + { + m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, winstd::event_data((BYTE)EAPMETHOD_TYPE), winstd::event_data::blank); + } + + + /// + /// Obtains a set of function pointers for an implementation of the EAP peer method currently loaded on the EAPHost service + /// + /// \sa [EapPeerGetInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363608.aspx) + /// + inline void get_info(_Out_ EAP_PEER_METHOD_ROUTINES *pEapPeerMethodRoutines) const + { + ETW_FN_VOID; + + assert(pEapPeerMethodRoutines); + + pEapPeerMethodRoutines->dwVersion = PRODUCT_VERSION; + pEapPeerMethodRoutines->pEapType = NULL; + + pEapPeerMethodRoutines->EapPeerInitialize = initialize; + pEapPeerMethodRoutines->EapPeerShutdown = shutdown; + pEapPeerMethodRoutines->EapPeerBeginSession = begin_session; + pEapPeerMethodRoutines->EapPeerEndSession = end_session; + pEapPeerMethodRoutines->EapPeerSetCredentials = NULL; // Always NULL unless we want to use generic credential UI + pEapPeerMethodRoutines->EapPeerGetIdentity = get_identity; + pEapPeerMethodRoutines->EapPeerProcessRequestPacket = process_request_packet; + pEapPeerMethodRoutines->EapPeerGetResponsePacket = get_response_packet; + pEapPeerMethodRoutines->EapPeerGetResult = get_result; + pEapPeerMethodRoutines->EapPeerGetUIContext = get_ui_context; + pEapPeerMethodRoutines->EapPeerSetUIContext = set_ui_context; + pEapPeerMethodRoutines->EapPeerGetResponseAttributes = get_response_attributes; + pEapPeerMethodRoutines->EapPeerSetResponseAttributes = set_response_attributes; + } + + + /// + /// Free BLOB allocated with this peer + /// + inline void free_memory(_In_ void *ptr) + { + ETW_FN_VOID; + + if (ptr) { + // Since we do security here and some of the BLOBs contain credentials, sanitize every memory block before freeing. + SecureZeroMemory(ptr, HeapSize(m_heap, 0, ptr)); + HeapFree(m_heap, 0, ptr); + } + } + + + /// + /// Allocate a EAP_ERROR and fill it according to dwErrorCode + /// + EAP_ERROR *make_error(_In_ DWORD dwErrorCode, _In_ DWORD dwReasonCode, _In_ LPCGUID pRootCauseGuid, _In_ LPCGUID pRepairGuid, _In_ LPCGUID pHelpLinkGuid, _In_z_ LPCWSTR pszRootCauseString, _In_z_ LPCWSTR pszRepairString) const + { + // Calculate memory size requirement. + SIZE_T + nRootCauseSize = pszRootCauseString != NULL && pszRootCauseString[0] ? (wcslen(pszRootCauseString) + 1)*sizeof(WCHAR) : 0, + nRepairStringSize = pszRepairString != NULL && pszRepairString [0] ? (wcslen(pszRepairString ) + 1)*sizeof(WCHAR) : 0, + nEapErrorSize = sizeof(EAP_ERROR) + nRootCauseSize + nRepairStringSize; + + EAP_ERROR *pError = (EAP_ERROR*)HeapAlloc(m_heap, 0, nEapErrorSize); + if (!pError) + return NULL; + BYTE *p = (BYTE*)(pError + 1); + + // Fill the error descriptor. + pError->dwWinError = dwErrorCode; + pError->type.eapType.type = EAPMETHOD_TYPE; + pError->type.eapType.dwVendorId = 0; + pError->type.eapType.dwVendorType = 0; + pError->type.dwAuthorId = 67532; + pError->dwReasonCode = dwReasonCode; + pError->rootCauseGuid = pRootCauseGuid != NULL ? *pRootCauseGuid : GUID_NULL; + pError->repairGuid = pRepairGuid != NULL ? *pRepairGuid : GUID_NULL; + pError->helpLinkGuid = pHelpLinkGuid != NULL ? *pHelpLinkGuid : GUID_NULL; + if (nRootCauseSize) { + pError->pRootCauseString = (LPWSTR)p; + memcpy(pError->pRootCauseString, pszRootCauseString, nRootCauseSize); + p += nRootCauseSize; + } else + pError->pRootCauseString = NULL; + if (nRepairStringSize) { + pError->pRepairString = (LPWSTR)p; + memcpy(pError->pRepairString, pszRepairString, nRepairStringSize); + p += nRepairStringSize; + } else + pError->pRepairString = NULL; + + // Write trace event. + std::vector evt_desc; + evt_desc.reserve(8); + evt_desc.push_back(winstd::event_data(pError->dwWinError)); + evt_desc.push_back(winstd::event_data(pError->type.eapType.type)); + evt_desc.push_back(winstd::event_data(pError->dwReasonCode)); + evt_desc.push_back(winstd::event_data(&(pError->rootCauseGuid), sizeof(GUID))); + evt_desc.push_back(winstd::event_data(&(pError->repairGuid), sizeof(GUID))); + evt_desc.push_back(winstd::event_data(&(pError->helpLinkGuid), sizeof(GUID))); + evt_desc.push_back(winstd::event_data(pError->pRootCauseString)); + evt_desc.push_back(winstd::event_data(pError->pRepairString)); + m_ep.write(&EAPMETHOD_TRACE_EAP_ERROR, (ULONG)evt_desc.size(), evt_desc.data()); + + return pError; + } + + + /// + /// Free EAP_ERROR allocated with `make_error()` method + /// + void free_error_memory(_In_ EAP_ERROR *err) + { + ETW_FN_VOID; + + if (err) { + // pRootCauseString and pRepairString always trail the ppEapError to reduce number of (de)allocations. + HeapFree(m_heap, 0, err); + } + } + + protected: + /// + /// Initializes an EAP peer method for EAPHost. + /// + /// \sa [EapPeerGetInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363613.aspx) + /// + static DWORD APIENTRY initialize(_Out_ EAP_ERROR **ppEapError) + { + UNREFERENCED_PARAMETER(ppEapError); + return ERROR_SUCCESS; + } + + + /// + /// Shuts down the EAP method and prepares to unload its corresponding DLL. + /// + /// \sa [EapPeerShutdown function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363627.aspx) + /// + static DWORD APIENTRY shutdown(_Out_ EAP_ERROR **ppEapError) + { + UNREFERENCED_PARAMETER(ppEapError); + return ERROR_SUCCESS; + } + + + /// + /// Returns the user data and user identity after being called by EAPHost. + /// + /// \sa [EapPeerGetIdentity function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363607.aspx) + /// + static DWORD APIENTRY get_identity(_In_ DWORD dwFlags, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) const BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) const BYTE *pUserData, _In_ HANDLE hTokenImpersonateUser, _Out_ BOOL *pfInvokeUI, _Inout_ DWORD *pdwSizeOfUserDataOut, _Out_cap_(*pdwSizeOfUserDataOut) BYTE **ppUserDataOut, _Out_ WCHAR **ppwszIdentity, _Out_ EAP_ERROR **ppEapError) + { + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(dwSizeofConnectionData); + UNREFERENCED_PARAMETER(pConnectionData); + UNREFERENCED_PARAMETER(dwSizeofUserData); + UNREFERENCED_PARAMETER(pUserData); + UNREFERENCED_PARAMETER(hTokenImpersonateUser); + UNREFERENCED_PARAMETER(pfInvokeUI); + UNREFERENCED_PARAMETER(pdwSizeOfUserDataOut); + UNREFERENCED_PARAMETER(ppUserDataOut); + UNREFERENCED_PARAMETER(ppwszIdentity); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_NOT_SUPPORTED; + } + + + /// + /// 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) + /// + static DWORD APIENTRY begin_session(_In_ DWORD dwFlags, _In_ const EapAttributes *pAttributeArray, _In_ HANDLE hTokenImpersonateUser, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) BYTE *pUserData, _In_ DWORD dwMaxSendPacketSize, _Out_ EAP_SESSION_HANDLE *phSession, _Out_ EAP_ERROR **ppEapError) + { + // Allocate new session. + Ts *session = new Ts(); + if (!session) + return ERROR_OUTOFMEMORY; + + // Begin the session. + DWORD dwResult = session->begin(dwFlags, pAttributeArray, hTokenImpersonateUser, dwSizeofConnectionData, pConnectionData, dwSizeofUserData, pUserData, dwMaxSendPacketSize, ppEapError); + if (dwResult == ERROR_SUCCESS) { + assert(phSession); + *phSession = session; + return ERROR_SUCCESS; + } + + // Cleanup. + delete session; + return dwResult; + } + + + /// + /// Ends an EAP authentication session for the EAP method. + /// + /// \sa [EapPeerEndSession function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363604.aspx) + /// + static DWORD APIENTRY end_session(_In_ EAP_SESSION_HANDLE hSession, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + + DWORD dwResult = static_cast(hSession)->end(ppEapError); + delete static_cast(hSession); + + return dwResult; + } + + + /// + /// Processes a packet received by EAPHost from a supplicant. + /// + /// \sa [EapPeerProcessRequestPacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363621.aspx) + /// + static DWORD APIENTRY process_request_packet(_In_ EAP_SESSION_HANDLE hSession, _In_ DWORD dwSizeofReceivePacket, _In_bytecount_(dwSizeofReceivePacket) EapPacket *pReceivePacket, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->process_request_packet(dwSizeofReceivePacket, pReceivePacket, pEapOutput, ppEapError); + } + + + /// + /// Obtains a response packet from the EAP method. + /// + /// \sa [EapPeerGetResponsePacket function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363610.aspx) + /// + static DWORD APIENTRY get_response_packet(_In_ EAP_SESSION_HANDLE hSession, _Inout_ DWORD *pcbSendPacket, _Out_cap_(*pcbSendPacket) EapPacket *pSendPacket, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->get_response_packet(pcbSendPacket, pSendPacket, 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) + /// + static DWORD APIENTRY get_result(_In_ EAP_SESSION_HANDLE hSession, _In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->get_result(reason, ppResult, ppEapError); + } + + + /// + /// Obtains the user interface context from the EAP method. + /// + /// \note This function is always followed by the `EapPeerInvokeInteractiveUI()` function, which is followed by the `EapPeerSetUIContext()` function. + /// + /// \sa [EapPeerGetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363612.aspx) + /// + static DWORD APIENTRY get_ui_context(_In_ EAP_SESSION_HANDLE hSession, _Out_ DWORD *dwSizeOfUIContextData, _Out_cap_(*dwSizeOfUIContextData) BYTE **pUIContextData, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->get_ui_context(dwSizeOfUIContextData, pUIContextData, ppEapError); + } + + + /// + /// Provides a user interface context to the EAP method. + /// + /// \note This function is called after the UI has been raised through the `EapPeerGetUIContext()` function. + /// + /// \sa [EapPeerSetUIContext function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363626.aspx) + /// + static DWORD APIENTRY set_ui_context(_In_ EAP_SESSION_HANDLE hSession, _In_ DWORD dwSizeOfUIContextData, _In_count_(dwSizeOfUIContextData) const BYTE *pUIContextData, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->set_ui_context(dwSizeOfUIContextData, pUIContextData, pEapOutput, ppEapError); + } + + + /// + /// Obtains an array of EAP response attributes from the EAP method. + /// + /// \sa [EapPeerGetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363609.aspx) + /// + static DWORD APIENTRY get_response_attributes(_In_ EAP_SESSION_HANDLE hSession, _Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->get_response_attributes(pAttribs, ppEapError); + } + + + /// + /// Provides an updated array of EAP response attributes to the EAP method. + /// + /// \sa [EapPeerSetResponseAttributes function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363625.aspx) + /// + static DWORD APIENTRY set_response_attributes(_In_ EAP_SESSION_HANDLE hSession, _In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) + { + assert(hSession); + return static_cast(hSession)->set_response_attributes(pAttribs, pEapOutput, ppEapError); + } + + protected: + winstd::heap m_heap; ///< Heap + mutable winstd::event_provider m_ep; ///< Event Provider + }; +}; diff --git a/EAPMethods/include/EAPTTLS.h b/EAPMethods/include/EAPTTLS.h new file mode 100644 index 0000000..7bce9b7 --- /dev/null +++ b/EAPMethods/include/EAPTTLS.h @@ -0,0 +1,47 @@ +/* + Copyright 2015-2016 Amebis + Copyright 2016 GÉANT + + This file is part of GEANTLink. + + GEANTLink 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. + + GEANTLink 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 GEANTLink. If not, see . +*/ + +#include "EAPMethods.h" + +namespace eap +{ + class session_ttls; + class peer_ttls; +} + +#pragma once + + +namespace eap +{ + class session_ttls : public session_base + { + public: + /// + /// Constructor + /// + session_ttls(); + }; + + + class peer_ttls : public peer + { + }; +} diff --git a/EAPMethods/include/StdAfx.h b/EAPMethods/include/StdAfx.h index 773bd73..30139ff 100644 --- a/EAPMethods/include/StdAfx.h +++ b/EAPMethods/include/StdAfx.h @@ -20,12 +20,21 @@ #pragma once +#include "../../include/Version.h" + +#include "../include/EAPTTLS.h" + #include #include #include +extern "C" { +#include +} +#include #include +#include #include #include diff --git a/EAPMethods/res/EAPMethodETW.man b/EAPMethods/res/EAPMethodETW.man index 4b9df02..0bff491 100644 Binary files a/EAPMethods/res/EAPMethodETW.man and b/EAPMethods/res/EAPMethodETW.man differ diff --git a/EAPMethods/src/EAPMethods.cpp b/EAPMethods/src/EAPMethods.cpp new file mode 100644 index 0000000..3c46fc6 --- /dev/null +++ b/EAPMethods/src/EAPMethods.cpp @@ -0,0 +1,132 @@ +/* + Copyright 2015-2016 Amebis + Copyright 2016 GÉANT + + This file is part of GEANTLink. + + GEANTLink 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. + + GEANTLink 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 GEANTLink. If not, see . +*/ + +#include + + +////////////////////////////////////////////////////////////////////// +// eap::session_base +////////////////////////////////////////////////////////////////////// + +eap::session_base::session_base() +{ +} + + +DWORD eap::session_base::begin(_In_ DWORD dwFlags, _In_ const EapAttributes *pAttributeArray, _In_ HANDLE hTokenImpersonateUser, _In_ DWORD dwSizeofConnectionData, _In_count_(dwSizeofConnectionData) BYTE *pConnectionData, _In_ DWORD dwSizeofUserData, _In_count_(dwSizeofUserData) BYTE *pUserData, _In_ DWORD dwMaxSendPacketSize, _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(pAttributeArray); + UNREFERENCED_PARAMETER(hTokenImpersonateUser); + UNREFERENCED_PARAMETER(dwSizeofConnectionData); + UNREFERENCED_PARAMETER(pConnectionData); + UNREFERENCED_PARAMETER(dwSizeofUserData); + UNREFERENCED_PARAMETER(pUserData); + UNREFERENCED_PARAMETER(dwMaxSendPacketSize); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_SUCCESS; +} + + +DWORD eap::session_base::end(_Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_SUCCESS; +} + + +DWORD eap::session_base::process_request_packet(_In_ DWORD dwSizeofReceivePacket, _In_bytecount_(dwSizeofReceivePacket) EapPacket *pReceivePacket, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(dwSizeofReceivePacket); + UNREFERENCED_PARAMETER(pReceivePacket); + UNREFERENCED_PARAMETER(pEapOutput); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_NOT_SUPPORTED; +} + + +DWORD eap::session_base::get_response_packet(_Inout_ DWORD *pcbSendPacket, _Out_cap_(*pcbSendPacket) EapPacket *pSendPacket, _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(pcbSendPacket); + UNREFERENCED_PARAMETER(pSendPacket); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_NOT_SUPPORTED; +} + + +DWORD eap::session_base::get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(reason); + UNREFERENCED_PARAMETER(ppResult); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_NOT_SUPPORTED; +} + + +DWORD eap::session_base::get_ui_context(_Out_ DWORD *dwSizeOfUIContextData, _Out_cap_(*dwSizeOfUIContextData) BYTE **pUIContextData, _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(dwSizeOfUIContextData); + UNREFERENCED_PARAMETER(pUIContextData); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_NOT_SUPPORTED; +} + + +DWORD eap::session_base::set_ui_context(_In_ DWORD dwSizeOfUIContextData, _In_count_(dwSizeOfUIContextData) const BYTE *pUIContextData, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) +{ + UNREFERENCED_PARAMETER(dwSizeOfUIContextData); + UNREFERENCED_PARAMETER(pUIContextData); + UNREFERENCED_PARAMETER(pEapOutput); + UNREFERENCED_PARAMETER(ppEapError); + + return ERROR_NOT_SUPPORTED; +} + + +DWORD eap::session_base::get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError) +{ + assert(pAttribs); + UNREFERENCED_PARAMETER(ppEapError); + + pAttribs->dwNumberOfAttributes = 0; + pAttribs->pAttribs = NULL; + + return ERROR_SUCCESS; +} + + +DWORD eap::session_base::set_response_attributes(_In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError) +{ + assert(pAttribs); + assert(pEapOutput); + UNREFERENCED_PARAMETER(ppEapError); + + pEapOutput->action = EapPeerMethodResponseActionNone; + pAttribs->dwNumberOfAttributes = 0; + pAttribs->pAttribs = NULL; + + return ERROR_SUCCESS; +} diff --git a/EAPMethods/src/EAPTTLS.cpp b/EAPMethods/src/EAPTTLS.cpp new file mode 100644 index 0000000..711444d --- /dev/null +++ b/EAPMethods/src/EAPTTLS.cpp @@ -0,0 +1,30 @@ +/* + Copyright 2015-2016 Amebis + Copyright 2016 GÉANT + + This file is part of GEANTLink. + + GEANTLink 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. + + GEANTLink 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 GEANTLink. If not, see . +*/ + +#include + + +////////////////////////////////////////////////////////////////////// +// eap::session_ttls +////////////////////////////////////////////////////////////////////// + +eap::session_ttls::session_ttls() : session_base() +{ +} diff --git a/EAPMethods/src/Main.cpp b/EAPMethods/src/Main.cpp index b9ced08..6031a2e 100644 --- a/EAPMethods/src/Main.cpp +++ b/EAPMethods/src/Main.cpp @@ -20,94 +20,40 @@ #include -using namespace std; -using namespace winstd; +#pragma comment(lib, "Comctl32.lib") +#pragma comment(lib, "Shlwapi.lib") +#if EAPMETHOD_TYPE==21 +#define _EAPMETHOD_PEER eap::peer_ttls +#else +#error Unknown EAP Method type. +#endif -#define ETW_FN_VOID event_fn_auto < &EAPMETHOD_TRACE_EVT_FN_CALL, &EAPMETHOD_TRACE_EVT_FN_RETURN > _event_auto(*g_ep, __FUNCTION__) -#define ETW_FN_DWORD(res) event_fn_auto_ret _event_auto(*g_ep, __FUNCTION__, res) -#define ETW_FN_HRESULT(res) event_fn_auto_ret _event_auto(*g_ep, __FUNCTION__, res) - - -event_provider *g_ep = NULL; - - -// event_fn_auto actually and winstd::event_auto_res<> do not need an assignment operator actually, so the C4512 warning is safely ignored. -#pragma warning(push) -#pragma warning(disable: 4512) - -/// -/// Helper class to write an event on entry/exit of scope. -/// -/// It writes one string event at creation and another at destruction. -/// -template -class event_fn_auto -{ -public: - inline event_fn_auto(_In_ event_provider &ep, _In_z_ LPCSTR pszFnName) : m_ep(ep) - { - EventDataDescCreate(&m_fn_name, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName)); - m_ep.write(event_cons, 1, &m_fn_name); - } - - inline ~event_fn_auto() - { - m_ep.write(event_dest, 1, &m_fn_name); - } - -protected: - event_provider &m_ep; ///< Reference to event provider in use - EVENT_DATA_DESCRIPTOR m_fn_name; ///< Function name -}; +_EAPMETHOD_PEER g_peer; /// -/// Helper template to write an event on entry/exit of scope with one parameter (typically result). +/// DLL main entry point /// -/// It writes one string event at creation and another at destruction, with allowing one sprintf type parameter for string event at destruction. +/// \sa [DllMain entry point](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583.aspx) /// -template -class event_fn_auto_ret -{ -public: - inline event_fn_auto_ret(_In_ event_provider &ep, _In_z_ LPCSTR pszFnName, T &result) : m_ep(ep), m_result(result) - { - EventDataDescCreate(m_desc + 0, pszFnName, (ULONG)(strlen(pszFnName) + 1)*sizeof(*pszFnName)); - m_ep.write(event_cons, 1, m_desc); - } - - inline ~event_fn_auto_ret() - { - EventDataDescCreate(m_desc + 1, &m_result, sizeof(T)); - m_ep.write(event_dest, 2, m_desc); - } - -protected: - event_provider &m_ep; ///< Reference to event provider in use - T &m_result; ///< Function result - EVENT_DATA_DESCRIPTOR m_desc[2]; ///< Function name and return value -}; - -#pragma warning(pop) - - - BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) { UNREFERENCED_PARAMETER(hinstDLL); UNREFERENCED_PARAMETER(lpvReserved); if (fdwReason == DLL_PROCESS_ATTACH) { - g_ep = new event_provider(); - assert(g_ep); - g_ep->create(&EAPMETHOD_TRACE_EVENT_PROVIDER); - g_ep->write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, event_data((unsigned int)EAPMETHOD_TYPE), event_data::blank); - } else if (fdwReason == DLL_PROCESS_DETACH) { - assert(g_ep); - g_ep->write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, event_data((unsigned int)EAPMETHOD_TYPE), event_data::blank); - delete g_ep; + //// Load EAPMethodEvents.dll + //tstring path; + //GetModuleFileName(hinstDLL, path); + //LPTSTR pszFilename = PathFindFileName(path.c_str()); + //path.resize(pszFilename ? (size_t)(pszFilename - (LPCTSTR)path.c_str()) : 0); + //path += _T("EAPMethodEvents.dll"); + //g_EAPMethodEvents.load(path.c_str(), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); + if (!g_peer.create()) + return FALSE; + } else if (fdwReason == DLL_PROCESS_DETACH) { assert(!_CrtDumpMemoryLeaks()); } @@ -115,66 +61,183 @@ BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID l } -//#pragma comment(linker, "/EXPORT:DllRegisterServer,PRIVATE") -//#pragma comment(linker, "/EXPORT:DllUnregisterServer,PRIVATE") - - -extern "C" +/// +/// Releases all memory associated with an opaque user interface context data buffer. +/// +/// \sa [EapPeerFreeMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363606.aspx) +/// +VOID WINAPI EapPeerFreeMemory(_In_ void *pUIContextData) { - ///// - ///// Registers the EAP method. - ///// - //HRESULT STDAPICALLTYPE DllRegisterServer() - //{ - // HRESULT hr = S_OK; - // ETW_FN_HRESULT(hr); + g_peer.free_memory(pUIContextData); +} - // return hr; - //} +#pragma comment(linker, "/EXPORT:EapPeerFreeMemory") - ///// - ///// Unregisters the EAP method. - ///// - //HRESULT STDAPICALLTYPE DllUnregisterServer() - //{ - // HRESULT hr = S_OK; - // ETW_FN_HRESULT(hr); +/// +/// Releases error-specific memory allocated by the EAP peer method. +/// +/// \sa [EapPeerFreeErrorMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363605.aspx) +/// +VOID WINAPI EapPeerFreeErrorMemory(_In_ EAP_ERROR *ppEapError) +{ + g_peer.free_error_memory(ppEapError); +} - // return hr; - //} +#pragma comment(linker, "/EXPORT:EapPeerFreeErrorMemory") - /// - /// Releases all memory associated with an opaque user interface context data buffer. - /// - /// \sa [EapPeerFreeMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363606.aspx) - /// - __declspec(dllexport) VOID WINAPI EapPeerFreeMemory(_In_ void *pUIContextData) - { - ETW_FN_VOID; +/// +/// Obtains a set of function pointers for an implementation of the EAP peer method currently loaded on the EAPHost service. +/// +/// \sa [EapPeerGetInfo function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363608.aspx) +/// +DWORD WINAPI EapPeerGetInfo(_In_ EAP_TYPE* pEapType, _Out_ EAP_PEER_METHOD_ROUTINES* pEapPeerMethodRoutines, _Out_ EAP_ERROR **ppEapError) +{ + DWORD dwResult = NO_ERROR; +#ifdef _DEBUG + //Sleep(10000); +#endif - if (pUIContextData) { - // Since we do security here and some of the BLOBs contain credentials, sanitize every memory block before freeing. - HANDLE hHeap = GetProcessHeap(); - SecureZeroMemory(pUIContextData, HeapSize(hHeap, 0, pUIContextData)); - HeapFree(hHeap, 0, pUIContextData); - } + // Parameter check + if (!ppEapError) { + dwResult = ERROR_INVALID_PARAMETER; + } else if (!pEapType) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL); + } else if (pEapType->type != EAPMETHOD_TYPE) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->type, (int)EAPMETHOD_TYPE).c_str(), NULL); + } else if (!pEapPeerMethodRoutines) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapPeerMethodRoutines is NULL."), NULL); + } else + g_peer.get_info(pEapPeerMethodRoutines); + + return dwResult; +} + +#pragma comment(linker, "/EXPORT:EapPeerGetInfo") + + +/// +/// Raises the EAP method's specific connection configuration user interface dialog on the client. +/// +/// \sa [EapPeerInvokeConfigUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363614.aspx) +/// +DWORD WINAPI EapPeerInvokeConfigUI(_In_ EAP_METHOD_TYPE *pEapType, _In_ HWND hwndParent, _In_ DWORD dwFlags, _In_ DWORD dwSizeOfConnectionDataIn, _In_ BYTE *pConnectionDataIn, _Out_ DWORD *pdwSizeOfConnectionDataOut, _Out_ BYTE **ppConnectionDataOut, _Out_ EAP_ERROR **ppEapError) +{ + DWORD dwResult = NO_ERROR; + +#ifdef _DEBUG + //MessageBox(NULL, _T("Attach debugger!"), _T(__FUNCTION__), MB_OK); +#endif + + // Parameter check + if (!ppEapError) { + dwResult = ERROR_INVALID_PARAMETER; + } else if (!pEapType) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL); + } else if (pEapType->eapType.type != EAPMETHOD_TYPE) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL); + } else if (pEapType->dwAuthorId != 67532) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL); + } else if (!pdwSizeOfConnectionDataOut) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwSizeOfConnectionDataOut is NULL."), NULL); + } else if (!ppConnectionDataOut) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppConnectionDataOut is NULL."), NULL); + } else { + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(dwSizeOfConnectionDataIn); + UNREFERENCED_PARAMETER(pConnectionDataIn); + + InitCommonControls(); + MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" configuration goes here!"), _T(PRODUCT_NAME_STR) _T(" Settings"), MB_OK); } + return dwResult; +} - /// - /// Releases error-specific memory allocated by the EAP peer method. - /// - /// \sa [EapPeerFreeErrorMemory function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363605.aspx) - /// - __declspec(dllexport) VOID WINAPI EapPeerFreeErrorMemory(_In_ EAP_ERROR *ppEapError) - { - ETW_FN_VOID; +#pragma comment(linker, "/EXPORT:EapPeerInvokeConfigUI") - if (ppEapError) { - // pRootCauseString and pRepairString always trail the ppEapError to reduce number of (de)allocations. - HeapFree(GetProcessHeap(), 0, ppEapError); - } + +/// +/// Raises a custom interactive user interface dialog to obtain user identity information for the EAP method on the client. +/// +/// \sa [EapPeerInvokeIdentityUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363615.aspx) +/// +DWORD WINAPI EapPeerInvokeIdentityUI(_In_ EAP_METHOD_TYPE *pEapType, _In_ DWORD dwFlags, _In_ HWND hwndParent, _In_ DWORD dwSizeOfConnectionData, _In_ const BYTE *pConnectionData, _Out_ DWORD dwSizeOfUserData, _In_ const BYTE *pUserData, _Out_ DWORD *pdwSizeOfUserDataOut, _Out_ BYTE **ppUserDataOut, _Out_ LPWSTR *ppwszIdentity, _Out_ EAP_ERROR **ppEapError) +{ + DWORD dwResult = NO_ERROR; + +#ifdef _DEBUG + //MessageBox(NULL, _T("Attach debugger!"), _T(__FUNCTION__), MB_OK); +#endif + + // Parameter check + if (!ppEapError) { + dwResult = ERROR_INVALID_PARAMETER; + } else if (!pEapType) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL); + } else if (pEapType->eapType.type != EAPMETHOD_TYPE) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL); + } else if (pEapType->dwAuthorId != 67532) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL); + } else if (!pdwSizeOfUserDataOut) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwSizeOfUserDataOut is NULL."), NULL); + } else if (!ppUserDataOut) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppUserDataOut is NULL."), NULL); + } else if (!ppwszIdentity) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppwszIdentity is NULL."), NULL); + } else { + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(pUserData); + UNREFERENCED_PARAMETER(dwSizeOfUserData); + UNREFERENCED_PARAMETER(pConnectionData); + UNREFERENCED_PARAMETER(dwSizeOfConnectionData); + + InitCommonControls(); + MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" credential prompt goes here!"), _T(PRODUCT_NAME_STR) _T(" Credentials"), MB_OK); } -}; + + return dwResult; +} + +#pragma comment(linker, "/EXPORT:EapPeerInvokeIdentityUI") + + +/// +/// Raises a custom interactive user interface dialog for the EAP method on the client. +/// +/// \sa [EapPeerInvokeInteractiveUI function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa363616.aspx) +/// +DWORD WINAPI EapPeerInvokeInteractiveUI(_In_ EAP_METHOD_TYPE *pEapType, _In_ HWND hwndParent, _In_ DWORD dwSizeofUIContextData, _In_ BYTE *pUIContextData, _Out_ DWORD *pdwSizeOfDataFromInteractiveUI, _Out_ BYTE **ppDataFromInteractiveUI, _Out_ EAP_ERROR **ppEapError) +{ + DWORD dwResult = NO_ERROR; + +#ifdef _DEBUG + //MessageBox(NULL, _T("Attach debugger!"), _T(__FUNCTION__), MB_OK); +#endif + + // Parameter check + if (!ppEapError) { + dwResult = ERROR_INVALID_PARAMETER; + } else if (!pEapType) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pEapType is NULL."), NULL); + } else if (pEapType->eapType.type != EAPMETHOD_TYPE) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" Input EAP type (%d) does not match the supported EAP type (%d)."), (int)pEapType->eapType.type, (int)EAPMETHOD_TYPE).c_str(), NULL); + } else if (pEapType->dwAuthorId != 67532) { + *ppEapError = g_peer.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, winstd::wstring_printf(_T(__FUNCTION__) _T(" EAP author (%d) does not match the supported author (%d)."), (int)pEapType->dwAuthorId, (int)67532).c_str(), NULL); + } else if (!pdwSizeOfDataFromInteractiveUI) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" pdwSizeOfDataFromInteractiveUI is NULL."), NULL); + } else if (!ppDataFromInteractiveUI) { + *ppEapError = g_peer.make_error(dwResult = ERROR_INVALID_PARAMETER, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" ppDataFromInteractiveUI is NULL."), NULL); + } else { + UNREFERENCED_PARAMETER(dwSizeofUIContextData); + UNREFERENCED_PARAMETER(pUIContextData); + + InitCommonControls(); + MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" interactive UI goes here!"), _T(PRODUCT_NAME_STR) _T(" Prompt"), MB_OK); + } + + return dwResult; +} + +#pragma comment(linker, "/EXPORT:EapPeerInvokeInteractiveUI") diff --git a/lib/WinStd b/lib/WinStd index 03cb7ee..61a8704 160000 --- a/lib/WinStd +++ b/lib/WinStd @@ -1 +1 @@ -Subproject commit 03cb7ee822826b30f18d9e0fc0a71583999e6b12 +Subproject commit 61a87046166b363382176f2d42f7efa2871d69a0