blob: 069c1beaf2037673df299a1d74cd89b801231bbd [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 Pesavento0c526032024-01-31 21:14:01 -05003 * Copyright (c) 2013-2024 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{
Davide Pesavento0c526032024-01-31 21:14:01 -050041 static auto
Alexander Afanasyev93338872017-01-30 22:37:00 -080042 getOptions()
43 {
Davide Pesavento0c526032024-01-31 21:14:01 -050044 return ValidationPolicyCommandInterest::Options{};
Alexander Afanasyev93338872017-01-30 22:37:00 -080045 }
46};
47
Davide Pesavento0c526032024-01-31 21:14:01 -050048template<class ValidationOptions, class InnerPolicy>
Alexander Afanasyev93338872017-01-30 22:37:00 -080049class CommandInterestPolicyWrapper : public ValidationPolicyCommandInterest
50{
51public:
52 CommandInterestPolicyWrapper()
Davide Pesavento0c526032024-01-31 21:14:01 -050053 : ValidationPolicyCommandInterest(make_unique<InnerPolicy>(), ValidationOptions::getOptions())
Alexander Afanasyev93338872017-01-30 22:37:00 -080054 {
55 }
56};
57
Davide Pesavento0c526032024-01-31 21:14:01 -050058template<class ValidationOptions = CommandInterestDefaultOptions,
59 class InnerPolicy = ValidationPolicySimpleHierarchy>
Davide Pesavento2acce252022-09-08 22:03:03 -040060class ValidationPolicyCommandInterestFixture
Davide Pesavento0c526032024-01-31 21:14:01 -050061 : public HierarchicalValidatorFixture<CommandInterestPolicyWrapper<ValidationOptions, InnerPolicy>>
Alexander Afanasyev93338872017-01-30 22:37:00 -080062{
Davide Pesavento2acce252022-09-08 22:03:03 -040063protected:
Alexander Afanasyev93338872017-01-30 22:37:00 -080064 Interest
Davide Pesaventof6b45892023-03-13 15:00:51 -040065 makeCommandInterest(const Identity& id, SignedInterestFormat format = SignedInterestFormat::V02)
Alexander Afanasyev93338872017-01-30 22:37:00 -080066 {
Davide Pesaventof6b45892023-03-13 15:00:51 -040067 Name name = id.getName();
Davide Pesavento2acce252022-09-08 22:03:03 -040068 name.append("CMD");
69 switch (format) {
70 case SignedInterestFormat::V02:
Davide Pesaventof6b45892023-03-13 15:00:51 -040071 return m_signer.makeCommandInterest(name, signingByIdentity(id));
Davide Pesavento2acce252022-09-08 22:03:03 -040072 case SignedInterestFormat::V03: {
73 Interest interest(name);
Davide Pesaventof6b45892023-03-13 15:00:51 -040074 m_signer.makeSignedInterest(interest, signingByIdentity(id));
Davide Pesavento2acce252022-09-08 22:03:03 -040075 return interest;
76 }
Eric Newberry17d7c472020-06-18 21:29:22 -070077 }
Davide Pesavento2acce252022-09-08 22:03:03 -040078 NDN_CXX_UNREACHABLE;
Alexander Afanasyev93338872017-01-30 22:37:00 -080079 }
80
Davide Pesavento2acce252022-09-08 22:03:03 -040081protected:
Davide Pesavento77c5ce82021-05-07 16:12:02 -040082 InterestSigner m_signer{this->m_keyChain};
Alexander Afanasyev93338872017-01-30 22:37:00 -080083};
84
Davide Pesavento0c526032024-01-31 21:14:01 -050085BOOST_FIXTURE_TEST_SUITE(TestValidationPolicyCommandInterest, ValidationPolicyCommandInterestFixture<>)
Alexander Afanasyev93338872017-01-30 22:37:00 -080086
Davide Pesavento2acce252022-09-08 22:03:03 -040087template<int secs>
88struct GracePeriodSeconds
89{
Davide Pesavento0c526032024-01-31 21:14:01 -050090 static auto
Davide Pesavento2acce252022-09-08 22:03:03 -040091 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
Davide Pesavento0c526032024-01-31 21:14:01 -0500144BOOST_FIXTURE_TEST_CASE(SignedWithSha256, ValidationPolicyAcceptAllCommands,
145 * ut::description("test for bug #4635"))
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400146{
147 auto i1 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
148 VALIDATE_SUCCESS(i1, "Should succeed (within grace period)");
149 VALIDATE_FAILURE(i1, "Should fail (replay attack)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400150 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev31fd4672018-06-17 13:25:52 -0400151
152 advanceClocks(5_ms);
153 auto i2 = m_signer.makeCommandInterest("/hello/world/CMD", signingWithSha256());
154 VALIDATE_SUCCESS(i2, "Should succeed (timestamp larger than previous)");
155}
156
Alexander Afanasyev93338872017-01-30 22:37:00 -0800157BOOST_AUTO_TEST_SUITE_END() // Accepts
158
159BOOST_AUTO_TEST_SUITE(Rejects)
160
Davide Pesavento2acce252022-09-08 22:03:03 -0400161BOOST_AUTO_TEST_CASE(NotSigned)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800162{
Davide Pesavento2acce252022-09-08 22:03:03 -0400163 auto i1 = Interest("/short");
164 BOOST_TEST_REQUIRE(i1.getName().size() < signed_interest::MIN_SIZE);
165 VALIDATE_FAILURE(i1, "Should fail (not signed / name too short)");
Davide Pesavento637ea3b2022-09-10 00:11:34 -0400166 BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800167}
168
169BOOST_AUTO_TEST_CASE(BadSigInfo)
170{
Davide Pesavento2acce252022-09-08 22:03:03 -0400171 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800172 setNameComponent(i1, command_interest::POS_SIG_INFO, "not-SignatureInfo");
Davide Pesavento2acce252022-09-08 22:03:03 -0400173 BOOST_TEST_REQUIRE(i1.getName().size() >= command_interest::MIN_SIZE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800174 VALIDATE_FAILURE(i1, "Should fail (signature info is missing)");
Davide Pesavento637ea3b2022-09-10 00:11:34 -0400175 BOOST_TEST(lastError.getCode() == ValidationError::MALFORMED_SIGNATURE);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800176}
177
Davide Pesavento2acce252022-09-08 22:03:03 -0400178BOOST_AUTO_TEST_CASE(BadTimestampV02)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800179{
Davide Pesavento2acce252022-09-08 22:03:03 -0400180 // i1 is a valid signed interest (in v0.2 format) but is not a valid command interest
181 auto i1 = Interest("/short");
182 m_keyChain.sign(i1, signingByIdentity(identity).setSignedInterestFormat(SignedInterestFormat::V02));
183 BOOST_TEST_REQUIRE((i1.getName().size() >= signed_interest::MIN_SIZE &&
184 i1.getName().size() < command_interest::MIN_SIZE));
185 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
186 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
187
188 auto i2 = makeCommandInterest(identity, SignedInterestFormat::V02);
189 setNameComponent(i2, command_interest::POS_TIMESTAMP, "not-timestamp");
190 BOOST_TEST_REQUIRE(i2.getName().size() >= command_interest::MIN_SIZE);
191 VALIDATE_FAILURE(i2, "Should fail (timestamp is malformed)");
192 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
193}
194
195BOOST_AUTO_TEST_CASE(BadTimestampV03)
196{
197 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
198 auto si = i1.getSignatureInfo().value();
Davide Pesaventof6b45892023-03-13 15:00:51 -0400199 si.setTime(std::nullopt);
Davide Pesavento2acce252022-09-08 22:03:03 -0400200 i1.setSignatureInfo(si);
201 VALIDATE_FAILURE(i1, "Should fail (timestamp is missing)");
202 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
203}
204
205BOOST_AUTO_TEST_CASE(MissingKeyLocatorV02)
206{
207 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Junxiao Shi605671d2017-08-26 13:41:06 +0000208 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800209 setNameComponent(i1, command_interest::POS_SIG_INFO,
210 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
211 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400212 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
213}
214
215BOOST_AUTO_TEST_CASE(MissingKeyLocatorV03)
216{
217 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V03);
218 auto si = i1.getSignatureInfo().value();
Davide Pesaventof6b45892023-03-13 15:00:51 -0400219 si.setKeyLocator(std::nullopt);
Davide Pesavento2acce252022-09-08 22:03:03 -0400220 i1.setSignatureInfo(si);
221 VALIDATE_FAILURE(i1, "Should fail (missing KeyLocator)");
222 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800223}
224
225BOOST_AUTO_TEST_CASE(BadKeyLocatorType)
226{
Davide Pesavento2acce252022-09-08 22:03:03 -0400227 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800228 KeyLocator kl;
Davide Pesaventofbea4fc2022-02-08 07:26:04 -0500229 kl.setKeyDigest(makeBinaryBlock(tlv::KeyDigest, {0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD}));
Davide Pesavento2acce252022-09-08 22:03:03 -0400230 SignatureInfo sigInfo(tlv::SignatureSha256WithRsa, kl);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800231 setNameComponent(i1, command_interest::POS_SIG_INFO,
232 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
233 VALIDATE_FAILURE(i1, "Should fail (bad KeyLocator type)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400234 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800235}
236
237BOOST_AUTO_TEST_CASE(BadCertName)
238{
Davide Pesavento2acce252022-09-08 22:03:03 -0400239 auto i1 = makeCommandInterest(identity, SignedInterestFormat::V02);
240 SignatureInfo sigInfo(tlv::SignatureSha256WithEcdsa, KeyLocator("/bad/cert/name"));
Alexander Afanasyev93338872017-01-30 22:37:00 -0800241 setNameComponent(i1, command_interest::POS_SIG_INFO,
242 sigInfo.wireEncode().begin(), sigInfo.wireEncode().end());
243 VALIDATE_FAILURE(i1, "Should fail (bad certificate name)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400244 BOOST_TEST(lastError.getCode() == ValidationError::INVALID_KEY_LOCATOR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800245}
246
247BOOST_AUTO_TEST_CASE(InnerPolicyReject)
248{
Davide Pesavento2acce252022-09-08 22:03:03 -0400249 auto i1 = makeCommandInterest(otherIdentity, SignedInterestFormat::V02);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800250 VALIDATE_FAILURE(i1, "Should fail (inner policy should reject)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400251 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
252
253 auto i2 = makeCommandInterest(otherIdentity, SignedInterestFormat::V03);
254 VALIDATE_FAILURE(i2, "Should fail (inner policy should reject)");
255 BOOST_TEST(lastError.getCode() == ValidationError::LOOP_DETECTED);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800256}
257
Davide Pesavento2acce252022-09-08 22:03:03 -0400258BOOST_FIXTURE_TEST_CASE(TimestampOutOfGracePositive,
259 ValidationPolicyCommandInterestFixture<GracePeriodSeconds<15>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800260{
261 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500262 advanceClocks(16_s); // verifying at +16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800263 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400264 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800265 rewindClockAfterValidation();
266
267 auto i2 = makeCommandInterest(identity); // signed at +16s
268 VALIDATE_SUCCESS(i2, "Should succeed");
269}
270
Davide Pesavento2acce252022-09-08 22:03:03 -0400271BOOST_FIXTURE_TEST_CASE(TimestampOutOfGraceNegative,
272 ValidationPolicyCommandInterestFixture<GracePeriodSeconds<15>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800273{
274 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500275 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800276 auto i2 = makeCommandInterest(identity); // signed at +1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500277 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800278 auto i3 = makeCommandInterest(identity); // signed at +2s
279
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500280 m_systemClock->advance(-18_s); // verifying at -16s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800281 VALIDATE_FAILURE(i1, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400282 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800283 rewindClockAfterValidation();
284
285 // CommandInterestValidator should not remember i1's timestamp
286 VALIDATE_FAILURE(i2, "Should fail (timestamp outside the grace period)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400287 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800288 rewindClockAfterValidation();
289
290 // CommandInterestValidator should not remember i2's timestamp, and should treat i3 as initial
Davide Pesavento0f830802018-01-16 23:58:58 -0500291 advanceClocks(18_s); // verifying at +2s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800292 VALIDATE_SUCCESS(i3, "Should succeed");
293}
294
295BOOST_AUTO_TEST_CASE(TimestampReorderEqual)
296{
297 auto i1 = makeCommandInterest(identity); // signed at 0s
298 VALIDATE_SUCCESS(i1, "Should succeed");
299
300 auto i2 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento2acce252022-09-08 22:03:03 -0400301 setNameComponent(i2, command_interest::POS_TIMESTAMP, i1.getName()[command_interest::POS_TIMESTAMP]);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800302 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400303 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800304
Davide Pesavento0f830802018-01-16 23:58:58 -0500305 advanceClocks(2_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800306 auto i3 = makeCommandInterest(identity); // signed at +2s
307 VALIDATE_SUCCESS(i3, "Should succeed");
308}
309
310BOOST_AUTO_TEST_CASE(TimestampReorderNegative)
311{
312 auto i2 = makeCommandInterest(identity); // signed at 0ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500313 advanceClocks(200_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800314 auto i3 = makeCommandInterest(identity); // signed at +200ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500315 advanceClocks(900_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800316 auto i1 = makeCommandInterest(identity); // signed at +1100ms
Davide Pesavento0f830802018-01-16 23:58:58 -0500317 advanceClocks(300_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800318 auto i4 = makeCommandInterest(identity); // signed at +1400ms
319
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500320 m_systemClock->advance(-300_ms); // verifying at +1100ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800321 VALIDATE_SUCCESS(i1, "Should succeed");
322 rewindClockAfterValidation();
323
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500324 m_systemClock->advance(-1100_ms); // verifying at 0ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800325 VALIDATE_FAILURE(i2, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400326 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800327 rewindClockAfterValidation();
328
329 // CommandInterestValidator should not remember i2's timestamp
Davide Pesavento0f830802018-01-16 23:58:58 -0500330 advanceClocks(200_ms); // verifying at +200ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800331 VALIDATE_FAILURE(i3, "Should fail (timestamp reordered)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400332 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800333 rewindClockAfterValidation();
334
Davide Pesavento0f830802018-01-16 23:58:58 -0500335 advanceClocks(1200_ms); // verifying at 1400ms
Alexander Afanasyev93338872017-01-30 22:37:00 -0800336 VALIDATE_SUCCESS(i4, "Should succeed");
337}
338
339BOOST_AUTO_TEST_SUITE_END() // Rejects
340
Davide Pesavento0c526032024-01-31 21:14:01 -0500341template<ssize_t count>
342struct MaxRecords
343{
344 static auto
345 getOptions()
346 {
347 ValidationPolicyCommandInterest::Options options;
348 options.gracePeriod = 15_s;
349 options.maxRecords = count;
350 return options;
351 }
352};
353
Alexander Afanasyev93338872017-01-30 22:37:00 -0800354BOOST_AUTO_TEST_SUITE(Options)
355
Davide Pesavento49e1e872023-11-11 00:45:23 -0500356using NonPositiveGracePeriods = boost::mp11::mp_list<GracePeriodSeconds<0>, GracePeriodSeconds<-1>>;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800357
Davide Pesavento2acce252022-09-08 22:03:03 -0400358BOOST_FIXTURE_TEST_CASE_TEMPLATE(GraceNonPositive, GracePeriod, NonPositiveGracePeriods,
Alexander Afanasyev93338872017-01-30 22:37:00 -0800359 ValidationPolicyCommandInterestFixture<GracePeriod>)
360{
361 auto i1 = this->makeCommandInterest(this->identity); // signed at 0ms
362 auto i2 = this->makeCommandInterest(this->subIdentity); // signed at 0ms
363 for (auto interest : {&i1, &i2}) {
364 setNameComponent(*interest, command_interest::POS_TIMESTAMP,
365 name::Component::fromNumber(time::toUnixTimestamp(time::system_clock::now()).count()));
366 } // ensure timestamps are exactly 0ms
367
368 VALIDATE_SUCCESS(i1, "Should succeed when validating at 0ms");
369 this->rewindClockAfterValidation();
370
Davide Pesavento0f830802018-01-16 23:58:58 -0500371 this->advanceClocks(1_ms);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800372 VALIDATE_FAILURE(i2, "Should fail when validating at 1ms");
Davide Pesavento2acce252022-09-08 22:03:03 -0400373 BOOST_TEST(this->lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800374}
375
Davide Pesavento0c526032024-01-31 21:14:01 -0500376BOOST_FIXTURE_TEST_CASE(LimitedRecords, ValidationPolicyCommandInterestFixture<MaxRecords<3>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800377{
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400378 Identity id1 = this->addSubCertificate("/Security/ValidatorFixture/Sub1", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800379 this->cache.insert(id1.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400380 Identity id2 = this->addSubCertificate("/Security/ValidatorFixture/Sub2", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800381 this->cache.insert(id2.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400382 Identity id3 = this->addSubCertificate("/Security/ValidatorFixture/Sub3", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800383 this->cache.insert(id3.getDefaultKey().getDefaultCertificate());
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400384 Identity id4 = this->addSubCertificate("/Security/ValidatorFixture/Sub4", identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800385 this->cache.insert(id4.getDefaultKey().getDefaultCertificate());
386
387 auto i1 = makeCommandInterest(id2);
388 auto i2 = makeCommandInterest(id3);
389 auto i3 = makeCommandInterest(id4);
390 auto i00 = makeCommandInterest(id1); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500391 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800392 auto i01 = makeCommandInterest(id1); // signed at 1s
Davide Pesavento0f830802018-01-16 23:58:58 -0500393 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800394 auto i02 = makeCommandInterest(id1); // signed at 2s
395
396 VALIDATE_SUCCESS(i00, "Should succeed");
397 rewindClockAfterValidation();
398
399 VALIDATE_SUCCESS(i02, "Should succeed");
400 rewindClockAfterValidation();
401
402 VALIDATE_SUCCESS(i1, "Should succeed");
403 rewindClockAfterValidation();
404
405 VALIDATE_SUCCESS(i2, "Should succeed");
406 rewindClockAfterValidation();
407
408 VALIDATE_SUCCESS(i3, "Should succeed, forgets identity id1");
409 rewindClockAfterValidation();
410
411 VALIDATE_SUCCESS(i01, "Should succeed despite timestamp is reordered, because record has been evicted");
412}
413
Davide Pesavento0c526032024-01-31 21:14:01 -0500414BOOST_FIXTURE_TEST_CASE(UnlimitedRecords, ValidationPolicyCommandInterestFixture<MaxRecords<-1>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800415{
416 std::vector<Identity> identities;
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500417 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev09236c22020-06-03 13:42:38 -0400418 Identity id = this->addSubCertificate("/Security/ValidatorFixture/Sub" + to_string(i), identity);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800419 this->cache.insert(id.getDefaultKey().getDefaultCertificate());
420 identities.push_back(id);
421 }
422
423 auto i1 = makeCommandInterest(identities.at(0)); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500424 advanceClocks(1_s);
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500425 for (size_t i = 0; i < 20; ++i) {
Alexander Afanasyev93338872017-01-30 22:37:00 -0800426 auto i2 = makeCommandInterest(identities.at(i)); // signed at +1s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800427 VALIDATE_SUCCESS(i2, "Should succeed");
428 rewindClockAfterValidation();
429 }
Davide Pesavento2acce252022-09-08 22:03:03 -0400430
Alexander Afanasyev93338872017-01-30 22:37:00 -0800431 VALIDATE_FAILURE(i1, "Should fail (timestamp reorder)");
Davide Pesavento2acce252022-09-08 22:03:03 -0400432 BOOST_TEST(lastError.getCode() == ValidationError::POLICY_ERROR);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800433}
434
Davide Pesavento0c526032024-01-31 21:14:01 -0500435BOOST_FIXTURE_TEST_CASE(ZeroRecords, ValidationPolicyCommandInterestFixture<MaxRecords<0>>)
Alexander Afanasyev93338872017-01-30 22:37:00 -0800436{
437 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500438 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800439 auto i2 = makeCommandInterest(identity); // signed at +1s
440 VALIDATE_SUCCESS(i2, "Should succeed");
441 rewindClockAfterValidation();
442
443 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record isn't kept");
444}
445
Davide Pesavento0c526032024-01-31 21:14:01 -0500446struct LimitedRecordLifetimeOptions
Alexander Afanasyev93338872017-01-30 22:37:00 -0800447{
Davide Pesavento0c526032024-01-31 21:14:01 -0500448 static auto
Alexander Afanasyev93338872017-01-30 22:37:00 -0800449 getOptions()
450 {
451 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500452 options.gracePeriod = 400_s;
453 options.recordLifetime = 300_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800454 return options;
455 }
456};
457
458BOOST_FIXTURE_TEST_CASE(LimitedRecordLifetime, ValidationPolicyCommandInterestFixture<LimitedRecordLifetimeOptions>)
459{
460 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500461 advanceClocks(240_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800462 auto i2 = makeCommandInterest(identity); // signed at +240s
Davide Pesavento0f830802018-01-16 23:58:58 -0500463 advanceClocks(120_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800464 auto i3 = makeCommandInterest(identity); // signed at +360s
465
Davide Pesavento4c1ad4c2020-11-16 21:12:02 -0500466 m_systemClock->advance(-360_s); // rewind system clock to 0s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800467 VALIDATE_SUCCESS(i1, "Should succeed");
468 rewindClockAfterValidation();
469
470 VALIDATE_SUCCESS(i3, "Should succeed");
471 rewindClockAfterValidation();
472
Davide Pesavento0f830802018-01-16 23:58:58 -0500473 advanceClocks(30_s, 301_s); // advance steady clock by 301s, and system clock to +301s
Alexander Afanasyev93338872017-01-30 22:37:00 -0800474 VALIDATE_SUCCESS(i2, "Should succeed despite timestamp is reordered, because record has been expired");
475}
476
Davide Pesavento0c526032024-01-31 21:14:01 -0500477struct ZeroRecordLifetimeOptions
Alexander Afanasyev93338872017-01-30 22:37:00 -0800478{
Davide Pesavento0c526032024-01-31 21:14:01 -0500479 static auto
Alexander Afanasyev93338872017-01-30 22:37:00 -0800480 getOptions()
481 {
482 ValidationPolicyCommandInterest::Options options;
Davide Pesavento0f830802018-01-16 23:58:58 -0500483 options.gracePeriod = 15_s;
Davide Pesavento0c526032024-01-31 21:14:01 -0500484 options.recordLifetime = 0_s;
Alexander Afanasyev93338872017-01-30 22:37:00 -0800485 return options;
486 }
487};
488
489BOOST_FIXTURE_TEST_CASE(ZeroRecordLifetime, ValidationPolicyCommandInterestFixture<ZeroRecordLifetimeOptions>)
490{
491 auto i1 = makeCommandInterest(identity); // signed at 0s
Davide Pesavento0f830802018-01-16 23:58:58 -0500492 advanceClocks(1_s);
Alexander Afanasyev93338872017-01-30 22:37:00 -0800493 auto i2 = makeCommandInterest(identity); // signed at +1s
494 VALIDATE_SUCCESS(i2, "Should succeed");
495 rewindClockAfterValidation();
496
497 VALIDATE_SUCCESS(i1, "Should succeed despite timestamp is reordered, because record has been expired");
498}
499
500BOOST_AUTO_TEST_SUITE_END() // Options
501
502BOOST_AUTO_TEST_SUITE_END() // TestValidationPolicyCommandInterest
Alexander Afanasyev93338872017-01-30 22:37:00 -0800503BOOST_AUTO_TEST_SUITE_END() // Security
504
Davide Pesavento47ce2ee2023-05-09 01:33:33 -0400505} // namespace ndn::tests