blob: 5c051481d34adcdd99e97805c9d7fd0ede81bf02 [file] [log] [blame]
Manika Mittal95c80702017-01-27 09:54:41 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento0f830802018-01-16 23:58:58 -05002/*
Alexander Afanasyev09236c22020-06-03 13:42:38 -04003 * Copyright (c) 2013-2020 Regents of the University of California.
Manika Mittal95c80702017-01-27 09:54:41 -08004 *
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/certificate-bundle-fetcher.hpp"
23#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
Davide Pesavento7e780642018-11-24 15:51:34 -050024#include "ndn-cxx/util/regex/regex-pattern-list-matcher.hpp"
25#include "ndn-cxx/lp/nack.hpp"
Manika Mittal95c80702017-01-27 09:54:41 -080026
Davide Pesavento7e780642018-11-24 15:51:34 -050027#include "tests/boost-test.hpp"
Alexander Afanasyev09236c22020-06-03 13:42:38 -040028#include "tests/unit/security/validator-fixture.hpp"
Manika Mittal95c80702017-01-27 09:54:41 -080029
30namespace ndn {
31namespace security {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040032inline namespace v2 {
Manika Mittal95c80702017-01-27 09:54:41 -080033namespace tests {
34
35using namespace ndn::tests;
36
37BOOST_AUTO_TEST_SUITE(Security)
Manika Mittal95c80702017-01-27 09:54:41 -080038BOOST_AUTO_TEST_SUITE(TestCertificateBundleFetcher)
39
40class CertificateBundleFetcherWrapper : public CertificateBundleFetcher
41{
42public:
43 CertificateBundleFetcherWrapper(Face& face)
44 : CertificateBundleFetcher(make_unique<CertificateFetcherFromNetwork>(face), face)
45 {
46 }
47};
48
49class Bundle
50{
51};
52
53class Cert
54{
55};
56
57class Timeout
58{
59};
60
61class Nack
62{
63};
64
65template<class Response>
66class CertificateBundleFetcherFixture : public HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy,
67 CertificateBundleFetcherWrapper>
68{
69public:
70 CertificateBundleFetcherFixture()
Alexander Afanasyev09236c22020-06-03 13:42:38 -040071 : data("/Security/ValidatorFixture/Sub1/Sub3/Data")
Manika Mittal95c80702017-01-27 09:54:41 -080072 {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040073 subSubIdentity = addSubCertificate("/Security/ValidatorFixture/Sub1/Sub3", subIdentity);
Manika Mittal95c80702017-01-27 09:54:41 -080074 cache.insert(subSubIdentity.getDefaultKey().getDefaultCertificate());
75
76 m_keyChain.sign(data, signingByIdentity(subSubIdentity));
77 bundleRegexMatcher = make_shared<RegexPatternListMatcher>("<>*<_BUNDLE><>*", nullptr);
78 processInterest = [this] (const Interest& interest) {
79 // check if the interest is for Bundle or individual certificates
80 if (bundleRegexMatcher->match(interest.getName(), 0, interest.getName().size())) {
81 makeResponse(interest);
82 }
83 else {
84 auto cert = cache.find(interest);
85 if (cert == nullptr) {
86 return;
87 }
88 face.receive(*cert);
89 }
90 };
91 }
92
93 void
94 makeResponse(const Interest& interest);
95
96public:
97 Data data;
98 Identity subSubIdentity;
99 shared_ptr<RegexPatternListMatcher> bundleRegexMatcher;
100};
101
102template<>
103void
104CertificateBundleFetcherFixture<Bundle>::makeResponse(const Interest& interest)
105{
106 Block certList = Block(tlv::Content);
107 Name bundleName(interest.getName());
108
109 if (!bundleName.get(-1).isSegment() || bundleName.get(-1).toSegment() == 0) {
110 Block subSubCert = subSubIdentity.getDefaultKey().getDefaultCertificate().wireEncode();
111 certList.push_back(subSubCert);
112
113 if (!bundleName.get(-1).isSegment()) {
114 bundleName
115 .appendVersion()
116 .appendSegment(0);
117 }
118 }
119 else {
120 Block subCert = subIdentity.getDefaultKey().getDefaultCertificate().wireEncode();
121 Block anchor = identity.getDefaultKey().getDefaultCertificate().wireEncode();
122 certList.push_back(subCert);
123 certList.push_back(anchor);
124 }
125
126 shared_ptr<Data> certBundle = make_shared<Data>();
127 certBundle->setName(bundleName);
Davide Pesavento0f830802018-01-16 23:58:58 -0500128 certBundle->setFreshnessPeriod(100_s);
Manika Mittal95c80702017-01-27 09:54:41 -0800129 certBundle->setContent(certList);
Junxiao Shiebfe4a22018-04-01 23:53:40 +0000130 certBundle->setFinalBlock(name::Component::fromSegment(1));
Manika Mittal95c80702017-01-27 09:54:41 -0800131
132 m_keyChain.sign(*certBundle, signingWithSha256());
133
134 face.receive(*certBundle);
135}
136
137template<>
138void
139CertificateBundleFetcherFixture<Timeout>::makeResponse(const Interest& interest)
140{
Davide Pesavento0f830802018-01-16 23:58:58 -0500141 this->advanceClocks(200_s);
Manika Mittal95c80702017-01-27 09:54:41 -0800142}
143
144template<>
145void
146CertificateBundleFetcherFixture<Nack>::makeResponse(const Interest& interest)
147{
148 lp::Nack nack(interest);
149 nack.setHeader(lp::NackHeader().setReason(lp::NackReason::NO_ROUTE));
150 face.receive(nack);
151}
152
153BOOST_FIXTURE_TEST_CASE(ValidateSuccessWithBundle, CertificateBundleFetcherFixture<Bundle>)
154{
155 VALIDATE_SUCCESS(this->data, "Should get accepted, as interest brings the bundle segments");
156 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 2); // produced bundle has 2 segments
157
158 for (const auto& sentInterest : this->face.sentInterests) {
159 BOOST_CHECK(this->bundleRegexMatcher->match(sentInterest.getName(), 0, sentInterest.getName().size()));
160 }
161}
162
163using SuccessWithoutBundle = boost::mpl::vector<Nack, Timeout>;
164
165BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateSuccessWithoutBundle, T, SuccessWithoutBundle, CertificateBundleFetcherFixture<T>)
166{
167 VALIDATE_SUCCESS(this->data, "Should get accepted, as interest brings the certs");
168 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4); // since interest for Bundle fails, each cert is retrieved
169
170 bool toggle = true;
171 for (const auto& sentInterest : this->face.sentInterests) {
172 if (toggle) {
173 // every alternate interest is going to be that of a bundle
174 BOOST_CHECK(this->bundleRegexMatcher->match(sentInterest.getName(), 0, sentInterest.getName().size()));
175 }
176 else {
177 BOOST_CHECK(!this->bundleRegexMatcher->match(sentInterest.getName(), 0, sentInterest.getName().size()));
178 }
179 toggle = !toggle;
180 }
181}
182
183BOOST_AUTO_TEST_SUITE_END() // TestCertificateBundleFetcher
Manika Mittal95c80702017-01-27 09:54:41 -0800184BOOST_AUTO_TEST_SUITE_END() // Security
185
186} // namespace tests
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400187} // inline namespace v2
Manika Mittal95c80702017-01-27 09:54:41 -0800188} // namespace security
189} // namespace ndn