From 00e07962e79faf0b6f7c2c61f298e3da2469a4eb Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Thu, 24 Jul 2014 20:59:52 +0200 Subject: [PATCH] Certificate exception differentiation for easier error handling. --- doc/book/net.tex | 8 +- examples/example6_certificateVerifier.hpp | 4 +- src/vmime/exception.cpp | 53 ++--------- src/vmime/exception.hpp | 54 ++--------- .../net/tls/openssl/TLSSession_OpenSSL.cpp | 6 +- src/vmime/security/cert/X509Certificate.cpp | 24 +++++ src/vmime/security/cert/X509Certificate.hpp | 9 ++ .../security/cert/certificateException.cpp | 78 ++++++++++++++++ .../security/cert/certificateException.hpp | 89 +++++++++++++++++++ .../cert/certificateExpiredException.cpp | 55 ++++++++++++ .../cert/certificateExpiredException.hpp | 65 ++++++++++++++ ...certificateIssuerVerificationException.cpp | 55 ++++++++++++ ...certificateIssuerVerificationException.hpp | 65 ++++++++++++++ .../cert/certificateNotTrustedException.cpp | 55 ++++++++++++ .../cert/certificateNotTrustedException.hpp | 65 ++++++++++++++ .../cert/certificateNotYetValidException.cpp | 55 ++++++++++++ .../cert/certificateNotYetValidException.hpp | 65 ++++++++++++++ .../security/cert/certificateVerifier.hpp | 20 ++++- .../cert/defaultCertificateVerifier.cpp | 31 +++---- .../cert/openssl/X509Certificate_OpenSSL.cpp | 7 +- .../security/cert/serverIdentityException.cpp | 55 ++++++++++++ .../security/cert/serverIdentityException.hpp | 65 ++++++++++++++ .../unsupportedCertificateTypeException.cpp | 61 +++++++++++++ .../unsupportedCertificateTypeException.hpp | 72 +++++++++++++++ 24 files changed, 991 insertions(+), 125 deletions(-) create mode 100644 src/vmime/security/cert/certificateException.cpp create mode 100644 src/vmime/security/cert/certificateException.hpp create mode 100644 src/vmime/security/cert/certificateExpiredException.cpp create mode 100644 src/vmime/security/cert/certificateExpiredException.hpp create mode 100644 src/vmime/security/cert/certificateIssuerVerificationException.cpp create mode 100644 src/vmime/security/cert/certificateIssuerVerificationException.hpp create mode 100644 src/vmime/security/cert/certificateNotTrustedException.cpp create mode 100644 src/vmime/security/cert/certificateNotTrustedException.hpp create mode 100644 src/vmime/security/cert/certificateNotYetValidException.cpp create mode 100644 src/vmime/security/cert/certificateNotYetValidException.hpp create mode 100644 src/vmime/security/cert/serverIdentityException.cpp create mode 100644 src/vmime/security/cert/serverIdentityException.hpp create mode 100644 src/vmime/security/cert/unsupportedCertificateTypeException.cpp create mode 100644 src/vmime/security/cert/unsupportedCertificateTypeException.hpp diff --git a/doc/book/net.tex b/doc/book/net.tex index 4d99f1bf..c5581e33 100644 --- a/doc/book/net.tex +++ b/doc/book/net.tex @@ -874,7 +874,7 @@ default behaviour is to fallback on a normal connection. To make \subsubsection{How it works} % ............................................... If you tried the previous examples, a -{\vcode certificate\_verification\_exception} might have been thrown. +{\vcode certificateException} might have been thrown. This is because the default certificate verifier in VMime did not manage to verify the certificate, and so could not trust it. @@ -905,6 +905,8 @@ used is quite simple: issued by the next certificate in the chain; \item for every certificate in the chain, verify that the certificate is valid at the current time; +\item ensure that the first certificate's subject name matches the hostname +of the server; \item decide whether the subject's certificate can be trusted: \begin{itemize} \item first, verify that the the last certificate in the chain was @@ -981,7 +983,7 @@ write your own verifier. Your verifier should inherit from the {\vcode vmime::security::cert::certificateVerifier} class and implement the method {\vcode verify()}. Then, if the specified certificate chain is trusted, simply return from the function, or else throw a -{\vcode certificate\_verification\_exception}. +{\vcode certificateException}. The following example shows how to implement an interactive certificate verifier which relies on the user's decision, and nothing else (you SHOULD NOT @@ -1011,7 +1013,7 @@ public: return; // OK, we trust the certificate // Don't trust this certificate - throw exceptions::certificate_verification_exception(); + throw vmime::security::cert::certificateException(); } }; \end{lstlisting} diff --git a/examples/example6_certificateVerifier.hpp b/examples/example6_certificateVerifier.hpp index 65f0f4ad..e98f7874 100644 --- a/examples/example6_certificateVerifier.hpp +++ b/examples/example6_certificateVerifier.hpp @@ -15,7 +15,7 @@ public: defaultCertificateVerifier::verify(chain, hostname); } - catch (vmime::exceptions::certificate_verification_exception&) + catch (vmime::security::cert::certificateException&) { // Obtain subject's certificate vmime::shared_ptr cert = chain->getAt(0); @@ -44,7 +44,7 @@ public: return; } - throw vmime::exceptions::certificate_verification_exception + throw vmime::security::cert::certificateException ("User did not accept the certificate."); } } diff --git a/src/vmime/exception.cpp b/src/vmime/exception.cpp index dff7d497..ce57883c 100644 --- a/src/vmime/exception.cpp +++ b/src/vmime/exception.cpp @@ -35,19 +35,19 @@ const exception exception::NO_EXCEPTION; exception::exception() - : m_what(""), m_other(NULL) + : std::runtime_error(""), m_other(NULL) { } exception::exception(const string& what, const exception& other) - : m_what(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) + : std::runtime_error(what), m_other(&other != &NO_EXCEPTION ? other.clone() : NULL) { } exception::exception(const exception& e) - : std::exception(), m_what(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) + : std::runtime_error(e.what()), m_other(e.m_other == NULL ? NULL : e.m_other->clone()) { } @@ -58,15 +58,12 @@ exception::~exception() throw() } -const char* exception::what() const throw() +void exception::chainException(const exception& other) { - return (m_what.c_str()); -} + exception* e = other.clone(); - -const char* exception::what() throw() -{ - return (m_what.c_str()); + delete m_other; + m_other = e; } @@ -715,42 +712,6 @@ exception* tls_exception::clone() const { return new tls_exception(*this); } const char* tls_exception::name() const throw() { return "tls_exception"; } -// -// certificate_exception -// - -certificate_exception::~certificate_exception() throw() {} -certificate_exception::certificate_exception(const string& what, const exception& other) - : tls_exception(what, other) {} - -exception* certificate_exception::clone() const { return new certificate_exception(*this); } -const char* certificate_exception::name() const throw() { return "certificate_exception"; } - - -// -// certificate_verification_exception -// - -certificate_verification_exception::~certificate_verification_exception() throw() {} -certificate_verification_exception::certificate_verification_exception(const string& what, const exception& other) - : certificate_exception(what, other) {} - -exception* certificate_verification_exception::clone() const { return new certificate_verification_exception(*this); } -const char* certificate_verification_exception::name() const throw() { return "certificate_verification_exception"; } - - -// -// unsupported_certificate_type -// - -unsupported_certificate_type::~unsupported_certificate_type() throw() {} -unsupported_certificate_type::unsupported_certificate_type(const string& type, const exception& other) - : certificate_exception("Unsupported certificate type: '" + type + "'", other) {} - -exception* unsupported_certificate_type::clone() const { return new unsupported_certificate_type(*this); } -const char* unsupported_certificate_type::name() const throw() { return "unsupported_certificate_type"; } - - #endif // VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/exception.hpp b/src/vmime/exception.hpp index 3c547756..a279f305 100644 --- a/src/vmime/exception.hpp +++ b/src/vmime/exception.hpp @@ -39,11 +39,10 @@ namespace vmime /** Base class for VMime exceptions. */ -class VMIME_EXPORT exception : public std::exception +class VMIME_EXPORT exception : public std::runtime_error { private: - string m_what; exception* m_other; exception(); @@ -55,19 +54,14 @@ public: virtual ~exception() throw(); - /** Return a description of the error. + /** Chain the specified exception with this exception. * - * @return error message + * @param other next exception in the chain */ - const char* what() const throw(); + void chainException(const exception& other); - /** Return a description of the error. - * - * @return error message - */ - const char* what() throw(); - - /** Return the next exception in the chain (encapsulated exception). + /** Return the next exception in the chain, that is the exception + * that caused this exception. This permits nesting exceptions. * * @return next exception in the chain */ @@ -874,42 +868,6 @@ public: }; -class VMIME_EXPORT certificate_exception : public tls_exception -{ -public: - - certificate_exception(const string& what, const exception& other = NO_EXCEPTION); - ~certificate_exception() throw(); - - exception* clone() const; - const char* name() const throw(); -}; - - -class VMIME_EXPORT certificate_verification_exception : public certificate_exception -{ -public: - - certificate_verification_exception(const string& what, const exception& other = NO_EXCEPTION); - ~certificate_verification_exception() throw (); - - exception* clone() const; - const char* name() const throw (); -}; - - -class VMIME_EXPORT unsupported_certificate_type : public certificate_exception -{ -public: - - unsupported_certificate_type(const string& type, const exception& other = NO_EXCEPTION); - ~unsupported_certificate_type() throw (); - - exception* clone() const; - const char* name() const throw (); -}; - - #endif // VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp index cf600a63..54e299ee 100644 --- a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp @@ -31,7 +31,7 @@ #include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp" #include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" -#include "vmime/exception.hpp" +#include "vmime/security/cert/certificateException.hpp" #include #include @@ -99,7 +99,7 @@ void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) std::ostringstream oss; oss << "Error loading private key from file " << keyfile; oss << " - msg: " << sslErr; - throw exceptions::certificate_exception(oss.str()); + throw security::cert::certificateException(oss.str()); } } @@ -115,7 +115,7 @@ void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) std::ostringstream oss; oss << "Error loading certificate from file " << chainFile; oss << " - msg: " << sslErr; - throw exceptions::certificate_exception(oss.str()); + throw security::cert::certificateException(oss.str()); } } diff --git a/src/vmime/security/cert/X509Certificate.cpp b/src/vmime/security/cert/X509Certificate.cpp index 2eebabfd..e4b14682 100644 --- a/src/vmime/security/cert/X509Certificate.cpp +++ b/src/vmime/security/cert/X509Certificate.cpp @@ -29,6 +29,9 @@ #include "vmime/security/cert/X509Certificate.hpp" +#include "vmime/security/cert/certificateNotYetValidException.hpp" +#include "vmime/security/cert/certificateExpiredException.hpp" + namespace vmime { namespace security { @@ -40,6 +43,27 @@ X509Certificate::~X509Certificate() } +void X509Certificate::checkValidity() +{ + const datetime now = datetime::now(); + + if (now < getActivationDate()) + { + certificateNotYetValidException ex; + ex.setCertificate(dynamicCast (shared_from_this())); + + throw ex; + } + else if (now > getExpirationDate()) + { + certificateExpiredException ex; + ex.setCertificate(dynamicCast (shared_from_this())); + + throw ex; + } +} + + } // cert } // security } // vmime diff --git a/src/vmime/security/cert/X509Certificate.hpp b/src/vmime/security/cert/X509Certificate.hpp index 90e26d1f..d816646b 100644 --- a/src/vmime/security/cert/X509Certificate.hpp +++ b/src/vmime/security/cert/X509Certificate.hpp @@ -153,6 +153,15 @@ public: * @return the fingerprint of this certificate */ virtual const byteArray getFingerprint(const DigestAlgorithm algo) const = 0; + + /** Checks that the certificate is currently valid. For the certificate + * to be valid, the current date and time must be in the validity period + * specified in the certificate. + * + * @throw certificateExpiredException if the certificate has expired + * @throw certificateNotYetValidException if the certificate is not yet valid + */ + virtual void checkValidity(); }; diff --git a/src/vmime/security/cert/certificateException.cpp b/src/vmime/security/cert/certificateException.cpp new file mode 100644 index 00000000..29c987a9 --- /dev/null +++ b/src/vmime/security/cert/certificateException.cpp @@ -0,0 +1,78 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateException::certificateException() + : exception("A problem occured with a certificate.") +{ +} + + +certificateException::certificateException(const std::string& what) + : exception(what) +{ +} + + +certificateException::~certificateException() throw() +{ +} + + +exception* certificateException::clone() const +{ + return new certificateException(what()); +} + + +void certificateException::setCertificate(shared_ptr cert) +{ + m_cert = cert; +} + + +shared_ptr certificateException::getCertificate() +{ + return m_cert; +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/certificateException.hpp b/src/vmime/security/cert/certificateException.hpp new file mode 100644 index 00000000..b60c06f6 --- /dev/null +++ b/src/vmime/security/cert/certificateException.hpp @@ -0,0 +1,89 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" + +#include "vmime/exception.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown to indicate a problem with a certificate or certificate verification. + */ +class VMIME_EXPORT certificateException : public exception +{ +public: + + /** Constructs a certificateException with no detail message. + */ + certificateException(); + + /** Constructs a certificateException with a detail message. + * + * @param what a message that describes this exception + */ + certificateException(const std::string& what); + + ~certificateException() throw(); + + exception* clone() const; + + /** Sets the certificate on which the problem occured. + * + * @param cert certificate + */ + void setCertificate(shared_ptr cert); + + /** Returns the certificate on which the problem occured. + * + * @return certificate + */ + shared_ptr getCertificate(); + +private: + + shared_ptr m_cert; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED diff --git a/src/vmime/security/cert/certificateExpiredException.cpp b/src/vmime/security/cert/certificateExpiredException.cpp new file mode 100644 index 00000000..c450f6be --- /dev/null +++ b/src/vmime/security/cert/certificateExpiredException.cpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/certificateExpiredException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateExpiredException::certificateExpiredException() + : certificateException("The certificate has expired.") +{ +} + + +exception* certificateExpiredException::clone() const +{ + return new certificateExpiredException(); +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/certificateExpiredException.hpp b/src/vmime/security/cert/certificateExpiredException.hpp new file mode 100644 index 00000000..7560741b --- /dev/null +++ b/src/vmime/security/cert/certificateExpiredException.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATEEXPIREDEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATEEXPIREDEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" +#include "vmime/security/cert/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown when the current date and time is after the validity period + * specified in the certificate. + */ +class VMIME_EXPORT certificateExpiredException : public certificateException +{ +public: + + /** Constructs a certificateExpiredException with no detail message. + */ + certificateExpiredException(); + + exception* clone() const; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_CERTIFICATEEXPIREDEXCEPTION_HPP_INCLUDED diff --git a/src/vmime/security/cert/certificateIssuerVerificationException.cpp b/src/vmime/security/cert/certificateIssuerVerificationException.cpp new file mode 100644 index 00000000..1e57b6d2 --- /dev/null +++ b/src/vmime/security/cert/certificateIssuerVerificationException.cpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/certificateIssuerVerificationException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateIssuerVerificationException::certificateIssuerVerificationException() + : certificateException("Certificate subject/issuer verification failed.") +{ +} + + +exception* certificateIssuerVerificationException::clone() const +{ + return new certificateIssuerVerificationException(); +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/certificateIssuerVerificationException.hpp b/src/vmime/security/cert/certificateIssuerVerificationException.hpp new file mode 100644 index 00000000..3d3f9a1d --- /dev/null +++ b/src/vmime/security/cert/certificateIssuerVerificationException.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATEISSUERVERIFICATIONEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATEISSUERVERIFICATIONEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" +#include "vmime/security/cert/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown when a certificate in a certificate chain cannot be verified + * against the next certificate in the chain (the issuer). + */ +class VMIME_EXPORT certificateIssuerVerificationException : public certificateException +{ +public: + + /** Constructs a certificateIssuerVerificationException with no detail message. + */ + certificateIssuerVerificationException(); + + exception* clone() const; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_CERTIFICATEISSUERVERIFICATIONEXCEPTION_HPP_INCLUDED diff --git a/src/vmime/security/cert/certificateNotTrustedException.cpp b/src/vmime/security/cert/certificateNotTrustedException.cpp new file mode 100644 index 00000000..12b932e6 --- /dev/null +++ b/src/vmime/security/cert/certificateNotTrustedException.cpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/certificateNotTrustedException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateNotTrustedException::certificateNotTrustedException() + : certificateException("Cannot verify certificate against trusted certificates.") +{ +} + + +exception* certificateNotTrustedException::clone() const +{ + return new certificateNotTrustedException(); +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/certificateNotTrustedException.hpp b/src/vmime/security/cert/certificateNotTrustedException.hpp new file mode 100644 index 00000000..35881cc3 --- /dev/null +++ b/src/vmime/security/cert/certificateNotTrustedException.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATENOTTRUSTEDEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATENOTTRUSTEDEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" +#include "vmime/security/cert/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown when a certificate cannot be verified against root and/or + * trusted certificates. + */ +class VMIME_EXPORT certificateNotTrustedException : public certificateException +{ +public: + + /** Constructs a certificateNotTrustedException with no detail message. + */ + certificateNotTrustedException(); + + exception* clone() const; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_CERTIFICATENOTTRUSTEDEXCEPTION_HPP_INCLUDED diff --git a/src/vmime/security/cert/certificateNotYetValidException.cpp b/src/vmime/security/cert/certificateNotYetValidException.cpp new file mode 100644 index 00000000..da712b35 --- /dev/null +++ b/src/vmime/security/cert/certificateNotYetValidException.cpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/certificateNotYetValidException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateNotYetValidException::certificateNotYetValidException() + : certificateException("The certificate is not yet valid.") +{ +} + + +exception* certificateNotYetValidException::clone() const +{ + return new certificateNotYetValidException(); +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/certificateNotYetValidException.hpp b/src/vmime/security/cert/certificateNotYetValidException.hpp new file mode 100644 index 00000000..e412f466 --- /dev/null +++ b/src/vmime/security/cert/certificateNotYetValidException.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATENOTYETVALIDEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATENOTYETVALIDEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" +#include "vmime/security/cert/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown when the current date and time is before the validity period + * specified in the certificate. + */ +class VMIME_EXPORT certificateNotYetValidException : public certificateException +{ +public: + + /** Constructs a certificateNotYetValidException with no detail message. + */ + certificateNotYetValidException(); + + exception* clone() const; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_CERTIFICATENOTYETVALIDEXCEPTION_HPP_INCLUDED diff --git a/src/vmime/security/cert/certificateVerifier.hpp b/src/vmime/security/cert/certificateVerifier.hpp index c72c84cb..ae1ee312 100644 --- a/src/vmime/security/cert/certificateVerifier.hpp +++ b/src/vmime/security/cert/certificateVerifier.hpp @@ -29,6 +29,11 @@ #include "vmime/security/cert/certificateChain.hpp" +#include "vmime/security/cert/unsupportedCertificateTypeException.hpp" +#include "vmime/security/cert/certificateIssuerVerificationException.hpp" +#include "vmime/security/cert/certificateNotTrustedException.hpp" +#include "vmime/security/cert/serverIdentityException.hpp" + namespace vmime { namespace security { @@ -45,9 +50,18 @@ public: * * @param chain certificate chain * @param hostname server hostname - * @throw exceptions::certificate_verification_exception if one - * or more certificates can not be trusted, or the server identity - * cannot be verified + * @throw unsupportedCertificateTypeException if a certificate in the + * chain is of unsupported format + * @throw certificateExpiredException if a certificate in the chain + * has expired + * @throw certificateNotYetValidException if a certificate in the chain + * is not yet valid + * @throw certificateNotTrustedException if a certificate in the chain + * cannot be verified against root and/or trusted certificates + * @throw certificateIssuerVerificationException if a certificate in the + * chain cannot be verified against the next certificate (issuer) + * @throw serverIdentityException if the subject name of the certificate + * does not match the hostname of the server */ virtual void verify(shared_ptr chain, const string& hostname) = 0; }; diff --git a/src/vmime/security/cert/defaultCertificateVerifier.cpp b/src/vmime/security/cert/defaultCertificateVerifier.cpp index 1a95b353..31661617 100644 --- a/src/vmime/security/cert/defaultCertificateVerifier.cpp +++ b/src/vmime/security/cert/defaultCertificateVerifier.cpp @@ -65,7 +65,7 @@ void defaultCertificateVerifier::verify if (type == "X.509") verifyX509(chain, hostname); else - throw exceptions::unsupported_certificate_type(type); + throw unsupportedCertificateTypeException(type); } @@ -86,29 +86,22 @@ void defaultCertificateVerifier::verifyX509 if (!cert->checkIssuer(next)) { - throw exceptions::certificate_verification_exception - ("Subject/issuer verification failed."); + certificateIssuerVerificationException ex; + ex.setCertificate(cert); + + throw ex; } } } // For every certificate in the chain, verify that the certificate // is valid at the current time - const datetime now = datetime::now(); - for (unsigned int i = 0 ; i < chain->getCount() ; ++i) { shared_ptr cert = dynamicCast (chain->getAt(i)); - const datetime begin = cert->getActivationDate(); - const datetime end = cert->getExpirationDate(); - - if (now < begin || now > end) - { - throw exceptions::certificate_verification_exception - ("Validity date check failed."); - } + cert->checkValidity(); } // Check whether the certificate can be trusted @@ -144,15 +137,19 @@ void defaultCertificateVerifier::verifyX509 if (!trusted) { - throw exceptions::certificate_verification_exception - ("Cannot verify certificate against trusted certificates."); + certificateNotTrustedException ex; + ex.setCertificate(firstCert); + + throw ex; } // Ensure the first certificate's subject name matches server hostname if (!firstCert->verifyHostName(hostname)) { - throw exceptions::certificate_verification_exception - ("Server identity cannot be verified."); + serverIdentityException ex; + ex.setCertificate(firstCert); + + throw ex; } } diff --git a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp index 58d74bf9..70ff50c0 100644 --- a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp +++ b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp @@ -38,7 +38,8 @@ #include "vmime/utility/outputStreamByteArrayAdapter.hpp" -#include "vmime/exception.hpp" +#include "vmime/security/cert/certificateException.hpp" +#include "vmime/security/cert/unsupportedCertificateTypeException.hpp" #include #include @@ -234,7 +235,7 @@ void X509Certificate_OpenSSL::write } else { - throw vmime::exceptions::unsupported_certificate_type("Unknown cert type"); + throw unsupportedCertificateTypeException("Unknown format"); } return; // #### Early Return #### @@ -250,7 +251,7 @@ err: char errstr[256]; long ec = ERR_get_error(); ERR_error_string(ec, errstr); - throw vmime::exceptions::certificate_exception( + throw certificateException( "OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr)); } } diff --git a/src/vmime/security/cert/serverIdentityException.cpp b/src/vmime/security/cert/serverIdentityException.cpp new file mode 100644 index 00000000..585d1021 --- /dev/null +++ b/src/vmime/security/cert/serverIdentityException.cpp @@ -0,0 +1,55 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/serverIdentityException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +serverIdentityException::serverIdentityException() + : certificateException("Server identity cannot be verified.") +{ +} + + +exception* serverIdentityException::clone() const +{ + return new serverIdentityException(); +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/serverIdentityException.hpp b/src/vmime/security/cert/serverIdentityException.hpp new file mode 100644 index 00000000..47feced7 --- /dev/null +++ b/src/vmime/security/cert/serverIdentityException.hpp @@ -0,0 +1,65 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_SERVERIDENTITYEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_SERVERIDENTITYEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" +#include "vmime/security/cert/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown when the subject name of a certificate does not match + * the hostname of the server. + */ +class VMIME_EXPORT serverIdentityException : public certificateException +{ +public: + + /** Constructs a serverIdentityException with no detail message. + */ + serverIdentityException(); + + exception* clone() const; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_SERVERIDENTITYEXCEPTION_HPP_INCLUDED diff --git a/src/vmime/security/cert/unsupportedCertificateTypeException.cpp b/src/vmime/security/cert/unsupportedCertificateTypeException.cpp new file mode 100644 index 00000000..b27bb8be --- /dev/null +++ b/src/vmime/security/cert/unsupportedCertificateTypeException.cpp @@ -0,0 +1,61 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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/unsupportedCertificateTypeException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +unsupportedCertificateTypeException::unsupportedCertificateTypeException(const string& type) + : certificateException(string("Unsupported certificate type: '") + type + "'."), + m_type(type) +{ +} + + +unsupportedCertificateTypeException::~unsupportedCertificateTypeException() throw() +{ +} + + +exception* unsupportedCertificateTypeException::clone() const +{ + return new unsupportedCertificateTypeException(m_type); +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/vmime/security/cert/unsupportedCertificateTypeException.hpp b/src/vmime/security/cert/unsupportedCertificateTypeException.hpp new file mode 100644 index 00000000..356ac32b --- /dev/null +++ b/src/vmime/security/cert/unsupportedCertificateTypeException.hpp @@ -0,0 +1,72 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002-2013 Vincent Richard +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_UNSUPPORTEDCERTIFICATETYPEEXCEPTION_HPP_INCLUDED +#define VMIME_SECURITY_CERT_UNSUPPORTEDCERTIFICATETYPEEXCEPTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" +#include "vmime/security/cert/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Thrown when a certificate is of unsupported format. + */ +class VMIME_EXPORT unsupportedCertificateTypeException : public certificateException +{ +public: + + /** Constructs a unsupportedCertificateTypeException. + * + * @param type certificate type + */ + unsupportedCertificateTypeException(const string& type); + + ~unsupportedCertificateTypeException() throw(); + + exception* clone() const; + +private: + + string m_type; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_UNSUPPORTEDCERTIFICATETYPEEXCEPTION_HPP_INCLUDED