NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.5: NDN, CCN, CCNx, content centric networks
API Documentation
validation-policy-command-interest.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2020 Regents of the University of California.
4  *
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 
23 
24 namespace ndn {
25 namespace security {
26 inline namespace v2 {
27 
29  const Options& options)
30  : m_options(options)
31  , m_index(m_container.get<0>())
32  , m_queue(m_container.get<1>())
33 {
34  if (inner == nullptr) {
35  NDN_THROW(std::invalid_argument("inner policy is missing"));
36  }
37  setInnerPolicy(std::move(inner));
38 
39  m_options.gracePeriod = std::max(m_options.gracePeriod, 0_ns);
40 }
41 
42 void
43 ValidationPolicyCommandInterest::checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
44  const ValidationContinuation& continueValidation)
45 {
46  getInnerPolicy().checkPolicy(data, state, continueValidation);
47 }
48 
49 void
50 ValidationPolicyCommandInterest::checkPolicy(const Interest& interest, const shared_ptr<ValidationState>& state,
51  const ValidationContinuation& continueValidation)
52 {
53  bool isOk;
54  Name keyName;
56  std::tie(isOk, keyName, timestamp) = parseCommandInterest(interest, state);
57  if (!isOk) {
58  return;
59  }
60 
61  if (!checkTimestamp(state, keyName, timestamp)) {
62  return;
63  }
64  getInnerPolicy().checkPolicy(interest, state, std::bind(continueValidation, _1, _2));
65 }
66 
67 void
68 ValidationPolicyCommandInterest::cleanup()
69 {
70  auto expiring = time::steady_clock::now() - m_options.recordLifetime;
71 
72  while ((!m_queue.empty() && m_queue.front().lastRefreshed <= expiring) ||
73  (m_options.maxRecords >= 0 &&
74  m_queue.size() > static_cast<size_t>(m_options.maxRecords))) {
75  m_queue.pop_front();
76  }
77 }
78 
79 std::tuple<bool, Name, time::system_clock::TimePoint>
80 ValidationPolicyCommandInterest::parseCommandInterest(const Interest& interest,
81  const shared_ptr<ValidationState>& state) const
82 {
83  auto fmt = state->getTag<SignedInterestFormatTag>();
84  BOOST_ASSERT(fmt);
85 
87 
88  if (*fmt == SignedInterestFormat::V03) {
89  BOOST_ASSERT(interest.getSignatureInfo());
90  auto optionalTimestamp = interest.getSignatureInfo()->getTime();
91 
92  // Note that timestamp is a hard requirement of this policy
93  // TODO: Refactor to support other/combinations of the restrictions based on Nonce, Time, and/or SeqNum
94  if (!optionalTimestamp) {
95  state->fail({ValidationError::POLICY_ERROR, "Signed Interest `" +
96  interest.getName().toUri() + "` doesn't include required SignatureTime element"});
97  return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
98  }
99  timestamp = *optionalTimestamp;
100  }
101  else {
102  const Name& name = interest.getName();
103  if (name.size() < command_interest::MIN_SIZE) {
104  state->fail({ValidationError::POLICY_ERROR, "Command interest name `" +
105  interest.getName().toUri() + "` is too short"});
106  return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
107  }
108 
109  const name::Component& timestampComp = name.at(command_interest::POS_TIMESTAMP);
110  if (!timestampComp.isNumber()) {
111  state->fail({ValidationError::POLICY_ERROR, "Command interest `" +
112  interest.getName().toUri() + "` doesn't include timestamp component"});
113  return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
114  }
115  timestamp = time::fromUnixTimestamp(time::milliseconds(timestampComp.toNumber()));
116  }
117 
118  Name klName = getKeyLocatorName(interest, *state);
119  if (!state->getOutcome()) { // already failed
120  return std::make_tuple(false, Name(), time::system_clock::TimePoint{});
121  }
122 
123  return std::make_tuple(true, klName, timestamp);
124 }
125 
126 bool
127 ValidationPolicyCommandInterest::checkTimestamp(const shared_ptr<ValidationState>& state,
128  const Name& keyName, time::system_clock::TimePoint timestamp)
129 {
130  this->cleanup();
131 
132  auto now = time::system_clock::now();
133 
134  if (timestamp < now - m_options.gracePeriod || timestamp > now + m_options.gracePeriod) {
135  state->fail({ValidationError::POLICY_ERROR,
136  "Timestamp is outside the grace period for key " + keyName.toUri()});
137  return false;
138  }
139 
140  auto it = m_index.find(keyName);
141  if (it != m_index.end()) {
142  if (timestamp <= it->timestamp) {
143  state->fail({ValidationError::POLICY_ERROR,
144  "Timestamp is reordered for key " + keyName.toUri()});
145  return false;
146  }
147  }
148 
149  auto interestState = dynamic_pointer_cast<InterestValidationState>(state);
150  BOOST_ASSERT(interestState != nullptr);
151  interestState->afterSuccess.connect([=] (const Interest&) { insertNewRecord(keyName, timestamp); });
152  return true;
153 }
154 
155 void
156 ValidationPolicyCommandInterest::insertNewRecord(const Name& keyName, time::system_clock::TimePoint timestamp)
157 {
158  // try to insert new record
159  auto now = time::steady_clock::now();
160  auto i = m_queue.end();
161  bool isNew = false;
162  LastTimestampRecord newRecord{keyName, timestamp, now};
163  std::tie(i, isNew) = m_queue.push_back(newRecord);
164 
165  if (!isNew) {
166  BOOST_ASSERT(i->keyName == keyName);
167 
168  // set lastRefreshed field, and move to queue tail
169  m_queue.erase(i);
170  isNew = m_queue.push_back(newRecord).second;
171  BOOST_VERIFY(isNew);
172  }
173 }
174 
175 } // inline namespace v2
176 } // namespace security
177 } // namespace ndn
void setInnerPolicy(unique_ptr< ValidationPolicy > innerPolicy)
Set inner policy.
Sign Interest using Packet Specification v0.3 semantics.
Copyright (c) 2011-2015 Regents of the University of California.
static time_point now() noexcept
Definition: time.cpp:80
R & get(variant< T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15 > &v, nonstd_lite_in_place_type_t(R)=nonstd_lite_in_place_type(R))
Represents an Interest packet.
Definition: interest.hpp:48
ValidationPolicy & getInnerPolicy()
Return the inner policy.
void checkPolicy(const Data &data, const shared_ptr< ValidationState > &state, const ValidationContinuation &continueValidation) override
Check data against the policy.
static time_point now() noexcept
Definition: time.cpp:46
optional< SignatureInfo > getSignatureInfo() const
Get the InterestSignatureInfo.
Definition: interest.cpp:544
#define NDN_THROW(e)
Definition: exception.hpp:61
provides a tag type for simple types
Definition: tag.hpp:58
const Component & at(ssize_t i) const
Returns an immutable reference to the component at the specified index, with bounds checking...
Definition: name.cpp:171
system_clock::time_point fromUnixTimestamp(milliseconds duration)
Convert UNIX timestamp to system_clock::time_point.
Definition: time.cpp:119
std::function< void(const shared_ptr< CertificateRequest > &certRequest, const shared_ptr< ValidationState > &state)> ValidationContinuation
static Name getKeyLocatorName(const SignatureInfo &si, ValidationState &state)
Validation state for an interest packet.
const size_t MIN_SIZE
minimal number of components for Command Interest
Represents an absolute name.
Definition: name.hpp:41
time::nanoseconds recordLifetime
max lifetime of a last timestamp record
size_t size() const
Returns the number of components.
Definition: name.hpp:151
ssize_t maxRecords
max number of distinct public keys of which to record the last timestamp
Represents a name component.
const ssize_t POS_TIMESTAMP
const Name & getName() const noexcept
Definition: interest.hpp:172
void toUri(std::ostream &os, name::UriFormat format=name::UriFormat::DEFAULT) const
Write URI representation of the name to the output stream.
Definition: name.cpp:349
virtual void checkPolicy(const Data &data, const shared_ptr< ValidationState > &state, const ValidationContinuation &continueValidation)=0
Check data against the policy.
Represents a Data packet.
Definition: data.hpp:37
time_point TimePoint
Definition: time.hpp:203
ValidationPolicyCommandInterest(unique_ptr< ValidationPolicy > inner, const Options &options={})
constructor
boost::chrono::milliseconds milliseconds
Definition: time.hpp:48