EAP modules divided to libraries
This commit is contained in:
@@ -1,727 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace winstd;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::session
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::session::session()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::session::~session()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::begin(
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ const EapAttributes *pAttributeArray,
|
||||
_In_ HANDLE hTokenImpersonateUser,
|
||||
_In_ DWORD dwConnectionDataSize,
|
||||
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
|
||||
_In_ DWORD dwUserDataSize,
|
||||
_In_count_(dwUserDataSize) const BYTE *pUserData,
|
||||
_In_ DWORD dwMaxSendPacketSize,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dwFlags);
|
||||
UNREFERENCED_PARAMETER(pAttributeArray);
|
||||
UNREFERENCED_PARAMETER(hTokenImpersonateUser);
|
||||
UNREFERENCED_PARAMETER(dwConnectionDataSize);
|
||||
UNREFERENCED_PARAMETER(pConnectionData);
|
||||
UNREFERENCED_PARAMETER(dwUserDataSize);
|
||||
UNREFERENCED_PARAMETER(pUserData);
|
||||
UNREFERENCED_PARAMETER(dwMaxSendPacketSize);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::end(_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::process_request_packet(
|
||||
_In_ DWORD dwReceivedPacketSize,
|
||||
_In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket,
|
||||
_Out_ EapPeerMethodOutput *pEapOutput,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dwReceivedPacketSize);
|
||||
UNREFERENCED_PARAMETER(pReceivedPacket);
|
||||
UNREFERENCED_PARAMETER(pEapOutput);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::get_response_packet(
|
||||
_Inout_ DWORD *pdwSendPacketSize,
|
||||
_Inout_bytecap_(*dwSendPacketSize) EapPacket *pSendPacket,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pdwSendPacketSize);
|
||||
UNREFERENCED_PARAMETER(pSendPacket);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::get_result(_In_ EapPeerMethodResultReason reason, _Out_ EapPeerMethodResult *ppResult, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(reason);
|
||||
UNREFERENCED_PARAMETER(ppResult);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::get_ui_context(
|
||||
_Out_ DWORD *pdwUIContextDataSize,
|
||||
_Out_ BYTE **ppUIContextData,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pdwUIContextDataSize);
|
||||
UNREFERENCED_PARAMETER(ppUIContextData);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::set_ui_context(
|
||||
_In_ DWORD dwUIContextDataSize,
|
||||
_In_count_(dwUIContextDataSize) const BYTE *pUIContextData,
|
||||
_In_ const EapPeerMethodOutput *pEapOutput,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dwUIContextDataSize);
|
||||
UNREFERENCED_PARAMETER(pUIContextData);
|
||||
UNREFERENCED_PARAMETER(pEapOutput);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::get_response_attributes(_Out_ EapAttributes *pAttribs, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pAttribs);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::session::set_response_attributes(const _In_ EapAttributes *pAttribs, _Out_ EapPeerMethodOutput *pEapOutput, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pAttribs);
|
||||
UNREFERENCED_PARAMETER(pEapOutput);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::config
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config::config(_In_ module &mod) :
|
||||
m_module(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config::config(_In_ const config &other) :
|
||||
m_module(other.m_module)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config::config(_Inout_ config &&other) :
|
||||
m_module(other.m_module)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config::~config()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config& eap::config::operator=(_In_ const config &other)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(other);
|
||||
assert(&m_module == &other.m_module); // Copy configuration within same module only!
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::config& eap::config::operator=(_Inout_ config &&other)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(other);
|
||||
assert(&m_module == &other.m_module); // Copy configuration within same module only!
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::config_method
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config_method::config_method(_In_ module &mod) :
|
||||
m_allow_save(true),
|
||||
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),
|
||||
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)),
|
||||
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;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::config_method::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
|
||||
DWORD dwResult;
|
||||
|
||||
// <ClientSideCredential>
|
||||
com_obj<IXMLDOMElement> 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, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ClientSideCredential> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// <ClientSideCredential>/<allow-save>
|
||||
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientSideCredential, bstr(L"allow-save"), bstrNamespace, m_allow_save)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <allow-save> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// <ClientSideCredential>/<AnonymousIdentity>
|
||||
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, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <AnonymousIdentity> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::config_method::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
m_allow_save = true;
|
||||
m_anonymous_identity.clear();
|
||||
|
||||
// <ClientSideCredential>
|
||||
com_obj<IXMLDOMElement> pXmlElClientSideCredential;
|
||||
if (eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ClientSideCredential"), &pXmlElClientSideCredential) == ERROR_SUCCESS) {
|
||||
// <allow-save>
|
||||
eapxml::get_element_value(pXmlElClientSideCredential, bstr(L"eap-metadata:allow-save"), &m_allow_save);
|
||||
|
||||
// <AnonymousIdentity>
|
||||
eapxml::get_element_value(pXmlElClientSideCredential, bstr(L"eap-metadata:AnonymousIdentity"), m_anonymous_identity);
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::credentials
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials& eap::credentials::operator=(_In_ const credentials &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(config&)*this = other;
|
||||
m_identity = other.m_identity;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::credentials& eap::credentials::operator=(_Inout_ credentials &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(config&)*this = std::move(other);
|
||||
m_identity = std::move(other.m_identity);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void eap::credentials::clear()
|
||||
{
|
||||
m_identity.clear();
|
||||
}
|
||||
|
||||
|
||||
bool eap::credentials::empty() const
|
||||
{
|
||||
return m_identity.empty();
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pDoc);
|
||||
UNREFERENCED_PARAMETER(pConfigRoot);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
// Yeah, right!? Credentials are non-exportable!
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::credentials_pass
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::credentials_pass::credentials_pass(_In_ module &mod) : credentials(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pass::credentials_pass(_In_ const credentials_pass &other) :
|
||||
m_password(other.m_password),
|
||||
credentials(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pass::credentials_pass(_Inout_ credentials_pass &&other) :
|
||||
m_password(std::move(other.m_password)),
|
||||
credentials(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pass& eap::credentials_pass::operator=(_In_ const credentials_pass &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials&)*this = other;
|
||||
m_password = other.m_password;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pass& eap::credentials_pass::operator=(_Inout_ credentials_pass &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials&)*this = std::move(other);
|
||||
m_password = std::move(other.m_password);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void eap::credentials_pass::clear()
|
||||
{
|
||||
credentials::clear();
|
||||
m_password.clear();
|
||||
}
|
||||
|
||||
|
||||
bool eap::credentials_pass::empty() const
|
||||
{
|
||||
return credentials::empty() && m_password.empty();
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_pass::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
assert(pConfigRoot);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:UserName"), m_identity);
|
||||
|
||||
bstr pass;
|
||||
if ((eapxml::get_element_value(pConfigRoot, bstr(L"eap-metadata:Password"), &pass)) == ERROR_SUCCESS)
|
||||
m_password = pass;
|
||||
SecureZeroMemory((BSTR)pass, sizeof(OLECHAR)*pass.length());
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_pass::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
assert(pszTargetName);
|
||||
assert(ppEapError);
|
||||
DWORD dwResult;
|
||||
string password_enc;
|
||||
|
||||
// Prepare cryptographics provider.
|
||||
crypt_prov cp;
|
||||
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Import the public key.
|
||||
HRSRC res = FindResource(m_module.m_instance, MAKEINTRESOURCE(IDR_EAP_KEY_PUBLIC), RT_RCDATA);
|
||||
assert(res);
|
||||
HGLOBAL res_handle = LoadResource(m_module.m_instance, res);
|
||||
assert(res_handle);
|
||||
crypt_key key;
|
||||
unique_ptr<CERT_PUBLIC_KEY_INFO, LocalFree_delete<CERT_PUBLIC_KEY_INFO> > keyinfo_data;
|
||||
DWORD keyinfo_size = 0;
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, (const BYTE*)::LockResource(res_handle), ::SizeofResource(m_module.m_instance, res), CRYPT_DECODE_ALLOC_FLAG, NULL, &keyinfo_data, &keyinfo_size)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptDecodeObjectEx failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
if (!key.import_public(cp, X509_ASN_ENCODING, keyinfo_data.get())) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Public key import failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Convert password to UTF-8.
|
||||
sanitizing_string password_utf8;
|
||||
WideCharToMultiByte(CP_UTF8, 0, m_password.c_str(), (int)m_password.length(), password_utf8, NULL, NULL);
|
||||
|
||||
// Pre-allocate memory to allow space, as encryption will grow the data, and we need additional 16B at the end for MD5 hash.
|
||||
DWORD dwBlockLen;
|
||||
vector<char, sanitizing_allocator<char> > password(password_utf8.length());
|
||||
memcpy(password.data(), password_utf8.c_str(), sizeof(char)*password_utf8.length());
|
||||
if (!CryptGetKeyParam(key, KP_BLOCKLEN, dwBlockLen, 0)) dwBlockLen = 0;
|
||||
password.reserve((password.size() + dwBlockLen - 1) / dwBlockLen * dwBlockLen + 16);
|
||||
|
||||
// Encrypt the password using our public key. Calculate MD5 hash and append it.
|
||||
crypt_hash hash;
|
||||
if (!hash.create(cp, CALG_MD5)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Creating MD5 hash failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
if (!CryptEncrypt(key, hash, TRUE, 0, password)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Encrypting password failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
vector<char> hash_bin;
|
||||
CryptGetHashParam(hash, HP_HASHVAL, hash_bin, 0);
|
||||
password.insert(password.end(), hash_bin.begin(), hash_bin.end());
|
||||
|
||||
// Convert encrypted password to Base64, since CredProtectA() fail for binary strings.
|
||||
string password_base64;
|
||||
base64_enc enc;
|
||||
enc.encode(password_base64, password.data(), password.size());
|
||||
|
||||
// Encrypt the password using user's key.
|
||||
CRED_PROTECTION_TYPE cpt;
|
||||
if (!CredProtectA(TRUE, password_base64.c_str(), (DWORD)password_base64.length(), password_enc, &cpt)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredProtect failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
tstring target(target_name(pszTargetName));
|
||||
|
||||
// Write credentials.
|
||||
assert(password_enc.size()*sizeof(char) < CRED_MAX_CREDENTIAL_BLOB_SIZE);
|
||||
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
|
||||
CREDENTIAL cred = {
|
||||
0, // Flags
|
||||
CRED_TYPE_GENERIC, // Type
|
||||
(LPTSTR)target.c_str(), // TargetName
|
||||
_T(""), // Comment
|
||||
{ 0, 0 }, // LastWritten
|
||||
(DWORD)password_enc.size()*sizeof(char), // CredentialBlobSize
|
||||
(LPBYTE)password_enc.data(), // CredentialBlob
|
||||
CRED_PERSIST_ENTERPRISE, // Persist
|
||||
0, // AttributeCount
|
||||
NULL, // Attributes
|
||||
NULL, // TargetAlias
|
||||
(LPTSTR)m_identity.c_str() // UserName
|
||||
};
|
||||
if (!CredWrite(&cred, 0)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredWrite failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_pass::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
assert(pszTargetName);
|
||||
DWORD dwResult;
|
||||
|
||||
// Read credentials.
|
||||
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
|
||||
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredRead failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
m_identity = cred->UserName;
|
||||
|
||||
// Decrypt the password using user's key.
|
||||
string password_base64;
|
||||
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize/sizeof(char), password_base64)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredUnprotect failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Convert Base64 to binary encrypted password, since CredProtectA() fail for binary strings.
|
||||
vector<char, sanitizing_allocator<char> > password;
|
||||
base64_dec dec;
|
||||
bool is_last;
|
||||
dec.decode(password, is_last, password_base64.c_str(), password_base64.length());
|
||||
|
||||
// Prepare cryptographics provider.
|
||||
crypt_prov cp;
|
||||
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Create hash.
|
||||
crypt_hash hash;
|
||||
if (!hash.create(cp, CALG_MD5)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Creating MD5 hash failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
DWORD dwHashSize, dwHashSizeSize = sizeof(dwHashSize);
|
||||
CryptGetHashParam(hash, HP_HASHSIZE, (LPBYTE)&dwHashSize, &dwHashSizeSize, 0);
|
||||
if (password.size() < dwHashSize) {
|
||||
*ppEapError = m_module.make_error(dwResult = ERROR_INVALID_DATA, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Encrypted password too short."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Truncate hash from encrypted password.
|
||||
vector<char> hash_bin;
|
||||
size_t enc_size = password.size() - dwHashSize;
|
||||
hash_bin.assign(password.begin() + enc_size, password.end());
|
||||
password.resize(enc_size);
|
||||
|
||||
// Import the private key.
|
||||
HRSRC res = FindResource(m_module.m_instance, MAKEINTRESOURCE(IDR_EAP_KEY_PRIVATE), RT_RCDATA);
|
||||
assert(res);
|
||||
HGLOBAL res_handle = LoadResource(m_module.m_instance, res);
|
||||
assert(res_handle);
|
||||
crypt_key key;
|
||||
unique_ptr<unsigned char[], LocalFree_delete<unsigned char[]> > keyinfo_data;
|
||||
DWORD keyinfo_size = 0;
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, (const BYTE*)::LockResource(res_handle), ::SizeofResource(m_module.m_instance, res), CRYPT_DECODE_ALLOC_FLAG, NULL, &keyinfo_data, &keyinfo_size)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptDecodeObjectEx failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
if (!key.import(cp, keyinfo_data.get(), keyinfo_size, NULL, 0)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Private key import failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Decrypt the password using our private key. Calculate MD5 hash and verify it.
|
||||
if (!CryptDecrypt(key, hash, TRUE, 0, password)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Decrypting password failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
vector<char> hash2_bin;
|
||||
CryptGetHashParam(hash, HP_HASHVAL, hash2_bin, 0);
|
||||
if (hash_bin != hash2_bin) {
|
||||
*ppEapError = m_module.make_error(dwResult = ERROR_INVALID_DATA, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Invalid password data."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Convert password from UTF-8.
|
||||
MultiByteToWideChar(CP_UTF8, 0, password.data(), (int)password.size(), m_password);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::module
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::module::module() :
|
||||
m_instance(NULL)
|
||||
{
|
||||
m_ep.create(&EAPMETHOD_TRACE_EVENT_PROVIDER);
|
||||
m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_LOAD, event_data((BYTE)EAPMETHOD_TYPE), event_data::blank);
|
||||
|
||||
m_heap.create(0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
eap::module::~module()
|
||||
{
|
||||
m_ep.write(&EAPMETHOD_TRACE_EVT_MODULE_UNLOAD, event_data((BYTE)EAPMETHOD_TYPE), event_data::blank);
|
||||
}
|
||||
|
||||
|
||||
EAP_ERROR* eap::module::make_error(_In_ DWORD dwErrorCode, _In_ DWORD dwReasonCode, _In_ LPCGUID pRootCauseGuid, _In_ LPCGUID pRepairGuid, _In_ LPCGUID pHelpLinkGuid, _In_z_ LPCWSTR pszRootCauseString, _In_z_ LPCWSTR pszRepairString) const
|
||||
{
|
||||
// Calculate memory size requirement.
|
||||
SIZE_T
|
||||
nRootCauseSize = pszRootCauseString != NULL && pszRootCauseString[0] ? (wcslen(pszRootCauseString) + 1)*sizeof(WCHAR) : 0,
|
||||
nRepairStringSize = pszRepairString != NULL && pszRepairString [0] ? (wcslen(pszRepairString ) + 1)*sizeof(WCHAR) : 0,
|
||||
nEapErrorSize = sizeof(EAP_ERROR) + nRootCauseSize + nRepairStringSize;
|
||||
|
||||
EAP_ERROR *pError = (EAP_ERROR*)HeapAlloc(m_heap, 0, nEapErrorSize);
|
||||
if (!pError)
|
||||
return NULL;
|
||||
BYTE *p = (BYTE*)(pError + 1);
|
||||
|
||||
// Fill the error descriptor.
|
||||
pError->dwWinError = dwErrorCode;
|
||||
pError->type.eapType.type = EAPMETHOD_TYPE;
|
||||
pError->type.eapType.dwVendorId = 0;
|
||||
pError->type.eapType.dwVendorType = 0;
|
||||
pError->type.dwAuthorId = 67532;
|
||||
pError->dwReasonCode = dwReasonCode;
|
||||
pError->rootCauseGuid = pRootCauseGuid != NULL ? *pRootCauseGuid : GUID_NULL;
|
||||
pError->repairGuid = pRepairGuid != NULL ? *pRepairGuid : GUID_NULL;
|
||||
pError->helpLinkGuid = pHelpLinkGuid != NULL ? *pHelpLinkGuid : GUID_NULL;
|
||||
if (nRootCauseSize) {
|
||||
pError->pRootCauseString = (LPWSTR)p;
|
||||
memcpy(pError->pRootCauseString, pszRootCauseString, nRootCauseSize);
|
||||
p += nRootCauseSize;
|
||||
} else
|
||||
pError->pRootCauseString = NULL;
|
||||
if (nRepairStringSize) {
|
||||
pError->pRepairString = (LPWSTR)p;
|
||||
memcpy(pError->pRepairString, pszRepairString, nRepairStringSize);
|
||||
p += nRepairStringSize;
|
||||
} else
|
||||
pError->pRepairString = NULL;
|
||||
|
||||
// Write trace event.
|
||||
vector<EVENT_DATA_DESCRIPTOR> evt_desc;
|
||||
evt_desc.reserve(8);
|
||||
evt_desc.push_back(event_data(pError->dwWinError));
|
||||
evt_desc.push_back(event_data(pError->type.eapType.type));
|
||||
evt_desc.push_back(event_data(pError->dwReasonCode));
|
||||
evt_desc.push_back(event_data(&(pError->rootCauseGuid), sizeof(GUID)));
|
||||
evt_desc.push_back(event_data(&(pError->repairGuid), sizeof(GUID)));
|
||||
evt_desc.push_back(event_data(&(pError->helpLinkGuid), sizeof(GUID)));
|
||||
evt_desc.push_back(event_data(pError->pRootCauseString));
|
||||
evt_desc.push_back(event_data(pError->pRepairString));
|
||||
m_ep.write(&EAPMETHOD_TRACE_EAP_ERROR, (ULONG)evt_desc.size(), evt_desc.data());
|
||||
|
||||
return pError;
|
||||
}
|
||||
|
||||
|
||||
BYTE* eap::module::alloc_memory(_In_ size_t size)
|
||||
{
|
||||
return (BYTE*)HeapAlloc(m_heap, 0, size);
|
||||
}
|
||||
|
||||
|
||||
void eap::module::free_memory(_In_ BYTE *ptr)
|
||||
{
|
||||
ETW_FN_VOID;
|
||||
|
||||
// Since we do security here and some of the BLOBs contain credentials, sanitize every memory block before freeing.
|
||||
SecureZeroMemory(ptr, HeapSize(m_heap, 0, ptr));
|
||||
HeapFree(m_heap, 0, ptr);
|
||||
}
|
||||
|
||||
|
||||
void eap::module::free_error_memory(_In_ EAP_ERROR *err)
|
||||
{
|
||||
ETW_FN_VOID;
|
||||
|
||||
// pRootCauseString and pRepairString always trail the ppEapError to reduce number of (de)allocations.
|
||||
HeapFree(m_heap, 0, err);
|
||||
}
|
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPCredentialsDialog
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPCredentialsDialog::wxEAPCredentialsDialog(wxWindow* parent) : wxEAPCredentialsDialogBase(parent)
|
||||
{
|
||||
// Set extra style here, as wxFormBuilder overrides all default flags.
|
||||
this->SetExtraStyle(this->GetExtraStyle() | wxWS_EX_VALIDATE_RECURSIVELY);
|
||||
|
||||
m_buttonsOK->SetDefault();
|
||||
}
|
||||
|
||||
|
||||
void wxEAPCredentialsDialog::AddContents(wxPanel **contents, size_t content_count)
|
||||
{
|
||||
if (content_count) {
|
||||
for (size_t i = 0; i < content_count; i++)
|
||||
m_panels->Add(contents[i], 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
this->Layout();
|
||||
this->GetSizer()->Fit(this);
|
||||
contents[0]->SetFocusFromKbd();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxEAPCredentialsDialog::OnInitDialog(wxInitDialogEvent& event)
|
||||
{
|
||||
for (wxSizerItemList::compatibility_iterator panel = m_panels->GetChildren().GetFirst(); panel; panel = panel->GetNext())
|
||||
panel->GetData()->GetWindow()->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPBannerPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPBannerPanel::wxEAPBannerPanel(wxWindow* parent) : wxEAPBannerPanelBase(parent)
|
||||
{
|
||||
m_title->SetLabelText(wxT(PRODUCT_NAME_STR));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxPasswordCredentialsPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
const wxStringCharType *wxPasswordCredentialsPanel::s_dummy_password = wxT("dummypass");
|
||||
|
||||
|
||||
wxPasswordCredentialsPanel::wxPasswordCredentialsPanel(eap::credentials_pass &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) :
|
||||
wxCredentialsPanel<wxPasswordCredentialsPanelBase, eap::credentials_pass>(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 wxPasswordCredentialsPanel::TransferDataToWindow()
|
||||
{
|
||||
wxCHECK(__super::TransferDataToWindow(), false);
|
||||
|
||||
m_identity->SetValue(m_cred.m_identity);
|
||||
m_identity->SetSelection(0, -1);
|
||||
m_password->SetValue(m_cred.m_password.empty() ? wxEmptyString : s_dummy_password);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxPasswordCredentialsPanel::TransferDataFromWindow()
|
||||
{
|
||||
m_cred.m_identity = m_identity->GetValue();
|
||||
|
||||
wxString pass = m_password->GetValue();
|
||||
if (pass.compare(s_dummy_password) != 0) {
|
||||
m_cred.m_password = pass;
|
||||
pass.assign(pass.length(), wxT('*'));
|
||||
}
|
||||
|
||||
return __super::TransferDataFromWindow();
|
||||
}
|
@@ -20,6 +20,8 @@
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
#pragma comment(lib, "msxml6.lib")
|
||||
|
||||
|
||||
#if EAPMETHOD_TYPE==21
|
||||
#define _EAPMETHOD_PEER_UI eap::peer_ttls_ui
|
||||
|
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::config_pap
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config_pap::config_pap(_In_ module &mod) : config_pass(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_pap::config_pap(_In_ const config_pap &other) :
|
||||
config_pass(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_pap::config_pap(_Inout_ config_pap &&other) :
|
||||
config_pass(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_pap& eap::config_pap::operator=(_In_ const config_pap &other)
|
||||
{
|
||||
if (this != &other)
|
||||
(config_pass&)*this = other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::config_pap& eap::config_pap::operator=(_Inout_ config_pap &&other)
|
||||
{
|
||||
if (this != &other)
|
||||
(config_pass&&)*this = std::move(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::credentials_pap
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::credentials_pap::credentials_pap(_In_ module &mod) : credentials_pass(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pap::credentials_pap(_In_ const credentials_pap &other) :
|
||||
credentials_pass(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pap::credentials_pap(_Inout_ credentials_pap &&other) :
|
||||
credentials_pass(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pap& eap::credentials_pap::operator=(_In_ const credentials_pap &other)
|
||||
{
|
||||
if (this != &other)
|
||||
(credentials_pass&)*this = other;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_pap& eap::credentials_pap::operator=(_Inout_ credentials_pap &&other)
|
||||
{
|
||||
if (this != &other)
|
||||
(credentials_pass&&)*this = std::move(other);
|
||||
|
||||
return *this;
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxPAPConfigPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxPAPConfigPanel::wxPAPConfigPanel(eap::config_pap &cfg, LPCTSTR pszCredTarget, wxWindow* parent) : wxPanel(parent)
|
||||
{
|
||||
wxBoxSizer* sb_content;
|
||||
sb_content = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
if (cfg.m_allow_save) {
|
||||
m_credentials = new wxPAPCredentialsConfigPanel(cfg, pszCredTarget, this);
|
||||
sb_content->Add(m_credentials, 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
m_label = NULL;
|
||||
} else {
|
||||
m_credentials = NULL;
|
||||
|
||||
m_label = new wxStaticText(this, wxID_ANY, _("This method requires no additional settings."), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_label->Wrap(-1);
|
||||
sb_content->Add(m_label, 0, wxALL|wxEXPAND, 5);
|
||||
}
|
||||
|
||||
sb_content->Add(10, 10, 1, wxEXPAND, 5);
|
||||
|
||||
this->SetSizer(sb_content);
|
||||
this->Layout();
|
||||
|
||||
// Connect Events
|
||||
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxPAPConfigPanel::OnInitDialog));
|
||||
}
|
||||
|
||||
|
||||
wxPAPConfigPanel::~wxPAPConfigPanel()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxPAPConfigPanel::OnInitDialog));
|
||||
}
|
||||
|
||||
|
||||
void wxPAPConfigPanel::OnInitDialog(wxInitDialogEvent& event)
|
||||
{
|
||||
// Forward the event to child panels.
|
||||
if (m_credentials)
|
||||
m_credentials->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
@@ -1,329 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace winstd;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::config_tls
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config_tls::config_tls(_In_ module &mod) : config_method(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_tls::config_tls(_In_ const config_tls &other) :
|
||||
m_trusted_root_ca(other.m_trusted_root_ca),
|
||||
m_server_names(other.m_server_names),
|
||||
config_method(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_tls::config_tls(_Inout_ config_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))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_tls& eap::config_tls::operator=(_In_ const eap::config_tls &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(config_method&)*this = other;
|
||||
m_trusted_root_ca = other.m_trusted_root_ca;
|
||||
m_server_names = other.m_server_names;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::config_tls& eap::config_tls::operator=(_Inout_ eap::config_tls &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(config_method&&)*this = std::move(other);
|
||||
m_trusted_root_ca = std::move(other.m_trusted_root_ca);
|
||||
m_server_names = std::move(other.m_server_names);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::config_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
|
||||
DWORD dwResult;
|
||||
HRESULT hr;
|
||||
|
||||
// <ServerSideCredential>
|
||||
com_obj<IXMLDOMElement> pXmlElServerSideCredential;
|
||||
if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:ServerSideCredential"), bstr(L"ServerSideCredential"), bstrNamespace, &pXmlElServerSideCredential)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ServerSideCredential> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
for (list<cert_context>::const_iterator i = m_trusted_root_ca.begin(), i_end = m_trusted_root_ca.end(); i != i_end; ++i) {
|
||||
// <CA>
|
||||
com_obj<IXMLDOMElement> pXmlElCA;
|
||||
if ((dwResult = eapxml::create_element(pDoc, bstr(L"CA"), bstrNamespace, &pXmlElCA))) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <CA> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// <CA>/<format>
|
||||
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElCA, bstr(L"format"), bstrNamespace, bstr(L"PEM"))) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <format> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// <CA>/<cert-data>
|
||||
const cert_context &cc = *i;
|
||||
if ((dwResult = eapxml::put_element_base64(pDoc, pXmlElCA, bstr(L"cert-data"), bstrNamespace, cc->pbCertEncoded, cc->cbCertEncoded)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <cert-data> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
if (FAILED(hr = pXmlElServerSideCredential->appendChild(pXmlElCA, NULL))) {
|
||||
*ppEapError = m_module.make_error(dwResult = HRESULT_CODE(hr), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error appending <CA> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
|
||||
// <ServerName>
|
||||
for (list<string>::const_iterator i = m_server_names.begin(), i_end = m_server_names.end(); i != i_end; ++i) {
|
||||
wstring str;
|
||||
MultiByteToWideChar(CP_UTF8, 0, i->c_str(), (int)i->length(), str);
|
||||
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElServerSideCredential, bstr(L"ServerName"), bstrNamespace, bstr(str))) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ServerName> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
|
||||
return config_method::save(pDoc, pConfigRoot, ppEapError);
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::config_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
m_trusted_root_ca.clear();
|
||||
m_server_names.clear();
|
||||
|
||||
// <ServerSideCredential>
|
||||
com_obj<IXMLDOMElement> pXmlElServerSideCredential;
|
||||
if (eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ServerSideCredential"), &pXmlElServerSideCredential) == ERROR_SUCCESS) {
|
||||
// <CA>
|
||||
com_obj<IXMLDOMNodeList> pXmlListCAs;
|
||||
long lCACount = 0;
|
||||
if (eapxml::select_nodes(pXmlElServerSideCredential, bstr(L"eap-metadata:CA"), &pXmlListCAs) == ERROR_SUCCESS && SUCCEEDED(pXmlListCAs->get_length(&lCACount))) {
|
||||
for (long j = 0; j < lCACount; j++) {
|
||||
// Load CA certificate.
|
||||
com_obj<IXMLDOMNode> pXmlElCA;
|
||||
pXmlListCAs->get_item(j, &pXmlElCA);
|
||||
bstr bstrFormat;
|
||||
if (eapxml::get_element_value(pXmlElCA, bstr(L"eap-metadata:format"), &bstrFormat) == ERROR_SUCCESS) {
|
||||
if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrFormat, bstrFormat.length(), L"PEM", -1, NULL, NULL, 0) == CSTR_EQUAL) {
|
||||
vector<unsigned char> aData;
|
||||
if (eapxml::get_element_base64(pXmlElCA, bstr(L"eap-metadata:cert-data"), aData) == ERROR_SUCCESS)
|
||||
add_trusted_ca(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, aData.data(), (DWORD)aData.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// <ServerName>
|
||||
com_obj<IXMLDOMNodeList> pXmlListServerIDs;
|
||||
long lServerIDCount = 0;
|
||||
if (eapxml::select_nodes(pXmlElServerSideCredential, bstr(L"eap-metadata:ServerName"), &pXmlListServerIDs) == ERROR_SUCCESS && SUCCEEDED(pXmlListServerIDs->get_length(&lServerIDCount))) {
|
||||
for (long j = 0; j < lServerIDCount; j++) {
|
||||
// Load server name (<ServerName>).
|
||||
com_obj<IXMLDOMNode> pXmlElServerID;
|
||||
pXmlListServerIDs->get_item(j, &pXmlElServerID);
|
||||
bstr bstrServerID;
|
||||
pXmlElServerID->get_text(&bstrServerID);
|
||||
|
||||
// Server names (FQDNs) are always ASCII. Hopefully. Convert them to UTF-8 anyway for consistent comparison. CP_ANSI varies.
|
||||
string str;
|
||||
WideCharToMultiByte(CP_UTF8, 0, bstrServerID, bstrServerID.length(), str, NULL, NULL);
|
||||
|
||||
m_server_names.push_back(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return config_method::load(pConfigRoot, ppEapError);
|
||||
}
|
||||
|
||||
|
||||
bool eap::config_tls::add_trusted_ca(_In_ DWORD dwCertEncodingType, _In_ const BYTE *pbCertEncoded, _In_ DWORD cbCertEncoded)
|
||||
{
|
||||
cert_context cert;
|
||||
if (!cert.create(dwCertEncodingType, pbCertEncoded, cbCertEncoded)) {
|
||||
// Invalid or unsupported certificate.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (list<cert_context>::const_iterator i = m_trusted_root_ca.cbegin(), i_end = m_trusted_root_ca.cend();; ++i) {
|
||||
if (i != i_end) {
|
||||
if (*i == cert) {
|
||||
// This certificate is already on the list.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// End of list reached. Append certificate.
|
||||
m_trusted_root_ca.push_back(std::move(cert));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::credentials_tls
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::credentials_tls::credentials_tls(_In_ module &mod) : credentials(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_tls::credentials_tls(_In_ const credentials_tls &other) :
|
||||
m_cert_hash(other.m_cert_hash),
|
||||
credentials(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_tls::credentials_tls(_Inout_ credentials_tls &&other) :
|
||||
m_cert_hash(std::move(m_cert_hash)),
|
||||
credentials(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_tls& eap::credentials_tls::operator=(_In_ const credentials_tls &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials&)*this = other;
|
||||
m_cert_hash = other.m_cert_hash;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_tls& eap::credentials_tls::operator=(_Inout_ credentials_tls &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials&)*this = std::move(other);
|
||||
m_cert_hash = std::move(other.m_cert_hash);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void eap::credentials_tls::clear()
|
||||
{
|
||||
credentials::clear();
|
||||
m_cert_hash.clear();
|
||||
}
|
||||
|
||||
|
||||
bool eap::credentials_tls::empty() const
|
||||
{
|
||||
return credentials::empty() && m_cert_hash.empty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
DWORD eap::credentials_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
assert(pConfigRoot);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
eapxml::get_element_hex(pConfigRoot, bstr(L"CertHash"), m_cert_hash);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
assert(pszTargetName);
|
||||
assert(ppEapError);
|
||||
DWORD dwResult;
|
||||
|
||||
tstring target(target_name(pszTargetName));
|
||||
|
||||
// Write credentials.
|
||||
assert(m_cert_hash.size()*sizeof(char) < CRED_MAX_CREDENTIAL_BLOB_SIZE);
|
||||
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
|
||||
CREDENTIAL cred = {
|
||||
0, // Flags
|
||||
CRED_TYPE_GENERIC, // Type
|
||||
(LPTSTR)target.c_str(), // TargetName
|
||||
_T(""), // Comment
|
||||
{ 0, 0 }, // LastWritten
|
||||
(DWORD)m_cert_hash.size()*sizeof(char), // CredentialBlobSize
|
||||
(LPBYTE)m_cert_hash.data(), // CredentialBlob
|
||||
CRED_PERSIST_ENTERPRISE, // Persist
|
||||
0, // AttributeCount
|
||||
NULL, // Attributes
|
||||
NULL, // TargetAlias
|
||||
(LPTSTR)m_identity.c_str() // UserName
|
||||
};
|
||||
if (!CredWrite(&cred, 0)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredWrite failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
assert(pszTargetName && _tcslen(pszTargetName) < CRED_MAX_GENERIC_TARGET_NAME_LENGTH);
|
||||
DWORD dwResult;
|
||||
|
||||
// Read credentials.
|
||||
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
|
||||
if (!CredRead(target_name(pszTargetName).c_str(), CRED_TYPE_GENERIC, 0, (PCREDENTIAL*)&cred)) {
|
||||
*ppEapError = m_module.make_error(dwResult = GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredRead failed."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
if (cred->UserName)
|
||||
m_identity = cred->UserName;
|
||||
else
|
||||
m_identity.clear();
|
||||
|
||||
m_cert_hash.assign(cred->CredentialBlob, cred->CredentialBlob + cred->CredentialBlobSize);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
@@ -1,658 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
#pragma comment(lib, "Cryptui.lib")
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::get_cert_title
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void eap::get_cert_title(PCCERT_CONTEXT cert, winstd::tstring &title)
|
||||
{
|
||||
winstd::tstring name, str, issuer;
|
||||
FILETIME ft;
|
||||
SYSTEMTIME st;
|
||||
|
||||
title.clear();
|
||||
|
||||
// Prepare certificate information
|
||||
CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, name);
|
||||
title += name;
|
||||
|
||||
FileTimeToLocalFileTime(&(cert->pCertInfo->NotBefore), &ft);
|
||||
FileTimeToSystemTime(&ft, &st);
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, str);
|
||||
title += _T(", ");
|
||||
title += str;
|
||||
|
||||
FileTimeToLocalFileTime(&(cert->pCertInfo->NotAfter ), &ft);
|
||||
FileTimeToSystemTime(&ft, &st);
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, str);
|
||||
title += _T('-');
|
||||
title += str;
|
||||
|
||||
CertGetNameString(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, issuer);
|
||||
if (name != issuer) {
|
||||
title += _T(", ");
|
||||
title += issuer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxCertificateClientData
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxCertificateClientData::wxCertificateClientData(PCCERT_CONTEXT cert) : m_cert(cert)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxCertificateClientData::~wxCertificateClientData()
|
||||
{
|
||||
if (m_cert)
|
||||
CertFreeCertificateContext(m_cert);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxCertificateSelectionClientData
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxCertificateSelectionClientData::wxCertificateSelectionClientData()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxCertificateSelectionClientData::wxCertificateSelectionClientData(const wchar_t *identity, unsigned char *hash, size_t hash_size) :
|
||||
m_identity(identity),
|
||||
m_hash(hash, hash + hash_size)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxCertificateSelectionClientData::wxCertificateSelectionClientData(const std::wstring &identity, const std::vector<unsigned char> &hash) :
|
||||
m_identity(identity),
|
||||
m_hash(hash)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxCertificateSelectionClientData::wxCertificateSelectionClientData(std::wstring &&identity, std::vector<unsigned char> &&hash) :
|
||||
m_identity(std::move(identity)),
|
||||
m_hash(std::move(hash))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxCertificateSelectionClientData::wxCertificateSelectionClientData(const wxCertificateSelectionClientData &other) :
|
||||
m_identity(other.m_identity),
|
||||
m_hash(other.m_hash)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxCertificateSelectionClientData::wxCertificateSelectionClientData(wxCertificateSelectionClientData &&other) :
|
||||
m_identity(std::move(other.m_identity)),
|
||||
m_hash(std::move(other.m_hash))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxHostNameValidator
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxHostNameValidator, wxValidator);
|
||||
|
||||
|
||||
wxHostNameValidator::wxHostNameValidator(std::string *val) :
|
||||
m_val(val),
|
||||
wxValidator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxHostNameValidator::wxHostNameValidator(const wxHostNameValidator &other) :
|
||||
m_val(other.m_val),
|
||||
wxValidator(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxObject* wxHostNameValidator::Clone() const
|
||||
{
|
||||
return new wxHostNameValidator(*this);
|
||||
}
|
||||
|
||||
|
||||
bool wxHostNameValidator::Validate(wxWindow *parent)
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
wxTextCtrl *ctrl = (wxTextCtrl*)GetWindow();
|
||||
if (!ctrl->IsEnabled()) return true;
|
||||
|
||||
wxString val(ctrl->GetValue());
|
||||
return Parse(val, 0, val.Length(), ctrl, parent);
|
||||
}
|
||||
|
||||
|
||||
bool wxHostNameValidator::TransferToWindow()
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
|
||||
if (m_val)
|
||||
((wxTextCtrl*)GetWindow())->SetValue(*m_val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxHostNameValidator::TransferFromWindow()
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
wxTextCtrl *ctrl = (wxTextCtrl*)GetWindow();
|
||||
|
||||
wxString val(ctrl->GetValue());
|
||||
return Parse(val, 0, val.Length(), ctrl, NULL, m_val);
|
||||
}
|
||||
|
||||
|
||||
bool wxHostNameValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::string *val_out)
|
||||
{
|
||||
const wxStringCharType *buf = val_in;
|
||||
|
||||
size_t i = i_start;
|
||||
for (;;) {
|
||||
if (i >= i_end) {
|
||||
// End of host name found.
|
||||
if (val_out) val_out->assign(val_in.c_str() + i_start, i - i_start);
|
||||
return true;
|
||||
} else if (_tcschr(wxT("abcdefghijklmnopqrstuvwxyz0123456789-*"), buf[i])) {
|
||||
// Valid character found.
|
||||
i++;
|
||||
} else {
|
||||
// Invalid character found.
|
||||
ctrl->SetFocus();
|
||||
ctrl->SetSelection(i, i + 1);
|
||||
wxMessageBox(wxString::Format(_("Invalid character in host name found: %c"), buf[i]), _("Validation conflict"), wxOK | wxICON_EXCLAMATION, parent);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxFQDNValidator
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxFQDNValidator, wxValidator);
|
||||
|
||||
|
||||
wxFQDNValidator::wxFQDNValidator(std::string *val) :
|
||||
m_val(val),
|
||||
wxValidator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxFQDNValidator::wxFQDNValidator(const wxFQDNValidator &other) :
|
||||
m_val(other.m_val),
|
||||
wxValidator(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxObject* wxFQDNValidator::Clone() const
|
||||
{
|
||||
return new wxFQDNValidator(*this);
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNValidator::Validate(wxWindow *parent)
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
wxTextCtrl *ctrl = (wxTextCtrl*)GetWindow();
|
||||
if (!ctrl->IsEnabled()) return true;
|
||||
|
||||
wxString val(ctrl->GetValue());
|
||||
return Parse(val, 0, val.Length(), ctrl, parent);
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNValidator::TransferToWindow()
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
|
||||
if (m_val)
|
||||
((wxTextCtrl*)GetWindow())->SetValue(*m_val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNValidator::TransferFromWindow()
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
wxTextCtrl *ctrl = (wxTextCtrl*)GetWindow();
|
||||
|
||||
wxString val(ctrl->GetValue());
|
||||
return Parse(val, 0, val.Length(), ctrl, NULL, m_val);
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::string *val_out)
|
||||
{
|
||||
const wxStringCharType *buf = val_in;
|
||||
|
||||
size_t i = i_start;
|
||||
for (;;) {
|
||||
const wxStringCharType *buf_next;
|
||||
if ((buf_next = wmemchr(buf + i, L'.', i_end - i)) != NULL) {
|
||||
// FQDN separator found.
|
||||
if (!wxHostNameValidator::Parse(val_in, i, buf_next - buf, ctrl, parent))
|
||||
return false;
|
||||
i = buf_next - buf + 1;
|
||||
} else if (wxHostNameValidator::Parse(val_in, i, i_end, ctrl, parent)) {
|
||||
// The rest of the FQDN parsed succesfully.
|
||||
if (val_out) val_out->assign(val_in.c_str() + i_start, i_end - i_start);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxFQDNListValidator
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(wxFQDNListValidator, wxValidator);
|
||||
|
||||
|
||||
wxFQDNListValidator::wxFQDNListValidator(std::list<std::string> *val) :
|
||||
m_val(val),
|
||||
wxValidator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxFQDNListValidator::wxFQDNListValidator(const wxFQDNListValidator &other) :
|
||||
m_val(other.m_val),
|
||||
wxValidator(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
wxObject* wxFQDNListValidator::Clone() const
|
||||
{
|
||||
return new wxFQDNListValidator(*this);
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNListValidator::Validate(wxWindow *parent)
|
||||
{
|
||||
wxTextCtrl *ctrl = (wxTextCtrl*)GetWindow();
|
||||
if (!ctrl->IsEnabled()) return true;
|
||||
|
||||
wxString val(ctrl->GetValue());
|
||||
return Parse(val, 0, val.Length(), ctrl, parent);
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNListValidator::TransferToWindow()
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
|
||||
if (m_val) {
|
||||
wxString str;
|
||||
for (std::list<std::string>::const_iterator name = m_val->cbegin(), name_end = m_val->cend(); name != name_end; ++name) {
|
||||
if (!str.IsEmpty()) str += wxT("; ");
|
||||
str += *name;
|
||||
}
|
||||
((wxTextCtrl*)GetWindow())->SetValue(str);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNListValidator::TransferFromWindow()
|
||||
{
|
||||
wxASSERT(GetWindow()->IsKindOf(CLASSINFO(wxTextCtrl)));
|
||||
wxTextCtrl *ctrl = (wxTextCtrl*)GetWindow();
|
||||
|
||||
wxString val(ctrl->GetValue());
|
||||
return Parse(val, 0, val.Length(), ctrl, NULL, m_val);
|
||||
}
|
||||
|
||||
|
||||
bool wxFQDNListValidator::Parse(const wxString &val_in, size_t i_start, size_t i_end, wxTextCtrl *ctrl, wxWindow *parent, std::list<std::string> *val_out)
|
||||
{
|
||||
const wxStringCharType *buf = val_in;
|
||||
std::string _fqdn, *fqdn = val_out ? &_fqdn : NULL;
|
||||
std::list<std::string> _val_out;
|
||||
|
||||
size_t i = i_start;
|
||||
for (;;) {
|
||||
// Skip initial white-space.
|
||||
for (; i < i_end && _istspace(buf[i]); i++);
|
||||
|
||||
const wxStringCharType *buf_next;
|
||||
if ((buf_next = wmemchr(buf + i, L';', i_end - i)) != NULL) {
|
||||
// FQDN list separator found.
|
||||
|
||||
// Skip trailing white-space.
|
||||
size_t i_next = buf_next - buf;
|
||||
for (; i < i_next && _istspace(buf[i_next - 1]); i_next--);
|
||||
|
||||
if (!wxFQDNValidator::Parse(val_in, i, i_next, ctrl, parent, fqdn))
|
||||
return false;
|
||||
if (fqdn && !fqdn->empty()) _val_out.push_back(std::move(*fqdn));
|
||||
|
||||
i = buf_next - buf + 1;
|
||||
} else {
|
||||
// Skip trailing white-space.
|
||||
for (; i < i_end && _istspace(buf[i_end - 1]); i_end--);
|
||||
|
||||
if (wxHostNameValidator::Parse(val_in, i, i_end, ctrl, parent, fqdn)) {
|
||||
// The rest of the FQDN list parsed succesfully.
|
||||
if (fqdn && !fqdn->empty()) _val_out.push_back(std::move(*fqdn));
|
||||
if (val_out) *val_out = std::move(_val_out);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPTLSCredentialsPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPTLSCredentialsPanel::wxEAPTLSCredentialsPanel(eap::credentials_tls &cred, LPCTSTR pszCredTarget, wxWindow* parent, bool is_config) :
|
||||
wxCredentialsPanel<wxEAPTLSCredentialsPanelBase, eap::credentials_tls>(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 wxEAPTLSCredentialsPanel::TransferDataToWindow()
|
||||
{
|
||||
wxCHECK(__super::TransferDataToWindow(), false);
|
||||
|
||||
// Populate certificate list.
|
||||
bool is_found = false;
|
||||
winstd::cert_store store;
|
||||
if (store.create(CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER, _T("My"))) {
|
||||
for (PCCERT_CONTEXT cert = NULL; (cert = CertEnumCertificatesInStore(store, cert)) != NULL;) {
|
||||
DWORD dwKeySpec = 0, dwSize = sizeof(dwKeySpec);
|
||||
if (!CertGetCertificateContextProperty(cert, CERT_KEY_SPEC_PROP_ID, &dwKeySpec, &dwSize) || !dwKeySpec) {
|
||||
// Skip certificates without private key.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Prepare certificate information.
|
||||
std::unique_ptr<wxCertificateSelectionClientData> data(new wxCertificateSelectionClientData);
|
||||
eap::get_cert_title(cert, data->m_identity);
|
||||
|
||||
// Add to list.
|
||||
CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID, data->m_hash);
|
||||
bool is_selected = data->m_hash == m_cred.m_cert_hash;
|
||||
int i = m_cert_select_val->Append(data->m_identity, data.release());
|
||||
if (is_selected) {
|
||||
m_cert_select_val->SetSelection(i);
|
||||
is_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_found) {
|
||||
m_cert_select ->SetValue(true);
|
||||
m_cert_select_val->Enable(true);
|
||||
} else {
|
||||
m_cert_none ->SetValue(true);
|
||||
m_cert_select_val->Enable(false);
|
||||
if (!m_cert_select_val->IsEmpty())
|
||||
m_cert_select_val->SetSelection(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTLSCredentialsPanel::TransferDataFromWindow()
|
||||
{
|
||||
if (m_cert_none->GetValue())
|
||||
m_cred.clear();
|
||||
else {
|
||||
const wxCertificateSelectionClientData *data = dynamic_cast<const wxCertificateSelectionClientData*>(m_cert_select_val->GetClientObject(m_cert_select_val->GetSelection()));
|
||||
if (data) {
|
||||
m_cred.m_identity = data->m_identity;
|
||||
m_cred.m_cert_hash = data->m_hash;
|
||||
} else
|
||||
m_cred.clear();
|
||||
}
|
||||
|
||||
return __super::TransferDataFromWindow();
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSCredentialsPanel::OnCertSelect(wxCommandEvent& event)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(event);
|
||||
m_cert_select_val->Enable(m_cert_select->GetValue());
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPTLSServerTrustPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPTLSServerTrustPanel::wxEAPTLSServerTrustPanel(eap::config_tls &cfg, wxWindow* parent) :
|
||||
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));
|
||||
|
||||
m_server_names->SetValidator(wxFQDNListValidator(&(m_cfg.m_server_names)));
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTLSServerTrustPanel::TransferDataToWindow()
|
||||
{
|
||||
wxCHECK(wxEAPTLSServerTrustConfigPanelBase::TransferDataToWindow(), 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()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTLSServerTrustPanel::TransferDataFromWindow()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
return wxEAPTLSServerTrustConfigPanelBase::TransferDataFromWindow();
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSServerTrustPanel::OnRootCA(wxCommandEvent& event)
|
||||
{
|
||||
wxCertificateClientData *cert = dynamic_cast<wxCertificateClientData*>(event.GetClientObject());
|
||||
m_root_ca_remove->Enable(cert ? true : false);
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSServerTrustPanel::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);
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSServerTrustPanel::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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSServerTrustPanel::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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSServerTrustPanel::OnRootCARemove(wxCommandEvent& event)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(event);
|
||||
|
||||
wxArrayInt selections;
|
||||
for (int i = m_root_ca->GetSelections(selections); i--; )
|
||||
m_root_ca->Delete(selections[i]);
|
||||
|
||||
m_root_ca_remove->Enable(false);
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTLSServerTrustPanel::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);
|
||||
m_root_ca_remove->Enable();
|
||||
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);
|
||||
m_root_ca_remove->Enable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPTLSConfigPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPTLSConfigPanel::wxEAPTLSConfigPanel(eap::config_tls &cfg, LPCTSTR pszCredTarget, wxWindow* parent) : wxPanel(parent)
|
||||
{
|
||||
wxBoxSizer* sb_content;
|
||||
sb_content = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_server_trust = new wxEAPTLSServerTrustPanel(cfg, this);
|
||||
sb_content->Add(m_server_trust, 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
if (cfg.m_allow_save) {
|
||||
m_credentials = new wxEAPTLSCredentialsConfigPanel(cfg, pszCredTarget, this);
|
||||
sb_content->Add(m_credentials, 0, wxALL|wxEXPAND, 5);
|
||||
} else
|
||||
m_credentials = NULL;
|
||||
|
||||
sb_content->Add(10, 10, 1, wxEXPAND, 5);
|
||||
|
||||
this->SetSizer(sb_content);
|
||||
this->Layout();
|
||||
|
||||
// Connect Events
|
||||
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTLSConfigPanel::OnInitDialog));
|
||||
}
|
||||
|
||||
|
||||
wxEAPTLSConfigPanel::~wxEAPTLSConfigPanel()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTLSConfigPanel::OnInitDialog));
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTLSConfigPanel::OnInitDialog(wxInitDialogEvent& event)
|
||||
{
|
||||
// Forward the event to child panels.
|
||||
m_server_trust->GetEventHandler()->ProcessEvent(event);
|
||||
if (m_credentials)
|
||||
m_credentials->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
@@ -1,375 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
#pragma comment(lib, "Msi.lib")
|
||||
#pragma comment(lib, "msxml6.lib")
|
||||
|
||||
using namespace std;
|
||||
using namespace winstd;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::config_ttls
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::config_ttls::config_ttls(_In_ module &mod) :
|
||||
m_inner(NULL),
|
||||
config_tls(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_ttls::config_ttls(const _In_ config_ttls &other) :
|
||||
m_inner(other.m_inner ? (config_method*)other.m_inner->clone() : NULL),
|
||||
config_tls(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::config_ttls::config_ttls(_Inout_ config_ttls &&other) :
|
||||
m_inner(other.m_inner),
|
||||
config_tls(std::move(other))
|
||||
{
|
||||
other.m_inner = NULL;
|
||||
}
|
||||
|
||||
|
||||
eap::config_ttls::~config_ttls()
|
||||
{
|
||||
if (m_inner)
|
||||
delete m_inner;
|
||||
}
|
||||
|
||||
|
||||
eap::config_ttls& eap::config_ttls::operator=(const _In_ config_ttls &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(config_tls&)*this = other;
|
||||
if (m_inner) delete m_inner;
|
||||
m_inner = other.m_inner ? (config_method*)other.m_inner->clone() : NULL;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::config_ttls& eap::config_ttls::operator=(_Inout_ config_ttls &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(config_tls&&)*this = std::move(other);
|
||||
if (m_inner) delete m_inner;
|
||||
m_inner = other.m_inner;
|
||||
other.m_inner = NULL;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::config_ttls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
|
||||
DWORD dwResult;
|
||||
|
||||
// <InnerAuthenticationMethod>
|
||||
com_obj<IXMLDOMElement> pXmlElInnerAuthenticationMethod;
|
||||
if ((dwResult = eapxml::create_element(pDoc, pConfigRoot, bstr(L"eap-metadata:InnerAuthenticationMethod"), bstr(L"InnerAuthenticationMethod"), bstrNamespace, &pXmlElInnerAuthenticationMethod)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <InnerAuthenticationMethod> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
if (dynamic_cast<const config_pap*>(m_inner)) {
|
||||
// <InnerAuthenticationMethod>/<NonEAPAuthMethod>
|
||||
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElInnerAuthenticationMethod, bstr(L"NonEAPAuthMethod"), bstrNamespace, bstr(L"PAP"))) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <NonEAPAuthMethod> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// <InnerAuthenticationMethod>/...
|
||||
if ((dwResult = m_inner->save(pDoc, pXmlElInnerAuthenticationMethod, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
} else
|
||||
return dwResult = ERROR_NOT_SUPPORTED;
|
||||
|
||||
return config_tls::save(pDoc, pConfigRoot, ppEapError);
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::config_ttls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
assert(ppEapError);
|
||||
DWORD dwResult;
|
||||
|
||||
// Load inner authentication configuration (<InnerAuthenticationMethod>).
|
||||
com_obj<IXMLDOMElement> pXmlElInnerAuthenticationMethod;
|
||||
if ((dwResult = eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:InnerAuthenticationMethod"), &pXmlElInnerAuthenticationMethod)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error selecting <InnerAuthenticationMethod> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
// Determine inner authentication type (<EAPMethod> and <NonEAPAuthMethod>).
|
||||
//DWORD dwMethodID;
|
||||
bstr bstrMethod;
|
||||
/*if (eapxml::get_element_value(pXmlElInnerAuthenticationMethod, bstr(L"eap-metadata:EAPMethod"), &dwMethodID) == ERROR_SUCCESS &&
|
||||
dwMethodID == EAP_TYPE_MSCHAPV2)
|
||||
{
|
||||
// MSCHAPv2
|
||||
// TODO: Add MSCHAPv2 support.
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
} else*/ if (eapxml::get_element_value(pXmlElInnerAuthenticationMethod, bstr(L"eap-metadata:NonEAPAuthMethod"), &bstrMethod) == ERROR_SUCCESS &&
|
||||
CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrMethod, bstrMethod.length(), L"PAP", -1, NULL, NULL, 0) == CSTR_EQUAL)
|
||||
{
|
||||
// PAP
|
||||
assert(!m_inner);
|
||||
m_inner = new eap::config_pap(m_module);
|
||||
if ((dwResult = m_inner->load(pXmlElInnerAuthenticationMethod, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
} else {
|
||||
*ppEapError = m_module.make_error(dwResult = ERROR_NOT_SUPPORTED, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Unsupported inner authentication method."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return config_tls::load(pConfigRoot, ppEapError);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::credentials_ttls
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::credentials_ttls::credentials_ttls(_In_ module &mod) : credentials_tls(mod)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_ttls::credentials_ttls(_In_ const credentials_ttls &other) :
|
||||
m_inner(other.m_inner ? (credentials*)other.m_inner->clone() : NULL),
|
||||
credentials_tls(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_ttls::credentials_ttls(_Inout_ credentials_ttls &&other) :
|
||||
m_inner(other.m_inner),
|
||||
credentials_tls(std::move(other))
|
||||
{
|
||||
other.m_inner = NULL;
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_ttls& eap::credentials_ttls::operator=(_In_ const credentials_ttls &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials_tls&)*this = other;
|
||||
|
||||
if (m_inner) delete m_inner;
|
||||
m_inner = other.m_inner ? (credentials*)other.m_inner->clone() : NULL;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
eap::credentials_ttls& eap::credentials_ttls::operator=(_Inout_ credentials_ttls &&other)
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials_tls&)*this = std::move(other);
|
||||
|
||||
if (m_inner) delete m_inner;
|
||||
m_inner = other.m_inner;
|
||||
other.m_inner = NULL;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void eap::credentials_ttls::clear()
|
||||
{
|
||||
credentials_tls::clear();
|
||||
if (m_inner)
|
||||
m_inner->clear();
|
||||
}
|
||||
|
||||
|
||||
bool eap::credentials_ttls::empty() const
|
||||
{
|
||||
return credentials_tls::empty() && (!m_inner || m_inner->empty());
|
||||
}
|
||||
|
||||
|
||||
|
||||
DWORD eap::credentials_ttls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
assert(pConfigRoot);
|
||||
DWORD dwResult;
|
||||
|
||||
if ((dwResult = credentials_tls::load(pConfigRoot, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
|
||||
if (m_inner) {
|
||||
com_obj<IXMLDOMNode> pXmlElInnerAuthenticationMethod;
|
||||
if ((dwResult = eapxml::select_node(pConfigRoot, bstr(L"eap-metadata:InnerAuthenticationMethod"), &pXmlElInnerAuthenticationMethod)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult = ERROR_NOT_FOUND, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error selecting <InnerAuthenticationMethod> element."), NULL);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
if ((dwResult = m_inner->load(pXmlElInnerAuthenticationMethod, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_ttls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
DWORD dwResult;
|
||||
|
||||
if ((dwResult = credentials_tls::store(pszTargetName, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
|
||||
if (m_inner) {
|
||||
if ((dwResult = m_inner->store(pszTargetName, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::credentials_ttls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
DWORD dwResult;
|
||||
|
||||
if ((dwResult = credentials_tls::retrieve(pszTargetName, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
|
||||
if (m_inner) {
|
||||
if ((dwResult = m_inner->retrieve(pszTargetName, ppEapError)) != ERROR_SUCCESS)
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::session_ttls
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::session_ttls::session_ttls() : session()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::peer_ttls
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::peer_ttls::peer_ttls() : peer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls::initialize(_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
// MSI's feature completeness check removed: It might invoke UI (prompt user for missing MSI),
|
||||
// which would be disasterous in EapHost system service.
|
||||
#if 0
|
||||
// Perform the Microsoft Installer's feature completeness check manually.
|
||||
// If execution got this far in the first place (dependent DLLs are present and loadable).
|
||||
// Furthermore, this increments program usage counter.
|
||||
if (MsiQueryFeatureState(_T(PRODUCT_VERSION_GUID), _T("featEAPTTLS")) != INSTALLSTATE_UNKNOWN)
|
||||
MsiUseFeature(_T(PRODUCT_VERSION_GUID), _T("featEAPTTLS"));
|
||||
#endif
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls::shutdown(_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls::get_identity(
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ DWORD dwConnectionDataSize,
|
||||
_In_count_(dwConnectionDataSize) const BYTE *pConnectionData,
|
||||
_In_ DWORD dwUserDataSize,
|
||||
_In_count_(dwUserDataSize) const BYTE *pUserData,
|
||||
_In_ HANDLE hTokenImpersonateUser,
|
||||
_Out_ BOOL *pfInvokeUI,
|
||||
_Out_ DWORD *pdwUserDataOutSize,
|
||||
_Out_ BYTE **ppUserDataOut,
|
||||
_Out_ WCHAR **ppwszIdentity,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dwFlags);
|
||||
UNREFERENCED_PARAMETER(dwConnectionDataSize);
|
||||
UNREFERENCED_PARAMETER(pConnectionData);
|
||||
UNREFERENCED_PARAMETER(dwUserDataSize);
|
||||
UNREFERENCED_PARAMETER(pUserData);
|
||||
UNREFERENCED_PARAMETER(hTokenImpersonateUser);
|
||||
UNREFERENCED_PARAMETER(pfInvokeUI);
|
||||
UNREFERENCED_PARAMETER(pdwUserDataOutSize);
|
||||
UNREFERENCED_PARAMETER(ppUserDataOut);
|
||||
UNREFERENCED_PARAMETER(ppwszIdentity);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
DWORD dwResult = ERROR_NOT_SUPPORTED;
|
||||
ETW_FN_DWORD(dwResult);
|
||||
return dwResult;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls::get_method_properties(
|
||||
_In_ DWORD dwVersion,
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ HANDLE hUserImpersonationToken,
|
||||
_In_ DWORD dwEapConnDataSize,
|
||||
_In_count_(dwEapConnDataSize) const BYTE *pEapConnData,
|
||||
_In_ DWORD dwUserDataSize,
|
||||
_In_count_(dwUserDataSize) const BYTE *pUserData,
|
||||
_Out_ EAP_METHOD_PROPERTY_ARRAY *pMethodPropertyArray,
|
||||
_Out_ EAP_ERROR **ppEapError) const
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dwVersion);
|
||||
UNREFERENCED_PARAMETER(dwFlags);
|
||||
UNREFERENCED_PARAMETER(hUserImpersonationToken);
|
||||
UNREFERENCED_PARAMETER(dwEapConnDataSize);
|
||||
UNREFERENCED_PARAMETER(pEapConnData);
|
||||
UNREFERENCED_PARAMETER(dwUserDataSize);
|
||||
UNREFERENCED_PARAMETER(pUserData);
|
||||
UNREFERENCED_PARAMETER(pMethodPropertyArray);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
DWORD dwResult = ERROR_NOT_SUPPORTED;
|
||||
ETW_FN_DWORD(dwResult);
|
||||
return dwResult;
|
||||
}
|
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
Copyright 2015-2016 Amebis
|
||||
Copyright 2016 GÉANT
|
||||
|
||||
This file is part of GÉANTLink.
|
||||
|
||||
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GÉANTLink is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <StdAfx.h>
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// eap::peer_ttls_ui
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
eap::peer_ttls_ui::peer_ttls_ui() : peer_ui<eap::config_ttls, eap::credentials_ttls, int, int>()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls_ui::invoke_config_ui(
|
||||
_In_ HWND hwndParent,
|
||||
_Inout_ config_type &cfg,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
// 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 configuration dialog.
|
||||
wxEAPConfigDialog<config_ttls, wxEAPTTLSConfig> dlg(cfg, &parent);
|
||||
result = dlg.ShowModal();
|
||||
|
||||
wxTopLevelWindows.DeleteObject(&parent);
|
||||
parent.SetHWND((WXHWND)NULL);
|
||||
}
|
||||
|
||||
// Clean-up and return.
|
||||
wxEntryCleanup();
|
||||
return result == wxID_OK ? ERROR_SUCCESS : ERROR_CANCELLED;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls_ui::invoke_identity_ui(
|
||||
_In_ HWND hwndParent,
|
||||
_In_ DWORD dwFlags,
|
||||
_Inout_ config_type &cfg,
|
||||
_Inout_ identity_type &usr,
|
||||
_Out_ LPWSTR *ppwszIdentity,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(dwFlags);
|
||||
UNREFERENCED_PARAMETER(cfg);
|
||||
UNREFERENCED_PARAMETER(usr);
|
||||
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);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD eap::peer_ttls_ui::invoke_interactive_ui(
|
||||
_In_ HWND hwndParent,
|
||||
_In_ const interactive_request_type &req,
|
||||
_Out_ interactive_response_type &res,
|
||||
_Out_ EAP_ERROR **ppEapError)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(req);
|
||||
UNREFERENCED_PARAMETER(res);
|
||||
UNREFERENCED_PARAMETER(ppEapError);
|
||||
|
||||
InitCommonControls();
|
||||
MessageBox(hwndParent, _T(PRODUCT_NAME_STR) _T(" interactive UI goes here!"), _T(PRODUCT_NAME_STR) _T(" Prompt"), MB_OK);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPTTLSConfigPanel
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPTTLSConfigPanel::wxEAPTTLSConfigPanel(eap::config_ttls &cfg, wxWindow* parent) :
|
||||
m_cfg(cfg),
|
||||
wxEAPTTLSConfigPanelBase(parent)
|
||||
{
|
||||
// Load and set icon.
|
||||
if (m_shell32.load(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE))
|
||||
wxSetIconFromResource(m_outer_identity_icon, m_icon, m_shell32, MAKEINTRESOURCE(265));
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTTLSConfigPanel::TransferDataToWindow()
|
||||
{
|
||||
wxCHECK(wxEAPTTLSConfigPanelBase::TransferDataToWindow(), false);
|
||||
|
||||
// Populate identity controls.
|
||||
if (m_cfg.m_anonymous_identity.empty()) {
|
||||
m_outer_identity_same->SetValue(true);
|
||||
m_outer_identity_custom_val->Enable(false);
|
||||
} else if (m_cfg.m_anonymous_identity == L"@") {
|
||||
m_outer_identity_empty->SetValue(true);
|
||||
m_outer_identity_custom_val->Enable(false);
|
||||
} else {
|
||||
m_outer_identity_custom->SetValue(true);
|
||||
m_outer_identity_custom_val->Enable(true);
|
||||
m_outer_identity_custom_val->SetValue(m_cfg.m_anonymous_identity);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTTLSConfigPanel::TransferDataFromWindow()
|
||||
{
|
||||
if (m_outer_identity_same->GetValue())
|
||||
m_cfg.m_anonymous_identity.clear();
|
||||
else if (m_outer_identity_empty->GetValue())
|
||||
m_cfg.m_anonymous_identity = L"@";
|
||||
else
|
||||
m_cfg.m_anonymous_identity = m_outer_identity_custom_val->GetValue();
|
||||
|
||||
return wxEAPTTLSConfigPanelBase::TransferDataFromWindow();
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTTLSConfigPanel::OnOuterIdentityCustom(wxCommandEvent& event)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(event);
|
||||
|
||||
m_outer_identity_custom_val->Enable(m_outer_identity_custom->GetValue());
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// wxEAPTTLSConfig
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
wxEAPTTLSConfig::wxEAPTTLSConfig(eap::config_ttls &cfg, LPCTSTR pszCredTarget, wxWindow* parent) :
|
||||
m_cfg(cfg),
|
||||
m_cfg_pap(cfg.m_module),
|
||||
wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxVSCROLL)
|
||||
{
|
||||
wxBoxSizer* sb_content;
|
||||
sb_content = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
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_identity = new wxEAPTTLSConfigPanel(m_cfg, this);
|
||||
sb_content->Add(m_outer_identity, 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
m_tls = new wxEAPTLSConfigPanel(m_cfg, pszCredTarget, this);
|
||||
sb_content->Add(m_tls, 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
sb_content->Add(20, 20, 1, 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);
|
||||
|
||||
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(m_cfg_pap, pszCredTarget, m_inner_type), _("PAP"));
|
||||
sb_content->Add(m_inner_type, 0, wxALL|wxEXPAND, 5);
|
||||
|
||||
wxSize size = sb_content->CalcMin();
|
||||
if (size.y > 500) {
|
||||
// Increase the width to allow space for vertical scroll bar (to prevent horizontal one) and truncate the height.
|
||||
size.x += wxSystemSettings::GetMetric(wxSYS_VSCROLL_X, this);
|
||||
size.y = 500;
|
||||
}
|
||||
this->SetMinSize(size);
|
||||
this->SetScrollRate(5, 5);
|
||||
|
||||
this->SetSizer(sb_content);
|
||||
this->Layout();
|
||||
|
||||
m_outer_identity->SetFocusFromKbd();
|
||||
|
||||
// Connect Events
|
||||
this->Connect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTTLSConfig::OnInitDialog));
|
||||
}
|
||||
|
||||
|
||||
wxEAPTTLSConfig::~wxEAPTTLSConfig()
|
||||
{
|
||||
// Disconnect Events
|
||||
this->Disconnect(wxEVT_INIT_DIALOG, wxInitDialogEventHandler(wxEAPTTLSConfig::OnInitDialog));
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTTLSConfig::TransferDataToWindow()
|
||||
{
|
||||
eap::config_pap *cfg_pap = dynamic_cast<eap::config_pap*>(m_cfg.m_inner);
|
||||
if (cfg_pap) {
|
||||
m_cfg_pap = *cfg_pap;
|
||||
m_inner_type->SetSelection(0); // 0=PAP
|
||||
} else
|
||||
wxFAIL_MSG(wxT("Unsupported inner authentication method type."));
|
||||
|
||||
return wxScrolledWindow::TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
||||
bool wxEAPTTLSConfig::TransferDataFromWindow()
|
||||
{
|
||||
wxCHECK(wxScrolledWindow::TransferDataFromWindow(), false);
|
||||
|
||||
switch (m_inner_type->GetSelection()) {
|
||||
case 0: // 0=PAP
|
||||
delete m_cfg.m_inner;
|
||||
m_cfg.m_inner = new eap::config_pap(m_cfg_pap);
|
||||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG(wxT("Unsupported inner authentication method type."));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void wxEAPTTLSConfig::OnInitDialog(wxInitDialogEvent& event)
|
||||
{
|
||||
// Forward the event to child panels.
|
||||
m_outer_identity->GetEventHandler()->ProcessEvent(event);
|
||||
m_tls->GetEventHandler()->ProcessEvent(event);
|
||||
for (wxWindowList::compatibility_iterator inner = m_inner_type->GetChildren().GetFirst(); inner; inner = inner->GetNext())
|
||||
inner->GetData()->GetEventHandler()->ProcessEvent(event);
|
||||
}
|
Reference in New Issue
Block a user