(Pre-shared) client certificates are no longer maintained by hash only
This commit is contained in:
parent
cda81dd696
commit
d430b63829
@ -59,6 +59,9 @@ namespace eapserial
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../EAPBase/include/Credentials.h"
|
#include "../../EAPBase/include/Credentials.h"
|
||||||
|
#include "../../EAPBase/include/EAPSerial.h"
|
||||||
|
|
||||||
|
#include <WinStd/Crypt.h>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -190,7 +193,7 @@ namespace eap
|
|||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<unsigned char> m_cert_hash; ///< Client certificate hash (certificates are kept in Personal Certificate Storage)
|
winstd::cert_context m_cert; ///< Client certificate
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,22 +202,30 @@ namespace eapserial
|
|||||||
{
|
{
|
||||||
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_tls &val)
|
inline void pack(_Inout_ unsigned char *&cursor, _In_ const eap::credentials_tls &val)
|
||||||
{
|
{
|
||||||
pack(cursor, (const eap::credentials&)val);
|
// Don't save m_identity. We rebuild it on every load.
|
||||||
pack(cursor, val.m_cert_hash );
|
//pack(cursor, (const eap::credentials&)val);
|
||||||
|
pack(cursor, val.m_cert );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline size_t get_pk_size(const eap::credentials_tls &val)
|
inline size_t get_pk_size(const eap::credentials_tls &val)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
get_pk_size((const eap::credentials&)val) +
|
// Don't save m_identity. We rebuild it on every load.
|
||||||
get_pk_size(val.m_cert_hash );
|
//get_pk_size((const eap::credentials&)val) +
|
||||||
|
get_pk_size(val.m_cert );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_tls &val)
|
inline void unpack(_Inout_ const unsigned char *&cursor, _Out_ eap::credentials_tls &val)
|
||||||
{
|
{
|
||||||
unpack(cursor, (eap::credentials&)val);
|
// Don't load m_identity. We rebuild it on load.
|
||||||
unpack(cursor, val.m_cert_hash );
|
//unpack(cursor, (eap::credentials&)val);
|
||||||
|
unpack(cursor, val.m_cert );
|
||||||
|
|
||||||
|
if (val.m_cert) {
|
||||||
|
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
|
||||||
|
CertGetNameString(val.m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, val.m_identity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,13 +156,23 @@ bool eap::config_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR **ppEa
|
|||||||
com_obj<IXMLDOMNode> pXmlElCA;
|
com_obj<IXMLDOMNode> pXmlElCA;
|
||||||
pXmlListCAs->get_item(j, &pXmlElCA);
|
pXmlListCAs->get_item(j, &pXmlElCA);
|
||||||
bstr bstrFormat;
|
bstr bstrFormat;
|
||||||
if (eapxml::get_element_value(pXmlElCA, bstr(L"eap-metadata:format"), &bstrFormat) == ERROR_SUCCESS) {
|
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) {
|
// <format> not specified.
|
||||||
vector<unsigned char> aData;
|
continue;
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrFormat, bstrFormat.length(), L"PEM", -1, NULL, NULL, 0) != CSTR_EQUAL) {
|
||||||
|
// Certificate must be PEM encoded.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<unsigned char> aData;
|
||||||
|
if (eapxml::get_element_base64(pXmlElCA, bstr(L"eap-metadata:cert-data"), aData) != ERROR_SUCCESS) {
|
||||||
|
// Error reading <cert-data> element.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_trusted_ca(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, aData.data(), (DWORD)aData.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +34,14 @@ eap::credentials_tls::credentials_tls(_In_ module &mod) : credentials(mod)
|
|||||||
|
|
||||||
|
|
||||||
eap::credentials_tls::credentials_tls(_In_ const credentials_tls &other) :
|
eap::credentials_tls::credentials_tls(_In_ const credentials_tls &other) :
|
||||||
m_cert_hash(other.m_cert_hash),
|
m_cert(other.m_cert),
|
||||||
credentials(other)
|
credentials(other)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eap::credentials_tls::credentials_tls(_Inout_ credentials_tls &&other) :
|
eap::credentials_tls::credentials_tls(_Inout_ credentials_tls &&other) :
|
||||||
m_cert_hash(std::move(other.m_cert_hash)),
|
m_cert(std::move(other.m_cert)),
|
||||||
credentials(std::move(other))
|
credentials(std::move(other))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ eap::credentials_tls& eap::credentials_tls::operator=(_In_ const credentials_tls
|
|||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
(credentials&)*this = other;
|
(credentials&)*this = other;
|
||||||
m_cert_hash = other.m_cert_hash;
|
m_cert = other.m_cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -62,7 +62,7 @@ eap::credentials_tls& eap::credentials_tls::operator=(_Inout_ credentials_tls &&
|
|||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
(credentials&)*this = std::move(other);
|
(credentials&)*this = std::move(other);
|
||||||
m_cert_hash = std::move(other.m_cert_hash);
|
m_cert = std::move(other.m_cert);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -78,13 +78,13 @@ eap::config* eap::credentials_tls::clone() const
|
|||||||
void eap::credentials_tls::clear()
|
void eap::credentials_tls::clear()
|
||||||
{
|
{
|
||||||
credentials::clear();
|
credentials::clear();
|
||||||
m_cert_hash.clear();
|
m_cert.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool eap::credentials_tls::empty() const
|
bool eap::credentials_tls::empty() const
|
||||||
{
|
{
|
||||||
return credentials::empty() && m_cert_hash.empty();
|
return credentials::empty() && !m_cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -92,13 +92,35 @@ bool eap::credentials_tls::save(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pC
|
|||||||
{
|
{
|
||||||
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
|
const bstr bstrNamespace(L"urn:ietf:params:xml:ns:yang:ietf-eap-metadata");
|
||||||
DWORD dwResult;
|
DWORD dwResult;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
if (!credentials::save(pDoc, pConfigRoot, ppEapError))
|
// Don't save m_identity. We rebuild it on every load.
|
||||||
|
//if (!credentials::save(pDoc, pConfigRoot, ppEapError))
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
// <ClientCertificate>
|
||||||
|
com_obj<IXMLDOMElement> pXmlElClientCertificate;
|
||||||
|
if ((dwResult = eapxml::create_element(pDoc, bstr(L"ClientCertificate"), bstrNamespace, &pXmlElClientCertificate))) {
|
||||||
|
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <ClientCertificate> element."), NULL);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// <CertHash>
|
if (m_cert) {
|
||||||
if ((dwResult = eapxml::put_element_hex(pDoc, pConfigRoot, bstr(L"CertHash"), bstrNamespace, m_cert_hash.data(), m_cert_hash.size())) != ERROR_SUCCESS) {
|
// <ClientCertificate>/<format>
|
||||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <CertHash> element."), NULL);
|
if ((dwResult = eapxml::put_element_value(pDoc, pXmlElClientCertificate, 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 false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// <ClientCertificate>/<cert-data>
|
||||||
|
if ((dwResult = eapxml::put_element_base64(pDoc, pXmlElClientCertificate, bstr(L"cert-data"), bstrNamespace, m_cert->pbCertEncoded, m_cert->cbCertEncoded)) != ERROR_SUCCESS) {
|
||||||
|
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <cert-data> element."), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr = pConfigRoot->appendChild(pXmlElClientCertificate, NULL))) {
|
||||||
|
*ppEapError = m_module.make_error(HRESULT_CODE(hr), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error appending <ClientCertificate> element."), NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,15 +133,35 @@ bool eap::credentials_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR *
|
|||||||
assert(pConfigRoot);
|
assert(pConfigRoot);
|
||||||
DWORD dwResult;
|
DWORD dwResult;
|
||||||
|
|
||||||
if (!credentials::load(pConfigRoot, ppEapError))
|
// Don't load m_identity. We rebuild it on load.
|
||||||
return false;
|
//if (!credentials::load(pConfigRoot, ppEapError))
|
||||||
|
// return false;
|
||||||
|
|
||||||
// <CertHash>
|
m_identity.clear();
|
||||||
if ((dwResult = eapxml::get_element_hex(pConfigRoot, bstr(L"eap-metadata:CertHash"), m_cert_hash)) != ERROR_SUCCESS) {
|
m_cert.free();
|
||||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error reading <CertHash> element."), NULL);
|
|
||||||
|
// <ClientCertificate>
|
||||||
|
com_obj<IXMLDOMElement> pXmlElClientCertificate;
|
||||||
|
if ((dwResult = eapxml::select_element(pConfigRoot, bstr(L"eap-metadata:ClientCertificate"), &pXmlElClientCertificate)) != ERROR_SUCCESS) {
|
||||||
|
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error reading <ClientCertificate> element."), NULL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// <ClientCertificate>/<format>
|
||||||
|
bstr bstrFormat;
|
||||||
|
if ((dwResult = eapxml::get_element_value(pXmlElClientCertificate, 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) {
|
||||||
|
// <ClientCertificate>/<cert-data>
|
||||||
|
vector<unsigned char> aData;
|
||||||
|
if ((dwResult = eapxml::get_element_base64(pXmlElClientCertificate, bstr(L"eap-metadata:cert-data"), aData)) == ERROR_SUCCESS) {
|
||||||
|
if (m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, aData.data(), (DWORD)aData.size())) {
|
||||||
|
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
|
||||||
|
CertGetNameString(m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, m_identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,11 +170,36 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
|
|||||||
{
|
{
|
||||||
assert(pszTargetName);
|
assert(pszTargetName);
|
||||||
assert(ppEapError);
|
assert(ppEapError);
|
||||||
|
string cert_enc;
|
||||||
|
|
||||||
|
// Prepare cryptographics provider.
|
||||||
|
crypt_prov cp;
|
||||||
|
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypt certificate.
|
||||||
|
vector<unsigned char> cert;
|
||||||
|
if (!m_module.encrypt_md5(cp, m_cert->pbCertEncoded, m_cert->cbCertEncoded, cert, ppEapError))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Convert encrypted certificate to Base64, since CredProtectA() fail for binary strings.
|
||||||
|
string cert_base64;
|
||||||
|
base64_enc enc;
|
||||||
|
enc.encode(cert_base64, cert.data(), cert.size());
|
||||||
|
|
||||||
|
// Encrypt the certificate using user's key.
|
||||||
|
CRED_PROTECTION_TYPE cpt;
|
||||||
|
if (!CredProtectA(TRUE, cert_base64.c_str(), (DWORD)cert_base64.length(), cert_enc, &cpt)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredProtect failed."), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
tstring target(target_name(pszTargetName));
|
tstring target(target_name(pszTargetName));
|
||||||
|
|
||||||
// Write credentials.
|
// Write credentials.
|
||||||
assert(m_cert_hash.size() < CRED_MAX_CREDENTIAL_BLOB_SIZE);
|
assert(cert_enc.size() < CRED_MAX_CREDENTIAL_BLOB_SIZE);
|
||||||
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
|
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
|
||||||
CREDENTIAL cred = {
|
CREDENTIAL cred = {
|
||||||
0, // Flags
|
0, // Flags
|
||||||
@ -140,8 +207,8 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
|
|||||||
(LPTSTR)target.c_str(), // TargetName
|
(LPTSTR)target.c_str(), // TargetName
|
||||||
_T(""), // Comment
|
_T(""), // Comment
|
||||||
{ 0, 0 }, // LastWritten
|
{ 0, 0 }, // LastWritten
|
||||||
(DWORD)m_cert_hash.size(), // CredentialBlobSize
|
(DWORD)cert_enc.size(), // CredentialBlobSize
|
||||||
(LPBYTE)m_cert_hash.data(), // CredentialBlob
|
(LPBYTE)cert_enc.data(), // CredentialBlob
|
||||||
CRED_PERSIST_ENTERPRISE, // Persist
|
CRED_PERSIST_ENTERPRISE, // Persist
|
||||||
0, // AttributeCount
|
0, // AttributeCount
|
||||||
NULL, // Attributes
|
NULL, // Attributes
|
||||||
@ -159,7 +226,7 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
|
|||||||
|
|
||||||
bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
|
bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **ppEapError)
|
||||||
{
|
{
|
||||||
assert(pszTargetName && _tcslen(pszTargetName) < CRED_MAX_GENERIC_TARGET_NAME_LENGTH);
|
assert(pszTargetName);
|
||||||
|
|
||||||
// Read credentials.
|
// Read credentials.
|
||||||
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
|
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
|
||||||
@ -168,12 +235,38 @@ bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cred->UserName)
|
// Decrypt the certificate using user's key.
|
||||||
m_identity = cred->UserName;
|
string cert_base64;
|
||||||
else
|
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize, cert_base64)) {
|
||||||
m_identity.clear();
|
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredUnprotect failed."), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_cert_hash.assign(cred->CredentialBlob, cred->CredentialBlob + cred->CredentialBlobSize);
|
// Convert Base64 to binary encrypted certificate, since CredProtectA() fail for binary strings.
|
||||||
|
vector<unsigned char> cert;
|
||||||
|
base64_dec dec;
|
||||||
|
bool is_last;
|
||||||
|
dec.decode(cert, is_last, cert_base64.c_str(), cert_base64.length());
|
||||||
|
|
||||||
|
// Prepare cryptographics provider.
|
||||||
|
crypt_prov cp;
|
||||||
|
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptAcquireContext failed."), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt certificate.
|
||||||
|
vector<unsigned char, sanitizing_allocator<unsigned char> > _cert;
|
||||||
|
if (!m_module.decrypt_md5(cp, cert.data(), cert.size(), _cert, ppEapError))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _cert.data(), (DWORD)_cert.size())) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error loading certificate."), NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
|
||||||
|
CertGetNameString(m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, m_identity);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,6 @@
|
|||||||
///
|
///
|
||||||
class wxCertificateClientData;
|
class wxCertificateClientData;
|
||||||
|
|
||||||
///
|
|
||||||
/// Helper class for auto-destroyable certificates used in wxWidget's item containers
|
|
||||||
///
|
|
||||||
class wxCertificateSelectionClientData;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Validator for host name
|
/// Validator for host name
|
||||||
///
|
///
|
||||||
@ -116,45 +111,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class wxCertificateSelectionClientData : public wxClientData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
/// Default constructor
|
|
||||||
///
|
|
||||||
wxCertificateSelectionClientData();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs client data object
|
|
||||||
///
|
|
||||||
wxCertificateSelectionClientData(const wchar_t *identity, unsigned char *hash, size_t hash_size);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs client data object with copy
|
|
||||||
///
|
|
||||||
wxCertificateSelectionClientData(const std::wstring &identity, const std::vector<unsigned char> &hash);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs client data object with move
|
|
||||||
///
|
|
||||||
wxCertificateSelectionClientData(std::wstring &&identity, std::vector<unsigned char> &&hash);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs client data object with copy
|
|
||||||
///
|
|
||||||
wxCertificateSelectionClientData(const wxCertificateSelectionClientData &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs client data object with move
|
|
||||||
///
|
|
||||||
wxCertificateSelectionClientData(wxCertificateSelectionClientData &&other);
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::wstring m_identity; ///< Client identity
|
|
||||||
std::vector<unsigned char> m_hash; ///< Client certificate hash (certificates are kept in Personal Certificate Storage)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class wxHostNameValidator : public wxValidator
|
class wxHostNameValidator : public wxValidator
|
||||||
{
|
{
|
||||||
wxDECLARE_DYNAMIC_CLASS(wxHostNameValidator);
|
wxDECLARE_DYNAMIC_CLASS(wxHostNameValidator);
|
||||||
|
@ -76,50 +76,6 @@ wxCertificateClientData::~wxCertificateClientData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// 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
|
// wxHostNameValidator
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -417,13 +373,16 @@ bool wxEAPTLSCredentialsPanel::TransferDataToWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prepare certificate information.
|
// Prepare certificate information.
|
||||||
std::unique_ptr<wxCertificateSelectionClientData> data(new wxCertificateSelectionClientData);
|
std::unique_ptr<wxCertificateClientData> data(new wxCertificateClientData(CertDuplicateCertificateContext(cert)));
|
||||||
eap::get_cert_title(cert, data->m_identity);
|
|
||||||
|
|
||||||
// Add to list.
|
// Add to list.
|
||||||
CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID, data->m_hash);
|
bool is_selected =
|
||||||
bool is_selected = data->m_hash == m_cred.m_cert_hash;
|
m_cred.m_cert &&
|
||||||
int i = m_cert_select_val->Append(data->m_identity, data.release());
|
m_cred.m_cert->cbCertEncoded == data->m_cert->cbCertEncoded &&
|
||||||
|
memcmp(m_cred.m_cert->pbCertEncoded, data->m_cert->pbCertEncoded, m_cred.m_cert->cbCertEncoded) == 0;
|
||||||
|
winstd::tstring name;
|
||||||
|
eap::get_cert_title(cert, name);
|
||||||
|
int i = m_cert_select_val->Append(name, data.release());
|
||||||
if (is_selected) {
|
if (is_selected) {
|
||||||
m_cert_select_val->SetSelection(i);
|
m_cert_select_val->SetSelection(i);
|
||||||
is_found = true;
|
is_found = true;
|
||||||
@ -450,10 +409,12 @@ bool wxEAPTLSCredentialsPanel::TransferDataFromWindow()
|
|||||||
if (m_cert_none->GetValue())
|
if (m_cert_none->GetValue())
|
||||||
m_cred.clear();
|
m_cred.clear();
|
||||||
else {
|
else {
|
||||||
const wxCertificateSelectionClientData *data = dynamic_cast<const wxCertificateSelectionClientData*>(m_cert_select_val->GetClientObject(m_cert_select_val->GetSelection()));
|
const wxCertificateClientData *data = dynamic_cast<const wxCertificateClientData*>(m_cert_select_val->GetClientObject(m_cert_select_val->GetSelection()));
|
||||||
if (data) {
|
if (data) {
|
||||||
m_cred.m_identity = data->m_identity;
|
m_cred.m_cert.attach_duplicated(data->m_cert);
|
||||||
m_cred.m_cert_hash = data->m_hash;
|
|
||||||
|
// Generate identity. TODO: Find which CERT_NAME_... constant returns valid identity (username@domain or DOMAIN\Username).
|
||||||
|
CertGetNameString(m_cred.m_cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, m_cred.m_identity);
|
||||||
} else
|
} else
|
||||||
m_cred.clear();
|
m_cred.clear();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user