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-2018 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 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  BOOST_THROW_EXCEPTION(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 = false;
54  Name keyName;
55  uint64_t timestamp = 0;
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, uint64_t>
80 ValidationPolicyCommandInterest::parseCommandInterest(const Interest& interest,
81  const shared_ptr<ValidationState>& state) const
82 {
83  const Name& name = interest.getName();
84  if (name.size() < command_interest::MIN_SIZE) {
85  state->fail({ValidationError::POLICY_ERROR, "Command interest name `" +
86  interest.getName().toUri() + "` is too short"});
87  return std::make_tuple(false, Name(), 0);
88  }
89 
90  const name::Component& timestampComp = name.at(command_interest::POS_TIMESTAMP);
91  if (!timestampComp.isNumber()) {
92  state->fail({ValidationError::POLICY_ERROR, "Command interest `" +
93  interest.getName().toUri() + "` doesn't include timestamp component"});
94  return std::make_tuple(false, Name(), 0);
95  }
96 
97  Name klName = getKeyLocatorName(interest, *state);
98  if (!state->getOutcome()) { // already failed
99  return std::make_tuple(false, Name(), 0);
100  }
101 
102  return std::make_tuple(true, klName, timestampComp.toNumber());
103 }
104 
105 bool
106 ValidationPolicyCommandInterest::checkTimestamp(const shared_ptr<ValidationState>& state,
107  const Name& keyName, uint64_t timestamp)
108 {
109  this->cleanup();
110 
111  auto now = time::system_clock::now();
112  auto timestampPoint = time::fromUnixTimestamp(time::milliseconds(timestamp));
113  if (timestampPoint < now - m_options.gracePeriod || timestampPoint > now + m_options.gracePeriod) {
114  state->fail({ValidationError::POLICY_ERROR,
115  "Timestamp is outside the grace period for key " + keyName.toUri()});
116  return false;
117  }
118 
119  auto it = m_index.find(keyName);
120  if (it != m_index.end()) {
121  if (timestamp <= it->timestamp) {
122  state->fail({ValidationError::POLICY_ERROR,
123  "Timestamp is reordered for key " + keyName.toUri()});
124  return false;
125  }
126  }
127 
128  auto interestState = dynamic_pointer_cast<InterestValidationState>(state);
129  BOOST_ASSERT(interestState != nullptr);
130  interestState->afterSuccess.connect([=] (const Interest&) { insertNewRecord(keyName, timestamp); });
131  return true;
132 }
133 
134 void
135 ValidationPolicyCommandInterest::insertNewRecord(const Name& keyName, uint64_t timestamp)
136 {
137  // try to insert new record
138  auto now = time::steady_clock::now();
139  auto i = m_queue.end();
140  bool isNew = false;
141  LastTimestampRecord newRecord{keyName, timestamp, now};
142  std::tie(i, isNew) = m_queue.push_back(newRecord);
143 
144  if (!isNew) {
145  BOOST_ASSERT(i->keyName == keyName);
146 
147  // set lastRefreshed field, and move to queue tail
148  m_queue.erase(i);
149  isNew = m_queue.push_back(newRecord).second;
150  BOOST_VERIFY(isNew);
151  }
152 }
153 
154 } // namespace v2
155 } // namespace security
156 } // namespace ndn
void setInnerPolicy(unique_ptr< ValidationPolicy > innerPolicy)
Set inner policy.
Copyright (c) 2011-2015 Regents of the University of California.
std::string toUri() const
Get URI representation of the name.
Definition: name.cpp:117
system_clock::TimePoint fromUnixTimestamp(milliseconds duration)
Convert UNIX timestamp to system_clock::TimePoint.
Definition: time.cpp:119
static time_point now() noexcept
Definition: time.cpp:80
Represents an Interest packet.
Definition: interest.hpp:42
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
bool isNumber() const
Check if the component is nonNegativeInteger.
std::function< void(const shared_ptr< CertificateRequest > &certRequest, const shared_ptr< ValidationState > &state)> ValidationContinuation
static Name getKeyLocatorName(const SignatureInfo &si, ValidationState &state)
const size_t MIN_SIZE
minimal number of components for Command Interest
Represents an absolute name.
Definition: name.hpp:42
time::nanoseconds recordLifetime
max lifetime of a last timestamp record
uint64_t toNumber() const
Interpret this name component as nonNegativeInteger.
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
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:35
const Name & getName() const
Definition: interest.hpp:137
ValidationPolicyCommandInterest(unique_ptr< ValidationPolicy > inner, const Options &options={})
constructor