Explicit checks on server certificate chain added:
- Certificate can not be self-signed: Cannot check trust against configured root CAs when server certificate is self-signed - Server can provide full certificate chain up-to and including root CA. Importing root CA to the store for certificate chain validation would implicitly trust this certificate chain. Thus, we skip all self-signed certificates on import.
This commit is contained in:
parent
078636eb14
commit
a02d1e7094
@ -1111,17 +1111,16 @@ void eap::method_tls::verify_server_trust() const
|
|||||||
assert(!m_server_cert_chain.empty());
|
assert(!m_server_cert_chain.empty());
|
||||||
const cert_context &cert = m_server_cert_chain.front();
|
const cert_context &cert = m_server_cert_chain.front();
|
||||||
|
|
||||||
|
string subj;
|
||||||
|
if (!CertGetNameStringA(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, subj))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error retrieving server's certificate subject name.");
|
||||||
|
|
||||||
const config_provider &cfg_prov(m_cfg.m_providers.front());
|
const config_provider &cfg_prov(m_cfg.m_providers.front());
|
||||||
const config_method_tls *cfg_method = dynamic_cast<const config_method_tls*>(cfg_prov.m_methods.front().get());
|
const config_method_tls *cfg_method = dynamic_cast<const config_method_tls*>(cfg_prov.m_methods.front().get());
|
||||||
assert(cfg_method);
|
assert(cfg_method);
|
||||||
|
|
||||||
if (!cfg_method->m_server_names.empty()) {
|
if (!cfg_method->m_server_names.empty()) {
|
||||||
// Check server name.
|
// Check server name.
|
||||||
|
|
||||||
string subj;
|
|
||||||
if (!CertGetNameStringA(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, subj))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error retrieving server's certificate subject name.");
|
|
||||||
|
|
||||||
for (list<string>::const_iterator s = cfg_method->m_server_names.cbegin(), s_end = cfg_method->m_server_names.cend();; ++s) {
|
for (list<string>::const_iterator s = cfg_method->m_server_names.cbegin(), s_end = cfg_method->m_server_names.cend();; ++s) {
|
||||||
if (s != s_end) {
|
if (s != s_end) {
|
||||||
const char
|
const char
|
||||||
@ -1142,6 +1141,10 @@ void eap::method_tls::verify_server_trust() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cert->pCertInfo->Issuer.cbData == cert->pCertInfo->Subject.cbData &&
|
||||||
|
memcmp(cert->pCertInfo->Issuer.pbData, cert->pCertInfo->Subject.pbData, cert->pCertInfo->Issuer.cbData) == 0)
|
||||||
|
throw com_runtime_error(CRYPT_E_SELF_SIGNED, string_printf(__FUNCTION__ " Server is using a self-signed certificate %s. Cannot trust it.", subj.c_str()).c_str());
|
||||||
|
|
||||||
// Create temporary certificate store of our trusted root CAs.
|
// Create temporary certificate store of our trusted root CAs.
|
||||||
cert_store store;
|
cert_store store;
|
||||||
if (!store.create(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, NULL))
|
if (!store.create(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, NULL))
|
||||||
@ -1150,8 +1153,17 @@ void eap::method_tls::verify_server_trust() const
|
|||||||
CertAddCertificateContextToStore(store, *c, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
CertAddCertificateContextToStore(store, *c, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
||||||
|
|
||||||
// Add all certificates from the server's certificate chain, except the first one.
|
// Add all certificates from the server's certificate chain, except the first one.
|
||||||
for (list<cert_context>::const_iterator c = m_server_cert_chain.cbegin(), c_end = m_server_cert_chain.cend(); ++c != c_end;)
|
for (list<cert_context>::const_iterator c = m_server_cert_chain.cbegin(), c_end = m_server_cert_chain.cend(); ++c != c_end;) {
|
||||||
|
const cert_context &_c = *c;
|
||||||
|
if (_c->pCertInfo->Issuer.cbData == _c->pCertInfo->Subject.cbData &&
|
||||||
|
memcmp(_c->pCertInfo->Issuer.pbData, _c->pCertInfo->Subject.pbData, _c->pCertInfo->Issuer.cbData) == 0)
|
||||||
|
{
|
||||||
|
// Skip the root CA certificates (self-signed). We define in whom we trust!
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
CertAddCertificateContextToStore(store, *c, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
CertAddCertificateContextToStore(store, *c, CERT_STORE_ADD_REPLACE_EXISTING, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the certificate chain validation, and check.
|
// Prepare the certificate chain validation, and check.
|
||||||
CERT_CHAIN_PARA chain_params = {
|
CERT_CHAIN_PARA chain_params = {
|
||||||
@ -1171,7 +1183,7 @@ void eap::method_tls::verify_server_trust() const
|
|||||||
};
|
};
|
||||||
cert_chain_context context;
|
cert_chain_context context;
|
||||||
if (!context.create(NULL, cert, NULL, store, &chain_params, 0))
|
if (!context.create(NULL, cert, NULL, store, &chain_params, 0))
|
||||||
throw win_runtime_error(ERROR_INVALID_DOMAINNAME, __FUNCTION__ " Error creating certificate chain context.");
|
throw win_runtime_error(__FUNCTION__ " Error creating certificate chain context.");
|
||||||
|
|
||||||
// Check chain validation error flags. Ignore CERT_TRUST_IS_UNTRUSTED_ROOT flag when we check root CA explicitly.
|
// Check chain validation error flags. Ignore CERT_TRUST_IS_UNTRUSTED_ROOT flag when we check root CA explicitly.
|
||||||
if (context->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR &&
|
if (context->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user