command-interest-validator.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
23 #include <boost/lexical_cast.hpp>
24 
25 namespace ndn {
26 namespace security {
27 
28 std::ostream&
30 {
31  switch (error) {
33  return os << "OK";
35  return os << "command Interest name is too short";
37  return os << "cannot parse timestamp";
39  return os << "cannot parse SignatureInfo";
41  return os << "KeyLocator is missing";
43  return os << "KeyLocator type is not Name";
45  return os << "cannot parse certificate name";
47  return os << "timestamp is out of grace period";
49  return os << "timestamp is less than or equal to last timestamp";
50  }
51  return os;
52 }
53 
54 static void
55 invokeReject(const OnInterestValidationFailed& reject, const Interest& interest,
57 {
58  reject(interest.shared_from_this(), boost::lexical_cast<std::string>(error));
59 }
60 
62  const Options& options)
63  : m_inner(std::move(inner))
64  , m_options(options)
65  , m_index(m_container.get<0>())
66  , m_queue(m_container.get<1>())
67 {
68  if (m_inner == nullptr) {
69  BOOST_THROW_EXCEPTION(std::invalid_argument("inner validator is nullptr"));
70  }
71 
72  m_options.gracePeriod = std::max(m_options.gracePeriod, time::nanoseconds::zero());
73 }
74 
75 void
76 CommandInterestValidator::checkPolicy(const Interest& interest, int nSteps,
77  const OnInterestValidated& accept,
78  const OnInterestValidationFailed& reject,
79  std::vector<shared_ptr<ValidationRequest>>& nextSteps)
80 {
81  BOOST_ASSERT(nSteps == 0);
82  this->cleanup();
83 
84  Name keyName;
85  uint64_t timestamp;
86  ErrorCode res = this->parseCommandInterest(interest, keyName, timestamp);
87  if (res != ErrorCode::NONE) {
88  return invokeReject(reject, interest, res);
89  }
90 
92 
93  m_inner->validate(interest,
94  [=] (const shared_ptr<const Interest>& interest) {
95  ErrorCode res = this->checkTimestamp(keyName, timestamp, receiveTime);
96  if (res != ErrorCode::NONE) {
97  return invokeReject(reject, *interest, res);
98  }
99  accept(interest);
100  }, reject);
101 }
102 
103 void
104 CommandInterestValidator::cleanup()
105 {
107 
108  while ((!m_queue.empty() && m_queue.front().lastRefreshed <= expiring) ||
109  (m_options.maxTimestamps >= 0 &&
110  m_queue.size() > static_cast<size_t>(m_options.maxTimestamps))) {
111  m_queue.pop_front();
112  }
113 }
114 
116 CommandInterestValidator::parseCommandInterest(const Interest& interest, Name& keyName,
117  uint64_t& timestamp) const
118 {
119  const Name& name = interest.getName();
120  if (name.size() < command_interest::MIN_SIZE) {
122  }
123 
124  const name::Component& timestampComp = name.at(command_interest::POS_TIMESTAMP);
125  if (!timestampComp.isNumber()) {
127  }
128  timestamp = timestampComp.toNumber();
129 
130  SignatureInfo sig;
131  try {
132  sig.wireDecode(name[signed_interest::POS_SIG_INFO].blockFromValue());
133  }
134  catch (const tlv::Error&) {
136  }
137 
138  if (!sig.hasKeyLocator()) {
140  }
141 
142  const KeyLocator& keyLocator = sig.getKeyLocator();
143  if (keyLocator.getType() != KeyLocator::KeyLocator_Name) {
145  }
146 
147  try {
149  }
150  catch (const std::invalid_argument&) {
152  }
153 
154  keyName = keyLocator.getName();
155 
156  return ErrorCode::NONE;
157 }
158 
160 CommandInterestValidator::checkTimestamp(const Name& keyName, uint64_t timestamp,
161  time::system_clock::TimePoint receiveTime)
162 {
164 
165  // try to insert new record
166  Queue::iterator i = m_queue.end();
167  bool isNew = false;
168  std::tie(i, isNew) = m_queue.push_back({keyName, timestamp, now});
169 
170  if (isNew) {
171  // check grace period
172  time::system_clock::TimePoint sigTime = time::fromUnixTimestamp(time::milliseconds(timestamp));
173  if (time::abs(sigTime - receiveTime) > m_options.gracePeriod) {
174  // out of grace period, delete new record
175  m_queue.erase(i);
177  }
178  }
179  else {
180  BOOST_ASSERT(i->keyName == keyName);
181 
182  // compare timestamp with last timestamp
183  if (timestamp <= i->timestamp) {
185  }
186 
187  // set lastRefreshed field, and move to queue tail
188  m_queue.erase(i);
189  isNew = m_queue.push_back({keyName, timestamp, now}).second;
190  BOOST_ASSERT(isNew);
191  }
192 
193  return ErrorCode::NONE;
194 }
195 
196 void
198  const OnDataValidated& accept,
199  const OnDataValidationFailed& reject,
200  std::vector<shared_ptr<ValidationRequest>>& nextSteps)
201 {
202  BOOST_ASSERT(nSteps == 0);
203  m_inner->validate(data, accept, reject);
204 }
205 
206 } // namespace security
207 } // namespace ndn
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestValidationFailed
Callback to report a failed Interest validation.
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:75
Represents a SignatureInfo TLV element.
static time_point now() noexcept
Definition: time.cpp:80
time::nanoseconds timestampTtl
max lifetime of a last timestamp record
STL namespace.
represents an Interest packet
Definition: interest.hpp:42
indicates KeyLocator contains a Name
Definition: key-locator.hpp:49
static time_point now() noexcept
Definition: time.cpp:46
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataValidationFailed
Callback to report a failed Data validation.
const KeyLocator & getKeyLocator() const
Get KeyLocator.
std::ostream & operator<<(std::ostream &os, CommandInterestValidator::ErrorCode error)
constexpr duration< Rep, Period > abs(duration< Rep, Period > d)
Definition: time.hpp:53
function< void(const shared_ptr< const Data > &)> OnDataValidated
Callback to report a successful Data validation.
function< void(const shared_ptr< const Interest > &)> OnInterestValidated
Callback to report a successful Interest validation.
const Name & getName() const
get Name element
Type getType() const
CommandInterestValidator(unique_ptr< Validator > inner, const Options &options=Options())
constructor
static void invokeReject(const OnInterestValidationFailed &reject, const Interest &interest, CommandInterestValidator::ErrorCode error)
void checkPolicy(const Interest &interest, int nSteps, const OnInterestValidated &accept, const OnInterestValidationFailed &reject, std::vector< shared_ptr< ValidationRequest >> &nextSteps) override
validate command Interest
time::nanoseconds gracePeriod
tolerance of initial timestamp
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_point TimePoint
Definition: time.hpp:90
Component holds a read-only name component value.
void wireDecode(const Block &wire)
Decode from wire format.
const ssize_t POS_TIMESTAMP
system_clock::TimePoint fromUnixTimestamp(const milliseconds &duration)
Convert UNIX timestamp to system_clock::TimePoint.
Definition: time.cpp:125
const ssize_t POS_SIG_INFO
bool isNumber() const
Check if the component is nonNegativeInteger.
ssize_t maxTimestamps
max number of distinct public keys to record last timestamp
bool hasKeyLocator() const
Check if KeyLocator exists.
Represents a Data packet.
Definition: data.hpp:35
uint64_t toNumber() const
Interpret this name component as nonNegativeInteger.
Name extractIdentityFromKeyName(const Name &keyName)
Extract identity namespace from the key name keyName.
Definition: key.cpp:148
represents an error in TLV encoding or decoding