blob: 19d6867c1930b2ec3a9b325340cc7515bcc213b8 [file] [log] [blame]
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento0f830802018-01-16 23:58:58 -05002/*
Junxiao Shi9ee770b2022-04-25 23:33:33 +00003 * Copyright (c) 2013-2022 Regents of the University of California.
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
Alexander Afanasyev09236c22020-06-03 13:42:38 -040022#include "ndn-cxx/security/trust-anchor-container.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050023#include "ndn-cxx/util/io.hpp"
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070024
Davide Pesavento7e780642018-11-24 15:51:34 -050025#include "tests/boost-test.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050026#include "tests/key-chain-fixture.hpp"
27#include "tests/unit/clock-fixture.hpp"
Davide Pesavento0f830802018-01-16 23:58:58 -050028
Davide Pesaventod8e0cad2021-05-26 21:43:47 -040029#include <boost/filesystem/operations.hpp>
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070030
31namespace ndn {
32namespace security {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040033inline namespace v2 {
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070034namespace tests {
35
36using namespace ndn::tests;
37
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070038/**
39 * This fixture creates a directory and prepares two certificates.
40 * cert1 is written to a file under the directory, while cert2 is not.
41 */
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050042class TrustAnchorContainerFixture : public ClockFixture, public KeyChainFixture
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070043{
44public:
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050045 TrustAnchorContainerFixture()
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070046 {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050047 boost::filesystem::create_directories(certDirPath);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070048
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050049 identity1 = m_keyChain.createIdentity("/TestAnchorContainer/First");
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070050 cert1 = identity1.getDefaultKey().getDefaultCertificate();
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050051 saveCert(cert1, certPath1.string());
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070052
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050053 identity2 = m_keyChain.createIdentity("/TestAnchorContainer/Second");
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070054 cert2 = identity2.getDefaultKey().getDefaultCertificate();
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050055 saveCert(cert2, certPath2.string());
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070056 }
57
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050058 ~TrustAnchorContainerFixture() override
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070059 {
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050060 boost::filesystem::remove_all(certDirPath);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070061 }
62
Junxiao Shi9ee770b2022-04-25 23:33:33 +000063 void
64 checkFindByInterest(const Name& name, bool canBePrefix, optional<Certificate> expected) const
65 {
66 Interest interest(name);
67 interest.setCanBePrefix(canBePrefix);
68 BOOST_TEST_CONTEXT(interest) {
69 auto found = anchorContainer.find(interest);
70 if (expected) {
71 BOOST_REQUIRE(found != nullptr);
72 BOOST_CHECK_EQUAL(found->getName(), expected->getName());
73 }
74 else {
75 BOOST_CHECK(found == nullptr);
76 }
77 }
78 }
79
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070080public:
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050081 const boost::filesystem::path certDirPath{boost::filesystem::path(UNIT_TESTS_TMPDIR) / "test-cert-dir"};
82 const boost::filesystem::path certPath1{certDirPath / "trust-anchor-1.cert"};
83 const boost::filesystem::path certPath2{certDirPath / "trust-anchor-2.cert"};
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070084
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050085 TrustAnchorContainer anchorContainer;
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070086
87 Identity identity1;
88 Identity identity2;
89
90 Certificate cert1;
91 Certificate cert2;
92};
93
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050094BOOST_AUTO_TEST_SUITE(Security)
95BOOST_FIXTURE_TEST_SUITE(TestTrustAnchorContainer, TrustAnchorContainerFixture)
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -070096
97// one static group and one dynamic group created from file
98BOOST_AUTO_TEST_CASE(Insert)
99{
100 // Static
101 anchorContainer.insert("group1", Certificate(cert1));
102 BOOST_CHECK(anchorContainer.find(cert1.getName()) != nullptr);
103 BOOST_CHECK(anchorContainer.find(identity1.getName()) != nullptr);
104 const Certificate* cert = anchorContainer.find(cert1.getName());
105 BOOST_CHECK_NO_THROW(anchorContainer.insert("group1", Certificate(cert1)));
106 BOOST_CHECK_EQUAL(cert, anchorContainer.find(cert1.getName())); // still the same instance of the certificate
107 // cannot add dynamic group when static already exists
Davide Pesavento0f830802018-01-16 23:58:58 -0500108 BOOST_CHECK_THROW(anchorContainer.insert("group1", certPath1.string(), 1_s), TrustAnchorContainer::Error);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700109 BOOST_CHECK_EQUAL(anchorContainer.getGroup("group1").size(), 1);
110 BOOST_CHECK_EQUAL(anchorContainer.size(), 1);
111
112 // From file
Davide Pesavento0f830802018-01-16 23:58:58 -0500113 anchorContainer.insert("group2", certPath2.string(), 1_s);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700114 BOOST_CHECK(anchorContainer.find(cert2.getName()) != nullptr);
115 BOOST_CHECK(anchorContainer.find(identity2.getName()) != nullptr);
116 BOOST_CHECK_THROW(anchorContainer.insert("group2", Certificate(cert2)), TrustAnchorContainer::Error);
Davide Pesavento0f830802018-01-16 23:58:58 -0500117 BOOST_CHECK_THROW(anchorContainer.insert("group2", certPath2.string(), 1_s), TrustAnchorContainer::Error);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700118 BOOST_CHECK_EQUAL(anchorContainer.getGroup("group2").size(), 1);
119 BOOST_CHECK_EQUAL(anchorContainer.size(), 2);
120
121 boost::filesystem::remove(certPath2);
Davide Pesavento0f830802018-01-16 23:58:58 -0500122 advanceClocks(1_s, 11);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700123
124 BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
125 BOOST_CHECK(anchorContainer.find(cert2.getName()) == nullptr);
126 BOOST_CHECK_EQUAL(anchorContainer.getGroup("group2").size(), 0);
127 BOOST_CHECK_EQUAL(anchorContainer.size(), 1);
128
129 TrustAnchorGroup& group = anchorContainer.getGroup("group1");
130 auto staticGroup = dynamic_cast<StaticTrustAnchorGroup*>(&group);
131 BOOST_REQUIRE(staticGroup != nullptr);
132 BOOST_CHECK_EQUAL(staticGroup->size(), 1);
133 staticGroup->remove(cert1.getName());
134 BOOST_CHECK_EQUAL(staticGroup->size(), 0);
135 BOOST_CHECK_EQUAL(anchorContainer.size(), 0);
136
137 BOOST_CHECK_THROW(anchorContainer.getGroup("non-existing-group"), TrustAnchorContainer::Error);
138}
139
140BOOST_AUTO_TEST_CASE(DynamicAnchorFromDir)
141{
142 boost::filesystem::remove(certPath2);
143
Davide Pesavento0f830802018-01-16 23:58:58 -0500144 anchorContainer.insert("group", certDirPath.string(), 1_s, true /* isDir */);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700145
146 BOOST_CHECK(anchorContainer.find(identity1.getName()) != nullptr);
147 BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
148 BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 1);
149
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500150 saveCert(cert2, certPath2.string());
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700151
Davide Pesavento0f830802018-01-16 23:58:58 -0500152 advanceClocks(100_ms, 11);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700153
154 BOOST_CHECK(anchorContainer.find(identity1.getName()) != nullptr);
155 BOOST_CHECK(anchorContainer.find(identity2.getName()) != nullptr);
156 BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 2);
157
158 boost::filesystem::remove_all(certDirPath);
159
Davide Pesavento0f830802018-01-16 23:58:58 -0500160 advanceClocks(100_ms, 11);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700161
162 BOOST_CHECK(anchorContainer.find(identity1.getName()) == nullptr);
163 BOOST_CHECK(anchorContainer.find(identity2.getName()) == nullptr);
164 BOOST_CHECK_EQUAL(anchorContainer.getGroup("group").size(), 0);
165}
166
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500167BOOST_AUTO_TEST_CASE(FindByInterest)
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700168{
Davide Pesavento0f830802018-01-16 23:58:58 -0500169 anchorContainer.insert("group1", certPath1.string(), 1_s);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700170
Junxiao Shi9ee770b2022-04-25 23:33:33 +0000171 checkFindByInterest(identity1.getName(), true, cert1);
172 checkFindByInterest(identity1.getName().getPrefix(-1), true, cert1);
173 checkFindByInterest(cert1.getKeyName(), true, cert1);
174 checkFindByInterest(cert1.getName(), false, cert1);
175 checkFindByInterest(Name(identity1.getName()).appendVersion(), true, nullopt);
176
177 auto makeIdentity1Cert = [=] (const std::string& issuerId) {
178 auto key = identity1.getDefaultKey();
179 MakeCertificateOptions opts;
180 opts.issuerId = name::Component::fromEscapedString(issuerId);
181 return m_keyChain.makeCertificate(key, signingByKey(key), opts);
182 };
183
184 auto cert3 = makeIdentity1Cert("3");
185 auto cert4 = makeIdentity1Cert("4");
186 auto cert5 = makeIdentity1Cert("5");
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700187
188 Certificate cert3Copy = cert3;
189 anchorContainer.insert("group2", std::move(cert3Copy));
190 anchorContainer.insert("group3", std::move(cert4));
191 anchorContainer.insert("group4", std::move(cert5));
192
Junxiao Shi9ee770b2022-04-25 23:33:33 +0000193 checkFindByInterest(cert3.getKeyName(), true, cert3);
194 checkFindByInterest(cert3.getName(), false, cert3);
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700195}
196
197BOOST_AUTO_TEST_SUITE_END() // TestTrustAnchorContainer
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700198BOOST_AUTO_TEST_SUITE_END() // Security
199
200} // namespace tests
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400201} // inline namespace v2
Qiuhan Ding4caa0cc2015-10-23 20:31:27 -0700202} // namespace security
203} // namespace ndn