diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-11-13 15:30:22 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-11-13 15:30:22 +0000 |
| commit | 7d7a93223e4dd32ca9bb1d7b1b2dd4fc4ea52be1 (patch) | |
| tree | fdc8ed1343cd1682b9392860ffe97760aac90b41 | |
| parent | 733b048746a5ac1e5dd7a594b7b9fdc30417e431 (diff) | |
Cope with certificate files that have no line breaks.
| -rw-r--r-- | src/certificate.cc | 52 | ||||
| -rw-r--r-- | test/certificates_test.cc | 13 |
2 files changed, 61 insertions, 4 deletions
diff --git a/src/certificate.cc b/src/certificate.cc index 3eb6e76b..72c53610 100644 --- a/src/certificate.cc +++ b/src/certificate.cc @@ -39,8 +39,13 @@ using std::list; using std::string; using std::ostream; +using std::min; +using std::stringstream; using namespace dcp; +static string const begin_certificate = "-----BEGIN CERTIFICATE-----"; +static string const end_certificate = "-----END CERTIFICATE-----"; + /** @param c X509 certificate, which this object will take ownership of */ Certificate::Certificate (X509* c) : _certificate (c) @@ -75,7 +80,48 @@ Certificate::Certificate (Certificate const & other) void Certificate::read_string (string cert) { - BIO* bio = BIO_new_mem_buf (const_cast<char *> (cert.c_str ()), -1); + /* Reformat cert so that it has line breaks every 64 characters. + See http://comments.gmane.org/gmane.comp.encryption.openssl.user/55593 + */ + + stringstream s (cert); + string line; + + /* BEGIN */ + getline (s, line); + boost::algorithm::trim (line); + if (line != begin_certificate) { + throw MiscError ("missing BEGIN line in certificate"); + } + + /* The base64 data */ + bool got_end = false; + string base64 = ""; + while (getline (s, line)) { + boost::algorithm::trim (line); + if (line == end_certificate) { + got_end = true; + break; + } + base64 += line; + } + + if (!got_end) { + throw MiscError ("missing END line in certificate"); + } + + /* Make up the fixed version */ + + string fixed = begin_certificate + "\n"; + while (!base64.empty ()) { + size_t const t = min (size_t(64), base64.length()); + fixed += base64.substr (0, t) + "\n"; + base64 = base64.substr (t, base64.length() - t); + } + + fixed += end_certificate; + + BIO* bio = BIO_new_mem_buf (const_cast<char *> (fixed.c_str ()), -1); if (!bio) { throw MiscError ("could not create memory BIO"); } @@ -141,8 +187,8 @@ Certificate::certificate (bool with_begin_end) const BIO_free (bio); if (!with_begin_end) { - boost::replace_all (s, "-----BEGIN CERTIFICATE-----\n", ""); - boost::replace_all (s, "\n-----END CERTIFICATE-----\n", ""); + boost::replace_all (s, begin_certificate + "\n", ""); + boost::replace_all (s, "\n" + end_certificate + "\n", ""); } return s; diff --git a/test/certificates_test.cc b/test/certificates_test.cc index 166ebb2d..a78c88d6 100644 --- a/test/certificates_test.cc +++ b/test/certificates_test.cc @@ -21,13 +21,15 @@ #include "certificate.h" #include "certificate_chain.h" #include "util.h" +#include "exceptions.h" +#include "test.h" using std::list; using std::string; using boost::shared_ptr; /** Check that loading certificates from files via strings works */ -BOOST_AUTO_TEST_CASE (certificates) +BOOST_AUTO_TEST_CASE (certificates1) { dcp::CertificateChain c; @@ -86,6 +88,15 @@ BOOST_AUTO_TEST_CASE (certificates) BOOST_CHECK_EQUAL (test.certificate(), c.root().certificate()); } +/** Check some more certificate-from-strings */ +BOOST_AUTO_TEST_CASE (certificates2) +{ + dcp::Certificate c (dcp::file_to_string (private_test / "CA.GDC-TECH.COM_SA2100_A14903.crt.crt")); + BOOST_CHECK_EQUAL (c.certificate(true), dcp::file_to_string (private_test / "CA.GDC-TECH.COM_SA2100_A14903.crt.crt.reformatted")); + + BOOST_CHECK_THROW (dcp::Certificate ("foo"), dcp::MiscError); +} + /** Check that dcp::CertificateChain::valid() and ::attempt_reorder() basically work */ BOOST_AUTO_TEST_CASE (certificates_validation) { |
