Certificate exception differentiation for easier error handling.

This commit is contained in:
Vincent Richard 2014-07-24 20:59:52 +02:00
parent 937d9c01cc
commit 00e07962e7
24 changed files with 991 additions and 125 deletions

View File

@ -874,7 +874,7 @@ default behaviour is to fallback on a normal connection. To make
\subsubsection{How it works} % ............................................... \subsubsection{How it works} % ...............................................
If you tried the previous examples, a 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 This is because the default certificate verifier in VMime did not manage to
verify the certificate, and so could not trust it. 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; issued by the next certificate in the chain;
\item for every certificate in the chain, verify that the certificate is valid \item for every certificate in the chain, verify that the certificate is valid
at the current time; 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: \item decide whether the subject's certificate can be trusted:
\begin{itemize} \begin{itemize}
\item first, verify that the the last certificate in the chain was \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 {\vcode vmime::security::cert::certificateVerifier} class and implement the
method {\vcode verify()}. Then, if the specified certificate chain is trusted, method {\vcode verify()}. Then, if the specified certificate chain is trusted,
simply return from the function, or else throw a 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 The following example shows how to implement an interactive certificate
verifier which relies on the user's decision, and nothing else (you SHOULD NOT 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 return; // OK, we trust the certificate
// Don't trust this certificate // Don't trust this certificate
throw exceptions::certificate_verification_exception(); throw vmime::security::cert::certificateException();
} }
}; };
\end{lstlisting} \end{lstlisting}

View File

@ -15,7 +15,7 @@ public:
defaultCertificateVerifier::verify(chain, hostname); defaultCertificateVerifier::verify(chain, hostname);
} }
catch (vmime::exceptions::certificate_verification_exception&) catch (vmime::security::cert::certificateException&)
{ {
// Obtain subject's certificate // Obtain subject's certificate
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0); vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
@ -44,7 +44,7 @@ public:
return; return;
} }
throw vmime::exceptions::certificate_verification_exception throw vmime::security::cert::certificateException
("User did not accept the certificate."); ("User did not accept the certificate.");
} }
} }

View File

@ -35,19 +35,19 @@ const exception exception::NO_EXCEPTION;
exception::exception() exception::exception()
: m_what(""), m_other(NULL) : std::runtime_error(""), m_other(NULL)
{ {
} }
exception::exception(const string& what, const exception& other) 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) 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();
}
delete m_other;
const char* exception::what() throw() m_other = e;
{
return (m_what.c_str());
} }
@ -715,42 +712,6 @@ exception* tls_exception::clone() const { return new tls_exception(*this); }
const char* tls_exception::name() const throw() { return "tls_exception"; } 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 #endif // VMIME_HAVE_TLS_SUPPORT

View File

@ -39,11 +39,10 @@ namespace vmime
/** Base class for VMime exceptions. /** Base class for VMime exceptions.
*/ */
class VMIME_EXPORT exception : public std::exception class VMIME_EXPORT exception : public std::runtime_error
{ {
private: private:
string m_what;
exception* m_other; exception* m_other;
exception(); exception();
@ -55,19 +54,14 @@ public:
virtual ~exception() throw(); 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 the next exception in the chain, that is the exception
* * that caused this exception. This permits nesting exceptions.
* @return error message
*/
const char* what() throw();
/** Return the next exception in the chain (encapsulated exception).
* *
* @return next exception in the chain * @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 #endif // VMIME_HAVE_TLS_SUPPORT

View File

@ -31,7 +31,7 @@
#include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp" #include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp"
#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" #include "vmime/net/tls/openssl/OpenSSLInitializer.hpp"
#include "vmime/exception.hpp" #include "vmime/security/cert/certificateException.hpp"
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
@ -99,7 +99,7 @@ void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile)
std::ostringstream oss; std::ostringstream oss;
oss << "Error loading private key from file " << keyfile; oss << "Error loading private key from file " << keyfile;
oss << " - msg: " << sslErr; 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; std::ostringstream oss;
oss << "Error loading certificate from file " << chainFile; oss << "Error loading certificate from file " << chainFile;
oss << " - msg: " << sslErr; oss << " - msg: " << sslErr;
throw exceptions::certificate_exception(oss.str()); throw security::cert::certificateException(oss.str());
} }
} }

View File

@ -29,6 +29,9 @@
#include "vmime/security/cert/X509Certificate.hpp" #include "vmime/security/cert/X509Certificate.hpp"
#include "vmime/security/cert/certificateNotYetValidException.hpp"
#include "vmime/security/cert/certificateExpiredException.hpp"
namespace vmime { namespace vmime {
namespace security { namespace security {
@ -40,6 +43,27 @@ X509Certificate::~X509Certificate()
} }
void X509Certificate::checkValidity()
{
const datetime now = datetime::now();
if (now < getActivationDate())
{
certificateNotYetValidException ex;
ex.setCertificate(dynamicCast <certificate>(shared_from_this()));
throw ex;
}
else if (now > getExpirationDate())
{
certificateExpiredException ex;
ex.setCertificate(dynamicCast <certificate>(shared_from_this()));
throw ex;
}
}
} // cert } // cert
} // security } // security
} // vmime } // vmime

View File

@ -153,6 +153,15 @@ public:
* @return the fingerprint of this certificate * @return the fingerprint of this certificate
*/ */
virtual const byteArray getFingerprint(const DigestAlgorithm algo) const = 0; 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();
}; };

View File

@ -0,0 +1,78 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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 <certificate> cert)
{
m_cert = cert;
}
shared_ptr <certificate> certificateException::getCertificate()
{
return m_cert;
}
} // cert
} // security
} // vmime
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT

View File

@ -0,0 +1,89 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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 <certificate> cert);
/** Returns the certificate on which the problem occured.
*
* @return certificate
*/
shared_ptr <certificate> getCertificate();
private:
shared_ptr <certificate> m_cert;
};
} // cert
} // security
} // vmime
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
#endif // VMIME_SECURITY_CERT_CERTIFICATEEXCEPTION_HPP_INCLUDED

View File

@ -0,0 +1,55 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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

View File

@ -0,0 +1,55 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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

View File

@ -0,0 +1,55 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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

View File

@ -0,0 +1,55 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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

View File

@ -29,6 +29,11 @@
#include "vmime/security/cert/certificateChain.hpp" #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 vmime {
namespace security { namespace security {
@ -45,9 +50,18 @@ public:
* *
* @param chain certificate chain * @param chain certificate chain
* @param hostname server hostname * @param hostname server hostname
* @throw exceptions::certificate_verification_exception if one * @throw unsupportedCertificateTypeException if a certificate in the
* or more certificates can not be trusted, or the server identity * chain is of unsupported format
* cannot be verified * @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 <certificateChain> chain, const string& hostname) = 0; virtual void verify(shared_ptr <certificateChain> chain, const string& hostname) = 0;
}; };

View File

@ -65,7 +65,7 @@ void defaultCertificateVerifier::verify
if (type == "X.509") if (type == "X.509")
verifyX509(chain, hostname); verifyX509(chain, hostname);
else else
throw exceptions::unsupported_certificate_type(type); throw unsupportedCertificateTypeException(type);
} }
@ -86,29 +86,22 @@ void defaultCertificateVerifier::verifyX509
if (!cert->checkIssuer(next)) if (!cert->checkIssuer(next))
{ {
throw exceptions::certificate_verification_exception certificateIssuerVerificationException ex;
("Subject/issuer verification failed."); ex.setCertificate(cert);
throw ex;
} }
} }
} }
// For every certificate in the chain, verify that the certificate // For every certificate in the chain, verify that the certificate
// is valid at the current time // is valid at the current time
const datetime now = datetime::now();
for (unsigned int i = 0 ; i < chain->getCount() ; ++i) for (unsigned int i = 0 ; i < chain->getCount() ; ++i)
{ {
shared_ptr <X509Certificate> cert = shared_ptr <X509Certificate> cert =
dynamicCast <X509Certificate>(chain->getAt(i)); dynamicCast <X509Certificate>(chain->getAt(i));
const datetime begin = cert->getActivationDate(); cert->checkValidity();
const datetime end = cert->getExpirationDate();
if (now < begin || now > end)
{
throw exceptions::certificate_verification_exception
("Validity date check failed.");
}
} }
// Check whether the certificate can be trusted // Check whether the certificate can be trusted
@ -144,15 +137,19 @@ void defaultCertificateVerifier::verifyX509
if (!trusted) if (!trusted)
{ {
throw exceptions::certificate_verification_exception certificateNotTrustedException ex;
("Cannot verify certificate against trusted certificates."); ex.setCertificate(firstCert);
throw ex;
} }
// Ensure the first certificate's subject name matches server hostname // Ensure the first certificate's subject name matches server hostname
if (!firstCert->verifyHostName(hostname)) if (!firstCert->verifyHostName(hostname))
{ {
throw exceptions::certificate_verification_exception serverIdentityException ex;
("Server identity cannot be verified."); ex.setCertificate(firstCert);
throw ex;
} }
} }

View File

@ -38,7 +38,8 @@
#include "vmime/utility/outputStreamByteArrayAdapter.hpp" #include "vmime/utility/outputStreamByteArrayAdapter.hpp"
#include "vmime/exception.hpp" #include "vmime/security/cert/certificateException.hpp"
#include "vmime/security/cert/unsupportedCertificateTypeException.hpp"
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
@ -234,7 +235,7 @@ void X509Certificate_OpenSSL::write
} }
else else
{ {
throw vmime::exceptions::unsupported_certificate_type("Unknown cert type"); throw unsupportedCertificateTypeException("Unknown format");
} }
return; // #### Early Return #### return; // #### Early Return ####
@ -250,7 +251,7 @@ err:
char errstr[256]; char errstr[256];
long ec = ERR_get_error(); long ec = ERR_get_error();
ERR_error_string(ec, errstr); ERR_error_string(ec, errstr);
throw vmime::exceptions::certificate_exception( throw certificateException(
"OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr)); "OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr));
} }
} }

View File

@ -0,0 +1,55 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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

View File

@ -0,0 +1,65 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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

View File

@ -0,0 +1,61 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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/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

View File

@ -0,0 +1,72 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 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.
//
#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