X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=test%2Fcertificates_test.cc;h=1dc1193221f12c3342faa65281c442131c18caef;hb=de2a8ad58860273610dcd4bf449f0ada51bafb5f;hp=d355ad5560b973d428f0d3a1bcf16ccab2b8f0a4;hpb=2ae92dcc97765deb2845dd07a338858aeb375cb3;p=libdcp.git diff --git a/test/certificates_test.cc b/test/certificates_test.cc index d355ad55..1dc11932 100644 --- a/test/certificates_test.cc +++ b/test/certificates_test.cc @@ -1,33 +1,50 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington - This program is free software; you can redistribute it and/or modify + This file is part of libdcp. + + libdcp 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 2 of the License, or (at your option) any later version. - This program is distributed in the hope that it will be useful, + libdcp 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., 675 Mass Ave, Cambridge, MA 02139, USA. + along with libdcp. If not, see . + + In addition, as a special exception, the copyright holders give + permission to link the code of portions of this program with the + OpenSSL library under certain conditions as described in each + individual source file, and distribute linked combinations + including the two. + You must obey the GNU General Public License in all respects + for all of the code used other than OpenSSL. If you modify + file(s) with this exception, you may extend this exception to your + version of the file(s), but you are not obligated to do so. If you + do not wish to do so, delete this exception statement from your + version. If you delete this exception statement from all source + files in the program, then also delete it here. */ -#include -#include "certificates.h" -#include "signer.h" +#include "certificate.h" +#include "certificate_chain.h" #include "util.h" +#include "exceptions.h" +#include "test.h" +#include +#include using std::list; using std::string; -using boost::shared_ptr; +using std::shared_ptr; /** Check that loading certificates from files via strings works */ -BOOST_AUTO_TEST_CASE (certificates) +BOOST_AUTO_TEST_CASE (certificates1) { dcp::CertificateChain c; @@ -41,6 +58,7 @@ BOOST_AUTO_TEST_CASE (certificates) /* Leaf */ BOOST_CHECK_EQUAL (*i, c.leaf ()); + BOOST_CHECK_EQUAL (i->thumbprint(), "EZg5wDcihccWqwdg59Y8D+IJpYM="); BOOST_CHECK_EQUAL ( c.leaf().issuer(), @@ -55,6 +73,7 @@ BOOST_AUTO_TEST_CASE (certificates) ++i; /* Intermediate */ + BOOST_CHECK_EQUAL (i->thumbprint(), "GwM6ex2UVlWclH8f1uV7W1n0EEU="); BOOST_CHECK_EQUAL ( i->issuer(), "dnQualifier=DCnRdHFbcv4ANVUq2\\+wMVALFSec=,CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION,OU=example.org,O=example.org" @@ -69,6 +88,7 @@ BOOST_AUTO_TEST_CASE (certificates) /* Root */ BOOST_CHECK_EQUAL (*i, c.root ()); + BOOST_CHECK_EQUAL (i->thumbprint(), "zU8NVNwI2PYejmSYRntG7c6sdTw="); BOOST_CHECK_EQUAL ( c.root().issuer(), "dnQualifier=DCnRdHFbcv4ANVUq2\\+wMVALFSec=,CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION,OU=example.org,O=example.org" @@ -86,51 +106,130 @@ BOOST_AUTO_TEST_CASE (certificates) BOOST_CHECK_EQUAL (test.certificate(), c.root().certificate()); } -/** Check that dcp::CertificateChain::valid() and ::attempt_reorder() basically work */ -BOOST_AUTO_TEST_CASE (certificates_validation) +/** 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")); + } + + { + dcp::Certificate c (dcp::file_to_string (private_test / "usl-cert.pem")); + BOOST_CHECK_EQUAL (c.certificate(true), dcp::file_to_string (private_test / "usl-cert.pem.trimmed")); + } + + { + /* This is a chain, not an individual certificate, so it should throw an exception */ + BOOST_CHECK_THROW (dcp::Certificate (dcp::file_to_string (private_test / "chain.pem")), dcp::MiscError); + } + + BOOST_CHECK_THROW (dcp::Certificate (dcp::file_to_string (private_test / "no-begin.pem")), dcp::MiscError); + BOOST_CHECK_THROW (dcp::Certificate ("foo"), dcp::MiscError); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation1) +{ + dcp::CertificateChain good; + good.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + good.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); + good.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); + BOOST_CHECK (good.chain_valid(good._certificates)); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation2) +{ + dcp::CertificateChain good; + good.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + BOOST_CHECK (good.chain_valid(good._certificates)); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation3) +{ + dcp::CertificateChain bad; + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); + BOOST_CHECK (!bad.chain_valid(bad._certificates)); + BOOST_CHECK_THROW (bad.root_to_leaf(), dcp::CertificateChainError); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation4) +{ + dcp::CertificateChain bad; + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); + BOOST_CHECK (!bad.chain_valid(bad._certificates)); + BOOST_CHECK_NO_THROW (bad.root_to_leaf()); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation5) +{ + dcp::CertificateChain bad; + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + BOOST_CHECK (!bad.chain_valid(bad._certificates)); + BOOST_CHECK_NO_THROW (bad.root_to_leaf()); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation6) +{ + dcp::CertificateChain bad; + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + BOOST_CHECK (!bad.chain_valid(bad._certificates)); + BOOST_CHECK_NO_THROW (bad.root_to_leaf()); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation7) +{ + dcp::CertificateChain bad; + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); + BOOST_CHECK (!bad.chain_valid(bad._certificates)); + BOOST_CHECK_THROW (bad.root_to_leaf(), dcp::CertificateChainError); +} + +/** Check that dcp::CertificateChain::chain_valid() and ::root_to_leaf() basically work */ +BOOST_AUTO_TEST_CASE (certificates_validation8) { - dcp::CertificateChain good1; - good1.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); - good1.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); - good1.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - BOOST_CHECK (good1.valid ()); - - dcp::CertificateChain good2; - good2.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); - BOOST_CHECK (good2.valid ()); - - dcp::CertificateChain bad1; - bad1.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); - bad1.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - BOOST_CHECK (!bad1.valid ()); - BOOST_CHECK (!bad1.attempt_reorder ()); - - dcp::CertificateChain bad2; - bad2.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - bad2.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); - bad2.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); - BOOST_CHECK (!bad2.valid ()); - BOOST_CHECK (bad2.attempt_reorder ()); - - dcp::CertificateChain bad3; - bad3.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); - bad3.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - bad3.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); - BOOST_CHECK (!bad3.valid ()); - BOOST_CHECK (bad3.attempt_reorder ()); - - dcp::CertificateChain bad4; - bad4.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - bad4.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); - bad4.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); - BOOST_CHECK (!bad4.valid ()); - BOOST_CHECK (bad4.attempt_reorder ()); - - dcp::CertificateChain bad5; - bad5.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); - bad5.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - BOOST_CHECK (!bad5.valid ()); - BOOST_CHECK (!bad5.attempt_reorder ()); + dcp::CertificateChain bad; + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); + bad.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); + BOOST_CHECK (!bad.chain_valid(bad._certificates)); + BOOST_CHECK_THROW (bad.root_to_leaf(), dcp::CertificateChainError); +} + +/** Check that we can create a valid chain */ +BOOST_AUTO_TEST_CASE (certificates_validation9) +{ + dcp::CertificateChain good ( + boost::filesystem::path ("openssl"), + "dcpomatic.com", + "dcpomatic.com", + ".dcpomatic.smpte-430-2.ROOT", + ".dcpomatic.smpte-430-2.INTERMEDIATE", + "CS.dcpomatic.smpte-430-2.LEAF" + ); + + BOOST_CHECK_NO_THROW (good.root_to_leaf()); +} + +/** Check that we can create a valid chain */ +BOOST_AUTO_TEST_CASE (certificates_validation10) +{ + dcp::CertificateChain good (boost::filesystem::path ("openssl")); + BOOST_CHECK_NO_THROW (good.root_to_leaf()); } /** Check that dcp::Signer::valid() basically works */ @@ -141,11 +240,41 @@ BOOST_AUTO_TEST_CASE (signer_validation) chain.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/ca.self-signed.pem"))); chain.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/intermediate.signed.pem"))); chain.add (dcp::Certificate (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem"))); - dcp::Signer signer (chain, dcp::file_to_string ("test/ref/crypt/leaf.key")); - BOOST_CHECK (signer.valid ()); + chain.set_key (dcp::file_to_string ("test/ref/crypt/leaf.key")); + BOOST_CHECK (chain.valid ()); /* Put in an unrelated key and the signer should no longer be valid */ - dcp::Signer another_signer ("openssl"); - signer.set_key (another_signer.key ()); - BOOST_CHECK (!signer.valid ()); + dcp::CertificateChain another_chain (boost::filesystem::path ("openssl")); + chain.set_key (another_chain.key().get ()); + BOOST_CHECK (!chain.valid ()); +} + +/** Check reading of a certificate chain from a string */ +BOOST_AUTO_TEST_CASE (certificate_chain_from_string) +{ + dcp::CertificateChain a (dcp::file_to_string (private_test / "chain.pem")); + BOOST_CHECK_EQUAL (a.root_to_leaf().size(), 3); + + dcp::CertificateChain b (dcp::file_to_string ("test/ref/crypt/leaf.signed.pem")); + BOOST_CHECK_EQUAL (b.root_to_leaf().size(), 1); +} + +/** Check not_before and not_after */ +BOOST_AUTO_TEST_CASE (certificate_not_before_after) +{ + dcp::Certificate c (dcp::file_to_string("test/ref/crypt/ca.self-signed.pem")); + struct tm not_before = c.not_before(); + BOOST_CHECK_EQUAL (not_before.tm_sec, 8); + BOOST_CHECK_EQUAL (not_before.tm_min, 20); + BOOST_CHECK_EQUAL (not_before.tm_hour, 13); + BOOST_CHECK_EQUAL (not_before.tm_mday, 5); + BOOST_CHECK_EQUAL (not_before.tm_mon, 5); + BOOST_CHECK_EQUAL (not_before.tm_year, 115); + struct tm not_after = c.not_after(); + BOOST_CHECK_EQUAL (not_after.tm_sec, 8); + BOOST_CHECK_EQUAL (not_after.tm_min, 20); + BOOST_CHECK_EQUAL (not_after.tm_hour, 13); + BOOST_CHECK_EQUAL (not_after.tm_mday, 2); + BOOST_CHECK_EQUAL (not_after.tm_mon, 5); + BOOST_CHECK_EQUAL (not_after.tm_year, 125); }