diff options
Diffstat (limited to 'src/security/cert')
| -rw-r--r-- | src/security/cert/X509Certificate.cpp | 48 | ||||
| -rw-r--r-- | src/security/cert/certificateChain.cpp | 53 | ||||
| -rw-r--r-- | src/security/cert/defaultCertificateVerifier.cpp | 178 | ||||
| -rw-r--r-- | src/security/cert/gnutls/X509Certificate_GnuTLS.cpp | 290 | ||||
| -rw-r--r-- | src/security/cert/openssl/X509Certificate_OpenSSL.cpp | 574 |
5 files changed, 0 insertions, 1143 deletions
diff --git a/src/security/cert/X509Certificate.cpp b/src/security/cert/X509Certificate.cpp deleted file mode 100644 index 2eebabfd..00000000 --- a/src/security/cert/X509Certificate.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// 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" - - -namespace vmime { -namespace security { -namespace cert { - - -X509Certificate::~X509Certificate() -{ -} - - -} // cert -} // security -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/security/cert/certificateChain.cpp b/src/security/cert/certificateChain.cpp deleted file mode 100644 index 3cb4e360..00000000 --- a/src/security/cert/certificateChain.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// 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) -{ -} - - -unsigned int certificateChain::getCount() const -{ - return static_cast <unsigned int>(m_certs.size()); -} - - -shared_ptr <certificate> certificateChain::getAt(const unsigned int index) -{ - return m_certs[index]; -} - - -} // cert -} // security -} // vmime - diff --git a/src/security/cert/defaultCertificateVerifier.cpp b/src/security/cert/defaultCertificateVerifier.cpp deleted file mode 100644 index 1a95b353..00000000 --- a/src/security/cert/defaultCertificateVerifier.cpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// 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_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 - (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 exceptions::unsupported_certificate_type(type); -} - - -void defaultCertificateVerifier::verifyX509 - (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 (unsigned int 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)) - { - throw exceptions::certificate_verification_exception - ("Subject/issuer verification failed."); - } - } - } - - // For every certificate in the chain, verify that the certificate - // is valid at the current time - const datetime now = datetime::now(); - - for (unsigned int i = 0 ; i < chain->getCount() ; ++i) - { - shared_ptr <X509Certificate> cert = - dynamicCast <X509Certificate>(chain->getAt(i)); - - const datetime begin = cert->getActivationDate(); - const datetime end = cert->getExpirationDate(); - - if (now < begin || now > end) - { - throw exceptions::certificate_verification_exception - ("Validity date check failed."); - } - } - - // 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 (unsigned int i = 0 ; !trusted && i < m_x509RootCAs.size() ; ++i) - { - shared_ptr <X509Certificate> rootCa = m_x509RootCAs[i]; - - if (lastCert->verify(rootCa)) - trusted = true; - } - - // -- Next, if the issuer certificate cannot be verified against - // -- root CAs, compare the subject's certificate against the - // -- trusted certificates - shared_ptr <X509Certificate> firstCert = - dynamicCast <X509Certificate>(chain->getAt(0)); - - for (unsigned int i = 0 ; !trusted && i < m_x509TrustedCerts.size() ; ++i) - { - shared_ptr <X509Certificate> cert = m_x509TrustedCerts[i]; - - if (firstCert->equals(cert)) - trusted = true; - } - - if (!trusted) - { - throw exceptions::certificate_verification_exception - ("Cannot verify certificate against trusted certificates."); - } - - // Ensure the first certificate's subject name matches server hostname - if (!firstCert->verifyHostName(hostname)) - { - throw exceptions::certificate_verification_exception - ("Server identity cannot be verified."); - } -} - - -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 diff --git a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp deleted file mode 100644 index f96ddddb..00000000 --- a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp +++ /dev/null @@ -1,290 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// 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); - } - - - gnutls_x509_crt 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 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; -} - - -void X509Certificate_GnuTLS::write - (utility::outputStream& os, const Format format) const -{ - size_t dataSize = 0; - gnutls_x509_crt_fmt 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(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(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) const -{ - return gnutls_x509_crt_check_hostname(m_data->cert, hostname.c_str()) != 0; -} - - -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 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::getType() const -{ - return "X.509"; -} - - -int X509Certificate_GnuTLS::getVersion() const -{ - return gnutls_x509_crt_get_version(m_data->cert); -} - - -bool X509Certificate_GnuTLS::equals(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/src/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp deleted file mode 100644 index 5f81b2bf..00000000 --- a/src/security/cert/openssl/X509Certificate_OpenSSL.cpp +++ /dev/null @@ -1,574 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> -// -// 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/exception.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; -}; - -#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 (!PEM_read_bio_X509(membio, &(cert->m_data->cert), 0, 0)) - { - BIO_vfree(membio); - return null; - } - - BIO_vfree(membio); - - return cert; -} - - -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 vmime::exceptions::unsupported_certificate_type("Unknown cert type"); - } - - 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 vmime::exceptions::certificate_exception( - "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(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(shared_ptr <const X509Certificate> caCert_) const -{ - shared_ptr <const X509Certificate_OpenSSL> caCert = - dynamicCast <const X509Certificate_OpenSSL>(caCert_); - - - 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) 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; - } - - // Now, look in subject alternative names - for (int i = 0, extCount = X509_get_ext_count(m_data->cert) ; i < extCount ; ++i) - { - X509_EXTENSION* ext = X509_get_ext(m_data->cert, i); - const char* extStr = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); - - if (strcmp(extStr, "subjectAltName") == 0) - { -#ifdef _WIN32 - X509V3_EXT_METHOD* method; -#else - const X509V3_EXT_METHOD* method; -#endif - - if ((method = X509V3_EXT_get(ext)) != NULL) - { - const unsigned char* extVal = ext->value->data; - void *extValStr; - - if (method->it) - { - extValStr = ASN1_item_d2i - (NULL, &extVal, ext->value->length, ASN1_ITEM_ptr(method->it)); - } - else - { - extValStr = method->d2i - (NULL, &extVal, ext->value->length); - } - - if (extValStr && method->i2v) - { - STACK_OF(CONF_VALUE)* val = method->i2v(method, extValStr, NULL); - - for (int j = 0 ; j < sk_CONF_VALUE_num(val) ; ++j) - { - CONF_VALUE* cnf = sk_CONF_VALUE_value(val, j); - - if ((strcasecmp(cnf->name, "DNS") == 0 && - strcasecmp(cnf->value, hostname.c_str()) == 0) - || - (strncasecmp(cnf->name, "IP", 2) == 0 && - strcasecmp(cnf->value, hostname.c_str()) == 0)) - { - return true; - } - } - } - } - } - } - - return false; -} - - -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); - - int 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, *result; - 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, ":"); - } - } - - n = BIO_get_mem_data(out, &fingerprint); - result = new unsigned char[n]; - memcpy (result, fingerprint, n); - BIO_free(out); - - byteArray res; - res.insert(res.end(), &result[0], &result[0] + n); - - 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::getType() const -{ - return "X.509"; -} - - -int X509Certificate_OpenSSL::getVersion() const -{ - return (int)X509_get_version(m_data->cert); -} - - -bool X509Certificate_OpenSSL::equals(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 - |
