diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-07-17 16:12:56 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-07-17 16:12:56 +0100 |
| commit | 3d77daab7639c06d1cdbeb852559fc4be5671819 (patch) | |
| tree | 1bbe412ad4107a4b3dde663eb6397079c65de465 | |
| parent | e21bb3e3c2cf5d0d971f1a5cf25da431fcde0409 (diff) | |
Add variousn new bits to CertificateChain.
| -rw-r--r-- | src/certificates.cc | 61 | ||||
| -rw-r--r-- | src/certificates.h | 11 | ||||
| -rw-r--r-- | test/certificates_test.cc | 28 |
3 files changed, 86 insertions, 14 deletions
diff --git a/src/certificates.cc b/src/certificates.cc index b6e45c0e..b331c6b6 100644 --- a/src/certificates.cc +++ b/src/certificates.cc @@ -33,9 +33,11 @@ #include <openssl/err.h> #include <boost/algorithm/string.hpp> #include <cerrno> +#include <algorithm> using std::list; using std::string; +using std::cout; using boost::shared_ptr; using namespace dcp; @@ -307,11 +309,18 @@ CertificateChain::leaf () const return _certificates.back (); } +/** @return Certificates in order from root to leaf */ +CertificateChain::List +CertificateChain::root_to_leaf () const +{ + return _certificates; +} + /** @return Certificates in order from leaf to root */ -list<shared_ptr<Certificate> > +CertificateChain::List CertificateChain::leaf_to_root () const { - list<shared_ptr<Certificate> > c = _certificates; + List c = _certificates; c.reverse (); return c; } @@ -325,6 +334,29 @@ CertificateChain::add (shared_ptr<Certificate> c) _certificates.push_back (c); } +void +CertificateChain::remove (shared_ptr<Certificate> c) +{ + _certificates.remove (c); +} + +/** Remove the i'th certificate in the list, as listed + * from root to leaf. + */ +void +CertificateChain::remove (int i) +{ + List::iterator j = _certificates.begin (); + while (j != _certificates.end () && i > 0) { + --i; + ++j; + } + + if (j != _certificates.end ()) { + _certificates.erase (j); + } +} + /** Verify the chain. * @return true if it's ok, false if not. */ @@ -335,9 +367,10 @@ CertificateChain::verify () const if (!store) { return false; } - - for (list<shared_ptr<Certificate> >::const_iterator i = _certificates.begin(); i != _certificates.end(); ++i) { - list<shared_ptr<Certificate> >::const_iterator j = i; + + for (List::const_iterator i = _certificates.begin(); i != _certificates.end(); ++i) { + + List::const_iterator j = i; ++j; if (j == _certificates.end ()) { break; @@ -373,3 +406,21 @@ CertificateChain::verify () const X509_STORE_free (store); return true; } + +/** @return true if the chain is now in order from root to leaf, + * false if no correct order was found. + */ +bool +CertificateChain::attempt_reorder () +{ + List original = _certificates; + _certificates.sort (); + do { + if (verify ()) { + return true; + } + } while (std::next_permutation (_certificates.begin(), _certificates.end ())); + + _certificates = original; + return false; +} diff --git a/src/certificates.h b/src/certificates.h index 5a2b9324..8ae562c9 100644 --- a/src/certificates.h +++ b/src/certificates.h @@ -93,17 +93,24 @@ public: CertificateChain () {} void add (boost::shared_ptr<Certificate> c); + void remove (boost::shared_ptr<Certificate> c); + void remove (int); boost::shared_ptr<Certificate> root () const; boost::shared_ptr<Certificate> leaf () const; - std::list<boost::shared_ptr<Certificate> > leaf_to_root () const; + typedef std::list<boost::shared_ptr<Certificate> > List; + + List leaf_to_root () const; + List root_to_leaf () const; bool verify () const; + bool attempt_reorder (); private: friend class ::certificates; - std::list<boost::shared_ptr<Certificate> > _certificates; + + List _certificates; }; } diff --git a/test/certificates_test.cc b/test/certificates_test.cc index 57ecd2f7..3e345948 100644 --- a/test/certificates_test.cc +++ b/test/certificates_test.cc @@ -82,35 +82,49 @@ BOOST_AUTO_TEST_CASE (certificates) BOOST_CHECK_EQUAL (test.certificate(), c.root()->certificate()); } -/** Check that dcp::CertificateChain::validate() basically works */ +/** Check that dcp::CertificateChain::validate() and ::attempt_reorder() basically work */ BOOST_AUTO_TEST_CASE (certificates_validation) { - dcp::CertificateChain good; - good.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); - good.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); - good.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); - BOOST_CHECK (good.verify ()); - + dcp::CertificateChain good1; + good1.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); + good1.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); + good1.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); + BOOST_CHECK (good1.verify ()); + + dcp::CertificateChain good2; + good2.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); + BOOST_CHECK (good2.verify ()); + dcp::CertificateChain bad1; bad1.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); bad1.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); BOOST_CHECK (!bad1.verify ()); + BOOST_CHECK (!bad1.attempt_reorder ()); dcp::CertificateChain bad2; bad2.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); bad2.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); bad2.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); BOOST_CHECK (!bad2.verify ()); + BOOST_CHECK (bad2.attempt_reorder ()); dcp::CertificateChain bad3; bad3.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); bad3.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); bad3.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); BOOST_CHECK (!bad3.verify ()); + BOOST_CHECK (bad3.attempt_reorder ()); dcp::CertificateChain bad4; bad4.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); bad4.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); bad4.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); BOOST_CHECK (!bad4.verify ()); + BOOST_CHECK (bad4.attempt_reorder ()); + + dcp::CertificateChain bad5; + bad5.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); + bad5.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); + BOOST_CHECK (!bad5.verify ()); + BOOST_CHECK (!bad5.attempt_reorder ()); } |
