blob: 7e513c6a78b55080b9a661073fc0c70814749cdb [file] [log] [blame]
Alexander Afanasyevba2cf392017-01-13 19:05:23 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Zhiyi Zhanga1302f62017-10-31 10:22:35 -07002/*
Alexander Afanasyev1660d002019-03-18 10:45:39 -04003 * Copyright (c) 2013-2019 Regents of the University of California.
Alexander Afanasyevba2cf392017-01-13 19:05:23 -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
Davide Pesavento7e780642018-11-24 15:51:34 -050022#include "ndn-cxx/security/v2/certificate-fetcher-direct-fetch.hpp"
23#include "ndn-cxx/security/v2/validation-policy-simple-hierarchy.hpp"
24#include "ndn-cxx/lp/nack.hpp"
25#include "ndn-cxx/lp/tags.hpp"
Alexander Afanasyevba2cf392017-01-13 19:05:23 -080026
Davide Pesavento7e780642018-11-24 15:51:34 -050027#include "tests/boost-test.hpp"
28#include "tests/unit/security/v2/validator-fixture.hpp"
Alexander Afanasyevba2cf392017-01-13 19:05:23 -080029
Alexander Afanasyevba2cf392017-01-13 19:05:23 -080030#include <boost/range/adaptor/sliced.hpp>
Davide Pesavento7e780642018-11-24 15:51:34 -050031#include <boost/range/adaptor/strided.hpp>
Alexander Afanasyevba2cf392017-01-13 19:05:23 -080032
33namespace ndn {
34namespace security {
35namespace v2 {
36namespace tests {
37
38using namespace ndn::tests;
39
40BOOST_AUTO_TEST_SUITE(Security)
41BOOST_AUTO_TEST_SUITE(V2)
42BOOST_AUTO_TEST_SUITE(TestCertificateFetcherDirectFetch)
43
44class Cert
45{
46};
47
48class Timeout
49{
50};
51
52class Nack
53{
54};
55
56template<class Response>
57class CertificateFetcherDirectFetchFixture : public HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy,
58 CertificateFetcherDirectFetch>
59{
60public:
Alexander Afanasyev1660d002019-03-18 10:45:39 -040061 enum class ResponseType {
62 INFRASTRUCTURE,
63 DIRECT,
64 BOTH
65 };
66
67public:
Alexander Afanasyevba2cf392017-01-13 19:05:23 -080068 CertificateFetcherDirectFetchFixture()
69 : data("/Security/V2/ValidatorFixture/Sub1/Sub3/Data")
70 , interest("/Security/V2/ValidatorFixture/Sub1/Sub3/Interest")
71 , interestNoTag("/Security/V2/ValidatorFixture/Sub1/Sub3/Interest2")
72 {
73 Identity subSubIdentity = addSubCertificate("/Security/V2/ValidatorFixture/Sub1/Sub3", subIdentity);
74 cache.insert(subSubIdentity.getDefaultKey().getDefaultCertificate());
75
76 m_keyChain.sign(data, signingByIdentity(subSubIdentity));
77 m_keyChain.sign(interest, signingByIdentity(subSubIdentity));
78 m_keyChain.sign(interestNoTag, signingByIdentity(subSubIdentity));
79
80 data.setTag(make_shared<lp::IncomingFaceIdTag>(123));
81 interest.setTag(make_shared<lp::IncomingFaceIdTag>(123));
82
83 processInterest = [this] (const Interest& interest) {
84 auto nextHopFaceIdTag = interest.template getTag<lp::NextHopFaceIdTag>();
85 if (nextHopFaceIdTag == nullptr) {
Alexander Afanasyev1660d002019-03-18 10:45:39 -040086 if (responseType == ResponseType::INFRASTRUCTURE || responseType == ResponseType::BOTH) {
87 makeResponse(interest);
88 }
89 }
90 else {
91 if (responseType == ResponseType::DIRECT || responseType == ResponseType::BOTH) {
92 makeResponse(interest);
93 }
Alexander Afanasyevba2cf392017-01-13 19:05:23 -080094 }
95 };
96 }
97
98 void
99 makeResponse(const Interest& interest);
100
Alexander Afanasyev1660d002019-03-18 10:45:39 -0400101 void
102 setResponseType(ResponseType type)
103 {
104 responseType = type;
105 }
106
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800107public:
108 Data data;
109 Interest interest;
110 Interest interestNoTag;
Alexander Afanasyev1660d002019-03-18 10:45:39 -0400111 ResponseType responseType = ResponseType::INFRASTRUCTURE;
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800112};
113
114template<>
115void
116CertificateFetcherDirectFetchFixture<Cert>::makeResponse(const Interest& interest)
117{
118 auto cert = cache.find(interest);
119 if (cert == nullptr) {
120 return;
121 }
122 face.receive(*cert);
123}
124
125template<>
126void
127CertificateFetcherDirectFetchFixture<Timeout>::makeResponse(const Interest& interest)
128{
129 // do nothing
130}
131
132template<>
133void
134CertificateFetcherDirectFetchFixture<Nack>::makeResponse(const Interest& interest)
135{
136 lp::Nack nack(interest);
137 nack.setHeader(lp::NackHeader().setReason(lp::NackReason::NO_ROUTE));
138 face.receive(nack);
139}
140
141using Failures = boost::mpl::vector<Timeout, Nack>;
142
143BOOST_FIXTURE_TEST_CASE(ValidateSuccessData, CertificateFetcherDirectFetchFixture<Cert>)
144{
Zhiyi Zhanga1302f62017-10-31 10:22:35 -0700145 VALIDATE_SUCCESS(this->data, "Should get accepted, normal and/or direct interests bring certs");
146 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800147
Zhiyi Zhanga1302f62017-10-31 10:22:35 -0700148 // odd interests
149 for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
150 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
151 }
152
153 // even interests
154 for (const auto& sentInterest : this->face.sentInterests |
155 boost::adaptors::sliced(1, this->face.sentInterests.size()) |
156 boost::adaptors::strided(2)) {
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800157 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
158 }
159}
160
Alexander Afanasyev1660d002019-03-18 10:45:39 -0400161BOOST_FIXTURE_TEST_CASE(ValidateSuccessDataDirectOnly, CertificateFetcherDirectFetchFixture<Cert>)
162{
163 setResponseType(ResponseType::DIRECT);
164 static_cast<CertificateFetcherDirectFetch&>(validator.getFetcher()).setSendDirectInterestOnly(true);
165
166 VALIDATE_SUCCESS(this->data, "Should get accepted, direct interests bring certs");
167 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 2);
168
169 for (const auto& sentInterest : this->face.sentInterests) {
170 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
171 }
172}
173
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800174BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureData, T, Failures, CertificateFetcherDirectFetchFixture<T>)
175{
Zhiyi Zhanga1302f62017-10-31 10:22:35 -0700176 VALIDATE_FAILURE(this->data, "Should fail, as all interests either NACKed or timeout");
Ashlesh Gawande3e39a4d2018-08-30 16:49:13 -0500177 // Direct fetcher sends two interests each time - to network and face
Alexander Afanasyev1660d002019-03-18 10:45:39 -0400178 // 3 retries on nack or timeout (2 * (1 + 3) = 8)
Ashlesh Gawande3e39a4d2018-08-30 16:49:13 -0500179 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 8);
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800180
Zhiyi Zhanga1302f62017-10-31 10:22:35 -0700181 // odd interests
182 for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
183 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
184 }
185
186 // even interests
187 for (const auto& sentInterest : this->face.sentInterests |
188 boost::adaptors::sliced(1, this->face.sentInterests.size()) |
189 boost::adaptors::strided(2)) {
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800190 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
191 }
192}
193
Alexander Afanasyev1660d002019-03-18 10:45:39 -0400194BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureDataDirectOnly, T, Failures, CertificateFetcherDirectFetchFixture<T>)
195{
196 this->setResponseType(CertificateFetcherDirectFetchFixture<T>::ResponseType::DIRECT);
197 static_cast<CertificateFetcherDirectFetch&>(this->validator.getFetcher()).setSendDirectInterestOnly(true);
198
199 VALIDATE_FAILURE(this->data, "Should fail, as all interests either NACKed or timeout");
200 // Direct fetcher sends two interests each time - to network and face
201 // 3 retries on nack or timeout (1 + 3 = 4)
202 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
203
204 for (const auto& sentInterest : this->face.sentInterests) {
205 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
206 }
207}
208
209BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureDataNoTagDirectOnly, T, Failures, CertificateFetcherDirectFetchFixture<T>)
210{
211 this->setResponseType(CertificateFetcherDirectFetchFixture<T>::ResponseType::DIRECT);
212 static_cast<CertificateFetcherDirectFetch&>(this->validator.getFetcher()).setSendDirectInterestOnly(true);
213
214 this->data.template removeTag<lp::IncomingFaceIdTag>();
215 this->interest.template removeTag<lp::IncomingFaceIdTag>();
216
217 VALIDATE_FAILURE(this->data, "Should fail, as no interests are expected");
218 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 0);
219 BOOST_CHECK(this->lastError.getCode() != ValidationError::Code::IMPLEMENTATION_ERROR);
220}
221
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800222BOOST_FIXTURE_TEST_CASE(ValidateSuccessInterest, CertificateFetcherDirectFetchFixture<Cert>)
223{
224 VALIDATE_SUCCESS(this->interest, "Should get accepted, normal and/or direct interests bring certs");
225 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 4);
226
227 // odd interests
228 for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
229 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
230 }
231
232 // even interests
233 for (const auto& sentInterest : this->face.sentInterests |
234 boost::adaptors::sliced(1, this->face.sentInterests.size()) |
235 boost::adaptors::strided(2)) {
236 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
237 }
238}
239
240BOOST_FIXTURE_TEST_CASE_TEMPLATE(ValidateFailureInterest, T, Failures, CertificateFetcherDirectFetchFixture<T>)
241{
242 VALIDATE_FAILURE(this->interest, "Should fail, as all interests either NACKed or timeout");
Ashlesh Gawande3e39a4d2018-08-30 16:49:13 -0500243 // Direct fetcher sends two interests each time - to network and face
244 // 3 retries on nack or timeout (2 * (1 + 3) = 4)
245 BOOST_CHECK_EQUAL(this->face.sentInterests.size(), 8);
Alexander Afanasyevba2cf392017-01-13 19:05:23 -0800246
247 // odd interests
248 for (const auto& sentInterest : this->face.sentInterests | boost::adaptors::strided(2)) {
249 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() != nullptr);
250 }
251
252 // even interests
253 for (const auto& sentInterest : this->face.sentInterests |
254 boost::adaptors::sliced(1, this->face.sentInterests.size()) |
255 boost::adaptors::strided(2)) {
256 BOOST_CHECK(sentInterest.template getTag<lp::NextHopFaceIdTag>() == nullptr);
257 }
258}
259
260BOOST_AUTO_TEST_SUITE_END() // TestCertificateFetcherDirectFetch
261BOOST_AUTO_TEST_SUITE_END() // V2
262BOOST_AUTO_TEST_SUITE_END() // Security
263
264} // namespace tests
265} // namespace v2
266} // namespace security
267} // namespace ndn