validation-policy-command-interest.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
23 #include "../pib/key.hpp"
24 
25 namespace ndn {
26 namespace security {
27 namespace v2 {
28 
30  const Options& options)
31  : m_options(options)
32  , m_index(m_container.get<0>())
33  , m_queue(m_container.get<1>())
34 {
35  if (inner == nullptr) {
36  BOOST_THROW_EXCEPTION(std::invalid_argument("inner policy is missing"));
37  }
38  setInnerPolicy(std::move(inner));
39 
40  m_options.gracePeriod = std::max(m_options.gracePeriod, time::nanoseconds::zero());
41 }
42 
43 void
44 ValidationPolicyCommandInterest::checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
45  const ValidationContinuation& continueValidation)
46 {
47  getInnerPolicy().checkPolicy(data, state, continueValidation);
48 }
49 
50 void
51 ValidationPolicyCommandInterest::checkPolicy(const Interest& interest, const shared_ptr<ValidationState>& state,
52  const ValidationContinuation& continueValidation)
53 {
54  bool isOk = false;
55  Name keyName;
56  uint64_t timestamp = 0;
57  std::tie(isOk, keyName, timestamp) = parseCommandInterest(interest, state);
58  if (!isOk) {
59  return;
60  }
61 
62  if (!checkTimestamp(state, keyName, timestamp)) {
63  return;
64  }
65  getInnerPolicy().checkPolicy(interest, state, std::bind(continueValidation, _1, _2));
66 }
67 
68 void
69 ValidationPolicyCommandInterest::cleanup()
70 {
72 
73  while ((!m_queue.empty() && m_queue.front().lastRefreshed <= expiring) ||
74  (m_options.maxRecords >= 0 &&
75  m_queue.size() > static_cast<size_t>(m_options.maxRecords))) {
76  m_queue.pop_front();
77  }
78 }
79 
80 std::tuple<bool, Name, uint64_t>
81 ValidationPolicyCommandInterest::parseCommandInterest(const Interest& interest,
82  const shared_ptr<ValidationState>& state) const
83 {
84  const Name& name = interest.getName();
85  if (name.size() < command_interest::MIN_SIZE) {
86  state->fail({ValidationError::POLICY_ERROR, "Command interest name `" +
87  interest.getName().toUri() + "` is too short"});
88  return std::make_tuple(false, Name(), 0);
89  }
90 
91  const name::Component& timestampComp = name.at(command_interest::POS_TIMESTAMP);
92  if (!timestampComp.isNumber()) {
93  state->fail({ValidationError::POLICY_ERROR, "Command interest `" +
94  interest.getName().toUri() + "` doesn't include timestamp component"});
95  return std::make_tuple(false, Name(), 0);
96  }
97 
98  Name klName = getKeyLocatorName(interest, *state);
99  if (!state->getOutcome()) { // already failed
100  return std::make_tuple(false, Name(), 0);
101  }
102 
103  return std::make_tuple(true, klName, timestampComp.toNumber());
104 }
105 
106 bool
107 ValidationPolicyCommandInterest::checkTimestamp(const shared_ptr<ValidationState>& state,
108  const Name& keyName, uint64_t timestamp)
109 {
110  this->cleanup();
111 
113  time::system_clock::TimePoint timestampPoint = time::fromUnixTimestamp(time::milliseconds(timestamp));
114  if (timestampPoint < now - m_options.gracePeriod || timestampPoint > now + m_options.gracePeriod) {
115  state->fail({ValidationError::POLICY_ERROR, "Timestamp is outside the grace period for key " + keyName.toUri()});
116  return false;
117  }
118  auto it = m_index.find(keyName);
119  if (it != m_index.end()) {
120  if (timestamp <= it->timestamp) {
121  state->fail({ValidationError::POLICY_ERROR, "Timestamp is reordered for key " + keyName.toUri()});
122  return false;
123  }
124  }
125 
126  shared_ptr<InterestValidationState> interestState = std::dynamic_pointer_cast<InterestValidationState>(state);
127  interestState->afterSuccess.connect(bind(&ValidationPolicyCommandInterest::insertNewRecord,
128  this, _1, keyName, timestamp));
129  return true;
130 }
131 
132 void
133 ValidationPolicyCommandInterest::insertNewRecord(const Interest& interest, const Name& keyName,
134  uint64_t timestamp)
135 {
136  // try to insert new record
138  Queue::iterator i = m_queue.end();
139  bool isNew = false;
140  LastTimestampRecord newRecord{keyName, timestamp, now};
141  std::tie(i, isNew) = m_queue.push_back(newRecord);
142 
143  if (!isNew) {
144  BOOST_ASSERT(i->keyName == keyName);
145 
146  // set lastRefreshed field, and move to queue tail
147  m_queue.erase(i);
148  isNew = m_queue.push_back(newRecord).second;
149  BOOST_VERIFY(isNew);
150  }
151 }
152 
153 } // namespace v2
154 } // namespace security
155 } // namespace ndn
void setInnerPolicy(unique_ptr< ValidationPolicy > innerPolicy)
Set inner policy.
time_point TimePoint
Definition: time.hpp:120
const Name & getName() const
Definition: interest.hpp:139
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
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
std::string toUri() const
Get URI representation of the name.
Definition: name.cpp:122
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.
util::Signal< InterestValidationState, Interest > afterSuccess
size_t size() const
Get number of components.
Definition: name.hpp:154
const size_t MIN_SIZE
minimal number of components for Command Interest
Represents an absolute name.
Definition: name.hpp:42
const Component & at(ssize_t i) const
Get the component at the given index.
Definition: name.cpp:185
time::nanoseconds recordLifetime
max lifetime of a last timestamp record
time_point TimePoint
Definition: time.hpp:90
ssize_t maxRecords
max number of distinct public keys of which to record the last timestamp
Component holds a read-only name component value.
const ssize_t POS_TIMESTAMP
system_clock::TimePoint fromUnixTimestamp(const milliseconds &duration)
Convert UNIX timestamp to system_clock::TimePoint.
Definition: time.cpp:125
bool isNumber() const
Check if the component is nonNegativeInteger.
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
uint64_t toNumber() const
Interpret this name component as nonNegativeInteger.
ValidationPolicyCommandInterest(unique_ptr< ValidationPolicy > inner, const Options &options={})
constructor