diff --git a/lib/EAPBase/include/Config.h b/lib/EAPBase/include/Config.h index 84a1bb5..93e1cb7 100644 --- a/lib/EAPBase/include/Config.h +++ b/lib/EAPBase/include/Config.h @@ -33,7 +33,6 @@ namespace eap #pragma once -#include "Module.h" #include "EAPXML.h" #include "../../../include/Version.h" @@ -52,6 +51,8 @@ namespace eap namespace eap { + class module; + /// /// \defgroup EAPBaseConfig Configuration /// Configuration management diff --git a/lib/EAPBase/include/Credentials.h b/lib/EAPBase/include/Credentials.h index a30f4b2..8dcab2b 100644 --- a/lib/EAPBase/include/Credentials.h +++ b/lib/EAPBase/include/Credentials.h @@ -28,7 +28,6 @@ namespace eap #pragma once #include "Config.h" -#include "Module.h" #include "../../../include/Version.h" @@ -45,6 +44,8 @@ namespace eap namespace eap { + class module; + /// \addtogroup EAPBaseCred /// @{ diff --git a/lib/EAPBase/include/Method.h b/lib/EAPBase/include/Method.h index 91911d4..56698b0 100644 --- a/lib/EAPBase/include/Method.h +++ b/lib/EAPBase/include/Method.h @@ -28,7 +28,6 @@ namespace eap #include "Config.h" #include "Credentials.h" -#include "Module.h" #include @@ -42,6 +41,8 @@ extern "C" { namespace eap { + class module; + /// /// \defgroup EAPBaseMethod Methods /// Methods diff --git a/lib/EAPBase/include/Module.h b/lib/EAPBase/include/Module.h index 7ed992f..ec47fb0 100644 --- a/lib/EAPBase/include/Module.h +++ b/lib/EAPBase/include/Module.h @@ -27,6 +27,9 @@ namespace eap #pragma once #include "EAP.h" +#include "Config.h" +#include "Credentials.h" +#include "Method.h" #include #include @@ -772,7 +775,7 @@ namespace eap _Out_ DWORD *pdwUserDataOutSize, _In_ HANDLE hTokenImpersonateUser, _Out_ BOOL *pfInvokeUI, - _Out_ WCHAR **ppwszIdentity) = 0; + _Out_ WCHAR **ppwszIdentity); /// /// Defines the implementation of an EAP method-specific function that retrieves the properties of an EAP method given the connection and user data. @@ -816,7 +819,7 @@ namespace eap _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, _In_ DWORD dwConnectionDataSize, _Out_ BYTE **ppCredentialsOut, - _Out_ DWORD *pdwCredentialsOutSize) = 0; + _Out_ DWORD *pdwCredentialsOutSize); /// /// Defines the implementation of an EAP method-specific function that obtains the EAP Single-Sign-On (SSO) credential input fields for an EAP method. @@ -925,7 +928,7 @@ namespace eap _In_ DWORD dwConnectionDataSize, _In_count_(dwUserDataSize) const BYTE *pUserData, _In_ DWORD dwUserDataSize, - _In_ DWORD dwMaxSendPacketSize) = 0; + _In_ DWORD dwMaxSendPacketSize); /// /// Ends an EAP authentication session for the EAP method. @@ -934,7 +937,7 @@ namespace eap /// /// \param[in] hSession A unique handle for this EAP authentication session on the EAPHost server. This handle is returned in the \p pSessionHandle parameter in a previous call to `EapPeerBeginSession()`. /// - virtual void end_session(_In_ EAP_SESSION_HANDLE hSession) = 0; + virtual void end_session(_In_ EAP_SESSION_HANDLE hSession); /// @} @@ -955,7 +958,7 @@ namespace eap _In_ EAP_SESSION_HANDLE hSession, _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) = 0; + _Out_ EapPeerMethodOutput *pEapOutput); /// /// Obtains a response packet from the EAP method. @@ -969,7 +972,7 @@ namespace eap virtual void get_response_packet( _In_ EAP_SESSION_HANDLE hSession, _Out_bytecapcount_(*pdwSendPacketSize) EapPacket *pSendPacket, - _Inout_ DWORD *pdwSendPacketSize) = 0; + _Inout_ DWORD *pdwSendPacketSize); /// @} @@ -985,7 +988,7 @@ namespace eap virtual void get_result( _In_ EAP_SESSION_HANDLE hSession, _In_ EapPeerMethodResultReason reason, - _Inout_ EapPeerMethodResult *pResult) = 0; + _Inout_ EapPeerMethodResult *pResult); /// \name User Interaction /// @{ @@ -1004,7 +1007,7 @@ namespace eap virtual void get_ui_context( _In_ EAP_SESSION_HANDLE hSession, _Out_ BYTE **ppUIContextData, - _Out_ DWORD *pdwUIContextDataSize) = 0; + _Out_ DWORD *pdwUIContextDataSize); /// /// Provides a user interface context to the EAP method. @@ -1022,7 +1025,7 @@ namespace eap _In_ EAP_SESSION_HANDLE hSession, _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput) = 0; + _Out_ EapPeerMethodOutput *pEapOutput); /// @} @@ -1039,7 +1042,7 @@ namespace eap /// virtual void get_response_attributes( _In_ EAP_SESSION_HANDLE hSession, - _Out_ EapAttributes *pAttribs) = 0; + _Out_ EapAttributes *pAttribs); /// /// Provides an updated array of EAP response attributes to the EAP method. @@ -1053,9 +1056,63 @@ namespace eap virtual void set_response_attributes( _In_ EAP_SESSION_HANDLE hSession, _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput) = 0; + _Out_ EapPeerMethodOutput *pEapOutput); /// @} + + protected: + /// + /// Makes a new method + /// + /// \param[in] cfg Method configuration + /// \param[in] cred Credentials + /// + /// \returns A new method + /// + virtual method* make_method(_In_ config_method &cfg, _In_ credentials &cred) = 0; + + /// + /// Checks all configured providers and tries to combine credentials. + /// + _Success_(return != 0) virtual const config_method_with_cred* combine_credentials( + _In_ DWORD dwFlags, + _In_ const config_connection &cfg, + _In_count_(dwUserDataSize) const BYTE *pUserData, + _In_ DWORD dwUserDataSize, + _Inout_ credentials_connection& cred_out, + _In_ HANDLE hTokenImpersonateUser) = 0; + + protected: + /// + /// Peer session + /// + /// Maintains EapHost session context. + /// + class session { + public: + /// + /// Constructs a session + /// + session(_In_ module &mod); + + /// + /// Destructs the session + /// + virtual ~session(); + + public: + module &m_module; ///< Module + config_connection m_cfg; ///< Connection configuration + credentials_connection m_cred; ///< Connection credentials + std::unique_ptr m_method; ///< EAP method + + // The following members are required to avoid memory leakage in get_result() and get_ui_context(). + BYTE *m_blob_cfg; ///< Configuration BLOB +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + BYTE *m_blob_cred; ///< Credentials BLOB +#endif + BYTE *m_blob_ui_ctx; ///< User Interface context data + }; }; /// @} diff --git a/lib/EAPBase/src/Module.cpp b/lib/EAPBase/src/Module.cpp index fda9569..827781f 100644 --- a/lib/EAPBase/src/Module.cpp +++ b/lib/EAPBase/src/Module.cpp @@ -187,12 +187,6 @@ void eap::module::log_error(_In_ const EAP_ERROR *err) const } -eap::config_method* eap::module::make_config() -{ - return NULL; -} - - std::vector eap::module::encrypt(_In_ HCRYPTPROV hProv, _In_bytecount_(size) const void *data, _In_ size_t size, _In_opt_ HCRYPTHASH hHash) const { // Generate 256-bit AES session key. @@ -352,6 +346,84 @@ void eap::peer::shutdown() } +void eap::peer::get_identity( + _In_ DWORD dwFlags, + _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, + _In_ DWORD dwConnectionDataSize, + _In_count_(dwUserDataSize) const BYTE *pUserData, + _In_ DWORD dwUserDataSize, + _Out_ BYTE **ppUserDataOut, + _Out_ DWORD *pdwUserDataOutSize, + _In_ HANDLE hTokenImpersonateUser, + _Out_ BOOL *pfInvokeUI, + _Out_ WCHAR **ppwszIdentity) +{ + assert(ppUserDataOut); + assert(pdwUserDataOutSize); + assert(pfInvokeUI); + assert(ppwszIdentity); + + // Unpack configuration. + config_connection cfg(*this); + unpack(cfg, pConnectionData, dwConnectionDataSize); + + // Combine credentials. + credentials_connection cred_out(*this, cfg); + auto cfg_method = combine_credentials(dwFlags, cfg, pUserData, dwUserDataSize, cred_out, hTokenImpersonateUser); + + if (cfg_method) { + // No UI will be necessary. + *pfInvokeUI = FALSE; + } else { + // Credentials missing or incomplete. + if ((dwFlags & EAP_FLAG_MACHINE_AUTH) == 0) { + // Per-user authentication, request UI. + log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI2, event_data::blank); + *ppUserDataOut = NULL; + *pdwUserDataOutSize = 0; + *pfInvokeUI = TRUE; + *ppwszIdentity = NULL; + return; + } else { + // Per-machine authentication, cannot use UI. + throw win_runtime_error(ERROR_NO_SUCH_USER, __FUNCTION__ " Credentials for per-machine authentication not available."); + } + } + + // Build our identity. ;) + wstring identity(std::move(cfg_method->get_public_identity(*cred_out.m_cred.get()))); + log_event(&EAPMETHOD_TRACE_EVT_CRED_OUTER_ID1, event_data((unsigned int)cfg_method->get_method_id()), event_data(identity), event_data::blank); + size_t size = sizeof(WCHAR)*(identity.length() + 1); + *ppwszIdentity = (WCHAR*)alloc_memory(size); + memcpy(*ppwszIdentity, identity.c_str(), size); + + // Pack credentials. + pack(cred_out, ppUserDataOut, pdwUserDataOutSize); +} + + +void eap::peer::credentials_xml2blob( + _In_ DWORD dwFlags, + _In_ IXMLDOMNode *pConfigRoot, + _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, + _In_ DWORD dwConnectionDataSize, + _Out_ BYTE **ppCredentialsOut, + _Out_ DWORD *pdwCredentialsOutSize) +{ + UNREFERENCED_PARAMETER(dwFlags); + UNREFERENCED_PARAMETER(pConnectionData); + UNREFERENCED_PARAMETER(dwConnectionDataSize); + + // Load credentials from XML. + unique_ptr cfg(make_config()); + unique_ptr cred(cfg->make_credentials()); + cred->load(pConfigRoot); + + // Pack credentials. + pack(*cred, ppCredentialsOut, pdwCredentialsOutSize); +} + + void eap::peer::query_credential_input_fields( _In_ HANDLE hUserImpersonationToken, _In_ DWORD dwFlags, @@ -426,3 +498,204 @@ void eap::peer::query_ui_blob_from_interactive_ui_input_fields( throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); } + + +EAP_SESSION_HANDLE eap::peer::begin_session( + _In_ DWORD dwFlags, + _In_ const EapAttributes *pAttributeArray, + _In_ HANDLE hTokenImpersonateUser, + _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, + _In_ DWORD dwConnectionDataSize, + _In_count_(dwUserDataSize) const BYTE *pUserData, + _In_ DWORD dwUserDataSize, + _In_ DWORD dwMaxSendPacketSize) +{ + // Create new session. + unique_ptr s(new session(*this)); + + // Unpack configuration. + unpack(s->m_cfg, pConnectionData, dwConnectionDataSize); + + // Unpack credentials. + unpack(s->m_cred, pUserData, dwUserDataSize); + + // Look-up the provider. + config_method *cfg_method; + for (auto cfg_prov = s->m_cfg.m_providers.begin(), cfg_prov_end = s->m_cfg.m_providers.end();; ++cfg_prov) { + if (cfg_prov != cfg_prov_end) { + if (s->m_cred.match(*cfg_prov)) { + // Matching provider found. + if (cfg_prov->m_methods.empty()) + throw invalid_argument(string_printf(__FUNCTION__ " %ls provider has no methods.", cfg_prov->get_id().c_str())); + cfg_method = cfg_prov->m_methods.front().get(); + break; + } + } else + throw invalid_argument(string_printf(__FUNCTION__ " Credentials do not match to any provider within this connection configuration (provider: %ls).", s->m_cred.get_id().c_str())); + } + + // We have configuration, we have credentials, create method. + s->m_method.reset(make_method(*cfg_method, *s->m_cred.m_cred)); + + // Initialize method. + s->m_method->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); + + return s.release(); +} + + +void eap::peer::end_session(_In_ EAP_SESSION_HANDLE hSession) +{ + assert(hSession); + + // End the session. + auto s = static_cast(hSession); + s->m_method->end_session(); + delete s; +} + + +void eap::peer::process_request_packet( + _In_ EAP_SESSION_HANDLE hSession, + _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, + _In_ DWORD dwReceivedPacketSize, + _Out_ EapPeerMethodOutput *pEapOutput) +{ + assert(dwReceivedPacketSize == ntohs(*(WORD*)pReceivedPacket->Length)); + assert(pEapOutput); + pEapOutput->action = static_cast(hSession)->m_method->process_request_packet(pReceivedPacket, dwReceivedPacketSize); + pEapOutput->fAllowNotifications = TRUE; +} + + +void eap::peer::get_response_packet( + _In_ EAP_SESSION_HANDLE hSession, + _Out_bytecapcount_(*pdwSendPacketSize) EapPacket *pSendPacket, + _Inout_ DWORD *pdwSendPacketSize) +{ + assert(pdwSendPacketSize); + assert(pSendPacket || !*pdwSendPacketSize); + + sanitizing_blob packet; + static_cast(hSession)->m_method->get_response_packet(packet, *pdwSendPacketSize); + assert(packet.size() <= *pdwSendPacketSize); + + memcpy(pSendPacket, packet.data(), *pdwSendPacketSize = (DWORD)packet.size()); +} + + +void eap::peer::get_result( + _In_ EAP_SESSION_HANDLE hSession, + _In_ EapPeerMethodResultReason reason, + _Inout_ EapPeerMethodResult *pResult) +{ + auto s = static_cast(hSession); + + s->m_method->get_result(reason, pResult); + + // Do not report failure to EapHost, as it will not save updated configuration then. But we need it to save it, to alert user on next connection attempt. + // EapHost should be aware of the failed condition. + pResult->fIsSuccess = TRUE; + pResult->dwFailureReasonCode = ERROR_SUCCESS; + + if (pResult->fSaveConnectionData) { + pack(s->m_cfg, &pResult->pConnectionData, &pResult->dwSizeofConnectionData); + if (s->m_blob_cfg) + free_memory(s->m_blob_cfg); + s->m_blob_cfg = pResult->pConnectionData; + } + +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + pResult->fSaveUserData = TRUE; + pack(s->m_cred, &pResult->pUserData, &pResult->dwSizeofUserData); + if (s->m_blob_cred) + free_memory(s->m_blob_cred); + s->m_blob_cred = pResult->pUserData; +#endif +} + + +void eap::peer::get_ui_context( + _In_ EAP_SESSION_HANDLE hSession, + _Out_ BYTE **ppUIContextData, + _Out_ DWORD *pdwUIContextDataSize) +{ + assert(ppUIContextData); + assert(pdwUIContextDataSize); + + auto s = static_cast(hSession); + + // Get context data from method. + ui_context ctx(s->m_cfg, s->m_cred); + s->m_method->get_ui_context(ctx.m_data); + + // Pack context data. + pack(ctx, ppUIContextData, pdwUIContextDataSize); + if (s->m_blob_ui_ctx) + free_memory(s->m_blob_ui_ctx); + s->m_blob_ui_ctx = *ppUIContextData; +} + + +void eap::peer::set_ui_context( + _In_ EAP_SESSION_HANDLE hSession, + _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, + _In_ DWORD dwUIContextDataSize, + _Out_ EapPeerMethodOutput *pEapOutput) +{ + assert(pEapOutput); + + sanitizing_blob data(std::move(unpack(pUIContextData, dwUIContextDataSize))); + pEapOutput->action = static_cast(hSession)->m_method->set_ui_context(data.data(), (DWORD)data.size()); + pEapOutput->fAllowNotifications = TRUE; +} + + +void eap::peer::get_response_attributes( + _In_ EAP_SESSION_HANDLE hSession, + _Out_ EapAttributes *pAttribs) +{ + static_cast(hSession)->m_method->get_response_attributes(pAttribs); +} + + +void eap::peer::set_response_attributes( + _In_ EAP_SESSION_HANDLE hSession, + _In_ const EapAttributes *pAttribs, + _Out_ EapPeerMethodOutput *pEapOutput) +{ + assert(pEapOutput); + pEapOutput->action = static_cast(hSession)->m_method->set_response_attributes(pAttribs); + pEapOutput->fAllowNotifications = TRUE; +} + + +////////////////////////////////////////////////////////////////////// +// eap::peer::session +////////////////////////////////////////////////////////////////////// + +eap::peer::session::session(_In_ module &mod) : + m_module(mod), + m_cfg(mod), + m_cred(mod, m_cfg), + m_blob_cfg(NULL), +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + m_blob_cred(NULL), +#endif + m_blob_ui_ctx(NULL) +{} + + +eap::peer::session::~session() +{ + if (m_blob_cfg) + m_module.free_memory(m_blob_cfg); + +#if EAP_USE_NATIVE_CREDENTIAL_CACHE + if (m_blob_cred) + m_module.free_memory(m_blob_cred); +#endif + + if (m_blob_ui_ctx) + m_module.free_memory(m_blob_ui_ctx); +} diff --git a/lib/EapHost/src/StdAfx.h b/lib/EapHost/src/StdAfx.h index c4f18e4..012050f 100644 --- a/lib/EapHost/src/StdAfx.h +++ b/lib/EapHost/src/StdAfx.h @@ -24,6 +24,8 @@ #include "../include/Credentials.h" #include "../include/Method.h" +#include "../../EAPBase/include/Module.h" + #include #include diff --git a/lib/GTC/src/StdAfx.h b/lib/GTC/src/StdAfx.h index d61f513..d3f93c7 100644 --- a/lib/GTC/src/StdAfx.h +++ b/lib/GTC/src/StdAfx.h @@ -23,6 +23,8 @@ #include "../include/Config.h" #include "../include/Method.h" +#include "../../EAPBase/include/Module.h" + #include #include diff --git a/lib/MSCHAPv2/src/StdAfx.h b/lib/MSCHAPv2/src/StdAfx.h index 04cee2d..1c0315a 100644 --- a/lib/MSCHAPv2/src/StdAfx.h +++ b/lib/MSCHAPv2/src/StdAfx.h @@ -24,6 +24,8 @@ #include "../include/Method.h" #include "../include/MSCHAPv2.h" +#include "../../EAPBase/include/Module.h" + #include #include diff --git a/lib/PAP/src/StdAfx.h b/lib/PAP/src/StdAfx.h index 0c9c72e..3651125 100644 --- a/lib/PAP/src/StdAfx.h +++ b/lib/PAP/src/StdAfx.h @@ -23,5 +23,7 @@ #include "../include/Config.h" #include "../include/Method.h" +#include "../../EAPBase/include/Module.h" + #include #include // include after Windows.h diff --git a/lib/TLS/include/Module.h b/lib/TLS/include/Module.h index 63d6726..cd2c167 100644 --- a/lib/TLS/include/Module.h +++ b/lib/TLS/include/Module.h @@ -29,6 +29,8 @@ namespace eap #include "Credentials.h" #include "Method.h" +#include "../../EAPBase/include/Module.h" + namespace eap { @@ -50,18 +52,6 @@ namespace eap virtual void shutdown(); - virtual void get_identity( - _In_ DWORD dwFlags, - _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, - _In_ DWORD dwConnectionDataSize, - _In_count_(dwUserDataSize) const BYTE *pUserData, - _In_ DWORD dwUserDataSize, - _Out_ BYTE **ppUserDataOut, - _Out_ DWORD *pdwUserDataOutSize, - _In_ HANDLE hTokenImpersonateUser, - _Out_ BOOL *pfInvokeUI, - _Out_ WCHAR **ppwszIdentity); - virtual void get_method_properties( _In_ DWORD dwVersion, _In_ DWORD dwFlags, @@ -72,82 +62,6 @@ namespace eap _In_ DWORD dwUserDataSize, _Out_ EAP_METHOD_PROPERTY_ARRAY *pMethodPropertyArray); - virtual void credentials_xml2blob( - _In_ DWORD dwFlags, - _In_ IXMLDOMNode *pConfigRoot, - _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, - _In_ DWORD dwConnectionDataSize, - _Out_ BYTE **ppCredentialsOut, - _Out_ DWORD *pdwCredentialsOutSize); - - /// \name Session management - /// @{ - - virtual EAP_SESSION_HANDLE begin_session( - _In_ DWORD dwFlags, - _In_ const EapAttributes *pAttributeArray, - _In_ HANDLE hTokenImpersonateUser, - _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, - _In_ DWORD dwConnectionDataSize, - _In_count_(dwUserDataSize) const BYTE *pUserData, - _In_ DWORD dwUserDataSize, - _In_ DWORD dwMaxSendPacketSize); - - virtual void end_session(_In_ EAP_SESSION_HANDLE hSession); - - /// @} - - /// \name Packet processing - /// @{ - - virtual void process_request_packet( - _In_ EAP_SESSION_HANDLE hSession, - _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput); - - virtual void get_response_packet( - _In_ EAP_SESSION_HANDLE hSession, - _Out_bytecapcount_(*pdwSendPacketSize) EapPacket *pSendPacket, - _Inout_ DWORD *pdwSendPacketSize); - - /// @} - - virtual void get_result( - _In_ EAP_SESSION_HANDLE hSession, - _In_ EapPeerMethodResultReason reason, - _Inout_ EapPeerMethodResult *pResult); - - /// \name User Interaction - /// @{ - - virtual void get_ui_context( - _In_ EAP_SESSION_HANDLE hSession, - _Out_ BYTE **ppUIContextData, - _Out_ DWORD *pdwUIContextDataSize); - - virtual void set_ui_context( - _In_ EAP_SESSION_HANDLE hSession, - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput); - - /// @} - - /// \name EAP Response Attributes - /// @{ - - virtual void get_response_attributes( - _In_ EAP_SESSION_HANDLE hSession, - _Out_ EapAttributes *pAttribs); - - virtual void set_response_attributes( - _In_ EAP_SESSION_HANDLE hSession, - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput); - - /// @} - /// /// Spawns a new certificate revocation check thread /// @@ -156,57 +70,6 @@ namespace eap void spawn_crl_check(_Inout_ winstd::cert_context &&cert); protected: - /// - /// Makes a new method - /// - /// \param[in] cfg Method configuration - /// \param[in] cred Credentials - /// - /// \returns A new method - /// - virtual method* make_method(_In_ config_method_tls &cfg, _In_ credentials_tls &cred) = 0; - - /// - /// Checks all configured providers and tries to combine credentials. - /// - _Success_(return != 0) virtual const config_method_with_cred* combine_credentials( - _In_ DWORD dwFlags, - _In_ const config_connection &cfg, - _In_count_(dwUserDataSize) const BYTE *pUserData, - _In_ DWORD dwUserDataSize, - _Inout_ credentials_connection& cred_out, - _In_ HANDLE hTokenImpersonateUser) = 0; - - protected: - /// - /// TTL tunnel session - /// - class session { - public: - /// - /// Constructs a session - /// - session(_In_ module &mod); - - /// - /// Destructs the session - /// - virtual ~session(); - - public: - module &m_module; ///< Module - config_connection m_cfg; ///< Connection configuration - credentials_connection m_cred; ///< Connection credentials - std::unique_ptr m_method; ///< EAP method - - // The following members are required to avoid memory leakage in get_result() and get_ui_context(). - BYTE *m_blob_cfg; ///< Configuration BLOB -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - BYTE *m_blob_cred; ///< Credentials BLOB -#endif - BYTE *m_blob_ui_ctx; ///< User Interface context data - }; - /// ///< Post-festum server certificate revocation verify thread /// diff --git a/lib/TLS/src/Module.cpp b/lib/TLS/src/Module.cpp index fcd5345..fdbef8d 100644 --- a/lib/TLS/src/Module.cpp +++ b/lib/TLS/src/Module.cpp @@ -48,62 +48,6 @@ void eap::peer_tls_base::shutdown() } -void eap::peer_tls_base::get_identity( - _In_ DWORD dwFlags, - _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, - _In_ DWORD dwConnectionDataSize, - _In_count_(dwUserDataSize) const BYTE *pUserData, - _In_ DWORD dwUserDataSize, - _Out_ BYTE **ppUserDataOut, - _Out_ DWORD *pdwUserDataOutSize, - _In_ HANDLE hTokenImpersonateUser, - _Out_ BOOL *pfInvokeUI, - _Out_ WCHAR **ppwszIdentity) -{ - assert(ppUserDataOut); - assert(pdwUserDataOutSize); - assert(pfInvokeUI); - assert(ppwszIdentity); - - // Unpack configuration. - config_connection cfg(*this); - unpack(cfg, pConnectionData, dwConnectionDataSize); - - // Combine credentials. - credentials_connection cred_out(*this, cfg); - const config_method_with_cred *cfg_method = combine_credentials(dwFlags, cfg, pUserData, dwUserDataSize, cred_out, hTokenImpersonateUser); - - if (cfg_method) { - // No UI will be necessary. - *pfInvokeUI = FALSE; - } else { - // Credentials missing or incomplete. - if ((dwFlags & EAP_FLAG_MACHINE_AUTH) == 0) { - // Per-user authentication, request UI. - log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI2, event_data::blank); - *ppUserDataOut = NULL; - *pdwUserDataOutSize = 0; - *pfInvokeUI = TRUE; - *ppwszIdentity = NULL; - return; - } else { - // Per-machine authentication, cannot use UI. - throw win_runtime_error(ERROR_NO_SUCH_USER, __FUNCTION__ " Credentials for per-machine authentication not available."); - } - } - - // Build our identity. ;) - wstring identity(std::move(cfg_method->get_public_identity(*cred_out.m_cred.get()))); - log_event(&EAPMETHOD_TRACE_EVT_CRED_OUTER_ID1, event_data((unsigned int)cfg_method->get_method_id()), event_data(identity), event_data::blank); - size_t size = sizeof(WCHAR)*(identity.length() + 1); - *ppwszIdentity = (WCHAR*)alloc_memory(size); - memcpy(*ppwszIdentity, identity.c_str(), size); - - // Pack credentials. - pack(cred_out, ppUserDataOut, pdwUserDataOutSize); -} - - void eap::peer_tls_base::get_method_properties( _In_ DWORD dwVersion, _In_ DWORD dwFlags, @@ -157,200 +101,6 @@ void eap::peer_tls_base::get_method_properties( } -void eap::peer_tls_base::credentials_xml2blob( - _In_ DWORD dwFlags, - _In_ IXMLDOMNode *pConfigRoot, - _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, - _In_ DWORD dwConnectionDataSize, - _Out_ BYTE **ppCredentialsOut, - _Out_ DWORD *pdwCredentialsOutSize) -{ - UNREFERENCED_PARAMETER(dwFlags); - UNREFERENCED_PARAMETER(pConnectionData); - UNREFERENCED_PARAMETER(dwConnectionDataSize); - - // Load credentials from XML. - unique_ptr cfg(make_config()); - unique_ptr cred(cfg->make_credentials()); - cred->load(pConfigRoot); - - // Pack credentials. - pack(*cred, ppCredentialsOut, pdwCredentialsOutSize); -} - - -EAP_SESSION_HANDLE eap::peer_tls_base::begin_session( - _In_ DWORD dwFlags, - _In_ const EapAttributes *pAttributeArray, - _In_ HANDLE hTokenImpersonateUser, - _In_count_(dwConnectionDataSize) const BYTE *pConnectionData, - _In_ DWORD dwConnectionDataSize, - _In_count_(dwUserDataSize) const BYTE *pUserData, - _In_ DWORD dwUserDataSize, - _In_ DWORD dwMaxSendPacketSize) -{ - // Create new session. - unique_ptr s(new session(*this)); - - // Unpack configuration. - unpack(s->m_cfg, pConnectionData, dwConnectionDataSize); - - // Unpack credentials. - unpack(s->m_cred, pUserData, dwUserDataSize); - - // Look-up the provider. - config_method_tls *cfg_method; - for (auto cfg_prov = s->m_cfg.m_providers.begin(), cfg_prov_end = s->m_cfg.m_providers.end();; ++cfg_prov) { - if (cfg_prov != cfg_prov_end) { - if (s->m_cred.match(*cfg_prov)) { - // Matching provider found. - if (cfg_prov->m_methods.empty()) - throw invalid_argument(string_printf(__FUNCTION__ " %ls provider has no methods.", cfg_prov->get_id().c_str())); - cfg_method = dynamic_cast(cfg_prov->m_methods.front().get()); - break; - } - } else - throw invalid_argument(string_printf(__FUNCTION__ " Credentials do not match to any provider within this connection configuration (provider: %ls).", s->m_cred.get_id().c_str())); - } - - // We have configuration, we have credentials, create method. - s->m_method.reset(make_method(*cfg_method, *dynamic_cast(s->m_cred.m_cred.get()))); - - // Initialize method. - s->m_method->begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); - - return s.release(); -} - - -void eap::peer_tls_base::end_session(_In_ EAP_SESSION_HANDLE hSession) -{ - assert(hSession); - - // End the session. - auto s = static_cast(hSession); - s->m_method->end_session(); - delete s; -} - - -void eap::peer_tls_base::process_request_packet( - _In_ EAP_SESSION_HANDLE hSession, - _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, - _In_ DWORD dwReceivedPacketSize, - _Out_ EapPeerMethodOutput *pEapOutput) -{ - assert(dwReceivedPacketSize == ntohs(*(WORD*)pReceivedPacket->Length)); - assert(pEapOutput); - pEapOutput->action = static_cast(hSession)->m_method->process_request_packet(pReceivedPacket, dwReceivedPacketSize); - pEapOutput->fAllowNotifications = TRUE; -} - - -void eap::peer_tls_base::get_response_packet( - _In_ EAP_SESSION_HANDLE hSession, - _Out_bytecapcount_(*pdwSendPacketSize) EapPacket *pSendPacket, - _Inout_ DWORD *pdwSendPacketSize) -{ - assert(pdwSendPacketSize); - assert(pSendPacket || !*pdwSendPacketSize); - - sanitizing_blob packet; - static_cast(hSession)->m_method->get_response_packet(packet, *pdwSendPacketSize); - assert(packet.size() <= *pdwSendPacketSize); - - memcpy(pSendPacket, packet.data(), *pdwSendPacketSize = (DWORD)packet.size()); -} - - -void eap::peer_tls_base::get_result( - _In_ EAP_SESSION_HANDLE hSession, - _In_ EapPeerMethodResultReason reason, - _Inout_ EapPeerMethodResult *pResult) -{ - auto s = static_cast(hSession); - - s->m_method->get_result(reason, pResult); - - // Do not report failure to EapHost, as it will not save updated configuration then. But we need it to save it, to alert user on next connection attempt. - // EapHost is well aware of the failed condition. - //pResult->fIsSuccess = FALSE; - //pResult->dwFailureReasonCode = EAP_E_AUTHENTICATION_FAILED; - pResult->fIsSuccess = TRUE; - pResult->dwFailureReasonCode = ERROR_SUCCESS; - - if (pResult->fSaveConnectionData) { - pack(s->m_cfg, &pResult->pConnectionData, &pResult->dwSizeofConnectionData); - if (s->m_blob_cfg) - free_memory(s->m_blob_cfg); - s->m_blob_cfg = pResult->pConnectionData; - } - -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - pResult->fSaveUserData = TRUE; - pack(s->m_cred, &pResult->pUserData, &pResult->dwSizeofUserData); - if (s->m_blob_cred) - free_memory(s->m_blob_cred); - s->m_blob_cred = pResult->pUserData; -#endif -} - - -void eap::peer_tls_base::get_ui_context( - _In_ EAP_SESSION_HANDLE hSession, - _Out_ BYTE **ppUIContextData, - _Out_ DWORD *pdwUIContextDataSize) -{ - assert(ppUIContextData); - assert(pdwUIContextDataSize); - - auto s = static_cast(hSession); - - // Get context data from method. - ui_context ctx(s->m_cfg, s->m_cred); - s->m_method->get_ui_context(ctx.m_data); - - // Pack context data. - pack(ctx, ppUIContextData, pdwUIContextDataSize); - if (s->m_blob_ui_ctx) - free_memory(s->m_blob_ui_ctx); - s->m_blob_ui_ctx = *ppUIContextData; -} - - -void eap::peer_tls_base::set_ui_context( - _In_ EAP_SESSION_HANDLE hSession, - _In_count_(dwUIContextDataSize) const BYTE *pUIContextData, - _In_ DWORD dwUIContextDataSize, - _Out_ EapPeerMethodOutput *pEapOutput) -{ - assert(pEapOutput); - - sanitizing_blob data(std::move(unpack(pUIContextData, dwUIContextDataSize))); - pEapOutput->action = static_cast(hSession)->m_method->set_ui_context(data.data(), (DWORD)data.size()); - pEapOutput->fAllowNotifications = TRUE; -} - - -void eap::peer_tls_base::get_response_attributes( - _In_ EAP_SESSION_HANDLE hSession, - _Out_ EapAttributes *pAttribs) -{ - static_cast(hSession)->m_method->get_response_attributes(pAttribs); -} - - -void eap::peer_tls_base::set_response_attributes( - _In_ EAP_SESSION_HANDLE hSession, - _In_ const EapAttributes *pAttribs, - _Out_ EapPeerMethodOutput *pEapOutput) -{ - assert(pEapOutput); - pEapOutput->action = static_cast(hSession)->m_method->set_response_attributes(pAttribs); - pEapOutput->fAllowNotifications = TRUE; -} - - void eap::peer_tls_base::spawn_crl_check(_Inout_ winstd::cert_context &&cert) { // Create the thread and add it to the list. @@ -362,37 +112,6 @@ void eap::peer_tls_base::spawn_crl_check(_Inout_ winstd::cert_context &&cert) } -////////////////////////////////////////////////////////////////////// -// eap::peer_tls_base::session -////////////////////////////////////////////////////////////////////// - -eap::peer_tls_base::session::session(_In_ module &mod) : - m_module(mod), - m_cfg(mod), - m_cred(mod, m_cfg), - m_blob_cfg(NULL), -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - m_blob_cred(NULL), -#endif - m_blob_ui_ctx(NULL) -{} - - -eap::peer_tls_base::session::~session() -{ - if (m_blob_cfg) - m_module.free_memory(m_blob_cfg); - -#if EAP_USE_NATIVE_CREDENTIAL_CACHE - if (m_blob_cred) - m_module.free_memory(m_blob_cred); -#endif - - if (m_blob_ui_ctx) - m_module.free_memory(m_blob_ui_ctx); -} - - ////////////////////////////////////////////////////////////////////// // eap::peer_tls_base::crl_checker ////////////////////////////////////////////////////////////////////// diff --git a/lib/TTLS/include/Module.h b/lib/TTLS/include/Module.h index 7abcafd..322bfb1 100644 --- a/lib/TTLS/include/Module.h +++ b/lib/TTLS/include/Module.h @@ -56,6 +56,9 @@ namespace eap virtual void shutdown(); protected: + /// + /// @copydoc eap::peer::combine_credentials() + /// _Success_(return != 0) virtual const config_method_with_cred* combine_credentials( _In_ DWORD dwFlags, _In_ const config_connection &cfg, @@ -85,9 +88,9 @@ namespace eap protected: /// - /// @copydoc eap::peer_tls_base::make_method() + /// @copydoc eap::peer::make_method() /// - virtual method* make_method(_In_ config_method_tls &cfg, _In_ credentials_tls &cred); + virtual method* make_method(_In_ config_method &cfg, _In_ credentials &cred); }; /// @} diff --git a/lib/TTLS/src/Module.cpp b/lib/TTLS/src/Module.cpp index 50e89f2..f1b941d 100644 --- a/lib/TTLS/src/Module.cpp +++ b/lib/TTLS/src/Module.cpp @@ -171,7 +171,7 @@ eap::config_method* eap::peer_ttls::make_config() } -eap::method* eap::peer_ttls::make_method(_In_ config_method_tls &cfg, _In_ credentials_tls &cred) +eap::method* eap::peer_ttls::make_method(_In_ config_method &cfg, _In_ credentials &cred) { unique_ptr meth_inner; auto &cfg_ttls = dynamic_cast(cfg);