aboutsummaryrefslogtreecommitdiffstats
path: root/src/security
diff options
context:
space:
mode:
Diffstat (limited to 'src/security')
-rw-r--r--src/security/cert/X509Certificate.cpp228
-rw-r--r--src/security/cert/gnutls/X509Certificate_GnuTLS.cpp278
-rwxr-xr-xsrc/security/cert/openssl/X509Certificate_OpenSSL.cpp467
3 files changed, 751 insertions, 222 deletions
diff --git a/src/security/cert/X509Certificate.cpp b/src/security/cert/X509Certificate.cpp
index 8df4e5e8..4b177f13 100644
--- a/src/security/cert/X509Certificate.cpp
+++ b/src/security/cert/X509Certificate.cpp
@@ -21,14 +21,13 @@
// the GNU General Public License cover the whole combination.
//
-#include <gnutls/gnutls.h>
-#include <gnutls/x509.h>
+#include "vmime/config.hpp"
-#include <ctime>
-#include "vmime/security/cert/X509Certificate.hpp"
+#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
+
-#include "vmime/utility/outputStreamByteArrayAdapter.hpp"
+#include "vmime/security/cert/X509Certificate.hpp"
namespace vmime {
@@ -36,225 +35,8 @@ namespace security {
namespace cert {
-#ifndef VMIME_BUILDING_DOC
-
-struct X509CertificateInternalData
-{
- X509CertificateInternalData()
- {
- gnutls_x509_crt_init(&cert);
- }
-
- ~X509CertificateInternalData()
- {
- gnutls_x509_crt_deinit(cert);
- }
-
-
- gnutls_x509_crt cert;
-};
-
-#endif // VMIME_BUILDING_DOC
-
-
-X509Certificate::X509Certificate()
- : m_data(new X509CertificateInternalData)
-{
-}
-
-
-X509Certificate::X509Certificate(const X509Certificate&)
- : certificate(), m_data(NULL)
-{
- // Not used
-}
-
-
X509Certificate::~X509Certificate()
{
- delete m_data;
-}
-
-
-// static
-ref <X509Certificate> X509Certificate::import(utility::inputStream& is)
-{
- byteArray bytes;
- utility::stream::value_type chunk[4096];
-
- while (!is.eof())
- {
- const int len = is.read(chunk, sizeof(chunk));
- bytes.insert(bytes.end(), chunk, chunk + len);
- }
-
- return import(&bytes[0], bytes.size());
-}
-
-
-// static
-ref <X509Certificate> X509Certificate::import
- (const byte_t* data, const unsigned int length)
-{
- gnutls_datum buffer;
- buffer.data = const_cast <byte_t*>(data);
- buffer.size = length;
-
- // Try DER format
- ref <X509Certificate> derCert = vmime::create <X509Certificate>();
-
- if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0)
- return derCert;
-
- // Try PEM format
- ref <X509Certificate> pemCert = vmime::create <X509Certificate>();
-
- if (gnutls_x509_crt_import(pemCert->m_data->cert, &buffer, GNUTLS_X509_FMT_PEM) >= 0)
- return pemCert;
-
- return NULL;
-}
-
-
-void X509Certificate::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 <utility::stream::value_type*>(&data[0]), dataSize);
-}
-
-
-const byteArray X509Certificate::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::checkIssuer(ref <const X509Certificate> issuer) const
-{
- return (gnutls_x509_crt_check_issuer
- (m_data->cert, issuer->m_data->cert) >= 1);
-}
-
-
-bool X509Certificate::verify(ref <const X509Certificate> caCert) const
-{
- 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);
-}
-
-
-const datetime X509Certificate::getActivationDate() const
-{
- const time_t t = gnutls_x509_crt_get_activation_time(m_data->cert);
- return datetime(t);
-}
-
-
-const datetime X509Certificate::getExpirationDate() const
-{
- const time_t t = gnutls_x509_crt_get_expiration_time(m_data->cert);
- return datetime(t);
-}
-
-
-const byteArray X509Certificate::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::getEncoded() const
-{
- byteArray bytes;
- utility::outputStreamByteArrayAdapter os(bytes);
-
- write(os, FORMAT_DER);
-
- return bytes;
-}
-
-
-const string X509Certificate::getType() const
-{
- return "X.509";
-}
-
-
-int X509Certificate::getVersion() const
-{
- return gnutls_x509_crt_get_version(m_data->cert);
-}
-
-
-bool X509Certificate::equals(ref <const certificate> other) const
-{
- ref <const X509Certificate> otherX509 =
- other.dynamicCast <const X509Certificate>();
-
- if (!otherX509)
- return false;
-
- const byteArray fp1 = getFingerprint(DIGEST_MD5);
- const byteArray fp2 = otherX509->getFingerprint(DIGEST_MD5);
-
- return fp1 == fp2;
}
@@ -262,3 +44,5 @@ bool X509Certificate::equals(ref <const certificate> other) const
} // security
} // vmime
+
+#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT
diff --git a/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
new file mode 100644
index 00000000..739b03f1
--- /dev/null
+++ b/src/security/cert/gnutls/X509Certificate_GnuTLS.cpp
@@ -0,0 +1,278 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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&)
+ : certificate(), m_data(NULL)
+{
+ // Not used
+}
+
+
+X509Certificate_GnuTLS::~X509Certificate_GnuTLS()
+{
+ delete m_data;
+}
+
+
+// static
+ref <X509Certificate> X509Certificate::import(utility::inputStream& is)
+{
+ byteArray bytes;
+ utility::stream::value_type chunk[4096];
+
+ while (!is.eof())
+ {
+ const int len = is.read(chunk, sizeof(chunk));
+ bytes.insert(bytes.end(), chunk, chunk + len);
+ }
+
+ return import(&bytes[0], bytes.size());
+}
+
+
+// static
+ref <X509Certificate> X509Certificate::import
+ (const byte_t* data, const unsigned int length)
+{
+ gnutls_datum buffer;
+ buffer.data = const_cast <byte_t*>(data);
+ buffer.size = length;
+
+ // Try DER format
+ ref <X509Certificate> derCert = vmime::create <X509Certificate_GnuTLS>();
+
+ if (gnutls_x509_crt_import(derCert->m_data->cert, &buffer, GNUTLS_X509_FMT_DER) >= 0)
+ return derCert;
+
+ // Try PEM format
+ ref <X509Certificate> pemCert = vmime::create <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 <utility::stream::value_type*>(&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(ref <const X509Certificate> issuer_) const
+{
+ ref <const X509Certificate_GnuTLS> issuer =
+ issuer.dynamicCast <const OpenSSLX509Certificate_GnuTLS>();
+
+ return (gnutls_x509_crt_check_issuer
+ (m_data->cert, issuer->m_data->cert) >= 1);
+}
+
+
+bool X509Certificate_GnuTLS::verify(ref <const X509Certificate> caCert_) const
+{
+ ref <const X509Certificate_GnuTLS> caCert =
+ caCert_.dynamicCast <const X509Certificate_GnuTLS>();
+
+ 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);
+}
+
+
+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(ref <const certificate> other) const
+{
+ ref <const X509Certificate_GnuTLS> otherX509 =
+ other.dynamicCast <const X509Certificate_GnuTLS>();
+
+ 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
new file mode 100755
index 00000000..dacb006e
--- /dev/null
+++ b/src/security/cert/openssl/X509Certificate_OpenSSL.cpp
@@ -0,0 +1,467 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2009 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/utility/outputStreamByteArrayAdapter.hpp"
+
+#include "vmime/exception.hpp"
+
+#include <openssl/x509.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+
+namespace vmime {
+namespace security {
+namespace cert {
+
+
+#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;
+}
+
+
+// static
+ref <X509Certificate> X509Certificate_OpenSSL::importInternal(X509* cert)
+{
+ if (cert)
+ return vmime::create <X509Certificate_OpenSSL>(reinterpret_cast <X509 *>(cert));
+
+ return NULL;
+}
+
+
+// static
+ref <X509Certificate> X509Certificate::import(utility::inputStream& is)
+{
+ byteArray bytes;
+ utility::stream::value_type chunk[4096];
+
+ while (!is.eof())
+ {
+ const int len = is.read(chunk, sizeof(chunk));
+ bytes.insert(bytes.end(), chunk, chunk + len);
+ }
+
+ return import(&bytes[0], bytes.size());
+}
+
+
+// static
+ref <X509Certificate> X509Certificate::import
+ (const byte_t* data, const unsigned int length)
+{
+ ref <X509Certificate_OpenSSL> cert = vmime::create <X509Certificate_OpenSSL>();
+
+ BIO* membio = BIO_new_mem_buf(const_cast <byte_t*>(data), 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;
+ int 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 <utility::stream::value_type*>(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 <utility::stream::value_type*>(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(ref <const X509Certificate> cert_) const
+{
+ ref <const X509Certificate_OpenSSL> cert =
+ cert_.dynamicCast <const X509Certificate_OpenSSL>();
+
+ // 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);
+ int 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(ref <const X509Certificate> caCert_) const
+{
+ ref <const X509Certificate_OpenSSL> caCert =
+ caCert_.dynamicCast <const X509Certificate_OpenSSL>();
+
+
+ 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;
+}
+
+
+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(ref <const certificate> other) const
+{
+ ref <const X509Certificate_OpenSSL> otherX509 =
+ other.dynamicCast <const X509Certificate_OpenSSL>();
+
+ 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
+