Merge pull request #257 from jacadcaps/defaultCertificateVerifier

Improved certificate verification.
This commit is contained in:
Vincent Richard 2021-03-24 20:52:05 +01:00 committed by GitHub
commit 7d64105dee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 118 additions and 0 deletions

View File

@ -115,6 +115,12 @@ void OpenSSLInitializer::initialize() {
OPENSSL_config(NULL);
#endif
#if OPENSSL_VERSION_NUMBER >=0x10100000L
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS | OPENSSL_INIT_ADD_ALL_DIGESTS |
OPENSSL_INIT_LOAD_CONFIG | OPENSSL_INIT_ENGINE_OPENSSL | OPENSSL_INIT_ENGINE_ALL_BUILTIN , NULL);
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_load_error_strings();
SSL_library_init();

View File

@ -75,6 +75,69 @@ void defaultCertificateVerifier::verify(
}
void defaultCertificateVerifier::verifyX509chain
(shared_ptr <certificateChain> chain, size_t chainLen)
{
// For every certificate in the chain, verify that the certificate
// has been issued by the next certificate in the chain
if (chainLen >= 2) {
for (size_t i = 0 ; i < chainLen - 1 ; ++i) {
shared_ptr <X509Certificate> cert = dynamicCast <X509Certificate>(chain->getAt(i));
shared_ptr <X509Certificate> next = dynamicCast <X509Certificate>(chain->getAt(i + 1));
if (!cert->checkIssuer(next)) {
certificateIssuerVerificationException ex;
ex.setCertificate(cert);
throw ex;
}
}
}
// For every certificate in the chain, verify that the certificate
// is valid at the current time
for (size_t i = 0 ; i < chainLen ; ++i) {
shared_ptr <X509Certificate> cert = dynamicCast <X509Certificate>(chain->getAt(i));
cert->checkValidity();
}
// Check whether the certificate can be trusted
// -- First, verify that the the last certificate in the chain was
// -- issued by a third-party that we trust
shared_ptr <X509Certificate> lastCert = dynamicCast <X509Certificate>(chain->getAt(chainLen - 1));
bool trusted = false;
for (size_t i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) {
shared_ptr <X509Certificate> rootCa = m_x509RootCAs[i];
if (lastCert->verify(rootCa)) {
trusted = true;
}
}
// -- Next, if the issuer certificate cannot be verified against
// -- root CAs, compare the subject's certificate against the
// -- trusted certificates
shared_ptr <X509Certificate> firstCert = dynamicCast <X509Certificate>(chain->getAt(0));
for (size_t i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) {
shared_ptr <X509Certificate> cert = m_x509TrustedCerts[i];
if (firstCert->equals(cert)) {
trusted = true;
}
}
if (!trusted) {
certificateNotTrustedException ex;
ex.setCertificate(firstCert);
throw ex;
}
}
void defaultCertificateVerifier::verifyX509(
const shared_ptr <certificateChain>& chain,
const string& hostname
@ -161,6 +224,44 @@ void defaultCertificateVerifier::verifyX509(
throw ex;
}
// Perform verification on all possible subchains in order to work
// around a server that sends extranous certificates in the chain
// after the valid one.
//
// Note: The TLS 1.3 draft says the following:
//
// Note: Prior to TLS 1.3, "certificate_list" ordering required each
// certificate to certify the one immediately preceding it; however,
// some implementations allowed some flexibility. Servers sometimes
// send both a current and deprecated intermediate for transitional
// purposes, and others are simply configured incorrectly, but these
// cases can nonetheless be validated properly. For maximum
// compatibility, all implementations SHOULD be prepared to handle
// potentially extraneous certificates and arbitrary orderings from any
// TLS version, with the exception of the end-entity certificate which
// MUST be first.
//
// This code does NOT yet handle arbitrary ordering.
//
for (size_t chainLen = chain->getCount(); chainLen > 0; chainLen--) {
try {
verifyX509chain(chain, chainLen);
return;
}
catch(...) {
if (chainLen == 1) {
throw;
}
}
}
// We really should never get here from the above loop
certificateNotTrustedException ex;
ex.setCertificate(firstCert);
throw ex;
}

View File

@ -73,6 +73,13 @@ public:
private:
/** Verify a chain of X.509 certificates.
*
* @param chain list of X.509 certificates
* @param chainLen number of certificates to verify
*/
void verifyX509chain(shared_ptr <certificateChain> chain, size_t chainLen);
/** Verify a chain of X.509 certificates.
*
* @param chain list of X.509 certificates

View File

@ -78,6 +78,10 @@ bool builtinSASLMechanism::step(
char* output = 0;
size_t outputLen = 0;
if (nullptr == sess->m_gsaslSession) {
throw exceptions::sasl_exception("Invalid SASL session");
}
const int result = gsasl_step(
sess->m_gsaslSession,
reinterpret_cast <const char*>(challenge), challengeLen,