// // VMime library (http://www.vmime.org) // Copyright (C) 2002 Vincent Richard <vincent@vmime.org> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 3 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // Linking this library statically or dynamically with other modules is making // a combined work based on this library. Thus, the terms and conditions of // the GNU General Public License cover the whole combination. // #include "vmime/config.hpp" #if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT #include "vmime/security/cert/defaultCertificateVerifier.hpp" #include "vmime/security/cert/X509Certificate.hpp" #include "vmime/exception.hpp" namespace vmime { namespace security { namespace cert { defaultCertificateVerifier::defaultCertificateVerifier() { } defaultCertificateVerifier::~defaultCertificateVerifier() { } defaultCertificateVerifier::defaultCertificateVerifier(const defaultCertificateVerifier&) : certificateVerifier() { // Not used } void defaultCertificateVerifier::verify( const shared_ptr <certificateChain>& chain, const string& hostname ) { if (chain->getCount() == 0) { return; } const string type = chain->getAt(0)->getType(); if (type == "X.509") { verifyX509(chain, hostname); } else { throw unsupportedCertificateTypeException(type); } } void defaultCertificateVerifier::verifyX509( const shared_ptr <certificateChain>& chain, const string& hostname ) { // For every certificate in the chain, verify that the certificate // has been issued by the next certificate in the chain if (chain->getCount() >= 2) { for (size_t i = 0 ; i < chain->getCount() - 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 < chain->getCount() ; ++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(chain->getCount() - 1)); bool trusted = false; for (size_t i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) { shared_ptr <X509Certificate> rootCa = m_x509RootCAs[i]; // printf("rootCAs size is %d, i is %d\n", m_x509RootCAs.size(), i); // printf("will cal verify with %p\n", rootCa.get()); if (lastCert->verify(rootCa)) { trusted = true; } // printf("called verify"); } // -- 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; } // Ensure the first certificate's subject name matches server hostname if (!firstCert->verifyHostName(hostname)) { serverIdentityException ex; ex.setCertificate(firstCert); throw ex; } } void defaultCertificateVerifier::setX509RootCAs( const std::vector <shared_ptr <X509Certificate> >& caCerts ) { m_x509RootCAs = caCerts; } void defaultCertificateVerifier::setX509TrustedCerts( const std::vector <shared_ptr <X509Certificate> >& trustedCerts ) { m_x509TrustedCerts = trustedCerts; } } // cert } // security } // vmime #endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT