diff --git a/lib/EAPBase/include/Config.h b/lib/EAPBase/include/Config.h index c9854f8..fcb69ae 100644 --- a/lib/EAPBase/include/Config.h +++ b/lib/EAPBase/include/Config.h @@ -34,6 +34,11 @@ namespace eap /// class config_method; + /// + /// Base class for method with credentials + /// + template class config_method_with_cred; + /// /// Base class for single provider configuration storage /// @@ -201,10 +206,6 @@ namespace eap }; - // Forward declaration, otherwise we would have to merge Credentials.h here. - class credentials; - - class config_method : public config { public: @@ -247,6 +248,101 @@ namespace eap /// config_method& operator=(_Inout_ config_method &&other); + /// + /// Returns EAP method type of this configuration + /// + /// \returns One of `eap::type_t` constants. + /// + virtual type_t get_method_id() const = 0; + }; + + + template + class config_method_with_cred : public config_method + { + public: + /// + /// Constructs configuration + /// + /// \param[in] mod Reference of the EAP module to use for global services + /// + config_method_with_cred(_In_ module &mod) : + m_allow_save(true), + m_use_preshared(false), + m_preshared(mod), + config_method(mod) + { + } + + + /// + /// Copies configuration + /// + /// \param[in] other Configuration to copy from + /// + config_method_with_cred(_In_ const config_method_with_cred<_Tcred> &other) : + m_allow_save(other.m_allow_save), + m_use_preshared(other.m_use_preshared), + m_preshared(other.m_preshared), + config_method(other) + { + } + + + /// + /// Moves configuration + /// + /// \param[in] other Configuration to move from + /// + config_method_with_cred(_Inout_ config_method_with_cred<_Tcred> &&other) : + m_allow_save(std::move(other.m_allow_save)), + m_use_preshared(std::move(other.m_use_preshared)), + m_preshared(std::move(other.m_preshared)), + config_method(std::move(other)) + { + } + + + /// + /// Copies configuration + /// + /// \param[in] other Configuration to copy from + /// + /// \returns Reference to this object + /// + config_method_with_cred& operator=(_In_ const config_method_with_cred<_Tcred> &other) + { + if (this != &other) { + (config_method&)*this = other; + m_allow_save = other.m_allow_save; + m_use_preshared = other.m_use_preshared; + m_preshared = other.m_preshared; + } + + return *this; + } + + + /// + /// Moves configuration + /// + /// \param[in] other Configuration to move from + /// + /// \returns Reference to this object + /// + config_method_with_cred& operator=(_Inout_ config_method_with_cred<_Tcred> &&other) + { + if (this != &other) { + (config_method&)*this = std::move(other ); + m_allow_save = std::move(other.m_allow_save ); + m_use_preshared = std::move(other.m_use_preshared); + m_preshared = std::move(other.m_preshared ); + } + + return *this; + } + + /// \name XML configuration management /// @{ @@ -261,7 +357,33 @@ namespace eap /// - \c true if succeeded /// - \c false otherwise. See \p ppEapError for details. /// - virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const; + virtual bool save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const + { + assert(pDoc); + assert(pConfigRoot); + assert(ppEapError); + + const winstd::bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); + DWORD dwResult; + + // + winstd::com_obj pXmlElClientSideCredential; + if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, winstd::bstr(L"eap-metadata:ClientSideCredential"), winstd::bstr(L"ClientSideCredential"), bstrNamespace, &pXmlElClientSideCredential)) != ERROR_SUCCESS) { + *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); + return false; + } + + // / + if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, winstd::bstr(L"allow-save"), bstrNamespace, m_allow_save)) != ERROR_SUCCESS) { + *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); + return false; + } + + if (m_use_preshared && !m_preshared.save(pDoc, pXmlElClientSideCredential, ppEapError)) + return false; + + return true; + } /// /// Load configuration from XML document @@ -273,7 +395,39 @@ namespace eap /// - \c true if succeeded /// - \c false otherwise. See \p ppEapError for details. /// - virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError); + virtual bool load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) + { + assert(pConfigRoot); + assert(ppEapError); + + m_allow_save = true; + m_use_preshared = false; + m_preshared.clear(); + + // + winstd::com_obj pXmlElClientSideCredential; + if (eapxml::select_element(pConfigRoot, winstd::bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential) == ERROR_SUCCESS) { + std::wstring xpath(eapxml::get_xpath(pXmlElClientSideCredential)); + + // + eapxml::get_element_value(pXmlElClientSideCredential, winstd::bstr(L"eap-metadata:allow-save"), &m_allow_save); + m_module.log_config((xpath + L"/allow-save").c_str(), m_allow_save); + + _Tcred preshared(m_module); + if (preshared.load(pXmlElClientSideCredential, ppEapError)) { + m_use_preshared = true; + m_preshared = std::move(preshared); + } else { + // This is not really an error - merely an indication pre-shared credentials are unavailable. + if (*ppEapError) { + m_module.free_error_memory(*ppEapError); + *ppEapError = NULL; + } + } + } + + return true; + } /// @} @@ -285,40 +439,49 @@ namespace eap /// /// \param[inout] cursor Memory cursor /// - virtual void operator<<(_Inout_ cursor_out &cursor) const; + virtual void operator<<(_Inout_ cursor_out &cursor) const + { + config_method::operator<<(cursor); + cursor << m_allow_save; + cursor << m_use_preshared; + cursor << m_preshared; + } + /// /// Returns packed size of a configuration /// /// \returns Size of data when packed (in bytes) /// - virtual size_t get_pk_size() const; + virtual size_t get_pk_size() const + { + return + config_method::get_pk_size() + + pksizeof(m_allow_save ) + + pksizeof(m_use_preshared) + + pksizeof(m_preshared ); + } + /// /// Unpacks a configuration /// /// \param[inout] cursor Memory cursor /// - virtual void operator>>(_Inout_ cursor_in &cursor); + virtual void operator>>(_Inout_ cursor_in &cursor) + { + config_method::operator>>(cursor); + cursor >> m_allow_save; + cursor >> m_use_preshared; + cursor >> m_preshared; + } /// @} - /// - /// Makes a new set of credentials for the given method type - /// - virtual credentials* make_credentials() const = 0; - - /// - /// Returns EAP method type of this configuration - /// - /// \returns One of `eap::type_t` constants. - /// - virtual type_t get_method_id() const = 0; - public: - bool m_allow_save; ///< Are credentials allowed to be saved to Windows Credential Manager? - std::wstring m_anonymous_identity; ///< Anonymous identity - std::unique_ptr m_preshared; ///< Pre-shared credentials + bool m_allow_save; ///< Are credentials allowed to be saved to Windows Credential Manager? + bool m_use_preshared; ///< Use pre-shared credentials + _Tcred m_preshared; ///< Pre-shared credentials }; diff --git a/lib/EAPBase/include/Module.h b/lib/EAPBase/include/Module.h index b4b3583..8e78b08 100644 --- a/lib/EAPBase/include/Module.h +++ b/lib/EAPBase/include/Module.h @@ -562,13 +562,13 @@ namespace eap return false; cursor_in cursor = { data.data(), data.data() + data.size() }; - cursor >> record; #else UNREFERENCED_PARAMETER(ppEapError); cursor_in cursor = { pDataIn, pDataIn + dwDataInSize }; - cursor >> record; #endif + cursor >> record; + assert(cursor.ptr == cursor.ptr_end); return true; } @@ -593,6 +593,9 @@ namespace eap _Out_ DWORD *pdwDataOutSize, _Out_ EAP_ERROR **ppEapError) { + assert(ppDataOut); + assert(pdwDataOutSize); + #if EAP_ENCRYPT_BLOBS // Allocate BLOB. std::vector > data; @@ -601,7 +604,7 @@ namespace eap // Pack to BLOB. cursor_out cursor = { data.data(), data.data() + data.size() }; cursor << record; - data.resize(cursor.ptr - &data.front()); + assert(cursor.ptr == cursor.ptr_end); // Prepare cryptographics provider. winstd::crypt_prov cp; @@ -616,8 +619,6 @@ namespace eap return false; // Copy encrypted BLOB to output. - assert(ppDataOut); - assert(pdwDataOutSize); *pdwDataOutSize = (DWORD)data_enc.size(); *ppDataOut = alloc_memory(*pdwDataOutSize); if (!*ppDataOut) { @@ -627,8 +628,6 @@ namespace eap memcpy(*ppDataOut, data_enc.data(), *pdwDataOutSize); #else // Allocate BLOB. - assert(ppDataOut); - assert(pdwDataOutSize); *pdwDataOutSize = (DWORD)pksizeof(record); *ppDataOut = alloc_memory(*pdwDataOutSize); if (!*ppDataOut) { @@ -639,6 +638,7 @@ namespace eap // Pack to BLOB. cursor_out cursor = { *ppDataOut, *ppDataOut + *pdwDataOutSize }; cursor << record; + assert(cursor.ptr == cursor.ptr_end); *pdwDataOutSize = cursor.ptr - *ppDataOut; #endif diff --git a/lib/EAPBase/src/Config.cpp b/lib/EAPBase/src/Config.cpp index 45ea8b9..19c8960 100644 --- a/lib/EAPBase/src/Config.cpp +++ b/lib/EAPBase/src/Config.cpp @@ -103,39 +103,25 @@ void eap::config::operator>>(_Inout_ cursor_in &cursor) // eap::config_method ////////////////////////////////////////////////////////////////////// -eap::config_method::config_method(_In_ module &mod) : - m_allow_save(true), - config(mod) +eap::config_method::config_method(_In_ module &mod) : config(mod) { } -eap::config_method::config_method(_In_ const config_method &other) : - m_allow_save(other.m_allow_save), - m_anonymous_identity(other.m_anonymous_identity), - m_preshared(other.m_preshared ? (credentials*)other.m_preshared->clone() : nullptr), - config(other) +eap::config_method::config_method(_In_ const config_method &other) : config(other) { } -eap::config_method::config_method(_Inout_ config_method &&other) : - m_allow_save(std::move(other.m_allow_save)), - m_anonymous_identity(std::move(other.m_anonymous_identity)), - m_preshared(std::move(other.m_preshared)), - config(std::move(other)) +eap::config_method::config_method(_Inout_ config_method &&other) : config(std::move(other)) { } eap::config_method& eap::config_method::operator=(_In_ const config_method &other) { - if (this != &other) { - (config&)*this = other; - m_allow_save = other.m_allow_save; - m_anonymous_identity = other.m_anonymous_identity; - m_preshared.reset(other.m_preshared ? (credentials*)other.m_preshared->clone() : nullptr); - } + if (this != &other) + (config&)*this = other; return *this; } @@ -143,142 +129,13 @@ eap::config_method& eap::config_method::operator=(_In_ const config_method &othe eap::config_method& eap::config_method::operator=(_Inout_ config_method &&other) { - if (this != &other) { - (config&&)*this = std::move(other); - m_allow_save = std::move(other.m_allow_save); - m_anonymous_identity = std::move(other.m_anonymous_identity); - m_preshared = std::move(other.m_preshared); - } + if (this != &other) + (config&&)*this = std::move(other); return *this; } -bool eap::config_method::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const -{ - assert(pDoc); - assert(pConfigRoot); - assert(ppEapError); - - if (!config::save(pDoc, pConfigRoot, ppEapError)) - return false; - - const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); - DWORD dwResult; - - // - com_obj pXmlElClientSideCredential; - if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), bstr(L"ClientSideCredential"), bstrNamespace, &pXmlElClientSideCredential)) != ERROR_SUCCESS) { - *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); - return false; - } - - // / - if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, bstr(L"allow-save"), bstrNamespace, m_allow_save)) != ERROR_SUCCESS) { - *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); - return false; - } - - // / - if (!m_anonymous_identity.empty()) - if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, bstr(L"AnonymousIdentity"), bstrNamespace, bstr(m_anonymous_identity))) != ERROR_SUCCESS) { - *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); - return false; - } - - if (m_preshared) - if (!m_preshared->save(pDoc, pXmlElClientSideCredential, ppEapError)) - return false; - - return true; -} - - -bool eap::config_method::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) -{ - assert(pConfigRoot); - assert(ppEapError); - - if (!config::load(pConfigRoot, ppEapError)) - return false; - - m_allow_save = true; - m_preshared.reset(nullptr); - m_anonymous_identity.clear(); - - // - com_obj pXmlElClientSideCredential; - if (eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential) == ERROR_SUCCESS) { - wstring xpath(eapxml::get_xpath(pXmlElClientSideCredential)); - - // - eapxml::get_element_value(pXmlElClientSideCredential, bstr(L"eap-metadata:allow-save"), &m_allow_save); - m_module.log_config((xpath + L"/allow-save").c_str(), m_allow_save); - - // - eapxml::get_element_value(pXmlElClientSideCredential, bstr(L"eap-metadata:AnonymousIdentity"), m_anonymous_identity); - m_module.log_config((xpath + L"/AnonymousIdentity").c_str(), m_anonymous_identity.c_str()); - - unique_ptr preshared(make_credentials()); - assert(preshared); - if (preshared->load(pXmlElClientSideCredential, ppEapError)) { - m_preshared = std::move(preshared); - } else { - // This is not really an error - merely an indication pre-shared credentials are unavailable. - if (*ppEapError) { - m_module.free_error_memory(*ppEapError); - *ppEapError = NULL; - } - } - } - - return true; -} - - -void eap::config_method::operator<<(_Inout_ cursor_out &cursor) const -{ - config::operator<<(cursor); - cursor << m_allow_save ; - cursor << m_anonymous_identity; - if (m_preshared) { - cursor << true; - cursor << *m_preshared; - } else - cursor << false; -} - - -size_t eap::config_method::get_pk_size() const -{ - return - config::get_pk_size() + - pksizeof(m_allow_save ) + - pksizeof(m_anonymous_identity) + - (m_preshared ? - pksizeof(true ) + - pksizeof(*m_preshared) : - pksizeof(false )); -} - - -void eap::config_method::operator>>(_Inout_ cursor_in &cursor) -{ - config::operator>>(cursor); - cursor >> m_allow_save ; - cursor >> m_anonymous_identity; - - bool use_preshared; - cursor >> use_preshared; - if (use_preshared) { - m_preshared.reset(make_credentials()); - assert(m_preshared); - cursor >> *m_preshared; - } else - m_preshared.reset(nullptr); -} - - ////////////////////////////////////////////////////////////////////// // eap::config_provider ////////////////////////////////////////////////////////////////////// diff --git a/lib/EAPBase_UI/include/EAP_UI.h b/lib/EAPBase_UI/include/EAP_UI.h index 60f6b0a..6734119 100644 --- a/lib/EAPBase_UI/include/EAP_UI.h +++ b/lib/EAPBase_UI/include/EAP_UI.h @@ -47,7 +47,7 @@ class wxEAPProviderLockedPanel; /// /// Base template for credential configuration panel /// -template class wxEAPCredentialsConfigPanel; +template class wxEAPCredentialsConfigPanel; /// /// Base template for all credential entry panels @@ -216,23 +216,23 @@ protected: }; -template +template class wxEAPCredentialsConfigPanel : public wxEAPCredentialsConfigPanelBase { public: /// /// Constructs a credential configuration panel /// - /// \param[inout] prov Provider configuration data + /// \param[in] prov Provider configuration data /// \param[inout] cfg Configuration data /// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name. /// \param[in] parent Parent window /// - wxEAPCredentialsConfigPanel(const eap::config_provider &prov, eap::config_method &cfg, LPCTSTR pszCredTarget, wxWindow *parent) : + wxEAPCredentialsConfigPanel(const eap::config_provider &prov, eap::config_method_with_cred<_Tcred> &cfg, LPCTSTR pszCredTarget, wxWindow *parent) : m_prov(prov), m_cfg(cfg), m_target(pszCredTarget), - m_cred(cfg.make_credentials()), + m_cred(cfg.m_module), wxEAPCredentialsConfigPanelBase(parent) { // Load and set icon. @@ -253,12 +253,12 @@ protected: m_preshared_set ->Enable(false); } - if (!m_cfg.m_preshared) { + if (!m_cfg.m_use_preshared) m_own->SetValue(true); - } else { + else m_preshared->SetValue(true); - m_cred.reset((eap::credentials*)m_cfg.m_preshared->clone()); - } + + m_cred = m_cfg.m_preshared; return wxEAPCredentialsConfigPanelBase::TransferDataToWindow(); } @@ -270,7 +270,8 @@ protected: if (!m_prov.m_read_only) { // This is not a provider-locked configuration. Save the data. - m_cfg.m_preshared.reset(m_own->GetValue() ? nullptr : (eap::credentials*)m_cred->clone()); + m_cfg.m_use_preshared = !m_own->GetValue(); + m_cfg.m_preshared = m_cred; } return true; @@ -285,7 +286,7 @@ protected: if (m_cfg.m_allow_save) { bool has_own; std::unique_ptr > cred; - if (CredRead(m_cred->target_name(m_target.c_str()).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) { + if (CredRead(m_cred.target_name(m_target.c_str()).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) { m_own_identity->SetValue(cred->UserName && cred->UserName[0] != 0 ? cred->UserName : _("")); has_own = true; } else if ((dwResult = GetLastError()) == ERROR_NOT_FOUND) { @@ -313,7 +314,7 @@ protected: m_own_clear ->Enable(false); } - m_preshared_identity->SetValue(!m_cred->empty() ? m_cred->get_name() : _("")); + m_preshared_identity->SetValue(!m_cred.empty() ? m_cred.get_name() : _("")); if (!m_prov.m_read_only) { // This is not a provider-locked configuration. Selectively enable/disable controls. @@ -334,7 +335,8 @@ protected: wxEAPCredentialsDialog dlg(m_prov, this); - _wxT *panel = new _wxT(m_prov, *m_cred, m_target.c_str(), &dlg, true); + _Tcred cred(m_cfg.m_module); + _wxT *panel = new _wxT(m_prov, m_cfg, cred, m_target.c_str(), &dlg, true); dlg.AddContents((wxPanel**)&panel, 1); dlg.ShowModal(); @@ -345,7 +347,7 @@ protected: { UNREFERENCED_PARAMETER(event); - if (!CredDelete(m_cred->target_name(m_target.c_str()).c_str(), CRED_TYPE_GENERIC, 0)) + if (!CredDelete(m_cred.target_name(m_target.c_str()).c_str(), CRED_TYPE_GENERIC, 0)) wxLogError(_("Deleting credentials failed (error %u)."), GetLastError()); } @@ -356,7 +358,7 @@ protected: wxEAPCredentialsDialog dlg(m_prov, this); - _wxT *panel = new _wxT(m_prov, *m_cred, _T(""), &dlg, true); + _wxT *panel = new _wxT(m_prov, m_cfg, m_cred, _T(""), &dlg, true); dlg.AddContents((wxPanel**)&panel, 1); dlg.ShowModal(); @@ -365,14 +367,14 @@ protected: /// \endcond protected: - const eap::config_provider &m_prov; ///< EAP provider - eap::config_method &m_cfg; ///< EAP method configuration - winstd::library m_shell32; ///< shell32.dll resource library reference - wxIcon m_icon; ///< Panel icon - winstd::tstring m_target; ///< Credential Manager target + const eap::config_provider &m_prov; ///< EAP provider + eap::config_method_with_cred<_Tcred> &m_cfg; ///< EAP method configuration + winstd::library m_shell32; ///< shell32.dll resource library reference + wxIcon m_icon; ///< Panel icon + winstd::tstring m_target; ///< Credential Manager target private: - std::unique_ptr m_cred; ///< Temporary credential data + _Tcred m_cred; ///< Temporary credential data }; @@ -383,12 +385,16 @@ public: /// /// Constructs a credentials panel /// + /// \param[in] prov Provider configuration data + /// \param[in] cfg Configuration data /// \param[inout] cred Credentials data /// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name. /// \param[in] parent Parent window /// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled. /// - wxEAPCredentialsPanelBase(eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false) : + wxEAPCredentialsPanelBase(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false) : + m_prov(prov), + m_cfg(cfg), m_cred(cred), m_target(pszCredTarget), _Tbase(parent) @@ -447,8 +453,10 @@ protected: /// \endcond protected: - eap::credentials &m_cred; ///< Generic credentials - winstd::tstring m_target; ///< Credential Manager target + const eap::config_provider &m_prov; ///< Provider configuration + const eap::config_method &m_cfg; ///< Method configuration + eap::credentials &m_cred; ///< Generic credentials + winstd::tstring m_target; ///< Credential Manager target }; @@ -458,13 +466,14 @@ public: /// /// Constructs a password credentials panel /// - /// \param[inout] prov EAP provider + /// \param[in] prov Provider configuration data + /// \param[in] cfg Configuration data /// \param[inout] cred Credentials data /// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name. /// \param[in] parent Parent window /// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled. /// - wxPasswordCredentialsPanel(const eap::config_provider &prov, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false); + wxPasswordCredentialsPanel(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false); protected: /// \cond internal diff --git a/lib/EAPBase_UI/src/EAP_UI.cpp b/lib/EAPBase_UI/src/EAP_UI.cpp index 374e004..ca8bc10 100644 --- a/lib/EAPBase_UI/src/EAP_UI.cpp +++ b/lib/EAPBase_UI/src/EAP_UI.cpp @@ -155,28 +155,28 @@ bool wxEAPProviderLockedPanel::AcceptsFocusFromKeyboard() const // wxPasswordCredentialsPanel ////////////////////////////////////////////////////////////////////// -wxPasswordCredentialsPanel::wxPasswordCredentialsPanel(const eap::config_provider &prov, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) : +wxPasswordCredentialsPanel::wxPasswordCredentialsPanel(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) : m_cred((eap::credentials_pass&)cred), - wxEAPCredentialsPanelBase(cred, pszCredTarget, parent, is_config) + wxEAPCredentialsPanelBase(prov, cfg, cred, pszCredTarget, parent, is_config) { // Load and set icon. if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)) wxSetIconFromResource(m_credentials_icon, m_icon, m_shell32, MAKEINTRESOURCE(269)); bool layout = false; - if (!prov.m_lbl_alt_credential.empty()) { - m_credentials_label->SetLabel(prov.m_lbl_alt_credential); + if (!m_prov.m_lbl_alt_credential.empty()) { + m_credentials_label->SetLabel(m_prov.m_lbl_alt_credential); m_credentials_label->Wrap( 446 ); layout = true; } - if (!prov.m_lbl_alt_identity.empty()) { - m_identity_label->SetLabel(prov.m_lbl_alt_identity); + if (!m_prov.m_lbl_alt_identity.empty()) { + m_identity_label->SetLabel(m_prov.m_lbl_alt_identity); layout = true; } - if (!prov.m_lbl_alt_password.empty()) { - m_password_label->SetLabel(prov.m_lbl_alt_password); + if (!m_prov.m_lbl_alt_password.empty()) { + m_password_label->SetLabel(m_prov.m_lbl_alt_password); layout = true; } diff --git a/lib/PAP/include/Config.h b/lib/PAP/include/Config.h index 1672fb4..a9e4aa2 100644 --- a/lib/PAP/include/Config.h +++ b/lib/PAP/include/Config.h @@ -40,7 +40,7 @@ namespace eap namespace eap { - class config_method_pap : public config_method + class config_method_pap : public config_method_with_cred { public: /// @@ -89,11 +89,6 @@ namespace eap /// virtual config* clone() const; - /// - /// Makes new set of credentials for the given method type - /// - virtual credentials* make_credentials() const; - /// /// Returns EAP method type of this configuration /// diff --git a/lib/PAP/src/Config.cpp b/lib/PAP/src/Config.cpp index 1faf345..316f838 100644 --- a/lib/PAP/src/Config.cpp +++ b/lib/PAP/src/Config.cpp @@ -25,19 +25,19 @@ // eap::config_method_pap ////////////////////////////////////////////////////////////////////// -eap::config_method_pap::config_method_pap(_In_ module &mod) : config_method(mod) +eap::config_method_pap::config_method_pap(_In_ module &mod) : config_method_with_cred(mod) { } eap::config_method_pap::config_method_pap(_In_ const config_method_pap &other) : - config_method(other) + config_method_with_cred(other) { } eap::config_method_pap::config_method_pap(_Inout_ config_method_pap &&other) : - config_method(std::move(other)) + config_method_with_cred(std::move(other)) { } @@ -45,7 +45,7 @@ eap::config_method_pap::config_method_pap(_Inout_ config_method_pap &&other) : eap::config_method_pap& eap::config_method_pap::operator=(_In_ const config_method_pap &other) { if (this != &other) - (config_method&)*this = other; + (config_method_with_cred&)*this = other; return *this; } @@ -54,7 +54,7 @@ eap::config_method_pap& eap::config_method_pap::operator=(_In_ const config_meth eap::config_method_pap& eap::config_method_pap::operator=(_Inout_ config_method_pap &&other) { if (this != &other) - (config_method&&)*this = std::move(other); + (config_method_with_cred&&)*this = std::move(other); return *this; } @@ -66,12 +66,6 @@ eap::config* eap::config_method_pap::clone() const } -eap::credentials* eap::config_method_pap::make_credentials() const -{ - return new credentials_pap(m_module); -} - - eap::type_t eap::config_method_pap::get_method_id() const { return eap::type_pap; diff --git a/lib/PAP_UI/include/PAP_UI.h b/lib/PAP_UI/include/PAP_UI.h index 1daa320..9db7488 100644 --- a/lib/PAP_UI/include/PAP_UI.h +++ b/lib/PAP_UI/include/PAP_UI.h @@ -25,13 +25,18 @@ /// /// PAP credential configuration panel /// -typedef wxEAPCredentialsConfigPanel wxPAPCredentialsConfigPanel; +typedef wxEAPCredentialsConfigPanel wxPAPCredentialsConfigPanel; /// /// PAP configuration panel /// class wxPAPConfigPanel; +/// +/// PAP credential entry panel +/// +typedef wxPasswordCredentialsPanel wxPAPCredentialsPanel; + #pragma once #include diff --git a/lib/TLS/include/Config.h b/lib/TLS/include/Config.h index eb64a4d..6c07363 100644 --- a/lib/TLS/include/Config.h +++ b/lib/TLS/include/Config.h @@ -54,7 +54,7 @@ namespace eap namespace eap { - class config_method_tls : public config_method + class config_method_tls : public config_method_with_cred { public: /// @@ -159,11 +159,6 @@ namespace eap /// @} - /// - /// Makes new set of credentials for the given method type - /// - virtual credentials* make_credentials() const; - /// /// Returns EAP method type of this configuration /// diff --git a/lib/TLS/src/Config.cpp b/lib/TLS/src/Config.cpp index 0968c3c..a9bc2cb 100644 --- a/lib/TLS/src/Config.cpp +++ b/lib/TLS/src/Config.cpp @@ -66,7 +66,7 @@ tstring eap::get_cert_title(PCCERT_CONTEXT cert) // eap::config_method_tls ////////////////////////////////////////////////////////////////////// -eap::config_method_tls::config_method_tls(_In_ module &mod) : config_method(mod) +eap::config_method_tls::config_method_tls(_In_ module &mod) : config_method_with_cred(mod) { } @@ -74,7 +74,7 @@ eap::config_method_tls::config_method_tls(_In_ module &mod) : config_method(mod) eap::config_method_tls::config_method_tls(_In_ const config_method_tls &other) : m_trusted_root_ca(other.m_trusted_root_ca), m_server_names(other.m_server_names), - config_method(other) + config_method_with_cred(other) { } @@ -82,7 +82,7 @@ eap::config_method_tls::config_method_tls(_In_ const config_method_tls &other) : eap::config_method_tls::config_method_tls(_Inout_ config_method_tls &&other) : m_trusted_root_ca(std::move(other.m_trusted_root_ca)), m_server_names(std::move(other.m_server_names)), - config_method(std::move(other)) + config_method_with_cred(std::move(other)) { } @@ -90,7 +90,7 @@ eap::config_method_tls::config_method_tls(_Inout_ config_method_tls &&other) : eap::config_method_tls& eap::config_method_tls::operator=(_In_ const config_method_tls &other) { if (this != &other) { - (config_method&)*this = other; + (config_method_with_cred&)*this = other; m_trusted_root_ca = other.m_trusted_root_ca; m_server_names = other.m_server_names; } @@ -102,7 +102,7 @@ eap::config_method_tls& eap::config_method_tls::operator=(_In_ const config_meth eap::config_method_tls& eap::config_method_tls::operator=(_Inout_ config_method_tls &&other) { if (this != &other) { - (config_method&&)*this = std::move(other); + (config_method_with_cred&&)*this = std::move(other); m_trusted_root_ca = std::move(other.m_trusted_root_ca); m_server_names = std::move(other.m_server_names); } @@ -123,7 +123,7 @@ bool eap::config_method_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode * assert(pConfigRoot); assert(ppEapError); - if (!config_method::save(pDoc, pConfigRoot, ppEapError)) + if (!config_method_with_cred::save(pDoc, pConfigRoot, ppEapError)) return false; const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); @@ -182,7 +182,7 @@ bool eap::config_method_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR { assert(pConfigRoot); - if (!config_method::load(pConfigRoot, ppEapError)) + if (!config_method_with_cred::load(pConfigRoot, ppEapError)) return false; std::wstring xpath(eapxml::get_xpath(pConfigRoot)); @@ -258,7 +258,7 @@ bool eap::config_method_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR void eap::config_method_tls::operator<<(_Inout_ cursor_out &cursor) const { - config_method::operator<<(cursor); + config_method_with_cred::operator<<(cursor); cursor << m_trusted_root_ca; cursor << m_server_names ; } @@ -267,7 +267,7 @@ void eap::config_method_tls::operator<<(_Inout_ cursor_out &cursor) const size_t eap::config_method_tls::get_pk_size() const { return - config_method::get_pk_size() + + config_method_with_cred::get_pk_size() + pksizeof(m_trusted_root_ca) + pksizeof(m_server_names ); } @@ -275,18 +275,12 @@ size_t eap::config_method_tls::get_pk_size() const void eap::config_method_tls::operator>>(_Inout_ cursor_in &cursor) { - config_method::operator>>(cursor); + config_method_with_cred::operator>>(cursor); cursor >> m_trusted_root_ca; cursor >> m_server_names ; } -eap::credentials* eap::config_method_tls::make_credentials() const -{ - return new credentials_tls(m_module); -} - - eap::type_t eap::config_method_tls::get_method_id() const { return type_tls; diff --git a/lib/TLS_UI/include/TLS_UI.h b/lib/TLS_UI/include/TLS_UI.h index 96d40d0..128f2bc 100644 --- a/lib/TLS_UI/include/TLS_UI.h +++ b/lib/TLS_UI/include/TLS_UI.h @@ -68,7 +68,7 @@ class wxTLSServerTrustPanel; /// /// TLS credentials configuration panel /// -typedef wxEAPCredentialsConfigPanel wxTLSCredentialsConfigPanel; +typedef wxEAPCredentialsConfigPanel wxTLSCredentialsConfigPanel; /// /// TLS configuration panel @@ -254,7 +254,14 @@ public: /// /// Constructs a configuration panel /// - wxTLSCredentialsPanel(const eap::config_provider &prov, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false); + /// \param[in] prov Provider configuration data + /// \param[in] cfg Configuration data + /// \param[inout] cred Credentials data + /// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name. + /// \param[in] parent Parent window + /// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled. + /// + wxTLSCredentialsPanel(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false); protected: /// \cond internal diff --git a/lib/TLS_UI/src/TLS_UI.cpp b/lib/TLS_UI/src/TLS_UI.cpp index 4afa02f..00b8c89 100644 --- a/lib/TLS_UI/src/TLS_UI.cpp +++ b/lib/TLS_UI/src/TLS_UI.cpp @@ -311,12 +311,10 @@ bool wxFQDNListValidator::Parse(const wxString &val_in, size_t i_start, size_t i // wxTLSCredentialsPanel ////////////////////////////////////////////////////////////////////// -wxTLSCredentialsPanel::wxTLSCredentialsPanel(const eap::config_provider &prov, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) : +wxTLSCredentialsPanel::wxTLSCredentialsPanel(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) : m_cred((eap::credentials_tls&)cred), - wxEAPCredentialsPanelBase(cred, pszCredTarget, parent, is_config) + wxEAPCredentialsPanelBase(prov, cfg, cred, pszCredTarget, parent, is_config) { - UNREFERENCED_PARAMETER(prov); - // Load and set icon. if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)) wxSetIconFromResource(m_credentials_icon, m_icon, m_shell32, MAKEINTRESOURCE(269)); diff --git a/lib/TTLS/include/Config.h b/lib/TTLS/include/Config.h index 4b90022..09517df 100644 --- a/lib/TTLS/include/Config.h +++ b/lib/TTLS/include/Config.h @@ -40,7 +40,7 @@ namespace eap namespace eap { - class config_method_ttls : public config_method_tls + class config_method_ttls : public config_method { public: /// @@ -150,7 +150,14 @@ namespace eap { /// virtual eap::type_t get_method_id() const; + /// + /// Generates public identity using current configuration and given credentials + /// + std::wstring get_public_identity(const credentials &cred) const; + public: + config_method_tls m_outer; ///< Outer authentication configuration std::unique_ptr m_inner; ///< Inner authentication configuration + std::wstring m_anonymous_identity; ///< Anonymous identity }; } diff --git a/lib/TTLS/include/Credentials.h b/lib/TTLS/include/Credentials.h index c37ae67..d34c42c 100644 --- a/lib/TTLS/include/Credentials.h +++ b/lib/TTLS/include/Credentials.h @@ -36,7 +36,7 @@ namespace eap namespace eap { - class credentials_ttls : public credentials_tls + class credentials_ttls : public credentials { public: /// @@ -189,6 +189,7 @@ namespace eap /// @} public: + credentials_tls m_outer; ///< Outer credentials std::unique_ptr m_inner; ///< Inner credentials }; } diff --git a/lib/TTLS/src/Config.cpp b/lib/TTLS/src/Config.cpp index ea905e2..be3430e 100644 --- a/lib/TTLS/src/Config.cpp +++ b/lib/TTLS/src/Config.cpp @@ -29,21 +29,26 @@ using namespace winstd; ////////////////////////////////////////////////////////////////////// eap::config_method_ttls::config_method_ttls(_In_ module &mod) : - config_method_tls(mod) + m_outer(mod), + config_method(mod) { } eap::config_method_ttls::config_method_ttls(const _In_ config_method_ttls &other) : + m_outer(other.m_outer), m_inner(other.m_inner ? (config_method*)other.m_inner->clone() : nullptr), - config_method_tls(other) + m_anonymous_identity(other.m_anonymous_identity), + config_method(other) { } eap::config_method_ttls::config_method_ttls(_Inout_ config_method_ttls &&other) : + m_outer(std::move(other.m_outer)), m_inner(std::move(other.m_inner)), - config_method_tls(std::move(other)) + m_anonymous_identity(std::move(other.m_anonymous_identity)), + config_method(std::move(other)) { } @@ -51,8 +56,10 @@ eap::config_method_ttls::config_method_ttls(_Inout_ config_method_ttls &&other) eap::config_method_ttls& eap::config_method_ttls::operator=(const _In_ config_method_ttls &other) { if (this != &other) { - (config_method_tls&)*this = other; + (config_method&)*this = other; + m_outer = other.m_outer; m_inner.reset(other.m_inner ? (config_method*)other.m_inner->clone() : nullptr); + m_anonymous_identity = other.m_anonymous_identity; } return *this; @@ -62,8 +69,10 @@ eap::config_method_ttls& eap::config_method_ttls::operator=(const _In_ config_me eap::config_method_ttls& eap::config_method_ttls::operator=(_Inout_ config_method_ttls &&other) { if (this != &other) { - (config_method_tls&&)*this = std::move(other); - m_inner = std::move(other.m_inner); + (config_method&&)*this = std::move(other); + m_outer = std::move(other.m_outer); + m_inner = std::move(other.m_inner); + m_anonymous_identity = std::move(other.m_anonymous_identity); } return *this; @@ -82,12 +91,29 @@ bool eap::config_method_ttls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode assert(pConfigRoot); assert(ppEapError); - if (!config_method_tls::save(pDoc, pConfigRoot, ppEapError)) + if (!config_method::save(pDoc, pConfigRoot, ppEapError)) return false; const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); DWORD dwResult; + // + com_obj pXmlElClientSideCredential; + if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), bstr(L"ClientSideCredential"), bstrNamespace, &pXmlElClientSideCredential)) != ERROR_SUCCESS) { + *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); + return false; + } + + // / + if (!m_anonymous_identity.empty()) + if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, bstr(L"AnonymousIdentity"), bstrNamespace, bstr(m_anonymous_identity))) != ERROR_SUCCESS) { + *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error creating element.")); + return false; + } + + if (!m_outer.save(pDoc, pConfigRoot, ppEapError)) + return false; + // com_obj pXmlElInnerAuthenticationMethod; if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:InnerAuthenticationMethod"), bstr(L"InnerAuthenticationMethod"), bstrNamespace, &pXmlElInnerAuthenticationMethod)) != ERROR_SUCCESS) { @@ -120,12 +146,27 @@ bool eap::config_method_ttls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERRO assert(ppEapError); DWORD dwResult; - if (!config_method_tls::load(pConfigRoot, ppEapError)) + if (!config_method::load(pConfigRoot, ppEapError)) return false; std::wstring xpath(eapxml::get_xpath(pConfigRoot)); - // Load inner authentication configuration (). + m_anonymous_identity.clear(); + + // + com_obj pXmlElClientSideCredential; + if (eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential) == ERROR_SUCCESS) { + wstring xpathClientSideCredential(xpath + L"/ClientSideCredential"); + + // + eapxml::get_element_value(pXmlElClientSideCredential, bstr(L"eap-metadata:AnonymousIdentity"), m_anonymous_identity); + m_module.log_config((xpathClientSideCredential + L"/AnonymousIdentity").c_str(), m_anonymous_identity.c_str()); + } + + if (!m_outer.load(pConfigRoot, ppEapError)) + return false; + + // com_obj pXmlElInnerAuthenticationMethod; if ((dwResult = eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:InnerAuthenticationMethod"), &pXmlElInnerAuthenticationMethod)) != ERROR_SUCCESS) { *ppEapError = m_module.make_error(dwResult, _T(__FUNCTION__) _T(" Error selecting element."), _T("Please make sure profile XML is a valid ") _T(PRODUCT_NAME_STR) _T(" profile XML document.")); @@ -160,7 +201,9 @@ bool eap::config_method_ttls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERRO void eap::config_method_ttls::operator<<(_Inout_ cursor_out &cursor) const { - config_method_tls::operator<<(cursor); + config_method::operator<<(cursor); + cursor << m_outer; + if (m_inner) { if (dynamic_cast(m_inner.get())) { cursor << type_pap; @@ -171,6 +214,8 @@ void eap::config_method_ttls::operator<<(_Inout_ cursor_out &cursor) const } } else cursor << type_undefined; + + cursor << m_anonymous_identity; } @@ -190,14 +235,17 @@ size_t eap::config_method_ttls::get_pk_size() const size_inner = pksizeof(type_undefined); return - config_method_tls::get_pk_size() + - size_inner; + config_method::get_pk_size() + + pksizeof(m_outer) + + size_inner + + pksizeof(m_anonymous_identity); } void eap::config_method_ttls::operator>>(_Inout_ cursor_in &cursor) { - config_method_tls::operator>>(cursor); + config_method::operator>>(cursor); + cursor >> m_outer; type_t eap_type; cursor >> eap_type; @@ -210,6 +258,8 @@ void eap::config_method_ttls::operator>>(_Inout_ cursor_in &cursor) assert(0); // Unsupported inner authentication method type. m_inner.reset(nullptr); } + + cursor >> m_anonymous_identity; } @@ -217,3 +267,21 @@ eap::type_t eap::config_method_ttls::get_method_id() const { return type_ttls; } + + +wstring eap::config_method_ttls::get_public_identity(const credentials &cred) const +{ + if (m_anonymous_identity.empty()) { + // Use the true identity. Outer has the right-of-way. + return cred.get_identity(); + } else if (m_anonymous_identity.compare(L"@") == 0) { + // Strip username part from identity (RFC 4822). + wstring identity(std::move(cred.get_identity())); + wstring::size_type offset = identity.find(L'@'); + if (offset != wstring::npos) identity.erase(0, offset); + return identity; + } else { + // Use configured identity. + return m_anonymous_identity; + } +} diff --git a/lib/TTLS/src/Credentials.cpp b/lib/TTLS/src/Credentials.cpp index 78f7601..1730b8a 100644 --- a/lib/TTLS/src/Credentials.cpp +++ b/lib/TTLS/src/Credentials.cpp @@ -29,21 +29,24 @@ using namespace winstd; ////////////////////////////////////////////////////////////////////// eap::credentials_ttls::credentials_ttls(_In_ module &mod) : - credentials_tls(mod) + m_outer(mod), + credentials(mod) { } eap::credentials_ttls::credentials_ttls(_In_ const credentials_ttls &other) : + m_outer(other.m_outer), m_inner(other.m_inner ? (credentials*)other.m_inner->clone() : nullptr), - credentials_tls(other) + credentials(other) { } eap::credentials_ttls::credentials_ttls(_Inout_ credentials_ttls &&other) : + m_outer(std::move(other.m_outer)), m_inner(std::move(other.m_inner)), - credentials_tls(std::move(other)) + credentials(std::move(other)) { } @@ -51,7 +54,8 @@ eap::credentials_ttls::credentials_ttls(_Inout_ credentials_ttls &&other) : eap::credentials_ttls& eap::credentials_ttls::operator=(_In_ const credentials_ttls &other) { if (this != &other) { - (credentials_tls&)*this = other; + (credentials&)*this = other; + m_outer = other.m_outer; m_inner.reset(other.m_inner ? (credentials*)other.m_inner->clone() : nullptr); } @@ -62,8 +66,9 @@ eap::credentials_ttls& eap::credentials_ttls::operator=(_In_ const credentials_t eap::credentials_ttls& eap::credentials_ttls::operator=(_Inout_ credentials_ttls &&other) { if (this != &other) { - (credentials_tls&)*this = std::move(other); - m_inner = std::move(other.m_inner); + (credentials&)*this = std::move(other); + m_outer = std::move(other.m_outer); + m_inner = std::move(other.m_inner); } return *this; @@ -78,7 +83,8 @@ eap::config* eap::credentials_ttls::clone() const void eap::credentials_ttls::clear() { - credentials_tls::clear(); + credentials::clear(); + m_outer.clear(); if (m_inner) m_inner->clear(); } @@ -86,7 +92,7 @@ void eap::credentials_ttls::clear() bool eap::credentials_ttls::empty() const { - return credentials_tls::empty() && (!m_inner || m_inner->empty()); + return credentials::empty() && m_outer.empty() && (!m_inner || m_inner->empty()); } @@ -96,7 +102,10 @@ bool eap::credentials_ttls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *p assert(pConfigRoot); assert(ppEapError); - if (!credentials_tls::save(pDoc, pConfigRoot, ppEapError)) + if (!credentials::save(pDoc, pConfigRoot, ppEapError)) + return false; + + if (!m_outer.save(pDoc, pConfigRoot, ppEapError)) return false; const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); @@ -130,7 +139,10 @@ bool eap::credentials_ttls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR assert(ppEapError); DWORD dwResult; - if (!credentials_tls::load(pConfigRoot, ppEapError)) + if (!credentials::load(pConfigRoot, ppEapError)) + return false; + + if (!m_outer.load(pConfigRoot, ppEapError)) return false; // TODO: For the time being, there is no detection what type is inner method. Introduce one! @@ -151,7 +163,8 @@ bool eap::credentials_ttls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR void eap::credentials_ttls::operator<<(_Inout_ cursor_out &cursor) const { - credentials_tls::operator<<(cursor); + credentials::operator<<(cursor); + cursor << m_outer; if (m_inner) { if (dynamic_cast(m_inner.get())) { cursor << type_pap; @@ -181,14 +194,16 @@ size_t eap::credentials_ttls::get_pk_size() const size_inner = pksizeof(type_undefined); return - credentials_tls::get_pk_size() + + credentials::get_pk_size() + + pksizeof(m_outer) + size_inner; } void eap::credentials_ttls::operator>>(_Inout_ cursor_in &cursor) { - credentials_tls::operator>>(cursor); + credentials::operator>>(cursor); + cursor >> m_outer; type_t eap_type; cursor >> eap_type; @@ -206,7 +221,7 @@ void eap::credentials_ttls::operator>>(_Inout_ cursor_in &cursor) bool eap::credentials_ttls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const { - if (!credentials_tls::store(pszTargetName, ppEapError)) + if (!m_outer.store(pszTargetName, ppEapError)) return false; if (m_inner) { @@ -220,7 +235,7 @@ bool eap::credentials_ttls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR ** bool eap::credentials_ttls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) { - if (!credentials_tls::retrieve(pszTargetName, ppEapError)) + if (!m_outer.retrieve(pszTargetName, ppEapError)) return false; if (m_inner) { @@ -242,8 +257,8 @@ LPCTSTR eap::credentials_ttls::target_suffix() const std::wstring eap::credentials_ttls::get_identity() const { // Outer identity has the right-of-way. - if (!credentials_tls::empty()) - return credentials_tls::get_identity(); + if (!m_outer.empty()) + return m_outer.get_identity(); // Inner identity. if (m_inner) diff --git a/lib/TTLS/src/Module.cpp b/lib/TTLS/src/Module.cpp index b7f3d0e..3c086e9 100644 --- a/lib/TTLS/src/Module.cpp +++ b/lib/TTLS/src/Module.cpp @@ -79,15 +79,15 @@ bool eap::peer_ttls::get_identity( const config_provider &cfg_prov(cfg.m_providers.front()); const config_method_ttls *cfg_method = dynamic_cast(cfg_prov.m_methods.front().get()); - wstring target_outer(std::move(cred_out.credentials_tls::target_suffix())); + assert(cfg_method); + wstring target_outer(std::move(cred_out.m_outer.target_suffix())); wstring target_inner; bool is_outer_set = false; - assert(cfg_method); - if (cfg_method->m_preshared) { + if (cfg_method->m_outer.m_use_preshared) { // Outer TLS: Preshared credentials. - (credentials_tls&)cred_out = (credentials_tls&)*cfg_method->m_preshared; - log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(target_outer), event_data(cred_out.credentials_tls::get_name()), event_data::blank); + cred_out.m_outer = (credentials_tls&)cfg_method->m_outer.m_preshared; + log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(target_outer), event_data(cred_out.m_outer.get_name()), event_data::blank); is_outer_set = true; } @@ -95,9 +95,9 @@ bool eap::peer_ttls::get_identity( const config_method_pap *cfg_inner_pap = dynamic_cast(cfg_method->m_inner.get()); if (cfg_inner_pap) { target_inner = L"PAP"; - if (cfg_inner_pap->m_preshared) { + if (cfg_inner_pap->m_use_preshared) { // Inner PAP: Preshared credentials. - cred_out.m_inner.reset((credentials*)cfg_inner_pap->m_preshared->clone()); + cred_out.m_inner.reset((credentials*)cfg_inner_pap->m_preshared.clone()); log_event(&EAPMETHOD_TRACE_EVT_CRED_PRESHARED, event_data(target_inner), event_data(cred_out.m_inner->get_name()), event_data::blank); is_inner_set = true; } @@ -114,8 +114,8 @@ bool eap::peer_ttls::get_identity( credentials_tls cred_loaded(*this); if (cred_loaded.retrieve(cfg_prov.m_id.c_str(), ppEapError)) { // Outer TLS: Stored credentials. - (credentials_tls&&)cred_out = std::move(cred_loaded); - log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED, event_data(target_outer), event_data(cred_out.credentials_tls::get_name()), event_data::blank); + cred_out.m_outer = std::move(cred_loaded); + log_event(&EAPMETHOD_TRACE_EVT_CRED_STORED, event_data(target_outer), event_data(cred_out.m_outer.get_name()), event_data::blank); is_outer_set = true; } else { // Not actually an error. @@ -147,8 +147,8 @@ bool eap::peer_ttls::get_identity( if (!is_outer_set) { // Outer TLS: EAP service cached credentials. - (credentials_tls&)cred_out = (const credentials_tls&)cred_in; - log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED, event_data(target_outer), event_data(cred_out.credentials_tls::get_name()), event_data::blank); + cred_out.m_outer = cred_in->m_outer; + log_event(&EAPMETHOD_TRACE_EVT_CRED_CACHED, event_data(target_outer), event_data(cred_out.m_outer.get_name()), event_data::blank); is_outer_set = true; } @@ -185,23 +185,8 @@ bool eap::peer_ttls::get_identity( // If we got here, we have all credentials we need. // Build our identity. ;) - wstring identity; - if (cfg_method->m_anonymous_identity.empty()) { - // Use the true identity. Outer has the right-of-way. - identity = std::move(cred_out.get_identity()); - } else if (cfg_method->m_anonymous_identity.compare(L"@") == 0) { - // Strip username part from identity (RFC 4822). - identity = std::move(cred_out.get_identity()); - wstring::size_type offset = identity.find(L'@'); - if (offset != wstring::npos) identity.erase(0, offset); - } else { - // Use configured identity. - identity = cfg_method->m_anonymous_identity; - } - + wstring identity(std::move(cfg_method->get_public_identity(cred_out))); log_event(&EAPMETHOD_TRACE_EVT_CRED_OUTER_ID, event_data(L"TTLS"), event_data(identity), event_data::blank); - - // Save the identity for EAPHost. size_t size = sizeof(WCHAR)*(identity.length() + 1); *ppwszIdentity = (WCHAR*)alloc_memory(size); memcpy(*ppwszIdentity, identity.c_str(), size); diff --git a/lib/TTLS_UI/include/TTLS_UI.h b/lib/TTLS_UI/include/TTLS_UI.h index befc052..bf2ddf3 100644 --- a/lib/TTLS_UI/include/TTLS_UI.h +++ b/lib/TTLS_UI/include/TTLS_UI.h @@ -28,6 +28,11 @@ class wxTTLSConfigPanel; /// class wxTTLSConfigWindow; +/// +/// TTLS credential panel +/// +class wxTTLSCredentialsPanel; + #pragma once #include "../res/wxTTLS_UI.h" @@ -102,6 +107,41 @@ protected: wxStaticText *m_inner_title; ///< Inner authentication title wxChoicebook *m_inner_type; ///< Inner authentication type - // Temprary inner method configurations to hold data until applied + // Temporary inner method configurations to hold data until applied eap::config_method_pap m_cfg_pap; ///< PAP configuration }; + + +class wxTTLSCredentialsPanel : public wxPanel +{ +public: + /// + /// Constructs a configuration panel + /// + /// \param[in] prov Provider configuration data + /// \param[in] cfg Configuration data + /// \param[inout] cred Credentials data + /// \param[in] pszCredTarget Target name of credentials in Windows Credential Manager. Can be further decorated to create final target name. + /// \param[in] parent Parent window + /// \param[in] is_config Is this panel used to pre-enter credentials? When \c true, the "Remember" checkbox is always selected and disabled. + /// + wxTTLSCredentialsPanel(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config = false); + + /// + /// Destructs the configuration panel + /// + virtual ~wxTTLSCredentialsPanel(); + +protected: + /// \cond internal + virtual void OnInitDialog(wxInitDialogEvent& event); + /// \endcond + +protected: + const eap::config_provider &m_prov; ///< EAP provider + const eap::config_method_ttls &m_cfg; ///< TTLS configuration + wxStaticText *m_outer_title; ///< Outer authentication title + wxTLSCredentialsPanel *m_outer_cred; ///< Outer credentials panel + wxStaticText *m_inner_title; ///< Inner authentication title + wxPanel *m_inner_cred; ///< Inner credentials panel +}; diff --git a/lib/TTLS_UI/src/Module.cpp b/lib/TTLS_UI/src/Module.cpp index ce2ce58..3d0824e 100644 --- a/lib/TTLS_UI/src/Module.cpp +++ b/lib/TTLS_UI/src/Module.cpp @@ -77,13 +77,51 @@ bool eap::peer_ttls_ui::invoke_identity_ui( _Out_ EAP_ERROR **ppEapError) { UNREFERENCED_PARAMETER(dwFlags); - UNREFERENCED_PARAMETER(cfg); - UNREFERENCED_PARAMETER(cred); - UNREFERENCED_PARAMETER(ppwszIdentity); - UNREFERENCED_PARAMETER(ppEapError); - InitCommonControls(); - MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" credential prompt goes here!"), _T(PRODUCT_NAME_STR) _T(" Credentials"), MB_OK); + if (cfg.m_providers.empty() || cfg.m_providers.front().m_methods.empty()) { + *ppEapError = make_error(ERROR_INVALID_PARAMETER, _T(__FUNCTION__) _T(" Configuration has no providers and/or methods.")); + return false; + } + + const config_provider &cfg_prov(cfg.m_providers.front()); + const config_method_ttls *cfg_method = dynamic_cast(cfg_prov.m_methods.front().get()); + assert(cfg_method); + + // Initialize application. + new wxApp(); + wxEntryStart(m_instance); + + int result; + { + // Create wxWidget-approved parent window. + wxWindow parent; + parent.SetHWND((WXHWND)hwndParent); + parent.AdoptAttributesFromHWND(); + wxTopLevelWindows.Append(&parent); + + // Create and launch credentials dialog. + wxEAPCredentialsDialog dlg(cfg_prov, &parent); + wxTTLSCredentialsPanel *panel = new wxTTLSCredentialsPanel(cfg_prov, *cfg_method, cred, cfg_prov.m_id.c_str(), &dlg, true); + dlg.AddContents((wxPanel**)&panel, 1); + result = dlg.ShowModal(); + + wxTopLevelWindows.DeleteObject(&parent); + parent.SetHWND((WXHWND)NULL); + } + + // Clean-up and return. + wxEntryCleanup(); + if (result != wxID_OK) { + *ppEapError = make_error(ERROR_CANCELLED, _T(__FUNCTION__) _T(" Cancelled.")); + return false; + } + + // Build our identity. ;) + std::wstring identity(std::move(cfg_method->get_public_identity(cred))); + log_event(&EAPMETHOD_TRACE_EVT_CRED_OUTER_ID, winstd::event_data(L"TTLS"), winstd::event_data(identity), winstd::event_data::blank); + size_t size = sizeof(WCHAR)*(identity.length() + 1); + *ppwszIdentity = (WCHAR*)alloc_memory(size); + memcpy(*ppwszIdentity, identity.c_str(), size); return true; } diff --git a/lib/TTLS_UI/src/TTLS_UI.cpp b/lib/TTLS_UI/src/TTLS_UI.cpp index ed76f55..4e9f6f2 100644 --- a/lib/TTLS_UI/src/TTLS_UI.cpp +++ b/lib/TTLS_UI/src/TTLS_UI.cpp @@ -102,8 +102,8 @@ wxTTLSConfigWindow::wxTTLSConfigWindow(const eap::config_provider &prov, eap::co wxBoxSizer* sb_content; sb_content = new wxBoxSizer( wxVERTICAL ); - if (prov.m_read_only) - sb_content->Add(new wxEAPProviderLockedPanel(prov, this), 0, wxALL|wxEXPAND, 5); + if (m_prov.m_read_only) + sb_content->Add(new wxEAPProviderLockedPanel(m_prov, this), 0, wxALL|wxEXPAND, 5); m_inner_title = new wxStaticText(this, wxID_ANY, _("Inner Authentication"), wxDefaultPosition, wxDefaultSize, 0); m_inner_title->SetFont(wxFont(18, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString)); @@ -112,7 +112,7 @@ wxTTLSConfigWindow::wxTTLSConfigWindow(const eap::config_provider &prov, eap::co m_inner_type = new wxChoicebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCHB_DEFAULT); m_inner_type->SetToolTip( _("Select inner authentication method from the list") ); - m_inner_type->AddPage(new wxPAPConfigPanel(prov, m_cfg_pap, pszCredTarget, m_inner_type), _("PAP")); + m_inner_type->AddPage(new wxPAPConfigPanel(m_prov, m_cfg_pap, pszCredTarget, m_inner_type), _("PAP")); sb_content->Add(m_inner_type, 0, wxALL|wxEXPAND, 5); sb_content->Add(20, 20, 1, wxALL|wxEXPAND, 5); @@ -122,10 +122,10 @@ wxTTLSConfigWindow::wxTTLSConfigWindow(const eap::config_provider &prov, eap::co m_outer_title->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVECAPTION ) ); sb_content->Add(m_outer_title, 0, wxALL|wxALIGN_RIGHT, 5); - m_outer_identity = new wxTTLSConfigPanel(prov, m_cfg, this); + m_outer_identity = new wxTTLSConfigPanel(m_prov, m_cfg, this); sb_content->Add(m_outer_identity, 0, wxALL|wxEXPAND, 5); - m_tls = new wxTLSConfigPanel(prov, m_cfg, pszCredTarget, this); + m_tls = new wxTLSConfigPanel(m_prov, m_cfg.m_outer, pszCredTarget, this); sb_content->Add(m_tls, 0, wxALL|wxEXPAND, 5); wxSize size = sb_content->CalcMin(); @@ -205,3 +205,67 @@ void wxTTLSConfigWindow::OnInitDialog(wxInitDialogEvent& event) for (wxWindowList::compatibility_iterator inner = m_inner_type->GetChildren().GetFirst(); inner; inner = inner->GetNext()) inner->GetData()->GetEventHandler()->ProcessEvent(event); } + + +////////////////////////////////////////////////////////////////////// +// wxTTLSCredentialsPanel +////////////////////////////////////////////////////////////////////// + +wxTTLSCredentialsPanel::wxTTLSCredentialsPanel(const eap::config_provider &prov, const eap::config_method &cfg, eap::credentials &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) : + m_prov(prov), + m_cfg((eap::config_method_ttls&)cfg), + wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) +{ + wxBoxSizer* sb_content; + sb_content = new wxBoxSizer( wxVERTICAL ); + + if (m_prov.m_read_only) + sb_content->Add(new wxEAPProviderLockedPanel(m_prov, this), 0, wxALL|wxEXPAND, 5); + + m_inner_title = new wxStaticText(this, wxID_ANY, _("Inner Authentication"), wxDefaultPosition, wxDefaultSize, 0); + m_inner_title->SetFont(wxFont(18, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString)); + m_inner_title->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVECAPTION ) ); + sb_content->Add(m_inner_title, 0, wxALL|wxALIGN_RIGHT, 5); + + assert(m_cfg.m_inner); + const eap::config_method_pap *cfg_inner_pap = dynamic_cast(m_cfg.m_inner.get()); + if (cfg_inner_pap) { + if (!((eap::credentials_ttls&)cred).m_inner) ((eap::credentials_ttls&)cred).m_inner.reset(new eap::credentials_pap(cred.m_module)); + m_inner_cred = new wxPAPCredentialsPanel(m_prov, *cfg_inner_pap, *((eap::credentials_ttls&)cred).m_inner.get(), pszCredTarget, this, is_config); + sb_content->Add(m_inner_cred, 0, wxALL|wxEXPAND, 5); + } else + assert(0); // Unsupported inner authentication method type. + + sb_content->Add(20, 20, 1, wxALL|wxEXPAND, 5); + + m_outer_title = new wxStaticText(this, wxID_ANY, _("Outer Authentication"), wxDefaultPosition, wxDefaultSize, 0); + m_outer_title->SetFont(wxFont(18, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString)); + m_outer_title->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_INACTIVECAPTION ) ); + sb_content->Add(m_outer_title, 0, wxALL|wxALIGN_RIGHT, 5); + + m_outer_cred = new wxTLSCredentialsPanel(m_prov, (const eap::config_method_tls&)m_cfg, (eap::credentials_tls&)cred, pszCredTarget, this, is_config); + sb_content->Add(m_outer_cred, 0, wxALL|wxEXPAND, 5); + + this->SetSizer(sb_content); + this->Layout(); + + m_inner_cred->SetFocusFromKbd(); + + // Connect Events + this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxTTLSCredentialsPanel::OnInitDialog)); +} + + +wxTTLSCredentialsPanel::~wxTTLSCredentialsPanel() +{ + // Disconnect Events + this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxTTLSCredentialsPanel::OnInitDialog)); +} + + +void wxTTLSCredentialsPanel::OnInitDialog(wxInitDialogEvent& event) +{ + // Forward the event to child panels. + m_outer_cred->GetEventHandler()->ProcessEvent(event); + m_inner_cred->GetEventHandler()->ProcessEvent(event); +}