Support for read-only configurations added

This commit is contained in:
2016-06-20 14:51:21 +02:00
parent 2f0948b4fd
commit e52b9a636f
28 changed files with 998 additions and 615 deletions

View File

@@ -24,9 +24,16 @@
#include <WinStd/Common.h>
#include <wx/filedlg.h>
#include <wx/msgdlg.h>
#include <cryptuiapi.h>
#include <Windows.h>
#include <WinCrypt.h> // Must include after <Windows.h>
#include <list>
#include <string>
///
/// Helper class for auto-destroyable certificates used in wxWidget's item containers
@@ -56,17 +63,17 @@ class wxEAPTLSCredentialsPanel;
///
/// EAPTLS server trust configuration panel
///
class wxEAPTLSServerTrustPanel;
template <class _Tprov> class wxEAPTLSServerTrustPanel;
///
/// TLS credentials configuration panel
///
typedef wxEAPCredentialsConfigPanel<eap::config_tls, eap::credentials_tls, wxEAPTLSCredentialsPanel> wxEAPTLSCredentialsConfigPanel;
template <class _Tprov> class wxEAPTLSCredentialsConfigPanel;
///
/// EAPTLS configuration panel
///
class wxEAPTLSConfigPanel;
template <class _Tprov> class wxEAPTLSConfigPanel;
namespace eap
{
@@ -249,7 +256,7 @@ protected:
};
class wxEAPTLSCredentialsPanel : public wxCredentialsPanel<wxEAPTLSCredentialsPanelBase, eap::credentials_tls>
class wxEAPTLSCredentialsPanel : public wxCredentialsPanel<eap::credentials_tls, wxEAPTLSCredentialsPanelBase>
{
public:
///
@@ -270,23 +277,150 @@ protected:
};
template <class _Tprov>
class wxEAPTLSServerTrustPanel : public wxEAPTLSServerTrustConfigPanelBase
{
public:
///
/// Constructs a configuration panel
///
wxEAPTLSServerTrustPanel(eap::config_tls &cfg, wxWindow* parent);
wxEAPTLSServerTrustPanel(_Tprov &prov, eap::config_tls &cfg, wxWindow* parent) :
m_prov(prov),
m_cfg(cfg),
wxEAPTLSServerTrustConfigPanelBase(parent)
{
// Load and set icon.
if (m_certmgr.load(_T("certmgr.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
wxSetIconFromResource(m_server_trust_icon, m_icon, m_certmgr, MAKEINTRESOURCE(218));
// Do not use cfg.m_server_names directly, so we can decide not to store the value in case of provider-locked configuration.
// Never rely on control disabled state alone, as they can be enabled using external tool like Spy++.
m_server_names->SetValidator(wxFQDNListValidator(&m_server_names_val));
}
protected:
/// \cond internal
virtual bool TransferDataToWindow();
virtual bool TransferDataFromWindow();
virtual void OnRootCA(wxCommandEvent& event);
virtual void OnRootCADClick(wxCommandEvent& event);
virtual void OnRootCAAddStore(wxCommandEvent& event);
virtual void OnRootCAAddFile(wxCommandEvent& event);
virtual void OnRootCARemove(wxCommandEvent& event);
virtual bool TransferDataToWindow()
{
if (m_prov.m_read_only) {
// This is provider-locked configuration. Disable controls.
m_root_ca_add_store->Enable(false);
m_root_ca_add_file ->Enable(false);
m_root_ca_remove ->Enable(false);
m_server_names ->Enable(false);
}
// Populate trusted CA list.
for (std::list<winstd::cert_context>::const_iterator cert = m_cfg.m_trusted_root_ca.cbegin(), cert_end = m_cfg.m_trusted_root_ca.cend(); cert != cert_end; ++cert) {
winstd::tstring name;
if (CertGetNameString(*cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name) > 0)
m_root_ca->Append(wxString(name), new wxCertificateClientData(cert->duplicate()));
}
// Set server acceptable names. The edit control will get populated by validator.
m_server_names_val = m_cfg.m_server_names;
return wxEAPTLSServerTrustConfigPanelBase::TransferDataToWindow();
}
virtual bool TransferDataFromWindow()
{
wxCHECK(wxEAPTLSServerTrustConfigPanelBase::TransferDataFromWindow(), false);
if (!m_prov.m_read_only) {
// This is not a provider-locked configuration. Save the data.
// Parse trusted CA list.
m_cfg.m_trusted_root_ca.clear();
for (unsigned int i = 0, i_end = m_root_ca->GetCount(); i < i_end; i++) {
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(m_root_ca->GetClientObject(i));
if (cert)
m_cfg.add_trusted_ca(cert->m_cert->dwCertEncodingType, cert->m_cert->pbCertEncoded, cert->m_cert->cbCertEncoded);
}
// Save acceptable server names.
m_cfg.m_server_names = m_server_names_val;
}
return true;
}
virtual void OnUpdateUI(wxUpdateUIEvent& event)
{
UNREFERENCED_PARAMETER(event);
if (!m_prov.m_read_only) {
// This is not a provider-locked configuration. Selectively enable/disable controls.
wxArrayInt selections;
m_root_ca_remove->Enable(m_root_ca->GetSelections(selections) ? true : false);
}
}
virtual void OnRootCADClick(wxCommandEvent& event)
{
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(event.GetClientObject());
if (cert)
CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, cert->m_cert, this->GetHWND(), NULL, 0, NULL);
}
virtual void OnRootCAAddStore(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
winstd::cert_store store;
if (store.create(NULL, _T("ROOT"))) {
winstd::cert_context cert;
cert.attach(CryptUIDlgSelectCertificateFromStore(store, this->GetHWND(), NULL, NULL, 0, 0, NULL));
if (cert)
AddRootCA(cert);
}
}
virtual void OnRootCAAddFile(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
const wxString separator(wxT("|"));
wxFileDialog open_dialog(this, _("Add Certificate"), wxEmptyString, wxEmptyString,
_("Certificate Files (*.cer;*.crt;*.der;*.p7b;*.pem)") + separator + wxT("*.cer;*.crt;*.der;*.p7b;*.pem") + separator +
_("X.509 Certificate Files (*.cer;*.crt;*.der;*.pem)") + separator + wxT("*.cer;*.crt;*.der;*.pem") + separator +
_("PKCS #7 Certificate Files (*.p7b)") + separator + wxT("*.p7b") + separator +
_("All Files (*.*)") + separator + wxT("*.*"),
wxFD_OPEN|wxFD_FILE_MUST_EXIST|wxFD_MULTIPLE);
if (open_dialog.ShowModal() == wxID_CANCEL) {
event.Skip();
return;
}
wxArrayString paths;
open_dialog.GetPaths(paths);
for (size_t i = 0, i_end = paths.GetCount(); i < i_end; i++) {
// Load certificate(s) from file.
winstd::cert_store cs;
if (cs.create(CERT_STORE_PROV_FILENAME, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, (LPCTSTR)(paths[i]))) {
for (PCCERT_CONTEXT cert = NULL; (cert = CertEnumCertificatesInStore(cs, cert)) != NULL;)
AddRootCA(cert);
} else
wxMessageBox(wxString::Format(_("Invalid or unsupported certificate file %s"), paths[i]), _("Error"), wxOK | wxICON_EXCLAMATION, this);
}
}
virtual void OnRootCARemove(wxCommandEvent& event)
{
UNREFERENCED_PARAMETER(event);
wxArrayInt selections;
for (int i = m_root_ca->GetSelections(selections); i--; )
m_root_ca->Delete(selections[i]);
}
/// \endcond
///
@@ -298,34 +432,110 @@ protected:
/// - \c true if certificate was added;
/// - \c false if duplicate found or an error occured.
///
bool AddRootCA(PCCERT_CONTEXT cert);
bool AddRootCA(PCCERT_CONTEXT cert)
{
for (unsigned int i = 0, i_end = m_root_ca->GetCount(); i < i_end; i++) {
wxCertificateClientData *c = dynamic_cast<wxCertificateClientData*>(m_root_ca->GetClientObject(i));
if (c && c->m_cert &&
c->m_cert->cbCertEncoded == cert->cbCertEncoded &&
memcmp(c->m_cert->pbCertEncoded, cert->pbCertEncoded, cert->cbCertEncoded) == 0)
{
// This certificate is already on the list.
m_root_ca->SetSelection(i);
return false;
}
}
// Add certificate to the list.
winstd::tstring name;
if (CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name) > 0) {
int i = m_root_ca->Append(wxString(name), new wxCertificateClientData(CertDuplicateCertificateContext(cert)));
if (0 <= i) {
m_root_ca->SetSelection(i);
}
return true;
}
return false;
}
protected:
eap::config_tls &m_cfg; ///< TLS configuration
winstd::library m_certmgr; ///< certmgr.dll resource library reference
wxIcon m_icon; ///< Panel icon
_Tprov &m_prov; ///< EAP provider
eap::config_tls &m_cfg; ///< TLS configuration
winstd::library m_certmgr; ///< certmgr.dll resource library reference
wxIcon m_icon; ///< Panel icon
std::list<std::string> m_server_names_val; ///< Acceptable authenticating server names
};
template <class _Tprov>
class wxEAPTLSCredentialsConfigPanel : public wxEAPCredentialsConfigPanel<_Tprov, eap::config_tls, wxEAPTLSCredentialsPanel>
{
public:
///
/// Constructs a credential configuration panel
///
/// \param[inout] 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
///
wxEAPTLSCredentialsConfigPanel(_Tprov &prov, eap::config_tls &cfg, LPCTSTR pszCredTarget, wxWindow *parent) :
wxEAPCredentialsConfigPanel<_Tprov, eap::config_tls, wxEAPTLSCredentialsPanel>(prov, cfg, pszCredTarget, parent)
{
}
};
template <class _Tprov>
class wxEAPTLSConfigPanel : public wxPanel
{
public:
///
/// Constructs a configuration panel
///
wxEAPTLSConfigPanel(eap::config_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent);
wxEAPTLSConfigPanel(_Tprov &prov, eap::config_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent) : wxPanel(parent)
{
wxBoxSizer* sb_content;
sb_content = new wxBoxSizer( wxVERTICAL );
m_server_trust = new wxEAPTLSServerTrustPanel<_Tprov>(prov, cfg, this);
sb_content->Add(m_server_trust, 0, wxDOWN|wxEXPAND, 5);
m_credentials = new wxEAPTLSCredentialsConfigPanel<_Tprov>(prov, cfg, pszCredTarget, this);
sb_content->Add(m_credentials, 0, wxUP|wxEXPAND, 5);
this->SetSizer(sb_content);
this->Layout();
// Connect Events
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTLSConfigPanel::OnInitDialog));
}
///
/// Destructs the configuration panel
///
virtual ~wxEAPTLSConfigPanel();
virtual ~wxEAPTLSConfigPanel()
{
// Disconnect Events
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTLSConfigPanel::OnInitDialog));
}
protected:
/// \cond internal
virtual void OnInitDialog(wxInitDialogEvent& event);
virtual void OnInitDialog(wxInitDialogEvent& event)
{
// Forward the event to child panels.
m_server_trust->GetEventHandler()->ProcessEvent(event);
if (m_credentials)
m_credentials->GetEventHandler()->ProcessEvent(event);
}
/// \endcond
protected:
wxEAPTLSServerTrustPanel *m_server_trust; ///< Server trust configuration panel
wxEAPTLSCredentialsConfigPanel *m_credentials; ///< Credentials configuration panel
wxEAPTLSServerTrustPanel<_Tprov> *m_server_trust; ///< Server trust configuration panel
wxEAPTLSCredentialsConfigPanel<_Tprov> *m_credentials; ///< Credentials configuration panel
};