From 6835f5279c5aea755c12f88f7e0b01baac26958c Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 24 Aug 2016 09:14:02 +0200 Subject: [PATCH] Certificate (TLS) credentials support custom identity now --- lib/EAPBase/include/Credentials.h | 57 ++++++- lib/EAPBase/src/Credentials.cpp | 101 +++++++---- lib/TLS/include/Credentials.h | 5 - lib/TLS/src/Credentials.cpp | 26 +-- lib/TLS_UI/res/wxTLS_UI.cpp | 19 +++ lib/TLS_UI/res/wxTLS_UI.fbp | 268 ++++++++++++++++++++++++++++++ lib/TLS_UI/res/wxTLS_UI.h | 3 + lib/TLS_UI/src/TLS_UI.cpp | 4 + lib/TTLS/src/Credentials.cpp | 4 + lib/TTLS_UI/res/wxTTLS_UI.cpp | 2 +- lib/TTLS_UI/res/wxTTLS_UI.fbp | 2 +- 11 files changed, 436 insertions(+), 55 deletions(-) diff --git a/lib/EAPBase/include/Credentials.h b/lib/EAPBase/include/Credentials.h index 2dc8428..a911cc5 100644 --- a/lib/EAPBase/include/Credentials.h +++ b/lib/EAPBase/include/Credentials.h @@ -120,6 +120,52 @@ namespace eap /// virtual bool empty() const; + /// \name XML configuration management + /// @{ + + /// + /// Save to XML document + /// + /// \param[in] pDoc XML document + /// \param[in] pConfigRoot Suggested root element for saving + /// + virtual void save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const; + + /// + /// Load from XML document + /// + /// \param[in] pConfigRoot Root element for loading + /// + virtual void load(_In_ IXMLDOMNode *pConfigRoot); + + /// @} + + /// \name BLOB management + /// @{ + + /// + /// Packs a configuration + /// + /// \param[inout] cursor Memory cursor + /// + virtual void operator<<(_Inout_ cursor_out &cursor) const; + + /// + /// Returns packed size of a configuration + /// + /// \returns Size of data when packed (in bytes) + /// + virtual size_t get_pk_size() const; + + /// + /// Unpacks a configuration + /// + /// \param[inout] cursor Memory cursor + /// + virtual void operator>>(_Inout_ cursor_in &cursor); + + /// @} + /// \name Storage /// @{ @@ -164,12 +210,15 @@ namespace eap /// /// Returns credential identity. /// - virtual std::wstring get_identity() const = 0; + virtual std::wstring get_identity() const; /// /// Returns credential name (for GUI display). /// virtual winstd::tstring get_name() const; + + public: + std::wstring m_identity; ///< Identity (username\@domain, certificate name etc.) }; @@ -294,13 +343,7 @@ namespace eap /// @} - /// - /// Returns credential identity. - /// - virtual std::wstring get_identity() const; - public: - std::wstring m_identity; ///< Identity (username\@domain, certificate name etc.) winstd::sanitizing_wstring m_password; ///< Password private: diff --git a/lib/EAPBase/src/Credentials.cpp b/lib/EAPBase/src/Credentials.cpp index 16cc690..ed9cc9a 100644 --- a/lib/EAPBase/src/Credentials.cpp +++ b/lib/EAPBase/src/Credentials.cpp @@ -36,12 +36,14 @@ eap::credentials::credentials(_In_ module &mod) : config(mod) eap::credentials::credentials(_In_ const credentials &other) : + m_identity(other.m_identity), config(other) { } eap::credentials::credentials(_Inout_ credentials &&other) : + m_identity(std::move(other.m_identity)), config(std::move(other)) { } @@ -49,8 +51,10 @@ eap::credentials::credentials(_Inout_ credentials &&other) : eap::credentials& eap::credentials::operator=(_In_ const credentials &other) { - if (this != &other) + if (this != &other) { (config&)*this = other; + m_identity = other.m_identity; + } return *this; } @@ -58,8 +62,10 @@ eap::credentials& eap::credentials::operator=(_In_ const credentials &other) eap::credentials& eap::credentials::operator=(_Inout_ credentials &&other) { - if (this != &other) + if (this != &other) { (config&)*this = std::move(other); + m_identity = std::move(other.m_identity); + } return *this; } @@ -67,13 +73,73 @@ eap::credentials& eap::credentials::operator=(_Inout_ credentials &&other) void eap::credentials::clear() { + m_identity.clear(); } bool eap::credentials::empty() const { - // Base class always report empty credentials. - return true; + return m_identity.empty(); +} + + +void eap::credentials::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot) const +{ + assert(pDoc); + assert(pConfigRoot); + + config::save(pDoc, pConfigRoot); + + const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); + HRESULT hr; + + // + if (FAILED(hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"UserName"), bstrNamespace, bstr(m_identity)))) + throw com_runtime_error(hr, __FUNCTION__ " Error creating element."); +} + + +void eap::credentials::load(_In_ IXMLDOMNode *pConfigRoot) +{ + assert(pConfigRoot); + HRESULT hr; + + config::load(pConfigRoot); + + std::wstring xpath(eapxml::get_xpath(pConfigRoot)); + + if (FAILED(hr = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:UserName"), m_identity))) + throw com_runtime_error(hr, __FUNCTION__ " Error reading element."); + + m_module.log_config((xpath + L"/UserName").c_str(), m_identity.c_str()); +} + + +void eap::credentials::operator<<(_Inout_ cursor_out &cursor) const +{ + config::operator<<(cursor); + cursor << m_identity; +} + + +size_t eap::credentials::get_pk_size() const +{ + return + config::get_pk_size() + + pksizeof(m_identity); +} + + +void eap::credentials::operator>>(_Inout_ cursor_in &cursor) +{ + config::operator>>(cursor); + cursor >> m_identity; +} + + +wstring eap::credentials::get_identity() const +{ + return m_identity; } @@ -93,7 +159,6 @@ eap::credentials_pass::credentials_pass(_In_ module &mod) : credentials(mod) eap::credentials_pass::credentials_pass(_In_ const credentials_pass &other) : - m_identity(other.m_identity), m_password(other.m_password), credentials(other) { @@ -101,7 +166,6 @@ eap::credentials_pass::credentials_pass(_In_ const credentials_pass &other) : eap::credentials_pass::credentials_pass(_Inout_ credentials_pass &&other) : - m_identity(std::move(other.m_identity)), m_password(std::move(other.m_password)), credentials(std::move(other)) { @@ -112,7 +176,6 @@ eap::credentials_pass& eap::credentials_pass::operator=(_In_ const credentials_p { if (this != &other) { (credentials&)*this = other; - m_identity = other.m_identity; m_password = other.m_password; } @@ -124,7 +187,6 @@ eap::credentials_pass& eap::credentials_pass::operator=(_Inout_ credentials_pass { if (this != &other) { (credentials&)*this = std::move(other); - m_identity = std::move(other.m_identity); m_password = std::move(other.m_password); } @@ -135,14 +197,13 @@ eap::credentials_pass& eap::credentials_pass::operator=(_Inout_ credentials_pass void eap::credentials_pass::clear() { credentials::clear(); - m_identity.clear(); m_password.clear(); } bool eap::credentials_pass::empty() const { - return credentials::empty() && m_identity.empty() && m_password.empty(); + return credentials::empty() && m_password.empty(); } @@ -156,10 +217,6 @@ void eap::credentials_pass::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *p const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata"); HRESULT hr; - // - if (FAILED(hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"UserName"), bstrNamespace, bstr(m_identity)))) - throw com_runtime_error(hr, __FUNCTION__ " Error creating element."); - // bstr pass(m_password); hr = eapxml::put_element_value(pDoc, pConfigRoot, bstr(L"Password"), bstrNamespace, pass); @@ -178,11 +235,6 @@ void eap::credentials_pass::load(_In_ IXMLDOMNode *pConfigRoot) std::wstring xpath(eapxml::get_xpath(pConfigRoot)); - if (FAILED(hr = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:UserName"), m_identity))) - throw com_runtime_error(hr, __FUNCTION__ " Error reading element."); - - m_module.log_config((xpath + L"/UserName").c_str(), m_identity.c_str()); - bstr pass; if (FAILED(hr = eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:Password"), &pass))) throw com_runtime_error(hr, __FUNCTION__ " Error reading element."); @@ -202,7 +254,6 @@ void eap::credentials_pass::load(_In_ IXMLDOMNode *pConfigRoot) void eap::credentials_pass::operator<<(_Inout_ cursor_out &cursor) const { credentials::operator<<(cursor); - cursor << m_identity; cursor << m_password; } @@ -211,7 +262,6 @@ size_t eap::credentials_pass::get_pk_size() const { return credentials::get_pk_size() + - pksizeof(m_identity) + pksizeof(m_password); } @@ -219,7 +269,6 @@ size_t eap::credentials_pass::get_pk_size() const void eap::credentials_pass::operator>>(_Inout_ cursor_in &cursor) { credentials::operator>>(cursor); - cursor >> m_identity; cursor >> m_password; } @@ -289,7 +338,7 @@ void eap::credentials_pass::retrieve(_In_z_ LPCTSTR pszTargetName) m_identity.clear(); wstring xpath(pszTargetName); - m_module.log_config((xpath + L"/Username").c_str(), m_identity.c_str()); + m_module.log_config((xpath + L"/Identity").c_str(), m_identity.c_str()); m_module.log_config((xpath + L"/Password").c_str(), #ifdef _DEBUG m_password.c_str() @@ -300,12 +349,6 @@ void eap::credentials_pass::retrieve(_In_z_ LPCTSTR pszTargetName) } -std::wstring eap::credentials_pass::get_identity() const -{ - return m_identity; -} - - const unsigned char eap::credentials_pass::s_entropy[1024] = { 0x40, 0x88, 0xd3, 0x13, 0x81, 0x8a, 0xf6, 0x74, 0x55, 0x8e, 0xcc, 0x73, 0x2c, 0xf8, 0x93, 0x37, 0x4f, 0xeb, 0x1d, 0x66, 0xb7, 0xfb, 0x47, 0x75, 0xb4, 0xfd, 0x07, 0xbb, 0xf6, 0xb3, 0x05, 0x30, diff --git a/lib/TLS/include/Credentials.h b/lib/TLS/include/Credentials.h index 7a0a485..64e70a8 100644 --- a/lib/TLS/include/Credentials.h +++ b/lib/TLS/include/Credentials.h @@ -180,11 +180,6 @@ namespace eap /// virtual std::wstring get_identity() const; - /// - /// Returns credential name (for GUI display). - /// - virtual winstd::tstring get_name() const; - /// /// Combine credentials in the following order: /// diff --git a/lib/TLS/src/Credentials.cpp b/lib/TLS/src/Credentials.cpp index 691df9c..bdfeac2 100644 --- a/lib/TLS/src/Credentials.cpp +++ b/lib/TLS/src/Credentials.cpp @@ -182,11 +182,10 @@ void eap::credentials_tls::store(_In_z_ LPCTSTR pszTargetName) const throw win_runtime_error(__FUNCTION__ " CryptProtectData failed."); tstring target(target_name(pszTargetName)); - wstring name(std::move(get_name())); // Write credentials. - assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE); - assert(name.length() < CRED_MAX_USERNAME_LENGTH ); + assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE); + assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH ); CREDENTIAL cred = { 0, // Flags CRED_TYPE_GENERIC, // Type @@ -199,7 +198,7 @@ void eap::credentials_tls::store(_In_z_ LPCTSTR pszTargetName) const 0, // AttributeCount NULL, // Attributes NULL, // TargetAlias - (LPTSTR)name.c_str() // UserName + (LPTSTR)m_identity.c_str() // UserName }; if (!CredWrite(&cred, 0)) throw win_runtime_error(__FUNCTION__ " CredWrite failed."); @@ -227,7 +226,14 @@ void eap::credentials_tls::retrieve(_In_z_ LPCTSTR pszTargetName) if (!bResult) throw win_runtime_error(__FUNCTION__ " Error loading certificate."); - m_module.log_config((wstring(pszTargetName) + L"/Certificate").c_str(), get_name().c_str()); + if (cred->UserName) + m_identity = cred->UserName; + else + m_identity.clear(); + + wstring xpath(pszTargetName); + m_module.log_config((xpath + L"/Identity").c_str(), m_identity.c_str()); + m_module.log_config((xpath + L"/Certificate").c_str(), get_name().c_str()); } @@ -239,7 +245,9 @@ LPCTSTR eap::credentials_tls::target_suffix() const std::wstring eap::credentials_tls::get_identity() const { - if (m_cert) { + if (!m_identity.empty()) { + return m_identity; + } else if (m_cert) { wstring identity; CertGetNameString(m_cert, CERT_NAME_EMAIL_TYPE, 0, NULL, identity); return identity; @@ -248,12 +256,6 @@ std::wstring eap::credentials_tls::get_identity() const } -tstring eap::credentials_tls::get_name() const -{ - return m_cert ? std::move(get_cert_title(m_cert)) : _T(""); -} - - eap::credentials::source_t eap::credentials_tls::combine( _In_ const credentials_tls *cred_cached, _In_ const config_method_tls &cfg, diff --git a/lib/TLS_UI/res/wxTLS_UI.cpp b/lib/TLS_UI/res/wxTLS_UI.cpp index eac078c..614ab7e 100644 --- a/lib/TLS_UI/res/wxTLS_UI.cpp +++ b/lib/TLS_UI/res/wxTLS_UI.cpp @@ -161,6 +161,25 @@ wxTLSCredentialsPanelBase::wxTLSCredentialsPanelBase( wxWindow* parent, wxWindow sb_credentials_vert->Add( sb_cert_radio, 0, wxEXPAND|wxALL, 5 ); + wxBoxSizer* sb_identity; + sb_identity = new wxBoxSizer( wxVERTICAL ); + + m_identity_label = new wxStaticText( sb_credentials->GetStaticBox(), wxID_ANY, _("Custom &identity:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_identity_label->Wrap( -1 ); + sb_identity->Add( m_identity_label, 0, wxBOTTOM, 5 ); + + m_identity = new wxTextCtrl( sb_credentials->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_identity->SetToolTip( _("Your identity (username@domain) to override one from certificate; or blank to use one provided in certificate") ); + + sb_identity->Add( m_identity, 0, wxEXPAND|wxBOTTOM, 5 ); + + m_identity_note = new wxStaticText( sb_credentials->GetStaticBox(), wxID_ANY, _("(Example: user@contoso.com)"), wxDefaultPosition, wxDefaultSize, 0 ); + m_identity_note->Wrap( -1 ); + sb_identity->Add( m_identity_note, 0, wxALIGN_RIGHT, 5 ); + + + sb_credentials_vert->Add( sb_identity, 1, wxEXPAND|wxALL, 5 ); + m_remember = new wxCheckBox( sb_credentials->GetStaticBox(), wxID_ANY, _("&Remember"), wxDefaultPosition, wxDefaultSize, 0 ); m_remember->SetHelpText( _("Check if you would like to save certificate selection") ); diff --git a/lib/TLS_UI/res/wxTLS_UI.fbp b/lib/TLS_UI/res/wxTLS_UI.fbp index 5435dc8..5135458 100644 --- a/lib/TLS_UI/res/wxTLS_UI.fbp +++ b/lib/TLS_UI/res/wxTLS_UI.fbp @@ -1527,6 +1527,274 @@ + + 5 + wxEXPAND|wxALL + 1 + + + sb_identity + wxVERTICAL + none + + 5 + wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Custom &identity: + + 0 + + + 0 + + 1 + m_identity_label + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + + 0 + + 1 + m_identity + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Your identity (username@domain) to override one from certificate; or blank to use one provided in certificate + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_RIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + (Example: user@contoso.com) + + 0 + + + 0 + + 1 + m_identity_note + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxALL|wxEXPAND diff --git a/lib/TLS_UI/res/wxTLS_UI.h b/lib/TLS_UI/res/wxTLS_UI.h index c991754..df69220 100644 --- a/lib/TLS_UI/res/wxTLS_UI.h +++ b/lib/TLS_UI/res/wxTLS_UI.h @@ -80,6 +80,9 @@ class wxTLSCredentialsPanelBase : public wxPanel wxRadioButton* m_cert_none; wxRadioButton* m_cert_select; wxChoice* m_cert_select_val; + wxStaticText* m_identity_label; + wxTextCtrl* m_identity; + wxStaticText* m_identity_note; wxCheckBox* m_remember; public: diff --git a/lib/TLS_UI/src/TLS_UI.cpp b/lib/TLS_UI/src/TLS_UI.cpp index d3f741e..5aea833 100644 --- a/lib/TLS_UI/src/TLS_UI.cpp +++ b/lib/TLS_UI/src/TLS_UI.cpp @@ -358,6 +358,8 @@ bool wxTLSCredentialsPanel::TransferDataToWindow() m_cert_select_val->SetSelection(0); } + m_identity->SetValue(m_cred.m_identity); + return wxEAPCredentialsPanelBase::TransferDataToWindow(); } @@ -374,6 +376,8 @@ bool wxTLSCredentialsPanel::TransferDataFromWindow() m_cred.m_cert.free(); } + m_cred.m_identity = m_identity->GetValue(); + // Inherited TransferDataFromWindow() calls m_cred.store(). // Therefore, call it only now, that m_cred is set. return wxEAPCredentialsPanelBase::TransferDataFromWindow(); diff --git a/lib/TTLS/src/Credentials.cpp b/lib/TTLS/src/Credentials.cpp index d626f62..400e07d 100644 --- a/lib/TTLS/src/Credentials.cpp +++ b/lib/TTLS/src/Credentials.cpp @@ -189,6 +189,8 @@ void eap::credentials_ttls::operator>>(_Inout_ cursor_in &cursor) void eap::credentials_ttls::store(_In_z_ LPCTSTR pszTargetName) const { + assert(0); // Not that we would ever store inner&outer credentials to Windows Credential Manager joined, but for completness sake... Here we go: + credentials_tls::store(pszTargetName); if (m_inner) @@ -198,6 +200,8 @@ void eap::credentials_ttls::store(_In_z_ LPCTSTR pszTargetName) const void eap::credentials_ttls::retrieve(_In_z_ LPCTSTR pszTargetName) { + assert(0); // Not that we would ever retrieve inner&outer credentials to Windows Credential Manager joined, but for completness sake... Here we go: + credentials_tls::retrieve(pszTargetName); if (m_inner) diff --git a/lib/TTLS_UI/res/wxTTLS_UI.cpp b/lib/TTLS_UI/res/wxTTLS_UI.cpp index ae31087..236b3f3 100644 --- a/lib/TTLS_UI/res/wxTTLS_UI.cpp +++ b/lib/TTLS_UI/res/wxTTLS_UI.cpp @@ -32,7 +32,7 @@ wxTTLSConfigPanelBase::wxTTLSConfigPanelBase( wxWindow* parent, wxWindowID id, c wxBoxSizer* sb_outer_identity_radio; sb_outer_identity_radio = new wxBoxSizer( wxVERTICAL ); - m_outer_identity_same = new wxRadioButton( sb_outer_identity->GetStaticBox(), wxID_ANY, _("&Same as inner identity"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); + m_outer_identity_same = new wxRadioButton( sb_outer_identity->GetStaticBox(), wxID_ANY, _("&True identity"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); m_outer_identity_same->SetToolTip( _("Use my true user name") ); sb_outer_identity_radio->Add( m_outer_identity_same, 1, wxEXPAND, 5 ); diff --git a/lib/TTLS_UI/res/wxTTLS_UI.fbp b/lib/TTLS_UI/res/wxTTLS_UI.fbp index dc480e7..47b1e0f 100644 --- a/lib/TTLS_UI/res/wxTTLS_UI.fbp +++ b/lib/TTLS_UI/res/wxTTLS_UI.fbp @@ -309,7 +309,7 @@ 0 0 wxID_ANY - &Same as inner identity + &True identity 0