blob: 657b830c90bb41503963c07dabe87a8fe1652132 [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
Davide Pesavento49e1e872023-11-11 00:45:23 -050031#include <boost/mp11/list.hpp>
Alexander Afanasyev93338872017-01-30 22:37:00 -080032
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 Pesavento49e1e872023-11-11 00:45:23 -0500342using NonPositiveGracePeriods = boost::mp11::mp_list<GracePeriodSeconds<0>, GracePeriodSeconds<-1>>;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800343
Davide Pesavento2acce252022-09-08 22:03:03 -0400344BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Alexander Afanasyev93338872017-01-30 22:37:00 -0800345 ValidationPolicyCommandInterestFixture<GracePeriod>)
346{
347 auto i1 = this->makeCommandInterest(this->identity); // signed at 0ms
348 auto i2 = this->makeCommandInterest(this->subIdentity); // signed at 0ms
349 for (auto interest : {&i1, &i2}) {
350 setNameComponent(*interest, command_interest::POS_TIMESTAMP,
351 name::Component::fromNumber(time::toUnixTimestamp(time::system_clock::now()).count()));
352 } // ensure timestamps are exactly 0ms
353
354 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
355 this->rewindClockAfterValidation();
356
Davide Pesavento0f830802018-01-16 23:58:58 -0500357 this->advanceClocks(1_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800358 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400359 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800360}
361
362class LimitedRecordsOptions
363{
364public:
365 static ValidationPolicyCommandInterest::Options
366 getOptions()
367 {
368 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500369 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800370 options.maxRecords = 3;
371 return options;
372 }
373};
374
375BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicyCommandInterestFixture<LimitedRecordsOptions>)
376{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400377 Identity id1 = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800378 this->cache.insert(id1.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400379 Identity id2 = this->addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800380 this->cache.insert(id2.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400381 Identity id3 = this->addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800382 this->cache.insert(id3.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400383 Identity id4 = this->addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800384 this->cache.insert(id4.getDefaultKey().getDefaultCertificate());
385
386 auto i1 = makeCommandInterest(id2);
387 auto i2 = makeCommandInterest(id3);
388 auto i3 = makeCommandInterest(id4);
389 auto i00 = makeCommandInterest(id1); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500390 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800391 auto i01 = makeCommandInterest(id1); // signed at 1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500392 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800393 auto i02 = makeCommandInterest(id1); // signed at 2s
394
395 VALIDATE_SUCCESS(i00, "Should succeed");
396 rewindClockAfterValidation();
397
398 VALIDATE_SUCCESS(i02, "Should succeed");
399 rewindClockAfterValidation();
400
401 VALIDATE_SUCCESS(i1, "Should succeed");
402 rewindClockAfterValidation();
403
404 VALIDATE_SUCCESS(i2, "Should succeed");
405 rewindClockAfterValidation();
406
407 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
408 rewindClockAfterValidation();
409
410 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
411}
412
413class UnlimitedRecordsOptions
414{
415public:
416 static ValidationPolicyCommandInterest::Options
417 getOptions()
418 {
419 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500420 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800421 options.maxRecords = -1;
422 return options;
423 }
424};
425
426BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<UnlimitedRecordsOptions>)
427{
428 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500429 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400430 Identity id = this->addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800431 this->cache.insert(id.getDefaultKey().getDefaultCertificate());
432 identities.push_back(id);
433 }
434
435 auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500436 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500437 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev93338872017-01-30 22:37:00 -0800438 auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800439 VALIDATE_SUCCESS(i2, "Should succeed");
440 rewindClockAfterValidation();
441 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400442
Alexander Afanasyev93338872017-01-30 22:37:00 -0800443 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400444 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800445}
446
447class ZeroRecordsOptions
448{
449public:
450 static ValidationPolicyCommandInterest::Options
451 getOptions()
452 {
453 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500454 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800455 options.maxRecords = 0;
456 return options;
457 }
458};
459
460BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicyCommandInterestFixture<ZeroRecordsOptions>)
461{
462 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500463 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800464 auto i2 = makeCommandInterest(identity); // signed at +1s
465 VALIDATE_SUCCESS(i2, "Should succeed");
466 rewindClockAfterValidation();
467
468 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record isn't kept");
469}
470
471class LimitedRecordLifetimeOptions
472{
473public:
474 static ValidationPolicyCommandInterest::Options
475 getOptions()
476 {
477 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500478 options.gracePeriod = 400_s;
479 options.recordLifetime = 300_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800480 return options;
481 }
482};
483
484BOOST_FIXTURE_TEST_CASE(LimitedRecordLifetime, ValidationPolicyCommandInterestFixture<LimitedRecordLifetimeOptions>)
485{
486 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500487 advanceClocks(240_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800488 auto i2 = makeCommandInterest(identity); // signed at +240s
Davide Pesavento0f830802018-01-16 23:58:58 -0500489 advanceClocks(120_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800490 auto i3 = makeCommandInterest(identity); // signed at +360s
491
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500492 m_systemClock->advance(-360_s); // rewind system clock to 0s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800493 VALIDATE_SUCCESS(i1, "Should succeed");
494 rewindClockAfterValidation();
495
496 VALIDATE_SUCCESS(i3, "Should succeed");
497 rewindClockAfterValidation();
498
Davide Pesavento0f830802018-01-16 23:58:58 -0500499 advanceClocks(30_s, 301_s); // advance steady clock by 301s, and system clock to +301s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800500 VALIDATE_SUCCESS(i2, "Should succeed despite timestamp is reordered, because record has been expired");
501}
502
503class ZeroRecordLifetimeOptions
504{
505public:
506 static ValidationPolicyCommandInterest::Options
507 getOptions()
508 {
509 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500510 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800511 options.recordLifetime = time::seconds::zero();
512 return options;
513 }
514};
515
516BOOST_FIXTURE_TEST_CASE(ZeroRecordLifetime, ValidationPolicyCommandInterestFixture<ZeroRecordLifetimeOptions>)
517{
518 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500519 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800520 auto i2 = makeCommandInterest(identity); // signed at +1s
521 VALIDATE_SUCCESS(i2, "Should succeed");
522 rewindClockAfterValidation();
523
524 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record has been expired");
525}
526
527BOOST_AUTO_TEST_SUITE_END() // Options
528
529BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyCommandInterest
Alexander Afanasyev93338872017-01-30 22:37:00 -0800530BOOST_AUTO_TEST_SUITE_END() // Security
531
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400532} // namespace ndn::tests