diff options
author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
---|---|---|
committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
commit | aa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch) | |
tree | 4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /vmime-master/src/vmime/security/cert | |
download | smtps-and-pop3s-console-program-master.tar.gz smtps-and-pop3s-console-program-master.zip |
Diffstat (limited to 'vmime-master/src/vmime/security/cert')
26 files changed, 3027 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/security/cert/X509Certificate.cpp b/vmime-master/src/vmime/security/cert/X509Certificate.cpp new file mode 100644 index 0000000..128fac1 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/X509Certificate.cpp @@ -0,0 +1,72 @@ +// +// 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/X509Certificate.hpp" + +#include "vmime/security/cert/certificateNotYetValidException.hpp" +#include "vmime/security/cert/certificateExpiredException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +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 +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/vmime-master/src/vmime/security/cert/X509Certificate.hpp b/vmime-master/src/vmime/security/cert/X509Certificate.hpp new file mode 100644 index 0000000..5434b45 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/X509Certificate.hpp @@ -0,0 +1,197 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED +#define VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificate.hpp" + +#include "vmime/utility/stream.hpp" + +#include "vmime/base.hpp" +#include "vmime/types.hpp" +#include "vmime/dateTime.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Identity certificate based on X.509 standard. + */ +class VMIME_EXPORT X509Certificate : public certificate { + +public: + + ~X509Certificate(); + + /** Supported encodings for X.509 certificates. */ + enum Format { + FORMAT_DER, /**< DER encoding */ + FORMAT_PEM /**< PEM encoding */ + }; + + /** Supported digest algorithms (used for fingerprint). */ + enum DigestAlgorithm { + DIGEST_MD5, /**< MD5 digest */ + DIGEST_SHA1 /**< SHA1 digest */ + }; + + + /** Imports a DER or PEM encoded X.509 certificate. + * + * @param is input stream to read data from + * @return a X.509 certificate, or NULL if the given data does not + * represent a valid certificate + */ + static shared_ptr <X509Certificate> import(utility::inputStream& is); + + /** Imports a DER or PEM encoded X.509 certificate. + * + * @param data points to raw data + * @param length size of data + * @return a X.509 certificate, or NULL if the given data does not + * represent a valid certificate + */ + static shared_ptr <X509Certificate> import(const byte_t* data, const size_t length); + + /** Import sveral DER or PEM encoded X.509 certificates. + * + * @param is input stream to read data from + * @param certs the resulting list of certificates + */ + static void import( + utility::inputStream& is, + std::vector <shared_ptr <X509Certificate> >& certs + ); + + /** Import several DER or PEM encoded X.509 certificates. + * + * @param data points to raw data + * @param length size of data + * @param certs the resulting list of certificates + */ + static void import( + const byte_t* data, + const size_t length, + std::vector <shared_ptr <X509Certificate> >& certs + ); + + /** Exports this X.509 certificate to the specified format. + * + * @param os output stream into which write data + * @param format output format + */ + virtual void write(utility::outputStream& os, const Format format) const = 0; + + /** Returns the X.509 certificate's serial number. This is obtained + * by the X.509 Certificate 'serialNumber' field. Serial is not + * always a 32 or 64bit number. Some CAs use large serial numbers, + * thus it may be wise to handle it as something opaque. + * + * @return serial number of this certificate + */ + virtual const byteArray getSerialNumber() const = 0; + + /** Returns the distinguished name of the issuer of this certificate. + * Eg. "C=US,O=VeriSign\, Inc.,OU=Class 1 Public Primary Certification Authority" + * + * @return distinguished name of the certificate issuer, as a string + */ + virtual const string getIssuerString() const = 0; + + /** Checks if this certificate has the given issuer. + * + * @param issuer certificate of a possible issuer + * @return true if this certificate was issued by the given issuer, + * false otherwise + */ + virtual bool checkIssuer(const shared_ptr <const X509Certificate>& issuer) const = 0; + + /** Verifies this certificate against a given trusted one. + * + * @param caCert a certificate that is considered to be trusted one + * @return true if the verification succeeded, false otherwise + */ + virtual bool verify(const shared_ptr <const X509Certificate>& caCert) const = 0; + + /** Verify certificate's subject name against the given hostname. + * + * @param hostname DNS name of the server + * @param nonMatchingNames if not NULL, will contain the names that do + * not match the identities in the certificate + * @return true if the match is successful, false otherwise + */ + virtual bool verifyHostName( + const string& hostname, + std::vector <std::string>* nonMatchingNames = NULL + ) const = 0; + + /** Gets the expiration date of this certificate. This is the date + * at which this certificate will not be valid anymore. + * + * @return expiration date of this certificate + */ + virtual const datetime getExpirationDate() const = 0; + + /** Gets the activation date of this certificate. This is the date + * at which this certificate will be valid. + * + * @return activation date of this certificate + */ + virtual const datetime getActivationDate() const = 0; + + /** Returns the fingerprint of this certificate. + * + * @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(); +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + +#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/certificate.hpp b/vmime-master/src/vmime/security/cert/certificate.hpp new file mode 100644 index 0000000..ed0f175 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificate.hpp @@ -0,0 +1,84 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATE_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATE_HPP_INCLUDED + + +#include "vmime/types.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** Identity certificate for a peer. + */ +class VMIME_EXPORT certificate : public object, public enable_shared_from_this <certificate> { + +public: + + /** Returns the encoded form of this certificate (for example, + * X.509 certificates are encoded as ASN.1 DER). + * + * @return the encoded form of this certificate + */ + virtual const byteArray getEncoded() const = 0; + + /** Return the type of this certificate. + * + * @return the type of this certificate + */ + virtual const string getType() const = 0; + + /** Return the version of this certificate. + * + * @return the version of this certificate + */ + virtual int getVersion() const = 0; + + /** Checks if two certificates are the same. + * + * @param other certificate to compare with + * @return true if the two certificates are the same, + * false otherwise + */ + virtual bool equals(const shared_ptr <const certificate>& other) const = 0; + + /** Returns a pointer to internal binary data for this certificate. + * The actual type of data depends on the library used for TLS support. + * + * @return pointer to underlying data + */ + virtual void* getInternalData() = 0; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_SECURITY_CERT_CERTIFICATE_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/certificateChain.cpp b/vmime-master/src/vmime/security/cert/certificateChain.cpp new file mode 100644 index 0000000..c506913 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateChain.cpp @@ -0,0 +1,53 @@ +// +// 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/security/cert/certificateChain.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateChain::certificateChain(const std::vector <shared_ptr <certificate> >& certs) + : m_certs(certs) { + +} + + +size_t certificateChain::getCount() const { + + return m_certs.size(); +} + + +const shared_ptr <certificate>& certificateChain::getAt(const size_t index) { + + return m_certs[index]; +} + + +} // cert +} // security +} // vmime + diff --git a/vmime-master/src/vmime/security/cert/certificateChain.hpp b/vmime-master/src/vmime/security/cert/certificateChain.hpp new file mode 100644 index 0000000..f8c363e --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateChain.hpp @@ -0,0 +1,79 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED + + +#include "vmime/types.hpp" + +#include "vmime/security/cert/certificate.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +/** An ordered list of certificates, from the subject certificate to + * the issuer certificate. + */ +class VMIME_EXPORT certificateChain : public object { + +public: + + /** Construct a new certificateChain object given an ordered list + * of certificates. + * + * @param certs chain of certificates + */ + certificateChain(const std::vector <shared_ptr <certificate> >& certs); + + /** Return the number of certificates in the chain. + * + * @return number of certificates in the chain + */ + size_t getCount() const; + + /** Return the certificate at the specified position. 0 is the + * subject certificate, 1 is the issuer's certificate, 2 is + * the issuer's issuer, etc. + * + * @param index position at which to retrieve certificate + * @return certificate at the specified position + */ + const shared_ptr <certificate>& getAt(const size_t index); + +protected: + + std::vector <shared_ptr <certificate> > m_certs; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_SECURITY_CERT_CERTIFICATECHAIN_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/certificateException.cpp b/vmime-master/src/vmime/security/cert/certificateException.cpp new file mode 100644 index 0000000..51a4f03 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateException.cpp @@ -0,0 +1,84 @@ +// +// 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/certificateException.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +certificateException::certificateException() + : exception("A problem occurred 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(const shared_ptr <certificate>& cert) { + + m_cert = cert; +} + + +shared_ptr <certificate> certificateException::getCertificate() { + + return m_cert; +} + + +shared_ptr <const certificate> certificateException::getCertificate() const { + + return m_cert; +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/vmime-master/src/vmime/security/cert/certificateException.hpp b/vmime-master/src/vmime/security/cert/certificateException.hpp new file mode 100644 index 0000000..9dd5443 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateException.hpp @@ -0,0 +1,95 @@ +// +// 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. +// + +#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(const shared_ptr <certificate>& cert); + + /** Returns the certificate on which the problem occured. + * + * @return certificate + */ + shared_ptr <certificate> getCertificate(); + + /** Returns the certificate on which the problem occured. + * + * @return certificate + */ + shared_ptr <const certificate> getCertificate() const; + +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 diff --git a/vmime-master/src/vmime/security/cert/certificateExpiredException.cpp b/vmime-master/src/vmime/security/cert/certificateExpiredException.cpp new file mode 100644 index 0000000..1aa248e --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateExpiredException.cpp @@ -0,0 +1,55 @@ +// +// 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/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/vmime-master/src/vmime/security/cert/certificateExpiredException.hpp b/vmime-master/src/vmime/security/cert/certificateExpiredException.hpp new file mode 100644 index 0000000..4db0a1e --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateExpiredException.hpp @@ -0,0 +1,65 @@ +// +// 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. +// + +#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/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp new file mode 100644 index 0000000..adf5049 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.cpp @@ -0,0 +1,55 @@ +// +// 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/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/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp new file mode 100644 index 0000000..e22bd92 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateIssuerVerificationException.hpp @@ -0,0 +1,65 @@ +// +// 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. +// + +#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/vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp new file mode 100644 index 0000000..a5ebb99 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.cpp @@ -0,0 +1,55 @@ +// +// 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/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/vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp new file mode 100644 index 0000000..8cdb2f0 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateNotTrustedException.hpp @@ -0,0 +1,65 @@ +// +// 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. +// + +#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/vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp new file mode 100644 index 0000000..ed8ca79 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.cpp @@ -0,0 +1,55 @@ +// +// 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/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/vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp new file mode 100644 index 0000000..8f321eb --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateNotYetValidException.hpp @@ -0,0 +1,65 @@ +// +// 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. +// + +#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/vmime-master/src/vmime/security/cert/certificateVerifier.hpp b/vmime-master/src/vmime/security/cert/certificateVerifier.hpp new file mode 100644 index 0000000..7e2913a --- /dev/null +++ b/vmime-master/src/vmime/security/cert/certificateVerifier.hpp @@ -0,0 +1,76 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED +#define VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED + + +#include "vmime/types.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 security { +namespace cert { + + +/** Verify that a certificate path issued by a server can be trusted. + */ +class VMIME_EXPORT certificateVerifier : public object { + +public: + + /** Verify that the specified certificate chain is trusted. + * + * @param chain certificate chain + * @param hostname server hostname + * @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(const shared_ptr <certificateChain>& chain, const string& hostname) = 0; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_SECURITY_CERT_CERTIFICATEVERIFIER_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp new file mode 100644 index 0000000..a67052e --- /dev/null +++ b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.cpp @@ -0,0 +1,191 @@ +// +// 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 diff --git a/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp new file mode 100644 index 0000000..4aa4445 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/defaultCertificateVerifier.hpp @@ -0,0 +1,98 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED +#define VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#include "vmime/security/cert/certificateVerifier.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +class X509Certificate; + + +/** Default implementation for certificate verification. + */ +class VMIME_EXPORT defaultCertificateVerifier : public certificateVerifier { + +private: + + defaultCertificateVerifier(const defaultCertificateVerifier&); + +public: + + defaultCertificateVerifier(); + ~defaultCertificateVerifier(); + + /** Sets a list of X.509 certificates that are trusted. + * + * @param trustedCerts list of trusted certificates + */ + void setX509TrustedCerts(const std::vector <shared_ptr <X509Certificate> >& trustedCerts); + + /** Sets the X.509 root CAs used for certificate verification. + * + * @param caCerts list of root CAs + */ + void setX509RootCAs(const std::vector <shared_ptr <X509Certificate> >& caCerts); + + + // Implementation of 'certificateVerifier' + void verify(const shared_ptr <certificateChain>& chain, const string& hostname); + +private: + + /** Verify a chain of X.509 certificates. + * + * @param chain list of X.509 certificates + * @param hostname server hostname + */ + void verifyX509(const shared_ptr <certificateChain>& chain, const string& hostname); + + + std::vector <shared_ptr <X509Certificate> > m_x509RootCAs; + std::vector <shared_ptr <X509Certificate> > m_x509TrustedCerts; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT + + +#endif // VMIME_SECURITY_CERT_DEFAULTCERTIFICATEVERIFIER_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp new file mode 100644 index 0000000..3dfa1c6 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp @@ -0,0 +1,395 @@ +// +// 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 && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS + + +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> + +#include <ctime> + +#include "vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp" + +#include "vmime/utility/outputStreamByteArrayAdapter.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +#ifndef VMIME_BUILDING_DOC + +struct GnuTLSX509CertificateInternalData { + + GnuTLSX509CertificateInternalData() { + + gnutls_x509_crt_init(&cert); + } + + ~GnuTLSX509CertificateInternalData() { + + gnutls_x509_crt_deinit(cert); + } + + void swap(gnutls_x509_crt_t to) { + gnutls_x509_crt_deinit(cert); + cert = to; + } + + + gnutls_x509_crt_t cert; +}; + +#endif // VMIME_BUILDING_DOC + + +X509Certificate_GnuTLS::X509Certificate_GnuTLS() + : m_data(new GnuTLSX509CertificateInternalData) { + +} + + +X509Certificate_GnuTLS::X509Certificate_GnuTLS(const X509Certificate&) + : X509Certificate(), m_data(NULL) { + + // Not used +} + + +X509Certificate_GnuTLS::~X509Certificate_GnuTLS() { + + delete m_data; +} + + +void* X509Certificate_GnuTLS::getInternalData() { + + return &m_data->cert; +} + + +// static +shared_ptr <X509Certificate> X509Certificate::import( + utility::inputStream& is +) { + + byteArray bytes; + byte_t chunk[4096]; + + while (!is.eof()) { + const size_t len = is.read(chunk, sizeof(chunk)); + bytes.insert(bytes.end(), chunk, chunk + len); + } + + return import(&bytes[0], bytes.size()); +} + + +// static +shared_ptr <X509Certificate> X509Certificate::import( + const byte_t* data, + const size_t length +) { + + gnutls_datum_t buffer; + buffer.data = const_cast <byte_t*>(data); + buffer.size = static_cast <unsigned int>(length); + + // Try DER format + shared_ptr <X509Certificate_GnuTLS> derCert = make_shared <X509Certificate_GnuTLS>(); + + if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0) { + return derCert; + } + + // Try PEM format + shared_ptr <X509Certificate_GnuTLS> pemCert = make_shared <X509Certificate_GnuTLS>(); + + if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0) { + return pemCert; + } + + return null; +} + + +// static +void X509Certificate::import( + utility::inputStream& is, + std::vector <shared_ptr <X509Certificate> >& certs +) { + + byteArray bytes; + byte_t chunk[4096]; + + while (!is.eof()) { + const size_t len = is.read(chunk, sizeof(chunk)); + bytes.insert(bytes.end(), chunk, chunk + len); + } + + import(&bytes[0], bytes.size(), certs); +} + + +// static +void X509Certificate::import( + const byte_t* data, + const size_t length, + std::vector <shared_ptr <X509Certificate> >& certs +) { + + gnutls_datum_t buffer; + buffer.data = const_cast <byte_t*>(data); + buffer.size = static_cast <unsigned int>(length); + + unsigned int size = 1024; + gnutls_x509_crt_t x509[1024]; + + // Try DER format + if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_DER, 0) < 0) { + + // Try PEM format + if (gnutls_x509_crt_list_import(x509, &size, &buffer, GNUTLS_X509_FMT_PEM, 0) < 0) { + return; + } + } + + for (unsigned int i = 0 ; i < size ; i += 1) { + + auto c = make_shared <X509Certificate_GnuTLS>(); + c->m_data->swap(x509[i]); + certs.push_back(c); + } +} + + +void X509Certificate_GnuTLS::write( + utility::outputStream& os, + const Format format +) const { + + size_t dataSize = 0; + gnutls_x509_crt_fmt_t fmt = GNUTLS_X509_FMT_DER; + + switch (format) { + case FORMAT_DER: fmt = GNUTLS_X509_FMT_DER; break; + case FORMAT_PEM: fmt = GNUTLS_X509_FMT_PEM; break; + } + + gnutls_x509_crt_export(m_data->cert, fmt, NULL, &dataSize); + + std::vector <byte_t> data(dataSize); + + gnutls_x509_crt_export(m_data->cert, fmt, &data[0], &dataSize); + + os.write(reinterpret_cast <byte_t*>(&data[0]), dataSize); +} + + +const byteArray X509Certificate_GnuTLS::getSerialNumber() const { + + char serial[64]; + size_t serialSize = sizeof(serial); + + gnutls_x509_crt_get_serial(m_data->cert, serial, &serialSize); + + return byteArray(serial, serial + serialSize); +} + + +bool X509Certificate_GnuTLS::checkIssuer(const shared_ptr <const X509Certificate>& issuer_) const { + + shared_ptr <const X509Certificate_GnuTLS> issuer = + dynamicCast <const X509Certificate_GnuTLS>(issuer_); + + return gnutls_x509_crt_check_issuer(m_data->cert, issuer->m_data->cert) >= 1; +} + + +bool X509Certificate_GnuTLS::verify(const shared_ptr <const X509Certificate>& caCert_) const { + + shared_ptr <const X509Certificate_GnuTLS> caCert = + dynamicCast <const X509Certificate_GnuTLS>(caCert_); + + unsigned int verify = 0; + + const int res = gnutls_x509_crt_verify( + m_data->cert, &(caCert->m_data->cert), 1, + GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, + &verify + ); + + return res == 0 && verify == 0; +} + + +bool X509Certificate_GnuTLS::verifyHostName( + const string& hostname, + std::vector <std::string>* nonMatchingNames +) const { + + if (gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0) { + return true; + } + + if (nonMatchingNames) { + + const int MAX_CN = 256; + const char* OID_X520_COMMON_NAME = "2.5.4.3"; + + char dnsName[MAX_CN]; + size_t dnsNameLength; + + dnsNameLength = sizeof(dnsName); + + if (gnutls_x509_crt_get_dn_by_oid(m_data->cert, OID_X520_COMMON_NAME, 0, 0, dnsName, &dnsNameLength) >= 0) { + nonMatchingNames->push_back(dnsName); + } + + for (int i = 0, ret = 0 ; ret >= 0 ; ++i) { + + dnsNameLength = sizeof(dnsName); + ret = gnutls_x509_crt_get_subject_alt_name(m_data->cert, i, dnsName, &dnsNameLength, NULL); + + if (ret == GNUTLS_SAN_DNSNAME) { + nonMatchingNames->push_back(dnsName); + } + } + } + + return false; +} + + +const datetime X509Certificate_GnuTLS::getActivationDate() const { + + const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert); + return datetime(t); +} + + +const datetime X509Certificate_GnuTLS::getExpirationDate() const { + + const time_t t = gnutls_x509_crt_get_expiration_time(m_data->cert); + return datetime(t); +} + + +const byteArray X509Certificate_GnuTLS::getFingerprint(const DigestAlgorithm algo) const { + + gnutls_digest_algorithm_t galgo; + + switch (algo) { + + case DIGEST_MD5: + + galgo = GNUTLS_DIG_MD5; + break; + + default: + case DIGEST_SHA1: + + galgo = GNUTLS_DIG_SHA; + break; + } + + size_t bufferSize = 0; + gnutls_x509_crt_get_fingerprint(m_data->cert, galgo, NULL, &bufferSize); + + std::vector <byte_t> buffer(bufferSize); + + if (gnutls_x509_crt_get_fingerprint(m_data->cert, galgo, &buffer[0], &bufferSize) == 0) { + + byteArray res; + res.insert(res.end(), &buffer[0], &buffer[0] + bufferSize); + + return res; + } + + return byteArray(); +} + + +const byteArray X509Certificate_GnuTLS::getEncoded() const { + + byteArray bytes; + utility::outputStreamByteArrayAdapter os(bytes); + + write(os, FORMAT_DER); + + return bytes; +} + + +const string X509Certificate_GnuTLS::getIssuerString() const { + + char buffer[4096]; + size_t bufferSize = sizeof(buffer); + + if (gnutls_x509_crt_get_issuer_dn(m_data->cert, buffer, &bufferSize) != GNUTLS_E_SUCCESS) { + return ""; + } + + return buffer; +} + + +const string X509Certificate_GnuTLS::getType() const { + + return "X.509"; +} + + +int X509Certificate_GnuTLS::getVersion() const { + + return gnutls_x509_crt_get_version(m_data->cert); +} + + +bool X509Certificate_GnuTLS::equals(const shared_ptr <const certificate>& other) const { + + shared_ptr <const X509Certificate_GnuTLS> otherX509 = + dynamicCast <const X509Certificate_GnuTLS>(other); + + if (!otherX509) { + return false; + } + + const byteArray fp1 = getFingerprint(DIGEST_MD5); + const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5); + + return fp1 == fp2; +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS diff --git a/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp new file mode 100644 index 0000000..c7c6c48 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.hpp @@ -0,0 +1,96 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED +#define VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS + + +#include "vmime/security/cert/X509Certificate.hpp" + + +namespace vmime { +namespace security { +namespace cert { + + +class X509Certificate_GnuTLS : public X509Certificate { + + friend class X509Certificate; + + X509Certificate_GnuTLS(const X509Certificate&); + +public: + + X509Certificate_GnuTLS(); + + ~X509Certificate_GnuTLS(); + + + void write(utility::outputStream& os, const Format format) const; + + const byteArray getSerialNumber() const; + + const string getIssuerString() const; + bool checkIssuer(const shared_ptr <const X509Certificate>& issuer) const; + + bool verify(const shared_ptr <const X509Certificate>& caCert) const; + + bool verifyHostName( + const string& hostname, + std::vector <std::string>* nonMatchingNames = NULL + ) const; + + const datetime getExpirationDate() const; + const datetime getActivationDate() const; + + const byteArray getFingerprint(const DigestAlgorithm algo) const; + + + // Implementation of 'certificate' + const byteArray getEncoded() const; + const string getType() const; + int getVersion() const; + bool equals(const shared_ptr <const certificate>& other) const; + void* getInternalData(); + +private: + + struct GnuTLSX509CertificateInternalData* m_data; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS + +#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_GNUTLS_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp new file mode 100644 index 0000000..5488801 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp @@ -0,0 +1,655 @@ +// +// 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 && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL + + +#include <cstdio> +#include <ctime> +#include <map> +#include <algorithm> + +#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp" + +#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" + +#include "vmime/utility/outputStreamByteArrayAdapter.hpp" + +#include "vmime/security/cert/certificateException.hpp" +#include "vmime/security/cert/unsupportedCertificateTypeException.hpp" + +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/conf.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/err.h> + + +#ifdef _WIN32 +# define strcasecmp _stricmp +# define strncasecmp _strnicmp +#endif + + +namespace vmime { +namespace security { +namespace cert { + + +static net::tls::OpenSSLInitializer::autoInitializer openSSLInitializer; + + +#ifndef VMIME_BUILDING_DOC + +class monthMap { + +public: + + monthMap() { + + m_monthMap["jan"] = vmime::datetime::JAN; + m_monthMap["feb"] = vmime::datetime::FEB; + m_monthMap["mar"] = vmime::datetime::MAR; + m_monthMap["apr"] = vmime::datetime::APR; + m_monthMap["may"] = vmime::datetime::MAY; + m_monthMap["jun"] = vmime::datetime::JUN; + m_monthMap["jul"] = vmime::datetime::JUL; + m_monthMap["aug"] = vmime::datetime::AUG; + m_monthMap["sep"] = vmime::datetime::SEP; + m_monthMap["oct"] = vmime::datetime::OCT; + m_monthMap["nov"] = vmime::datetime::NOV; + m_monthMap["dec"] = vmime::datetime::DEC; + } + + int getMonth(vmime::string mstr) { + + std::transform(mstr.begin(), mstr.end(), mstr.begin(), ::tolower); + + std::map <vmime::string, vmime::datetime::Months>::const_iterator + c_it = m_monthMap.find(mstr); + + if (c_it != m_monthMap.end()) { + return c_it->second; + } + + return -1; + } + +private: + + std::map<vmime::string, vmime::datetime::Months> m_monthMap; +}; + +static monthMap sg_monthMap; + + + +struct OpenSSLX509CertificateInternalData { + + OpenSSLX509CertificateInternalData() { + + cert = 0; + } + + ~OpenSSLX509CertificateInternalData() { + + if (cert) { + X509_free(cert); + } + } + + X509* cert; +}; + + +// Workaround for i2v() taking either a const or a non-const 'method' on some platforms +STACK_OF(CONF_VALUE)* call_i2v(const X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) { + + return m->i2v(m, p1, p2); +} + + +STACK_OF(CONF_VALUE)* call_i2v(X509V3_EXT_METHOD* m, void* p1, STACK_OF(CONF_VALUE)* p2) { + + return m->i2v(m, p1, p2); +} + + +#endif // VMIME_BUILDING_DOC + + +X509Certificate_OpenSSL::X509Certificate_OpenSSL() + : m_data(new OpenSSLX509CertificateInternalData) { + +} + + +X509Certificate_OpenSSL::X509Certificate_OpenSSL(X509* cert) + : m_data(new OpenSSLX509CertificateInternalData) { + + m_data->cert = X509_dup(cert); +} + + +X509Certificate_OpenSSL::X509Certificate_OpenSSL(const X509Certificate_OpenSSL&) + : X509Certificate(), m_data(NULL) { + + // Not used +} + + +X509Certificate_OpenSSL::~X509Certificate_OpenSSL() { + + delete m_data; +} + + +void* X509Certificate_OpenSSL::getInternalData() { + + return &m_data->cert; +} + + +// static +shared_ptr <X509Certificate> X509Certificate_OpenSSL::importInternal(X509* cert) { + + if (cert) { + return make_shared <X509Certificate_OpenSSL>(reinterpret_cast <X509 *>(cert)); + } + + return null; +} + + +// static +shared_ptr <X509Certificate> X509Certificate::import(utility::inputStream& is) { + + byteArray bytes; + byte_t chunk[4096]; + + while (!is.eof()) { + const size_t len = is.read(chunk, sizeof(chunk)); + bytes.insert(bytes.end(), chunk, chunk + len); + } + + return import(&bytes[0], bytes.size()); +} + + +// static +shared_ptr <X509Certificate> X509Certificate::import( + const byte_t* data, + const size_t length +) { + + shared_ptr <X509Certificate_OpenSSL> cert = make_shared <X509Certificate_OpenSSL>(); + + BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), static_cast <int>(length)); + + if (!(cert->m_data->cert = d2i_X509_bio(membio, NULL)) + /*!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)*/) { + BIO_vfree(membio); + return null; + } + + BIO_vfree(membio); + + return cert; +} + + +// static +void X509Certificate::import( + utility::inputStream& is, + std::vector <shared_ptr <X509Certificate> >& certs +) { + + byteArray bytes; + byte_t chunk[4096]; + + while (!is.eof()) { + const size_t len = is.read(chunk, sizeof(chunk)); + bytes.insert(bytes.end(), chunk, chunk + len); + } + + import(&bytes[0], bytes.size(), certs); +} + + +// static +void X509Certificate::import( + const byte_t* data, + const size_t length, + std::vector <shared_ptr <X509Certificate> >& certs +) { + + BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), static_cast <int>(length)); + shared_ptr <X509Certificate_OpenSSL> cert = null; + + while (true) { + + cert = make_shared <X509Certificate_OpenSSL>(); + + if (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) { + break; + } + + certs.push_back(cert); + } + + BIO_vfree(membio); +} + + +void X509Certificate_OpenSSL::write( + utility::outputStream& os, + const Format format +) const { + + BIO* membio = 0; + long dataSize = 0; + unsigned char* out = 0; + + if (format == FORMAT_DER) { + + if ((dataSize = i2d_X509(m_data->cert, &out)) < 0) { + goto err; + } + + os.write(reinterpret_cast <byte_t*>(out), dataSize); + os.flush(); + OPENSSL_free(out); + + } else if (format == FORMAT_PEM) { + + membio = BIO_new(BIO_s_mem()); + BIO_set_close(membio, BIO_CLOSE); + + if (!PEM_write_bio_X509(membio, m_data->cert)) { + goto pem_err; + } + + dataSize = BIO_get_mem_data(membio, &out); + os.write(reinterpret_cast <byte_t*>(out), dataSize); + os.flush(); + BIO_vfree(membio); + + } else { + + throw unsupportedCertificateTypeException("Unknown format"); + } + + return; // #### Early Return #### + +pem_err: + { + if (membio) { + BIO_vfree(membio); + } + } + +err: + { + char errstr[256]; + long ec = ERR_get_error(); + ERR_error_string(ec, errstr); + throw certificateException("OpenSSLX509Certificate_OpenSSL::write exception - " + string(errstr)); + } +} + + +const byteArray X509Certificate_OpenSSL::getSerialNumber() const { + + ASN1_INTEGER *serial = X509_get_serialNumber(m_data->cert); + BIGNUM *bnser = ASN1_INTEGER_to_BN(serial, NULL); + int n = BN_num_bytes(bnser); + byte_t* outbuf = new byte_t[n]; + BN_bn2bin(bnser, outbuf); + byteArray ser(outbuf, outbuf + n); + delete [] outbuf; + BN_free(bnser); + return ser; +} + + +bool X509Certificate_OpenSSL::checkIssuer(const shared_ptr <const X509Certificate>& cert_) const { + + shared_ptr <const X509Certificate_OpenSSL> cert = + dynamicCast <const X509Certificate_OpenSSL>(cert_); + + // Get issuer for this cert + BIO *out; + unsigned char *issuer; + + out = BIO_new(BIO_s_mem()); + X509_NAME_print_ex(out, X509_get_issuer_name(m_data->cert), 0, XN_FLAG_RFC2253); + long n = BIO_get_mem_data(out, &issuer); + vmime::string thisIssuerName((char*)issuer, n); + BIO_free(out); + + // Get subject of issuer + unsigned char *subject; + out = BIO_new(BIO_s_mem()); + X509_NAME_print_ex(out, X509_get_subject_name(cert->m_data->cert), 0, XN_FLAG_RFC2253); + n = BIO_get_mem_data(out, &subject); + vmime::string subjOfIssuer((char*)subject, n); + BIO_free(out); + + return subjOfIssuer == thisIssuerName; +} + + +bool X509Certificate_OpenSSL::verify(const shared_ptr <const X509Certificate>& caCert_) const { + + shared_ptr <const X509Certificate_OpenSSL> caCert = + dynamicCast <const X509Certificate_OpenSSL>(caCert_); + +// printf("ptr before cast is %p\n", caCert_.get()); +// printf("ptr is %p\n", caCert.get()); + + bool verified = false; + bool error = true; + + X509_STORE *store = X509_STORE_new(); + + if (store) { + + X509_STORE_CTX *verifyCtx = X509_STORE_CTX_new(); + + if (verifyCtx) { + + if (X509_STORE_add_cert(store, caCert->m_data->cert)) { + + X509_STORE_CTX_init(verifyCtx, store, m_data->cert, NULL); + + int ret = X509_verify_cert(verifyCtx); + + if (ret == 1) { + + verified = true; + error = false; + + } else if (ret == 0) { + + verified = false; + error = false; + } + + //X509_verify_cert_error_string(vrfy_ctx->error) + + X509_STORE_CTX_free(verifyCtx); + } + } + + X509_STORE_free(store); + } + + return verified && !error; +} + + +// static +bool X509Certificate_OpenSSL::cnMatch(const char* cnBuf, const char* host) { + + // Right-to-left match, looking for a '*' wildcard + const bool hasWildcard = (strlen(cnBuf) > 1 && cnBuf[0] == '*' && cnBuf[1] == '.'); + const char* cnBufReverseEndPtr = (cnBuf + (hasWildcard ? 2 : 0)); + const char* hostPtr = host + strlen(host); + const char* cnPtr = cnBuf + strlen(cnBuf); + + bool matches = true; + + while (matches && --hostPtr >= host && --cnPtr >= cnBufReverseEndPtr) { + matches = (toupper(*hostPtr) == toupper(*cnPtr)); + } + + return matches; +} + + +bool X509Certificate_OpenSSL::verifyHostName( + const string& hostname, + std::vector <std::string>* nonMatchingNames +) const { + + // First, check subject common name against hostname + char CNBuffer[1024]; + CNBuffer[sizeof(CNBuffer) - 1] = '\0'; + + X509_NAME* xname = X509_get_subject_name(m_data->cert); + + if (X509_NAME_get_text_by_NID(xname, NID_commonName, CNBuffer, sizeof(CNBuffer)) != -1) { + + if (cnMatch(CNBuffer, hostname.c_str())) { + return true; + } + + if (nonMatchingNames) { + nonMatchingNames->push_back(CNBuffer); + } + } + + // Now, look in subject alternative names + bool verify = false; + + STACK_OF(GENERAL_NAME)* altNames = static_cast <GENERAL_NAMES*> + (X509_get_ext_d2i(m_data->cert, NID_subject_alt_name, NULL, NULL)); + + if (altNames == NULL) { + return false; + } + + // Check each name within the extension + for (int i = 0, n = sk_GENERAL_NAME_num(altNames) ; i < n ; ++i) { + + const GENERAL_NAME* currentName = sk_GENERAL_NAME_value(altNames, i); + + if (currentName->type == GEN_DNS) { + + // Current name is a DNS name, let's check it + char *DNSName = (char *) ASN1_STRING_data(currentName->d.dNSName); + + // Make sure there isn't an embedded NUL character in the DNS name + if (ASN1_STRING_length(currentName->d.dNSName) != strlen(DNSName)) { + // Malformed certificate + break; + } + + if (cnMatch(DNSName, hostname.c_str())) { + verify = true; + break; + } + + if (nonMatchingNames) { + nonMatchingNames->push_back(DNSName); + } + } + } + + sk_GENERAL_NAME_pop_free(altNames, GENERAL_NAME_free); + + return verify; +} + + +const datetime X509Certificate_OpenSSL::convertX509Date(void* time) const { + + char* buffer; + BIO* out = BIO_new(BIO_s_mem()); + BIO_set_close(out, BIO_CLOSE); + + ASN1_TIME* asn1_time = reinterpret_cast<ASN1_TIME*>(time); + ASN1_TIME_print(out, asn1_time); + + const long sz = BIO_get_mem_data(out, &buffer); + char* dest = new char[sz + 1]; + dest[sz] = 0; + memcpy(dest, buffer, sz); + vmime::string t(dest); + + BIO_free(out); + delete [] dest; + + if (t.size() > 0) { + + char month[4] = {0}; + char zone[4] = {0}; + int day, hour, minute, second, year; + int nrconv = sscanf(t.c_str(), "%s %2d %02d:%02d:%02d %d%s", month, &day, &hour, &minute, &second,&year,zone); + + if (nrconv >= 6) { + return datetime(year, sg_monthMap.getMonth(vmime::string(month)), day, hour, minute, second); + } + } + + // let datetime try and parse it + return datetime(t); +} + + +const datetime X509Certificate_OpenSSL::getActivationDate() const { + + return convertX509Date(X509_get_notBefore(m_data->cert)); +} + + +const datetime X509Certificate_OpenSSL::getExpirationDate() const { + + return convertX509Date(X509_get_notAfter(m_data->cert)); +} + + +const byteArray X509Certificate_OpenSSL::getFingerprint(const DigestAlgorithm algo) const { + + BIO *out; + int j; + unsigned int n; + const EVP_MD *digest; + unsigned char * fingerprint; + unsigned char md[EVP_MAX_MD_SIZE]; + + switch (algo) { + + case DIGEST_MD5: + + digest = EVP_md5(); + break; + + default: + case DIGEST_SHA1: + + digest = EVP_sha1(); + break; + } + + out = BIO_new(BIO_s_mem()); + BIO_set_close(out, BIO_CLOSE); + + if (X509_digest(m_data->cert, digest, md, &n)) { + + for (j = 0 ; j < (int) n ; j++) { + BIO_printf(out, "%02X", md[j]); + if (j + 1 != (int) n) BIO_printf(out, ":"); + } + } + + const long resultLen = BIO_get_mem_data(out, &fingerprint); + unsigned char* result = new unsigned char[resultLen]; + memcpy(result, fingerprint, resultLen); + BIO_free(out); + + byteArray res; + res.insert(res.end(), &result[0], &result[0] + resultLen); + + delete [] result; + + return res; +} + + +const byteArray X509Certificate_OpenSSL::getEncoded() const { + + byteArray bytes; + utility::outputStreamByteArrayAdapter os(bytes); + + write(os, FORMAT_DER); + + return bytes; +} + + +const string X509Certificate_OpenSSL::getIssuerString() const { + + // Get issuer for this cert + BIO* out = BIO_new(BIO_s_mem()); + X509_NAME_print_ex(out, X509_get_issuer_name(m_data->cert), 0, XN_FLAG_RFC2253); + + unsigned char* issuer; + const long n = BIO_get_mem_data(out, &issuer); + + vmime::string name(reinterpret_cast <char*>(issuer), n); + BIO_free(out); + + return name; +} + + +const string X509Certificate_OpenSSL::getType() const { + + return "X.509"; +} + + +int X509Certificate_OpenSSL::getVersion() const { + + return (int) X509_get_version(m_data->cert); +} + + +bool X509Certificate_OpenSSL::equals(const shared_ptr <const certificate>& other) const { + + shared_ptr <const X509Certificate_OpenSSL> otherX509 = + dynamicCast <const X509Certificate_OpenSSL>(other); + + if (!otherX509) { + return false; + } + + const byteArray fp1 = getFingerprint(DIGEST_MD5); + const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5); + + return fp1 == fp2; +} + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL + diff --git a/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp new file mode 100644 index 0000000..c0ebf3c --- /dev/null +++ b/vmime-master/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp @@ -0,0 +1,119 @@ +// +// 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. +// + +#ifndef VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED +#define VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL + + +#include "vmime/security/cert/X509Certificate.hpp" + +#include <openssl/x509.h> + + +namespace vmime { +namespace security { +namespace cert { + + +class X509Certificate_OpenSSL : public X509Certificate { + + friend class X509Certificate; + + X509Certificate_OpenSSL(const X509Certificate_OpenSSL&); + +public: + + X509Certificate_OpenSSL(); + X509Certificate_OpenSSL(X509* cert); + + ~X509Certificate_OpenSSL(); + + + void write(utility::outputStream& os, const Format format) const; + + const byteArray getSerialNumber() const; + + const string getIssuerString() const; + bool checkIssuer(const shared_ptr <const X509Certificate>& issuer) const; + + bool verify(const shared_ptr <const X509Certificate>& caCert) const; + + bool verifyHostName( + const string& hostname, + std::vector <std::string>* nonMatchingNames = NULL + ) const; + + const datetime getExpirationDate() const; + const datetime getActivationDate() const; + + const byteArray getFingerprint(const DigestAlgorithm algo) const; + + + static shared_ptr <X509Certificate> importInternal(X509* cert); + + + // Implementation of 'certificate' + const byteArray getEncoded() const; + const string getType() const; + int getVersion() const; + bool equals(const shared_ptr <const certificate>& other) const; + void* getInternalData(); + +private: + + /** Internal utility function to test whether a hostname matches + * the specified X509 Common Name (wildcard is supported). + * + * @param cnBuf pointer to buffer holding Common Name + * @param host pointer to buffer holding host name + * @return true if the hostname matches the Common Name, or + * false otherwise + */ + static bool cnMatch(const char* cnBuf, const char* host); + + /** Internal utility function to convert ASN1_TIME + * structs to vmime::datetime + * + * @param pointer to ASN1_TIME struct to convert + */ + const datetime convertX509Date(void* time) const; + + struct OpenSSLX509CertificateInternalData* m_data; +}; + + +} // cert +} // security +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL + +#endif // VMIME_SECURITY_CERT_X509CERTIFICATE_OPENSSL_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/security/cert/serverIdentityException.cpp b/vmime-master/src/vmime/security/cert/serverIdentityException.cpp new file mode 100644 index 0000000..fcbe571 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/serverIdentityException.cpp @@ -0,0 +1,55 @@ +// +// 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/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/vmime-master/src/vmime/security/cert/serverIdentityException.hpp b/vmime-master/src/vmime/security/cert/serverIdentityException.hpp new file mode 100644 index 0000000..358553e --- /dev/null +++ b/vmime-master/src/vmime/security/cert/serverIdentityException.hpp @@ -0,0 +1,65 @@ +// +// 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. +// + +#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/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp new file mode 100644 index 0000000..5765651 --- /dev/null +++ b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.cpp @@ -0,0 +1,61 @@ +// +// 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/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/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp new file mode 100644 index 0000000..725035f --- /dev/null +++ b/vmime-master/src/vmime/security/cert/unsupportedCertificateTypeException.hpp @@ -0,0 +1,72 @@ +// +// 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. +// + +#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 |