blob: ac690e7a28875913014997498d9d7997f080d867 [file] [log] [blame]
Alexander Afanasyev93338872017-01-30 22:37:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shi2bea5c42017-08-14 20:10:32 +00002/*
Davide Pesaventof6b45892023-03-13 15:00:51 -04003 * Copyright (c) 2013-2023 Regents of the University of California.
Alexander Afanasyev93338872017-01-30 22:37:00 -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/validation-policy-command-interest.hpp"
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050023
Davide Pesavento77c5ce82021-05-07 16:12:02 -040024#include "ndn-cxx/security/interest-signer.hpp"
Alexander Afanasyev09236c22020-06-03 13:42:38 -040025#include "ndn-cxx/security/validation-policy-accept-all.hpp"
26#include "ndn-cxx/security/validation-policy-simple-hierarchy.hpp"
Alexander Afanasyev93338872017-01-30 22:37:00 -080027
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -050028#include "tests/test-common.hpp"
Alexander Afanasyev09236c22020-06-03 13:42:38 -040029#include "tests/unit/security/validator-fixture.hpp"
Alexander Afanasyev93338872017-01-30 22:37:00 -080030
Alexander Afanasyev93338872017-01-30 22:37:00 -080031#include <boost/mpl/vector.hpp>
32
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040033namespace ndn::tests {
Alexander Afanasyev93338872017-01-30 22:37:00 -080034
Davide Pesavento47ce2ee2023-05-09 01:33:33 -040035using namespace ndn::security;
Alexander Afanasyev93338872017-01-30 22:37:00 -080036
37BOOST_AUTO_TEST_SUITE(Security)
Alexander Afanasyev93338872017-01-30 22:37:00 -080038
Davide Pesavento2acce252022-09-08 22:03:03 -040039struct CommandInterestDefaultOptions
Alexander Afanasyev93338872017-01-30 22:37:00 -080040{
Alexander Afanasyev93338872017-01-30 22:37:00 -080041 static ValidationPolicyCommandInterest::Options
42 getOptions()
43 {
44 return {};
45 }
46};
47
48template<class T, class InnerPolicy>
49class CommandInterestPolicyWrapper : public ValidationPolicyCommandInterest
50{
51public:
52 CommandInterestPolicyWrapper()
53 : ValidationPolicyCommandInterest(make_unique<InnerPolicy>(), T::getOptions())
54 {
55 }
56};
57
58template<class T, class InnerPolicy = ValidationPolicySimpleHierarchy>
Davide Pesavento2acce252022-09-08 22:03:03 -040059class ValidationPolicyCommandInterestFixture
60 : public HierarchicalValidatorFixture<CommandInterestPolicyWrapper<T, InnerPolicy>>
Alexander Afanasyev93338872017-01-30 22:37:00 -080061{
Davide Pesavento2acce252022-09-08 22:03:03 -040062protected:
Alexander Afanasyev93338872017-01-30 22:37:00 -080063 Interest
Davide Pesaventof6b45892023-03-13 15:00:51 -040064 makeCommandInterest(const Identity& id, SignedInterestFormat format = SignedInterestFormat::V02)
Alexander Afanasyev93338872017-01-30 22:37:00 -080065 {
Davide Pesaventof6b45892023-03-13 15:00:51 -040066 Name name = id.getName();
Davide Pesavento2acce252022-09-08 22:03:03 -040067 name.append("CMD");
68 switch (format) {
69 case SignedInterestFormat::V02:
Davide Pesaventof6b45892023-03-13 15:00:51 -040070 return m_signer.makeCommandInterest(name, signingByIdentity(id));
Davide Pesavento2acce252022-09-08 22:03:03 -040071 case SignedInterestFormat::V03: {
72 Interest interest(name);
Davide Pesaventof6b45892023-03-13 15:00:51 -040073 m_signer.makeSignedInterest(interest, signingByIdentity(id));
Davide Pesavento2acce252022-09-08 22:03:03 -040074 return interest;
75 }
Eric Newberry17d7c472020-06-18 21:29:22 -070076 }
Davide Pesavento2acce252022-09-08 22:03:03 -040077 NDN_CXX_UNREACHABLE;
Alexander Afanasyev93338872017-01-30 22:37:00 -080078 }
79
Davide Pesavento2acce252022-09-08 22:03:03 -040080protected:
Davide Pesavento77c5ce82021-05-07 16:12:02 -040081 InterestSigner m_signer{this->m_keyChain};
Alexander Afanasyev93338872017-01-30 22:37:00 -080082};
83
Eric Newberry1caa6342020-08-23 19:29:08 -070084BOOST_FIXTURE_TEST_SUITE(TestValidationPolicyCommandInterest,
85 ValidationPolicyCommandInterestFixture<CommandInterestDefaultOptions>)
Alexander Afanasyev93338872017-01-30 22:37:00 -080086
Davide Pesavento2acce252022-09-08 22:03:03 -040087template<int secs>
88struct GracePeriodSeconds
89{
90 static ValidationPolicyCommandInterest::Options
91 getOptions()
92 {
93 ValidationPolicyCommandInterest::Options options;
94 options.gracePeriod = time::seconds(secs);
95 return options;
96 }
97};
98
Alexander Afanasyev93338872017-01-30 22:37:00 -080099BOOST_AUTO_TEST_SUITE(Accepts)
100
Davide Pesavento2acce252022-09-08 22:03:03 -0400101BOOST_AUTO_TEST_CASE(BasicV02)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800102{
Davide Pesavento2acce252022-09-08 22:03:03 -0400103 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800104 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400105 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400106 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800107
Davide Pesavento0f830802018-01-16 23:58:58 -0500108 advanceClocks(5_ms);
Davide Pesavento2acce252022-09-08 22:03:03 -0400109 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800110 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400111
Davide Pesavento2acce252022-09-08 22:03:03 -0400112 auto i3 = m_signer.makeCommandInterest(Name(identity.getName()).append("CMD"), signingWithSha256());
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400113 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400114 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800115}
116
Davide Pesavento2acce252022-09-08 22:03:03 -0400117BOOST_AUTO_TEST_CASE(BasicV03)
Eric Newberry17d7c472020-06-18 21:29:22 -0700118{
Davide Pesavento2acce252022-09-08 22:03:03 -0400119 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
Eric Newberry17d7c472020-06-18 21:29:22 -0700120 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
121 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400122 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry17d7c472020-06-18 21:29:22 -0700123
124 advanceClocks(5_ms);
Davide Pesavento2acce252022-09-08 22:03:03 -0400125 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V03);
Eric Newberry17d7c472020-06-18 21:29:22 -0700126 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
127
128 Interest i3(Name(identity.getName()).append("CMD"));
Eric Newberry17d7c472020-06-18 21:29:22 -0700129 m_signer.makeSignedInterest(i3, signingWithSha256());
130 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400131 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry17d7c472020-06-18 21:29:22 -0700132}
133
Davide Pesavento2acce252022-09-08 22:03:03 -0400134BOOST_AUTO_TEST_CASE(DataPassthrough)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800135{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400136 Data d1("/Security/ValidatorFixture/Sub1");
Alexander Afanasyev93338872017-01-30 22:37:00 -0800137 m_keyChain.sign(d1);
138 VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
139}
140
Eric Newberry1caa6342020-08-23 19:29:08 -0700141using ValidationPolicyAcceptAllCommands = ValidationPolicyCommandInterestFixture<CommandInterestDefaultOptions,
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400142 ValidationPolicyAcceptAll>;
143
144BOOST_FIXTURE_TEST_CASE(SignedWithSha256, ValidationPolicyAcceptAllCommands) // Bug 4635
145{
146 auto i1 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
147 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
148 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400149 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400150
151 advanceClocks(5_ms);
152 auto i2 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
153 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
154}
155
Alexander Afanasyev93338872017-01-30 22:37:00 -0800156BOOST_AUTO_TEST_SUITE_END() // Accepts
157
158BOOST_AUTO_TEST_SUITE(Rejects)
159
Davide Pesavento2acce252022-09-08 22:03:03 -0400160BOOST_AUTO_TEST_CASE(NotSigned)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800161{
Davide Pesavento2acce252022-09-08 22:03:03 -0400162 auto i1 = Interest("/short");
163 BOOST_TEST_REQUIRE(i1.getName().size() < signed_interest::MIN_SIZE);
164 VALIDATE_FAILURE(i1, "Should fail (not signed / name too short)");
Davide Pesavento637ea3b2022-09-10 00:11:34 -0400165 BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800166}
167
168BOOST_AUTO_TEST_CASE(BadSigInfo)
169{
Davide Pesavento2acce252022-09-08 22:03:03 -0400170 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800171 setNameComponent(i1, command_interest::POS_SIG_INFO, "not-SignatureInfo");
Davide Pesavento2acce252022-09-08 22:03:03 -0400172 BOOST_TEST_REQUIRE(i1.getName().size() >= command_interest::MIN_SIZE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800173 VALIDATE_FAILURE(i1, "Should fail (signature info is missing)");
Davide Pesavento637ea3b2022-09-10 00:11:34 -0400174 BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800175}
176
Davide Pesavento2acce252022-09-08 22:03:03 -0400177BOOST_AUTO_TEST_CASE(BadTimestampV02)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800178{
Davide Pesavento2acce252022-09-08 22:03:03 -0400179 // i1 is a valid signed interest (in v0.2 format) but is not a valid command interest
180 auto i1 = Interest("/short");
181 m_keyChain.sign(i1, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V02));
182 BOOST_TEST_REQUIRE((i1.getName().size() >= signed_interest::MIN_SIZE &&
183 i1.getName().size() < command_interest::MIN_SIZE));
184 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
185 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
186
187 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V02);
188 setNameComponent(i2, command_interest::POS_TIMESTAMP, "not-timestamp");
189 BOOST_TEST_REQUIRE(i2.getName().size() >= command_interest::MIN_SIZE);
190 VALIDATE_FAILURE(i2, "Should fail (timestamp is malformed)");
191 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
192}
193
194BOOST_AUTO_TEST_CASE(BadTimestampV03)
195{
196 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
197 auto si = i1.getSignatureInfo().value();
Davide Pesaventof6b45892023-03-13 15:00:51 -0400198 si.setTime(std::nullopt);
Davide Pesavento2acce252022-09-08 22:03:03 -0400199 i1.setSignatureInfo(si);
200 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
201 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
202}
203
204BOOST_AUTO_TEST_CASE(MissingKeyLocatorV02)
205{
206 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Junxiao Shi605671d2017-08-26 13:41:06 +0000207 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800208 setNameComponent(i1, command_interest::POS_SIG_INFO,
209 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
210 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400211 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
212}
213
214BOOST_AUTO_TEST_CASE(MissingKeyLocatorV03)
215{
216 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
217 auto si = i1.getSignatureInfo().value();
Davide Pesaventof6b45892023-03-13 15:00:51 -0400218 si.setKeyLocator(std::nullopt);
Davide Pesavento2acce252022-09-08 22:03:03 -0400219 i1.setSignatureInfo(si);
220 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
221 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800222}
223
224BOOST_AUTO_TEST_CASE(BadKeyLocatorType)
225{
Davide Pesavento2acce252022-09-08 22:03:03 -0400226 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800227 KeyLocator kl;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500228 kl.setKeyDigest(makeBinaryBlock(tlv::KeyDigest, {0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD}));
Davide Pesavento2acce252022-09-08 22:03:03 -0400229 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa, kl);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800230 setNameComponent(i1, command_interest::POS_SIG_INFO,
231 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
232 VALIDATE_FAILURE(i1, "Should fail (bad KeyLocator type)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400233 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800234}
235
236BOOST_AUTO_TEST_CASE(BadCertName)
237{
Davide Pesavento2acce252022-09-08 22:03:03 -0400238 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
239 SignatureInfo sigInfo(tlv::SignatureSha256WithEcdsa, KeyLocator("/bad/cert/name"));
Alexander Afanasyev93338872017-01-30 22:37:00 -0800240 setNameComponent(i1, command_interest::POS_SIG_INFO,
241 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
242 VALIDATE_FAILURE(i1, "Should fail (bad certificate name)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400243 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800244}
245
246BOOST_AUTO_TEST_CASE(InnerPolicyReject)
247{
Davide Pesavento2acce252022-09-08 22:03:03 -0400248 auto i1 = makeCommandInterest(otherIdentity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800249 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400250 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
251
252 auto i2 = makeCommandInterest(otherIdentity, SignedInterestFormat::V03);
253 VALIDATE_FAILURE(i2, "Should fail (inner policy should reject)");
254 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800255}
256
Davide Pesavento2acce252022-09-08 22:03:03 -0400257BOOST_FIXTURE_TEST_CASE(TimestampOutOfGracePositive,
258 ValidationPolicyCommandInterestFixture<GracePeriodSeconds<15>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800259{
260 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500261 advanceClocks(16_s); // verifying at +16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800262 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400263 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800264 rewindClockAfterValidation();
265
266 auto i2 = makeCommandInterest(identity); // signed at +16s
267 VALIDATE_SUCCESS(i2, "Should succeed");
268}
269
Davide Pesavento2acce252022-09-08 22:03:03 -0400270BOOST_FIXTURE_TEST_CASE(TimestampOutOfGraceNegative,
271 ValidationPolicyCommandInterestFixture<GracePeriodSeconds<15>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800272{
273 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500274 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800275 auto i2 = makeCommandInterest(identity); // signed at +1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500276 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800277 auto i3 = makeCommandInterest(identity); // signed at +2s
278
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500279 m_systemClock->advance(-18_s); // verifying at -16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800280 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400281 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800282 rewindClockAfterValidation();
283
284 // CommandInterestValidator should not remember i1's timestamp
285 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400286 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800287 rewindClockAfterValidation();
288
289 // CommandInterestValidator should not remember i2's timestamp, and should treat i3 as initial
Davide Pesavento0f830802018-01-16 23:58:58 -0500290 advanceClocks(18_s); // verifying at +2s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800291 VALIDATE_SUCCESS(i3, "Should succeed");
292}
293
294BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
295{
296 auto i1 = makeCommandInterest(identity); // signed at 0s
297 VALIDATE_SUCCESS(i1, "Should succeed");
298
299 auto i2 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento2acce252022-09-08 22:03:03 -0400300 setNameComponent(i2, command_interest::POS_TIMESTAMP, i1.getName()[command_interest::POS_TIMESTAMP]);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800301 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400302 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800303
Davide Pesavento0f830802018-01-16 23:58:58 -0500304 advanceClocks(2_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800305 auto i3 = makeCommandInterest(identity); // signed at +2s
306 VALIDATE_SUCCESS(i3, "Should succeed");
307}
308
309BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
310{
311 auto i2 = makeCommandInterest(identity); // signed at 0ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500312 advanceClocks(200_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800313 auto i3 = makeCommandInterest(identity); // signed at +200ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500314 advanceClocks(900_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800315 auto i1 = makeCommandInterest(identity); // signed at +1100ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500316 advanceClocks(300_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800317 auto i4 = makeCommandInterest(identity); // signed at +1400ms
318
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500319 m_systemClock->advance(-300_ms); // verifying at +1100ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800320 VALIDATE_SUCCESS(i1, "Should succeed");
321 rewindClockAfterValidation();
322
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500323 m_systemClock->advance(-1100_ms); // verifying at 0ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800324 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400325 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800326 rewindClockAfterValidation();
327
328 // CommandInterestValidator should not remember i2's timestamp
Davide Pesavento0f830802018-01-16 23:58:58 -0500329 advanceClocks(200_ms); // verifying at +200ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800330 VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400331 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800332 rewindClockAfterValidation();
333
Davide Pesavento0f830802018-01-16 23:58:58 -0500334 advanceClocks(1200_ms); // verifying at 1400ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800335 VALIDATE_SUCCESS(i4, "Should succeed");
336}
337
338BOOST_AUTO_TEST_SUITE_END() // Rejects
339
340BOOST_AUTO_TEST_SUITE(Options)
341
Davide Pesavento2acce252022-09-08 22:03:03 -0400342using NonPositiveGracePeriods = boost::mpl::vector<
343 GracePeriodSeconds<0>,
344 GracePeriodSeconds<-1>
345>;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800346
Davide Pesavento2acce252022-09-08 22:03:03 -0400347BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Alexander Afanasyev93338872017-01-30 22:37:00 -0800348 ValidationPolicyCommandInterestFixture<GracePeriod>)
349{
350 auto i1 = this->makeCommandInterest(this->identity); // signed at 0ms
351 auto i2 = this->makeCommandInterest(this->subIdentity); // signed at 0ms
352 for (auto interest : {&i1, &i2}) {
353 setNameComponent(*interest, command_interest::POS_TIMESTAMP,
354 name::Component::fromNumber(time::toUnixTimestamp(time::system_clock::now()).count()));
355 } // ensure timestamps are exactly 0ms
356
357 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
358 this->rewindClockAfterValidation();
359
Davide Pesavento0f830802018-01-16 23:58:58 -0500360 this->advanceClocks(1_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800361 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400362 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800363}
364
365class LimitedRecordsOptions
366{
367public:
368 static ValidationPolicyCommandInterest::Options
369 getOptions()
370 {
371 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500372 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800373 options.maxRecords = 3;
374 return options;
375 }
376};
377
378BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicyCommandInterestFixture<LimitedRecordsOptions>)
379{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400380 Identity id1 = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800381 this->cache.insert(id1.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400382 Identity id2 = this->addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800383 this->cache.insert(id2.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400384 Identity id3 = this->addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800385 this->cache.insert(id3.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400386 Identity id4 = this->addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800387 this->cache.insert(id4.getDefaultKey().getDefaultCertificate());
388
389 auto i1 = makeCommandInterest(id2);
390 auto i2 = makeCommandInterest(id3);
391 auto i3 = makeCommandInterest(id4);
392 auto i00 = makeCommandInterest(id1); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500393 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800394 auto i01 = makeCommandInterest(id1); // signed at 1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500395 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800396 auto i02 = makeCommandInterest(id1); // signed at 2s
397
398 VALIDATE_SUCCESS(i00, "Should succeed");
399 rewindClockAfterValidation();
400
401 VALIDATE_SUCCESS(i02, "Should succeed");
402 rewindClockAfterValidation();
403
404 VALIDATE_SUCCESS(i1, "Should succeed");
405 rewindClockAfterValidation();
406
407 VALIDATE_SUCCESS(i2, "Should succeed");
408 rewindClockAfterValidation();
409
410 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
411 rewindClockAfterValidation();
412
413 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
414}
415
416class UnlimitedRecordsOptions
417{
418public:
419 static ValidationPolicyCommandInterest::Options
420 getOptions()
421 {
422 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500423 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800424 options.maxRecords = -1;
425 return options;
426 }
427};
428
429BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<UnlimitedRecordsOptions>)
430{
431 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500432 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400433 Identity id = this->addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800434 this->cache.insert(id.getDefaultKey().getDefaultCertificate());
435 identities.push_back(id);
436 }
437
438 auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500439 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500440 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev93338872017-01-30 22:37:00 -0800441 auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800442 VALIDATE_SUCCESS(i2, "Should succeed");
443 rewindClockAfterValidation();
444 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400445
Alexander Afanasyev93338872017-01-30 22:37:00 -0800446 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400447 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800448}
449
450class ZeroRecordsOptions
451{
452public:
453 static ValidationPolicyCommandInterest::Options
454 getOptions()
455 {
456 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500457 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800458 options.maxRecords = 0;
459 return options;
460 }
461};
462
463BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicyCommandInterestFixture<ZeroRecordsOptions>)
464{
465 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500466 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800467 auto i2 = makeCommandInterest(identity); // signed at +1s
468 VALIDATE_SUCCESS(i2, "Should succeed");
469 rewindClockAfterValidation();
470
471 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record isn't kept");
472}
473
474class LimitedRecordLifetimeOptions
475{
476public:
477 static ValidationPolicyCommandInterest::Options
478 getOptions()
479 {
480 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500481 options.gracePeriod = 400_s;
482 options.recordLifetime = 300_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800483 return options;
484 }
485};
486
487BOOST_FIXTURE_TEST_CASE(LimitedRecordLifetime, ValidationPolicyCommandInterestFixture<LimitedRecordLifetimeOptions>)
488{
489 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500490 advanceClocks(240_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800491 auto i2 = makeCommandInterest(identity); // signed at +240s
Davide Pesavento0f830802018-01-16 23:58:58 -0500492 advanceClocks(120_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800493 auto i3 = makeCommandInterest(identity); // signed at +360s
494
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500495 m_systemClock->advance(-360_s); // rewind system clock to 0s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800496 VALIDATE_SUCCESS(i1, "Should succeed");
497 rewindClockAfterValidation();
498
499 VALIDATE_SUCCESS(i3, "Should succeed");
500 rewindClockAfterValidation();
501
Davide Pesavento0f830802018-01-16 23:58:58 -0500502 advanceClocks(30_s, 301_s); // advance steady clock by 301s, and system clock to +301s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800503 VALIDATE_SUCCESS(i2, "Should succeed despite timestamp is reordered, because record has been expired");
504}
505
506class ZeroRecordLifetimeOptions
507{
508public:
509 static ValidationPolicyCommandInterest::Options
510 getOptions()
511 {
512 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500513 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800514 options.recordLifetime = time::seconds::zero();
515 return options;
516 }
517};
518
519BOOST_FIXTURE_TEST_CASE(ZeroRecordLifetime, ValidationPolicyCommandInterestFixture<ZeroRecordLifetimeOptions>)
520{
521 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500522 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800523 auto i2 = makeCommandInterest(identity); // signed at +1s
524 VALIDATE_SUCCESS(i2, "Should succeed");
525 rewindClockAfterValidation();
526
527 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record has been expired");
528}
529
530BOOST_AUTO_TEST_SUITE_END() // Options
531
532BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyCommandInterest
Alexander Afanasyev93338872017-01-30 22:37:00 -0800533BOOST_AUTO_TEST_SUITE_END() // Security
534
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400535} // namespace ndn::tests