diff --git a/src/vmime/security/cert/X509Certificate.hpp b/src/vmime/security/cert/X509Certificate.hpp index 3aca9dd6..acf4ae21 100644 --- a/src/vmime/security/cert/X509Certificate.hpp +++ b/src/vmime/security/cert/X509Certificate.hpp @@ -85,6 +85,23 @@ public: */ static shared_ptr import(const byte_t* data, const size_t length); + /** Imports a DER or PEM encoded X.509 certificate. + * + * @param is input stream to read data from + * @param certs the resulting list of certificates + */ + static void import(utility::inputStream& is, + std::vector >& certs); + + /** Imports a DER or PEM encoded X.509 certificate. + * + * @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 >& certs); + /** Exports this X.509 certificate to the specified format. * * @param os output stream into which write data @@ -106,7 +123,7 @@ public: * * @return distinguished name of the certificate issuer, as a string */ - const string getIssuerString() const; + virtual const string getIssuerString() const = 0; /** Checks if this certificate has the given issuer. * diff --git a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp index 478c1418..e23abc6d 100644 --- a/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp +++ b/src/vmime/security/cert/gnutls/X509Certificate_GnuTLS.cpp @@ -56,6 +56,11 @@ struct 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; }; @@ -128,6 +133,49 @@ shared_ptr X509Certificate::import } +// static +void X509Certificate::import(utility::inputStream& is, + std::vector >& 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 >& certs) +{ + gnutls_datum_t buffer; + buffer.data = const_cast (data); + buffer.size = static_cast (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 (); + c->m_data->swap(x509[i]); + certs.push_back(c); + } +} + + void X509Certificate_GnuTLS::write (utility::outputStream& os, const Format format) const { diff --git a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp index 45481861..9ce09592 100644 --- a/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp +++ b/src/vmime/security/cert/openssl/X509Certificate_OpenSSL.cpp @@ -218,6 +218,41 @@ shared_ptr X509Certificate::import } +// static +void X509Certificate::import(utility::inputStream& is, + std::vector >& 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 >& certs) +{ + + BIO* membio = BIO_new_mem_buf(const_cast (data), static_cast (length)); + shared_ptr cert = null; + + while (true) { + cert = make_shared (); + 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 {