in host/cxpslib/cxpssslcontext.h [386:562]
inline int opensslVerifyClientCertCallback(int preverifyOk, X509_STORE_CTX* ctx)
{
#ifdef CXPS_x64
USES_CONVERSION;
HCERTSTORE hStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
X509* cert = X509_STORE_CTX_get_current_cert(ctx);
if (0 == cert) {
CXPS_LOG_ERROR(AT_LOC<<"cert verfication failed as current cert not present");
return preverifyOk;
}
SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx,
SSL_get_ex_data_X509_STORE_CTX_idx()));
if (0 == ssl)
{
CXPS_LOG_ERROR(AT_LOC<<"ssl details fetch failed");
return preverifyOk;
}
SSL_CTX* sslCtx = ::SSL_get_SSL_CTX(ssl);
if (0 == sslCtx)
{
CXPS_LOG_ERROR(AT_LOC<<"ssl context from ssl failed");
return preverifyOk;
}
if (!SSL_CTX_get_ex_data(sslCtx, 1))
{
CXPS_LOG_ERROR(AT_LOC<<"ssl ex_data fetch failed");
return preverifyOk;
}
std::string fingerprint = g_fingerprintMgr.getFingerprint(cert);
char subject_name[256];
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
CXPS_LOG_MONITOR(MONITOR_LOG_LEVEL_2, AT_LOC<<
"client cert name=" << subject_name << ", fingerprint=" << fingerprint);
if (X509_cmp_time(X509_get_notAfter(cert), 0) <= 0)
{
CXPS_LOG_ERROR(AT_LOC<<"Cert is expired, Not After Date="
<< X509_get_notAfter(cert)
<<", Not Before Date="<< X509_get_notBefore(cert));
return preverifyOk;
}
std::string certSubjectName = std::string(subject_name);
if (!(certSubjectName.find("CN=") == std::string::npos || certSubjectName.find("cn=") == std::string::npos))
{
CXPS_LOG_ERROR(AT_LOC<<"subject name does not contain CN=, cert subject name="<<certSubjectName);
return preverifyOk;
}
std::string certificateBiosId;
size_t biosIdIndex = certSubjectName.find_first_of("=");
if (std::string::npos != biosIdIndex) {
certificateBiosId = certSubjectName.substr(biosIdIndex + 1);
}
boost::regex guidRegex(GUID_REGEX);
if (!boost::regex_match(certificateBiosId, guidRegex))
{
CXPS_LOG_ERROR(AT_LOC<<"guid not found in subject name="<<certSubjectName);
return preverifyOk;
}
CxpsSslContext* cxpsctx = static_cast<CxpsSslContext*>(SSL_CTX_get_ex_data(sslCtx, 1));
CXPS_LOG_MONITOR(MONITOR_LOG_LEVEL_3, AT_LOC<<"opening the LocalMachine\\My cert store");
if (!(hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
USER_CERT_STORE)))
{
CXPS_LOG_ERROR(AT_LOC<<" LocalMachine\\My cert store opening failed");
return preverifyOk;
}
CXPS_LOG_MONITOR(MONITOR_LOG_LEVEL_3, AT_LOC<<"searching the thumbprint in the store.");
#ifdef _DEBUG
ON_BLOCK_EXIT(boost::bind(&cxpsCertCloseStore, hStore));
#else
ON_BLOCK_EXIT(boost::bind<void>(&CertCloseStore, hStore, 0));
#endif
std::string cacertThumbprint;
size_t cnt = cxpsctx->getCaCertThumbprint().length() / 2;
for (size_t i = 0; cnt > i; ++i)
{
uint32_t s = 0;
std::stringstream ss;
ss << std::hex << cxpsctx->getCaCertThumbprint().substr(i * 2, 2);
ss >> s;
cacertThumbprint.push_back(static_cast<unsigned char>(s));
}
CRYPT_HASH_BLOB hashBlob;
hashBlob.cbData = cacertThumbprint.length();
hashBlob.pbData = (BYTE *)cacertThumbprint.c_str();
// check the thumbprint in the certificate.
if (!(pCertContext = CertFindCertificateInStore(hStore,
(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING),
0,
CERT_FIND_SHA1_HASH,
&hashBlob,
NULL)))
{
CXPS_LOG_ERROR(AT_LOC<<"No certificate with ca thumbprint in local store :"
<< cxpsctx->getCaCertThumbprint()<<"\t");
return preverifyOk;
}
ON_BLOCK_EXIT(boost::bind<void>(&CertFreeCertificateContext, pCertContext));
CXPS_LOG_MONITOR(MONITOR_LOG_LEVEL_3, AT_LOC<<"Making the certificate chain");
X509_STORE *store = X509_STORE_new();
if (store == NULL)
{
CXPS_LOG_ERROR(AT_LOC<<"creation of cert store to check certificate validation failed");
return preverifyOk;
}
ON_BLOCK_EXIT(boost::bind(&X509_STORE_free, store));
X509 *matchingCert = d2i_X509(NULL,
(const unsigned char **)&pCertContext->pbCertEncoded,
pCertContext->cbCertEncoded);
if (matchingCert == NULL) {
CXPS_LOG_ERROR(AT_LOC<<"Cert in local store with same thumbprint's conversion to X509 Failed");
return preverifyOk;
}
ON_BLOCK_EXIT(boost::bind(&X509_free, matchingCert));
if (!X509_STORE_add_cert(store, matchingCert)) {
CXPS_LOG_ERROR(AT_LOC<<"Local Cert addition in Store Failed");
return preverifyOk;
}
X509_STORE_CTX * storectx= X509_STORE_CTX_new();
if (storectx == NULL)
{
CXPS_LOG_ERROR(AT_LOC<<"creation of cert store context to check certificate validation failed");
return preverifyOk;
}
ON_BLOCK_EXIT(boost::bind(&X509_STORE_CTX_free, storectx));
X509_STORE_set_verify_cb(store, verify_cb);
if (X509_STORE_CTX_init(storectx, store, cert, NULL) == 0)
{
CXPS_LOG_ERROR(AT_LOC << "Context Setup for Verification Failed");
return preverifyOk;
}
if (X509_verify_cert(storectx) <= 0)
{
CXPS_LOG_ERROR(AT_LOC<<"Verification of Cert Chain Failed");
return preverifyOk;
}
preverifyOk = 1;
X509_STORE_CTX_set_error(ctx, X509_V_OK);
cxpsctx->setCertBiosId(certificateBiosId);
CXPS_LOG_MONITOR(MONITOR_LOG_LEVEL_1, AT_LOC<<"client cert verification successful");
#endif
return preverifyOk;
}