(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
|
||||
|
||||
#include "../../EAPBase/include/Credentials.h"
|
||||
#include "../../EAPBase/include/EAPSerial.h"
|
||||
|
||||
#include <WinStd/Crypt.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <vector>
|
||||
@ -190,7 +193,7 @@ namespace eap
|
||||
/// @}
|
||||
|
||||
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)
|
||||
{
|
||||
pack(cursor, (const eap::credentials&)val);
|
||||
pack(cursor, val.m_cert_hash );
|
||||
// Don't save m_identity. We rebuild it on every load.
|
||||
//pack(cursor, (const eap::credentials&)val);
|
||||
pack(cursor, val.m_cert );
|
||||
}
|
||||
|
||||
|
||||
inline size_t get_pk_size(const eap::credentials_tls &val)
|
||||
{
|
||||
return
|
||||
get_pk_size((const eap::credentials&)val) +
|
||||
get_pk_size(val.m_cert_hash );
|
||||
// Don't save m_identity. We rebuild it on every load.
|
||||
//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)
|
||||
{
|
||||
unpack(cursor, (eap::credentials&)val);
|
||||
unpack(cursor, val.m_cert_hash );
|
||||
// Don't load m_identity. We rebuild it on load.
|
||||
//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;
|
||||
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());
|
||||
}
|
||||
if (eapxml::get_element_value(pXmlElCA, bstr(L"eap-metadata:format"), &bstrFormat) != ERROR_SUCCESS) {
|
||||
// <format> not specified.
|
||||
continue;
|
||||
}
|
||||
|
||||
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) :
|
||||
m_cert_hash(other.m_cert_hash),
|
||||
m_cert(other.m_cert),
|
||||
credentials(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))
|
||||
{
|
||||
}
|
||||
@ -51,7 +51,7 @@ eap::credentials_tls& eap::credentials_tls::operator=(_In_ const credentials_tls
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials&)*this = other;
|
||||
m_cert_hash = other.m_cert_hash;
|
||||
m_cert = other.m_cert;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -62,7 +62,7 @@ eap::credentials_tls& eap::credentials_tls::operator=(_Inout_ credentials_tls &&
|
||||
{
|
||||
if (this != &other) {
|
||||
(credentials&)*this = std::move(other);
|
||||
m_cert_hash = std::move(other.m_cert_hash);
|
||||
m_cert = std::move(other.m_cert);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -78,13 +78,13 @@ eap::config* eap::credentials_tls::clone() const
|
||||
void eap::credentials_tls::clear()
|
||||
{
|
||||
credentials::clear();
|
||||
m_cert_hash.clear();
|
||||
m_cert.free();
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
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;
|
||||
}
|
||||
|
||||
// <CertHash>
|
||||
if ((dwResult = eapxml::put_element_hex(pDoc, pConfigRoot, bstr(L"CertHash"), bstrNamespace, m_cert_hash.data(), m_cert_hash.size())) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error creating <CertHash> element."), NULL);
|
||||
if (m_cert) {
|
||||
// <ClientCertificate>/<format>
|
||||
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;
|
||||
}
|
||||
|
||||
@ -111,15 +133,35 @@ bool eap::credentials_tls::load(_In_ IXMLDOMNode *pConfigRoot, _Out_ EAP_ERROR *
|
||||
assert(pConfigRoot);
|
||||
DWORD dwResult;
|
||||
|
||||
if (!credentials::load(pConfigRoot, ppEapError))
|
||||
return false;
|
||||
// Don't load m_identity. We rebuild it on load.
|
||||
//if (!credentials::load(pConfigRoot, ppEapError))
|
||||
// return false;
|
||||
|
||||
// <CertHash>
|
||||
if ((dwResult = eapxml::get_element_hex(pConfigRoot, bstr(L"eap-metadata:CertHash"), m_cert_hash)) != ERROR_SUCCESS) {
|
||||
*ppEapError = m_module.make_error(dwResult, 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" Error reading <CertHash> element."), NULL);
|
||||
m_identity.clear();
|
||||
m_cert.free();
|
||||
|
||||
// <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;
|
||||
}
|
||||
|
||||
// <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;
|
||||
}
|
||||
|
||||
@ -128,11 +170,36 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
|
||||
{
|
||||
assert(pszTargetName);
|
||||
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));
|
||||
|
||||
// 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 );
|
||||
CREDENTIAL cred = {
|
||||
0, // Flags
|
||||
@ -140,8 +207,8 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
|
||||
(LPTSTR)target.c_str(), // TargetName
|
||||
_T(""), // Comment
|
||||
{ 0, 0 }, // LastWritten
|
||||
(DWORD)m_cert_hash.size(), // CredentialBlobSize
|
||||
(LPBYTE)m_cert_hash.data(), // CredentialBlob
|
||||
(DWORD)cert_enc.size(), // CredentialBlobSize
|
||||
(LPBYTE)cert_enc.data(), // CredentialBlob
|
||||
CRED_PERSIST_ENTERPRISE, // Persist
|
||||
0, // AttributeCount
|
||||
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)
|
||||
{
|
||||
assert(pszTargetName && _tcslen(pszTargetName) < CRED_MAX_GENERIC_TARGET_NAME_LENGTH);
|
||||
assert(pszTargetName);
|
||||
|
||||
// Read credentials.
|
||||
unique_ptr<CREDENTIAL, CredFree_delete<CREDENTIAL> > cred;
|
||||
@ -168,12 +235,38 @@ bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cred->UserName)
|
||||
m_identity = cred->UserName;
|
||||
else
|
||||
m_identity.clear();
|
||||
// Decrypt the certificate using user's key.
|
||||
string cert_base64;
|
||||
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize, cert_base64)) {
|
||||
*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;
|
||||
}
|
||||
|
@ -33,11 +33,6 @@
|
||||
///
|
||||
class wxCertificateClientData;
|
||||
|
||||
///
|
||||
/// Helper class for auto-destroyable certificates used in wxWidget's item containers
|
||||
///
|
||||
class wxCertificateSelectionClientData;
|
||||
|
||||
///
|
||||
/// 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
|
||||
{
|
||||
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
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -417,13 +373,16 @@ bool wxEAPTLSCredentialsPanel::TransferDataToWindow()
|
||||
}
|
||||
|
||||
// Prepare certificate information.
|
||||
std::unique_ptr<wxCertificateSelectionClientData> data(new wxCertificateSelectionClientData);
|
||||
eap::get_cert_title(cert, data->m_identity);
|
||||
std::unique_ptr<wxCertificateClientData> data(new wxCertificateClientData(CertDuplicateCertificateContext(cert)));
|
||||
|
||||
// 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());
|
||||
bool is_selected =
|
||||
m_cred.m_cert &&
|
||||
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) {
|
||||
m_cert_select_val->SetSelection(i);
|
||||
is_found = true;
|
||||
@ -450,10 +409,12 @@ 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()));
|
||||
const wxCertificateClientData *data = dynamic_cast<const wxCertificateClientData*>(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;
|
||||
m_cred.m_cert.attach_duplicated(data->m_cert);
|
||||
|
||||
// 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
|
||||
m_cred.clear();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user