From e94e3bdd60651d4330db211115821bc73c66744e Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 10 Oct 2016 14:29:54 +0200 Subject: [PATCH] credentials::combine() methods updated with support for EAPMsg: - Additional parameters - Additional result code - User impersonation now mounted inside of credentials::combine() when required --- lib/EAPBase/include/Credentials.h | 23 ++++++++---- lib/EAPBase/src/Credentials.cpp | 7 ++++ lib/EAPMsg/include/Credentials.h | 10 ++++-- lib/EAPMsg/src/Credentials.cpp | 58 +++++++++++++++++++++++++----- lib/EAPMsg/src/StdAfx.h | 2 ++ lib/Events/res/EventsETW.man | Bin 103654 -> 105042 bytes lib/TLS/include/Credentials.h | 10 ++++-- lib/TLS/src/Credentials.cpp | 7 ++++ lib/TTLS/include/Credentials.h | 10 ++++-- lib/TTLS/src/Credentials.cpp | 6 ++++ lib/TTLS_UI/src/Module.cpp | 4 +++ lib/WinStd | 2 +- 12 files changed, 113 insertions(+), 26 deletions(-) diff --git a/lib/EAPBase/include/Credentials.h b/lib/EAPBase/include/Credentials.h index a0d16b3..f82da6a 100644 --- a/lib/EAPBase/include/Credentials.h +++ b/lib/EAPBase/include/Credentials.h @@ -68,7 +68,8 @@ namespace eap source_unknown = -1, ///< Unknown source source_cache = 0, ///< Credentials were obtained from EapHost cache source_config, ///< Credentials were set by method configuration - source_storage ///< Credentials were loaded from Windows Credential Manager + source_storage, ///< Credentials were loaded from Windows Credential Manager + source_lower, ///< Credentials were set by lower EAP method }; @@ -242,9 +243,11 @@ namespace eap /// 2. Configured credentials (if \p cfg is derived from config_method_with_cred) /// 3. Stored credentials /// - /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be the same type of credentials as `this`) - /// \param[in] cfg Method configuration (must be the same type of configuration as `this` credentials belong to) - /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) + /// \param[in] dwFlags A combination of [EAP flags](https://msdn.microsoft.com/en-us/library/windows/desktop/bb891975.aspx) that describe the EAP authentication session behavior + /// \param[in] hTokenImpersonateUser Impersonation token for a logged-on user to collect user-related information + /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be the same type of credentials as `this`) + /// \param[in] cfg Method configuration (must be the same type of configuration as `this` credentials belong to) + /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) /// /// \returns /// - \c source_cache Credentials were obtained from EapHost cache @@ -252,6 +255,8 @@ namespace eap /// - \c source_storage Credentials were loaded from Windows Credential Manager /// virtual source_t combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName) = 0; @@ -414,9 +419,11 @@ namespace eap /// 2. Configured credentials (if \p cfg is derived from config_method_with_cred) /// 3. Stored credentials /// - /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_pass* type) - /// \param[in] cfg Method configuration (optional, can be \c NULL, must be config_method_pap type) - /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) + /// \param[in] dwFlags A combination of [EAP flags](https://msdn.microsoft.com/en-us/library/windows/desktop/bb891975.aspx) that describe the EAP authentication session behavior + /// \param[in] hTokenImpersonateUser Impersonation token for a logged-on user to collect user-related information + /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_eapmsg* type) + /// \param[in] cfg Method configuration (unused, as must be as config_method_eapmsg is not derived from config_method_with_cred) + /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) /// /// \returns /// - \c source_cache Credentials were obtained from EapHost cache @@ -424,6 +431,8 @@ namespace eap /// - \c source_storage Credentials were loaded from Windows Credential Manager /// virtual source_t combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName); diff --git a/lib/EAPBase/src/Credentials.cpp b/lib/EAPBase/src/Credentials.cpp index 5c6546f..96bb1b2 100644 --- a/lib/EAPBase/src/Credentials.cpp +++ b/lib/EAPBase/src/Credentials.cpp @@ -437,10 +437,14 @@ LPCTSTR eap::credentials_pass::target_suffix() const eap::credentials::source_t eap::credentials_pass::combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName) { + UNREFERENCED_PARAMETER(dwFlags); + if (cred_cached) { // Using EAP service cached credentials. *this = *dynamic_cast(cred_cached); @@ -457,6 +461,9 @@ eap::credentials::source_t eap::credentials_pass::combine( } if (pszTargetName) { + // Switch user context. + user_impersonator impersonating(hTokenImpersonateUser); + try { credentials_pass cred_loaded(m_module); cred_loaded.retrieve(pszTargetName, cfg.m_level); diff --git a/lib/EAPMsg/include/Credentials.h b/lib/EAPMsg/include/Credentials.h index ecb9309..84009a7 100644 --- a/lib/EAPMsg/include/Credentials.h +++ b/lib/EAPMsg/include/Credentials.h @@ -189,9 +189,11 @@ namespace eap /// 2. Configured credentials (if \p cfg is derived from config_method_with_cred) /// 3. Stored credentials /// - /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_eapmsg* type) - /// \param[in] cfg Method configuration (unused, as must be as config_method_eapmsg is not derived from config_method_with_cred) - /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) + /// \param[in] dwFlags A combination of [EAP flags](https://msdn.microsoft.com/en-us/library/windows/desktop/bb891975.aspx) that describe the EAP authentication session behavior + /// \param[in] hTokenImpersonateUser Impersonation token for a logged-on user to collect user-related information + /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_eapmsg* type) + /// \param[in] cfg Method configuration (unused, as must be as config_method_eapmsg is not derived from config_method_with_cred) + /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) /// /// \returns /// - \c source_cache Credentials were obtained from EapHost cache @@ -199,6 +201,8 @@ namespace eap /// - \c source_storage Credentials were loaded from Windows Credential Manager /// virtual source_t combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName); diff --git a/lib/EAPMsg/src/Credentials.cpp b/lib/EAPMsg/src/Credentials.cpp index 24d0557..694a5af 100644 --- a/lib/EAPMsg/src/Credentials.cpp +++ b/lib/EAPMsg/src/Credentials.cpp @@ -20,6 +20,8 @@ #include "StdAfx.h" +#pragma comment(lib, "Eappprxy.lib") + using namespace std; using namespace winstd; @@ -242,36 +244,74 @@ std::wstring eap::credentials_eapmsg::get_identity() const eap::credentials::source_t eap::credentials_eapmsg::combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName) { - UNREFERENCED_PARAMETER(cfg); + // When cached credentials are available, EapHost calls EapPeerGetIdentity() anyway. + // This allows each peer to decide to reuse or drop cached credentials itself. + // To mimic that behaviour, we do the same: + // 1. Retrieve credentials from cache (or store) + // 2. Call EapHostPeerGetIdentity() + source_t src = source_unknown; if (cred_cached) { // Using EAP service cached credentials. *this = *(credentials_eapmsg*)cred_cached; - m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED2, event_data((unsigned int)eap_type_tls), event_data(credentials_eapmsg::get_name()), event_data(pszTargetName), event_data::blank); - return source_cache; + m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED2, event_data((unsigned int)cfg.get_method_id()), event_data(get_name()), event_data(pszTargetName), event_data::blank); + src = source_cache; } - // We do not store inner EAP method credentials inside configuration. - // Therefore, we skip configured credentials. - - if (pszTargetName) { + if (src == source_unknown && pszTargetName) { try { credentials_eapmsg cred_loaded(m_module); cred_loaded.retrieve(pszTargetName, cfg.m_level); // Using stored credentials. *this = std::move(cred_loaded); - m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED2, event_data((unsigned int)eap_type_tls), event_data(credentials_eapmsg::get_name()), event_data(pszTargetName), event_data::blank); - return source_storage; + m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED2, event_data((unsigned int)cfg.get_method_id()), event_data(get_name()), event_data(pszTargetName), event_data::blank); + src = source_storage; } catch (...) { // Not actually an error. } } + auto const *cfg_eapmsg = dynamic_cast(&cfg); + BOOL fInvokeUI = FALSE; + DWORD cred_data_size = 0; + eap_blob_runtime cred_data; + unique_ptr identity; + eap_error error; + DWORD dwResult = EapHostPeerGetIdentity( + 0, + dwFlags, + cfg_eapmsg->m_type, + (DWORD)cfg_eapmsg->m_cfg_blob.size(), cfg_eapmsg->m_cfg_blob.data(), + src != source_unknown ? (DWORD)m_cred_blob.size() : 0, src != source_unknown ? m_cred_blob.data() : NULL, + hTokenImpersonateUser, + &fInvokeUI, + &cred_data_size, &cred_data._Myptr, + &identity._Myptr, + &error._Myptr, + NULL); + if (dwResult == ERROR_SUCCESS) { + if (identity && !fInvokeUI) { + // Inner EAP method provided identity and does not require additional UI prompt. + m_identity = identity.get(); + m_cred_blob.assign(cred_data.get(), cred_data.get() + cred_data_size); + m_module.log_event(&EAPMETHOD_TRACE_EVT_CRED_EAPMSG, event_data((unsigned int)cfg.get_method_id()), event_data(get_name()), event_data(pszTargetName), event_data::blank); + return source_lower; + } + } else if (error) { + // An EAP error in inner EAP method occurred. + m_module.log_error(error.get()); + } else { + // A runtime error in inner EAP method occurred. + m_module.log_event(&EAPMETHOD_TRACE_EVT_WIN_ERROR, event_data((unsigned int)dwResult), event_data(__FUNCTION__ " EapHostPeerGetIdentity failed."), event_data::blank); + } + return source_unknown; } diff --git a/lib/EAPMsg/src/StdAfx.h b/lib/EAPMsg/src/StdAfx.h index cc1d372..1dbf9a9 100644 --- a/lib/EAPMsg/src/StdAfx.h +++ b/lib/EAPMsg/src/StdAfx.h @@ -26,3 +26,5 @@ #include #include // include after Windows.h +#include +#include diff --git a/lib/Events/res/EventsETW.man b/lib/Events/res/EventsETW.man index 2e586a0062936175ad85cb8cd3caf49946797ed6..83723adbcf029f15360d3ecc1f790fe7b340e0ae 100644 GIT binary patch delta 258 zcmaF1lI_wKwhetntlPHuW)GP&Wp(c}Z$)Fx-`NaKXb7f-&pHFI*nQK8KRhf2C$BDlYn>-vkr9hG?zRq0SuE6&kVC}s(cred_cached); @@ -312,6 +316,9 @@ eap::credentials::source_t eap::credentials_tls::combine( } if (pszTargetName) { + // Switch user context. + user_impersonator impersonating(hTokenImpersonateUser); + try { credentials_tls cred_loaded(m_module); cred_loaded.retrieve(pszTargetName, cfg.m_level); diff --git a/lib/TTLS/include/Credentials.h b/lib/TTLS/include/Credentials.h index b715be0..5b7533b 100644 --- a/lib/TTLS/include/Credentials.h +++ b/lib/TTLS/include/Credentials.h @@ -175,9 +175,11 @@ namespace eap /// 2. Configured credentials (if \p cfg is derived from config_method_with_cred) /// 3. Stored credentials /// - /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_ttls* type) - /// \param[in] cfg Method configuration (must be config_method_ttls type) - /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) + /// \param[in] dwFlags A combination of [EAP flags](https://msdn.microsoft.com/en-us/library/windows/desktop/bb891975.aspx) that describe the EAP authentication session behavior + /// \param[in] hTokenImpersonateUser Impersonation token for a logged-on user to collect user-related information + /// \param[in] cred_cached Cached credentials (optional, can be \c NULL, must be credentials_eapmsg* type) + /// \param[in] cfg Method configuration (unused, as must be as config_method_eapmsg is not derived from config_method_with_cred) + /// \param[in] pszTargetName The name in Windows Credential Manager to retrieve credentials from (optional, can be \c NULL) /// /// \returns /// - \c source_cache Credentials were obtained from EapHost cache @@ -185,6 +187,8 @@ namespace eap /// - \c source_storage Credentials were loaded from Windows Credential Manager /// virtual source_t combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName); diff --git a/lib/TTLS/src/Credentials.cpp b/lib/TTLS/src/Credentials.cpp index c303661..030c28e 100644 --- a/lib/TTLS/src/Credentials.cpp +++ b/lib/TTLS/src/Credentials.cpp @@ -179,18 +179,24 @@ wstring eap::credentials_ttls::get_identity() const eap::credentials::source_t eap::credentials_ttls::combine( + _In_ DWORD dwFlags, + _In_ HANDLE hTokenImpersonateUser, _In_opt_ const credentials *cred_cached, _In_ const config_method &cfg, _In_opt_z_ LPCTSTR pszTargetName) { // Combine outer credentials. source_t src_outer = credentials_tls::combine( + dwFlags, + hTokenImpersonateUser, cred_cached, cfg, pszTargetName); // Combine inner credentials. source_t src_inner = m_inner->combine( + dwFlags, + hTokenImpersonateUser, cred_cached ? dynamic_cast(cred_cached)->m_inner.get() : NULL, *dynamic_cast(cfg).m_inner, pszTargetName); diff --git a/lib/TTLS_UI/src/Module.cpp b/lib/TTLS_UI/src/Module.cpp index 04d606b..16e3e90 100644 --- a/lib/TTLS_UI/src/Module.cpp +++ b/lib/TTLS_UI/src/Module.cpp @@ -213,6 +213,8 @@ void eap::peer_ttls_ui::invoke_identity_ui( // Combine outer credentials. eap::credentials::source_t src_outer = _cred_method->credentials_tls::combine( + dwFlags, + NULL, #ifdef EAP_USE_NATIVE_CREDENTIAL_CACHE has_cached ? cred_in.m_cred.get() : NULL, #else @@ -223,6 +225,8 @@ void eap::peer_ttls_ui::invoke_identity_ui( // Combine inner credentials. eap::credentials::source_t src_inner = _cred_method->m_inner->combine( + dwFlags, + NULL, #ifdef EAP_USE_NATIVE_CREDENTIAL_CACHE has_cached ? dynamic_cast(cred_in.m_cred.get())->m_inner.get() : NULL, #else diff --git a/lib/WinStd b/lib/WinStd index 7b1863d..1c70923 160000 --- a/lib/WinStd +++ b/lib/WinStd @@ -1 +1 @@ -Subproject commit 7b1863d8b2734e77796b0526f1cc6f58a8ad0b54 +Subproject commit 1c7092347c1306d55cfc2b800c669dcfeb5c449b