blob: 604c60d91264873e221266dca68749ad7e83f9dc [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 Pesaventofbea4fc2022-02-08 07:26:04 -05003 * Copyright (c) 2013-2022 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
33namespace ndn {
34namespace security {
Alexander Afanasyev09236c22020-06-03 13:42:38 -040035inline namespace v2 {
Alexander Afanasyev93338872017-01-30 22:37:00 -080036namespace tests {
37
38using namespace ndn::tests;
39
40BOOST_AUTO_TEST_SUITE(Security)
Alexander Afanasyev93338872017-01-30 22:37:00 -080041
Davide Pesavento2acce252022-09-08 22:03:03 -040042struct CommandInterestDefaultOptions
Alexander Afanasyev93338872017-01-30 22:37:00 -080043{
Alexander Afanasyev93338872017-01-30 22:37:00 -080044 static ValidationPolicyCommandInterest::Options
45 getOptions()
46 {
47 return {};
48 }
49};
50
51template<class T, class InnerPolicy>
52class CommandInterestPolicyWrapper : public ValidationPolicyCommandInterest
53{
54public:
55 CommandInterestPolicyWrapper()
56 : ValidationPolicyCommandInterest(make_unique<InnerPolicy>(), T::getOptions())
57 {
58 }
59};
60
61template<class T, class InnerPolicy = ValidationPolicySimpleHierarchy>
Davide Pesavento2acce252022-09-08 22:03:03 -040062class ValidationPolicyCommandInterestFixture
63 : public HierarchicalValidatorFixture<CommandInterestPolicyWrapper<T, InnerPolicy>>
Alexander Afanasyev93338872017-01-30 22:37:00 -080064{
Davide Pesavento2acce252022-09-08 22:03:03 -040065protected:
Alexander Afanasyev93338872017-01-30 22:37:00 -080066 Interest
Davide Pesavento2acce252022-09-08 22:03:03 -040067 makeCommandInterest(const Identity& identity, SignedInterestFormat format = SignedInterestFormat::V02)
Alexander Afanasyev93338872017-01-30 22:37:00 -080068 {
Davide Pesavento2acce252022-09-08 22:03:03 -040069 Name name = identity.getName();
70 name.append("CMD");
71 switch (format) {
72 case SignedInterestFormat::V02:
73 return m_signer.makeCommandInterest(name, signingByIdentity(identity));
74 case SignedInterestFormat::V03: {
75 Interest interest(name);
76 m_signer.makeSignedInterest(interest, signingByIdentity(identity));
77 return interest;
78 }
Eric Newberry17d7c472020-06-18 21:29:22 -070079 }
Davide Pesavento2acce252022-09-08 22:03:03 -040080 NDN_CXX_UNREACHABLE;
Alexander Afanasyev93338872017-01-30 22:37:00 -080081 }
82
Davide Pesavento2acce252022-09-08 22:03:03 -040083protected:
Davide Pesavento77c5ce82021-05-07 16:12:02 -040084 InterestSigner m_signer{this->m_keyChain};
Alexander Afanasyev93338872017-01-30 22:37:00 -080085};
86
Eric Newberry1caa6342020-08-23 19:29:08 -070087BOOST_FIXTURE_TEST_SUITE(TestValidationPolicyCommandInterest,
88 ValidationPolicyCommandInterestFixture<CommandInterestDefaultOptions>)
Alexander Afanasyev93338872017-01-30 22:37:00 -080089
Davide Pesavento2acce252022-09-08 22:03:03 -040090template<int secs>
91struct GracePeriodSeconds
92{
93 static ValidationPolicyCommandInterest::Options
94 getOptions()
95 {
96 ValidationPolicyCommandInterest::Options options;
97 options.gracePeriod = time::seconds(secs);
98 return options;
99 }
100};
101
Alexander Afanasyev93338872017-01-30 22:37:00 -0800102BOOST_AUTO_TEST_SUITE(Accepts)
103
Davide Pesavento2acce252022-09-08 22:03:03 -0400104BOOST_AUTO_TEST_CASE(BasicV02)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800105{
Davide Pesavento2acce252022-09-08 22:03:03 -0400106 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800107 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400108 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400109 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800110
Davide Pesavento0f830802018-01-16 23:58:58 -0500111 advanceClocks(5_ms);
Davide Pesavento2acce252022-09-08 22:03:03 -0400112 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800113 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400114
Davide Pesavento2acce252022-09-08 22:03:03 -0400115 auto i3 = m_signer.makeCommandInterest(Name(identity.getName()).append("CMD"), signingWithSha256());
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400116 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400117 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800118}
119
Davide Pesavento2acce252022-09-08 22:03:03 -0400120BOOST_AUTO_TEST_CASE(BasicV03)
Eric Newberry17d7c472020-06-18 21:29:22 -0700121{
Davide Pesavento2acce252022-09-08 22:03:03 -0400122 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
Eric Newberry17d7c472020-06-18 21:29:22 -0700123 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
124 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400125 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry17d7c472020-06-18 21:29:22 -0700126
127 advanceClocks(5_ms);
Davide Pesavento2acce252022-09-08 22:03:03 -0400128 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V03);
Eric Newberry17d7c472020-06-18 21:29:22 -0700129 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
130
131 Interest i3(Name(identity.getName()).append("CMD"));
Eric Newberry17d7c472020-06-18 21:29:22 -0700132 m_signer.makeSignedInterest(i3, signingWithSha256());
133 VALIDATE_FAILURE(i3, "Should fail (Sha256 signature violates policy)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400134 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Eric Newberry17d7c472020-06-18 21:29:22 -0700135}
136
Davide Pesavento2acce252022-09-08 22:03:03 -0400137BOOST_AUTO_TEST_CASE(DataPassthrough)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800138{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400139 Data d1("/Security/ValidatorFixture/Sub1");
Alexander Afanasyev93338872017-01-30 22:37:00 -0800140 m_keyChain.sign(d1);
141 VALIDATE_SUCCESS(d1, "Should succeed (fallback on inner validation policy for data)");
142}
143
Eric Newberry1caa6342020-08-23 19:29:08 -0700144using ValidationPolicyAcceptAllCommands = ValidationPolicyCommandInterestFixture<CommandInterestDefaultOptions,
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400145 ValidationPolicyAcceptAll>;
146
147BOOST_FIXTURE_TEST_CASE(SignedWithSha256, ValidationPolicyAcceptAllCommands) // Bug 4635
148{
149 auto i1 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
150 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
151 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400152 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400153
154 advanceClocks(5_ms);
155 auto i2 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
156 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
157}
158
Alexander Afanasyev93338872017-01-30 22:37:00 -0800159BOOST_AUTO_TEST_SUITE_END() // Accepts
160
161BOOST_AUTO_TEST_SUITE(Rejects)
162
Davide Pesavento2acce252022-09-08 22:03:03 -0400163BOOST_AUTO_TEST_CASE(NotSigned)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800164{
Davide Pesavento2acce252022-09-08 22:03:03 -0400165 auto i1 = Interest("/short");
166 BOOST_TEST_REQUIRE(i1.getName().size() < signed_interest::MIN_SIZE);
167 VALIDATE_FAILURE(i1, "Should fail (not signed / name too short)");
Davide Pesavento637ea3b2022-09-10 00:11:34 -0400168 BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800169}
170
171BOOST_AUTO_TEST_CASE(BadSigInfo)
172{
Davide Pesavento2acce252022-09-08 22:03:03 -0400173 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800174 setNameComponent(i1, command_interest::POS_SIG_INFO, "not-SignatureInfo");
Davide Pesavento2acce252022-09-08 22:03:03 -0400175 BOOST_TEST_REQUIRE(i1.getName().size() >= command_interest::MIN_SIZE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800176 VALIDATE_FAILURE(i1, "Should fail (signature info is missing)");
Davide Pesavento637ea3b2022-09-10 00:11:34 -0400177 BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800178}
179
Davide Pesavento2acce252022-09-08 22:03:03 -0400180BOOST_AUTO_TEST_CASE(BadTimestampV02)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800181{
Davide Pesavento2acce252022-09-08 22:03:03 -0400182 // i1 is a valid signed interest (in v0.2 format) but is not a valid command interest
183 auto i1 = Interest("/short");
184 m_keyChain.sign(i1, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V02));
185 BOOST_TEST_REQUIRE((i1.getName().size() >= signed_interest::MIN_SIZE &&
186 i1.getName().size() < command_interest::MIN_SIZE));
187 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
188 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
189
190 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V02);
191 setNameComponent(i2, command_interest::POS_TIMESTAMP, "not-timestamp");
192 BOOST_TEST_REQUIRE(i2.getName().size() >= command_interest::MIN_SIZE);
193 VALIDATE_FAILURE(i2, "Should fail (timestamp is malformed)");
194 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
195}
196
197BOOST_AUTO_TEST_CASE(BadTimestampV03)
198{
199 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
200 auto si = i1.getSignatureInfo().value();
201 si.setTime(nullopt);
202 i1.setSignatureInfo(si);
203 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
204 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
205}
206
207BOOST_AUTO_TEST_CASE(MissingKeyLocatorV02)
208{
209 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Junxiao Shi605671d2017-08-26 13:41:06 +0000210 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800211 setNameComponent(i1, command_interest::POS_SIG_INFO,
212 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
213 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400214 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
215}
216
217BOOST_AUTO_TEST_CASE(MissingKeyLocatorV03)
218{
219 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
220 auto si = i1.getSignatureInfo().value();
221 si.setKeyLocator(nullopt);
222 i1.setSignatureInfo(si);
223 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
224 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800225}
226
227BOOST_AUTO_TEST_CASE(BadKeyLocatorType)
228{
Davide Pesavento2acce252022-09-08 22:03:03 -0400229 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800230 KeyLocator kl;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500231 kl.setKeyDigest(makeBinaryBlock(tlv::KeyDigest, {0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD}));
Davide Pesavento2acce252022-09-08 22:03:03 -0400232 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa, kl);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800233 setNameComponent(i1, command_interest::POS_SIG_INFO,
234 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
235 VALIDATE_FAILURE(i1, "Should fail (bad KeyLocator type)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400236 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800237}
238
239BOOST_AUTO_TEST_CASE(BadCertName)
240{
Davide Pesavento2acce252022-09-08 22:03:03 -0400241 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
242 SignatureInfo sigInfo(tlv::SignatureSha256WithEcdsa, KeyLocator("/bad/cert/name"));
Alexander Afanasyev93338872017-01-30 22:37:00 -0800243 setNameComponent(i1, command_interest::POS_SIG_INFO,
244 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
245 VALIDATE_FAILURE(i1, "Should fail (bad certificate name)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400246 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800247}
248
249BOOST_AUTO_TEST_CASE(InnerPolicyReject)
250{
Davide Pesavento2acce252022-09-08 22:03:03 -0400251 auto i1 = makeCommandInterest(otherIdentity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800252 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400253 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
254
255 auto i2 = makeCommandInterest(otherIdentity, SignedInterestFormat::V03);
256 VALIDATE_FAILURE(i2, "Should fail (inner policy should reject)");
257 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800258}
259
Davide Pesavento2acce252022-09-08 22:03:03 -0400260BOOST_FIXTURE_TEST_CASE(TimestampOutOfGracePositive,
261 ValidationPolicyCommandInterestFixture<GracePeriodSeconds<15>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800262{
263 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500264 advanceClocks(16_s); // verifying at +16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800265 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400266 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800267 rewindClockAfterValidation();
268
269 auto i2 = makeCommandInterest(identity); // signed at +16s
270 VALIDATE_SUCCESS(i2, "Should succeed");
271}
272
Davide Pesavento2acce252022-09-08 22:03:03 -0400273BOOST_FIXTURE_TEST_CASE(TimestampOutOfGraceNegative,
274 ValidationPolicyCommandInterestFixture<GracePeriodSeconds<15>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800275{
276 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500277 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800278 auto i2 = makeCommandInterest(identity); // signed at +1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500279 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800280 auto i3 = makeCommandInterest(identity); // signed at +2s
281
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500282 m_systemClock->advance(-18_s); // verifying at -16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800283 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400284 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800285 rewindClockAfterValidation();
286
287 // CommandInterestValidator should not remember i1's timestamp
288 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400289 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800290 rewindClockAfterValidation();
291
292 // CommandInterestValidator should not remember i2's timestamp, and should treat i3 as initial
Davide Pesavento0f830802018-01-16 23:58:58 -0500293 advanceClocks(18_s); // verifying at +2s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800294 VALIDATE_SUCCESS(i3, "Should succeed");
295}
296
297BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
298{
299 auto i1 = makeCommandInterest(identity); // signed at 0s
300 VALIDATE_SUCCESS(i1, "Should succeed");
301
302 auto i2 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento2acce252022-09-08 22:03:03 -0400303 setNameComponent(i2, command_interest::POS_TIMESTAMP, i1.getName()[command_interest::POS_TIMESTAMP]);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800304 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400305 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800306
Davide Pesavento0f830802018-01-16 23:58:58 -0500307 advanceClocks(2_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800308 auto i3 = makeCommandInterest(identity); // signed at +2s
309 VALIDATE_SUCCESS(i3, "Should succeed");
310}
311
312BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
313{
314 auto i2 = makeCommandInterest(identity); // signed at 0ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500315 advanceClocks(200_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800316 auto i3 = makeCommandInterest(identity); // signed at +200ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500317 advanceClocks(900_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800318 auto i1 = makeCommandInterest(identity); // signed at +1100ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500319 advanceClocks(300_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800320 auto i4 = makeCommandInterest(identity); // signed at +1400ms
321
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500322 m_systemClock->advance(-300_ms); // verifying at +1100ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800323 VALIDATE_SUCCESS(i1, "Should succeed");
324 rewindClockAfterValidation();
325
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500326 m_systemClock->advance(-1100_ms); // verifying at 0ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800327 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400328 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800329 rewindClockAfterValidation();
330
331 // CommandInterestValidator should not remember i2's timestamp
Davide Pesavento0f830802018-01-16 23:58:58 -0500332 advanceClocks(200_ms); // verifying at +200ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800333 VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400334 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800335 rewindClockAfterValidation();
336
Davide Pesavento0f830802018-01-16 23:58:58 -0500337 advanceClocks(1200_ms); // verifying at 1400ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800338 VALIDATE_SUCCESS(i4, "Should succeed");
339}
340
341BOOST_AUTO_TEST_SUITE_END() // Rejects
342
343BOOST_AUTO_TEST_SUITE(Options)
344
Davide Pesavento2acce252022-09-08 22:03:03 -0400345using NonPositiveGracePeriods = boost::mpl::vector<
346 GracePeriodSeconds<0>,
347 GracePeriodSeconds<-1>
348>;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800349
Davide Pesavento2acce252022-09-08 22:03:03 -0400350BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Alexander Afanasyev93338872017-01-30 22:37:00 -0800351 ValidationPolicyCommandInterestFixture<GracePeriod>)
352{
353 auto i1 = this->makeCommandInterest(this->identity); // signed at 0ms
354 auto i2 = this->makeCommandInterest(this->subIdentity); // signed at 0ms
355 for (auto interest : {&i1, &i2}) {
356 setNameComponent(*interest, command_interest::POS_TIMESTAMP,
357 name::Component::fromNumber(time::toUnixTimestamp(time::system_clock::now()).count()));
358 } // ensure timestamps are exactly 0ms
359
360 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
361 this->rewindClockAfterValidation();
362
Davide Pesavento0f830802018-01-16 23:58:58 -0500363 this->advanceClocks(1_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800364 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400365 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800366}
367
368class LimitedRecordsOptions
369{
370public:
371 static ValidationPolicyCommandInterest::Options
372 getOptions()
373 {
374 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500375 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800376 options.maxRecords = 3;
377 return options;
378 }
379};
380
381BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicyCommandInterestFixture<LimitedRecordsOptions>)
382{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400383 Identity id1 = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800384 this->cache.insert(id1.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400385 Identity id2 = this->addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800386 this->cache.insert(id2.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400387 Identity id3 = this->addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800388 this->cache.insert(id3.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400389 Identity id4 = this->addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800390 this->cache.insert(id4.getDefaultKey().getDefaultCertificate());
391
392 auto i1 = makeCommandInterest(id2);
393 auto i2 = makeCommandInterest(id3);
394 auto i3 = makeCommandInterest(id4);
395 auto i00 = makeCommandInterest(id1); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500396 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800397 auto i01 = makeCommandInterest(id1); // signed at 1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500398 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800399 auto i02 = makeCommandInterest(id1); // signed at 2s
400
401 VALIDATE_SUCCESS(i00, "Should succeed");
402 rewindClockAfterValidation();
403
404 VALIDATE_SUCCESS(i02, "Should succeed");
405 rewindClockAfterValidation();
406
407 VALIDATE_SUCCESS(i1, "Should succeed");
408 rewindClockAfterValidation();
409
410 VALIDATE_SUCCESS(i2, "Should succeed");
411 rewindClockAfterValidation();
412
413 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
414 rewindClockAfterValidation();
415
416 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
417}
418
419class UnlimitedRecordsOptions
420{
421public:
422 static ValidationPolicyCommandInterest::Options
423 getOptions()
424 {
425 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500426 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800427 options.maxRecords = -1;
428 return options;
429 }
430};
431
432BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<UnlimitedRecordsOptions>)
433{
434 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500435 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400436 Identity id = this->addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800437 this->cache.insert(id.getDefaultKey().getDefaultCertificate());
438 identities.push_back(id);
439 }
440
441 auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500442 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500443 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev93338872017-01-30 22:37:00 -0800444 auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800445 VALIDATE_SUCCESS(i2, "Should succeed");
446 rewindClockAfterValidation();
447 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400448
Alexander Afanasyev93338872017-01-30 22:37:00 -0800449 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400450 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800451}
452
453class ZeroRecordsOptions
454{
455public:
456 static ValidationPolicyCommandInterest::Options
457 getOptions()
458 {
459 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500460 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800461 options.maxRecords = 0;
462 return options;
463 }
464};
465
466BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicyCommandInterestFixture<ZeroRecordsOptions>)
467{
468 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500469 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800470 auto i2 = makeCommandInterest(identity); // signed at +1s
471 VALIDATE_SUCCESS(i2, "Should succeed");
472 rewindClockAfterValidation();
473
474 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record isn't kept");
475}
476
477class LimitedRecordLifetimeOptions
478{
479public:
480 static ValidationPolicyCommandInterest::Options
481 getOptions()
482 {
483 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500484 options.gracePeriod = 400_s;
485 options.recordLifetime = 300_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800486 return options;
487 }
488};
489
490BOOST_FIXTURE_TEST_CASE(LimitedRecordLifetime, ValidationPolicyCommandInterestFixture<LimitedRecordLifetimeOptions>)
491{
492 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500493 advanceClocks(240_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800494 auto i2 = makeCommandInterest(identity); // signed at +240s
Davide Pesavento0f830802018-01-16 23:58:58 -0500495 advanceClocks(120_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800496 auto i3 = makeCommandInterest(identity); // signed at +360s
497
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500498 m_systemClock->advance(-360_s); // rewind system clock to 0s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800499 VALIDATE_SUCCESS(i1, "Should succeed");
500 rewindClockAfterValidation();
501
502 VALIDATE_SUCCESS(i3, "Should succeed");
503 rewindClockAfterValidation();
504
Davide Pesavento0f830802018-01-16 23:58:58 -0500505 advanceClocks(30_s, 301_s); // advance steady clock by 301s, and system clock to +301s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800506 VALIDATE_SUCCESS(i2, "Should succeed despite timestamp is reordered, because record has been expired");
507}
508
509class ZeroRecordLifetimeOptions
510{
511public:
512 static ValidationPolicyCommandInterest::Options
513 getOptions()
514 {
515 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500516 options.gracePeriod = 15_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800517 options.recordLifetime = time::seconds::zero();
518 return options;
519 }
520};
521
522BOOST_FIXTURE_TEST_CASE(ZeroRecordLifetime, ValidationPolicyCommandInterestFixture<ZeroRecordLifetimeOptions>)
523{
524 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500525 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800526 auto i2 = makeCommandInterest(identity); // signed at +1s
527 VALIDATE_SUCCESS(i2, "Should succeed");
528 rewindClockAfterValidation();
529
530 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record has been expired");
531}
532
533BOOST_AUTO_TEST_SUITE_END() // Options
534
535BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyCommandInterest
Alexander Afanasyev93338872017-01-30 22:37:00 -0800536BOOST_AUTO_TEST_SUITE_END() // Security
537
538} // namespace tests
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400539} // inline namespace v2
Alexander Afanasyev93338872017-01-30 22:37:00 -0800540} // namespace security
541} // namespace ndn