NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
validator-config.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
25 #include "validator-config.hpp"
27 #include "../util/io.hpp"
28 
29 #include <boost/filesystem.hpp>
30 #include <boost/property_tree/info_parser.hpp>
31 #include <boost/algorithm/string.hpp>
32 
33 namespace ndn {
34 namespace security {
35 
36 const shared_ptr<CertificateCache> ValidatorConfig::DEFAULT_CERTIFICATE_CACHE;
37 const time::milliseconds ValidatorConfig::DEFAULT_GRACE_INTERVAL(3000);
39 
41  const shared_ptr<CertificateCache>& certificateCache,
42  const time::milliseconds& graceInterval,
43  const size_t stepLimit,
44  const size_t maxTrackedKeys,
45  const time::system_clock::Duration& keyTimestampTtl)
46  : Validator(face)
47  , m_shouldValidate(true)
48  , m_stepLimit(stepLimit)
49  , m_certificateCache(certificateCache)
50  , m_graceInterval(graceInterval < time::milliseconds::zero() ?
51  DEFAULT_GRACE_INTERVAL : graceInterval)
52  , m_maxTrackedKeys(maxTrackedKeys)
53  , m_keyTimestampTtl(keyTimestampTtl)
54 {
55  if (m_certificateCache == nullptr && face != nullptr)
56  m_certificateCache = make_shared<CertificateCacheTtl>(ref(face->getIoService()));
57 }
58 
60  const shared_ptr<CertificateCache>& certificateCache,
61  const time::milliseconds& graceInterval,
62  const size_t stepLimit,
63  const size_t maxTrackedKeys,
64  const time::system_clock::Duration& keyTimestampTtl)
65  : Validator(face)
66  , m_shouldValidate(true)
67  , m_stepLimit(stepLimit)
68  , m_certificateCache(certificateCache)
69  , m_graceInterval(graceInterval < time::milliseconds::zero() ?
70  DEFAULT_GRACE_INTERVAL : graceInterval)
71  , m_maxTrackedKeys(maxTrackedKeys)
72  , m_keyTimestampTtl(keyTimestampTtl)
73 {
74  if (m_certificateCache == nullptr)
75  m_certificateCache = make_shared<CertificateCacheTtl>(ref(face.getIoService()));
76 }
77 
78 void
79 ValidatorConfig::load(const std::string& filename)
80 {
81  std::ifstream inputFile;
82  inputFile.open(filename.c_str());
83  if (!inputFile.good() || !inputFile.is_open()) {
84  std::string msg = "Failed to read configuration file: ";
85  msg += filename;
86  BOOST_THROW_EXCEPTION(security::conf::Error(msg));
87  }
88  load(inputFile, filename);
89  inputFile.close();
90 }
91 
92 void
93 ValidatorConfig::load(const std::string& input, const std::string& filename)
94 {
95  std::istringstream inputStream(input);
96  load(inputStream, filename);
97 }
98 
99 
100 void
101 ValidatorConfig::load(std::istream& input, const std::string& filename)
102 {
104  try {
105  boost::property_tree::read_info(input, tree);
106  }
107  catch (const boost::property_tree::info_parser_error& error) {
108  std::stringstream msg;
109  msg << "Failed to parse configuration file";
110  msg << " " << filename;
111  msg << " " << error.message() << " line " << error.line();
112  BOOST_THROW_EXCEPTION(security::conf::Error(msg.str()));
113  }
114 
115  load(tree, filename);
116 }
117 
118 void
120  const std::string& filename)
121 {
122  BOOST_ASSERT(!filename.empty());
123 
124  reset();
125 
126  if (configSection.begin() == configSection.end()) {
127  std::string msg = "Error processing configuration file";
128  msg += ": ";
129  msg += filename;
130  msg += " no data";
131  BOOST_THROW_EXCEPTION(security::conf::Error(msg));
132  }
133 
134  for (security::conf::ConfigSection::const_iterator i = configSection.begin();
135  i != configSection.end(); ++i) {
136  const std::string& sectionName = i->first;
137  const security::conf::ConfigSection& section = i->second;
138 
139  if (boost::iequals(sectionName, "rule")) {
140  onConfigRule(section, filename);
141  }
142  else if (boost::iequals(sectionName, "trust-anchor")) {
143  onConfigTrustAnchor(section, filename);
144  }
145  else {
146  std::string msg = "Error processing configuration file";
147  msg += " ";
148  msg += filename;
149  msg += " unrecognized section: " + sectionName;
150  BOOST_THROW_EXCEPTION(security::conf::Error(msg));
151  }
152  }
153 }
154 
155 void
156 ValidatorConfig::onConfigRule(const security::conf::ConfigSection& configSection,
157  const std::string& filename)
158 {
159  using namespace ndn::security::conf;
160 
161  ConfigSection::const_iterator propertyIt = configSection.begin();
162 
163  // Get rule.id
164  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "id"))
165  BOOST_THROW_EXCEPTION(Error("Expect <rule.id>!"));
166 
167  std::string ruleId = propertyIt->second.data();
168  propertyIt++;
169 
170  // Get rule.for
171  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first,"for"))
172  BOOST_THROW_EXCEPTION(Error("Expect <rule.for> in rule: " + ruleId + "!"));
173 
174  std::string usage = propertyIt->second.data();
175  propertyIt++;
176 
177  bool isForData = false;
178  if (boost::iequals(usage, "data"))
179  isForData = true;
180  else if (boost::iequals(usage, "interest"))
181  isForData = false;
182  else
183  BOOST_THROW_EXCEPTION(Error("Unrecognized <rule.for>: " + usage
184  + " in rule: " + ruleId));
185 
186  // Get rule.filter(s)
187  std::vector<shared_ptr<Filter>> filters;
188  for (; propertyIt != configSection.end(); propertyIt++) {
189  if (!boost::iequals(propertyIt->first, "filter")) {
190  if (boost::iequals(propertyIt->first, "checker"))
191  break;
192  BOOST_THROW_EXCEPTION(Error("Expect <rule.filter> in rule: " + ruleId));
193  }
194 
195  filters.push_back(FilterFactory::create(propertyIt->second));
196  continue;
197  }
198 
199  // Get rule.checker(s)
200  std::vector<shared_ptr<Checker>> checkers;
201  for (; propertyIt != configSection.end(); propertyIt++) {
202  if (!boost::iequals(propertyIt->first, "checker"))
203  BOOST_THROW_EXCEPTION(Error("Expect <rule.checker> in rule: " + ruleId));
204 
205  checkers.push_back(CheckerFactory::create(propertyIt->second, filename));
206  continue;
207  }
208 
209  // Check other stuff
210  if (propertyIt != configSection.end())
211  BOOST_THROW_EXCEPTION(Error("Expect the end of rule: " + ruleId));
212 
213  if (checkers.empty())
214  BOOST_THROW_EXCEPTION(Error("No <rule.checker> is specified in rule: " + ruleId));
215 
216  if (isForData) {
217  shared_ptr<DataRule> rule = make_shared<DataRule>(ruleId);
218  for (const auto& filter : filters)
219  rule->addFilter(filter);
220  for (const auto& checker : checkers)
221  rule->addChecker(checker);
222 
223  m_dataRules.push_back(rule);
224  }
225  else {
226  shared_ptr<InterestRule> rule = make_shared<InterestRule>(ruleId);;
227  for (const auto& filter : filters)
228  rule->addFilter(filter);
229  for (const auto& checker : checkers)
230  rule->addChecker(checker);
231 
232  m_interestRules.push_back(rule);
233  }
234 }
235 
236 void
237 ValidatorConfig::onConfigTrustAnchor(const security::conf::ConfigSection& configSection,
238  const std::string& filename)
239 {
240  using namespace ndn::security::conf;
241  using namespace boost::filesystem;
242 
243  ConfigSection::const_iterator propertyIt = configSection.begin();
244 
245  // Get trust-anchor.type
246  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
247  BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.type>!"));
248 
249  std::string type = propertyIt->second.data();
250  propertyIt++;
251 
252  if (boost::iequals(type, "file")) {
253  // Get trust-anchor.file
254  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
255  BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.file-name>!"));
256 
257  std::string file = propertyIt->second.data();
258  propertyIt++;
259 
260  // Check other stuff
261  if (propertyIt != configSection.end())
262  BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));
263 
264  path certfilePath = absolute(file, path(filename).parent_path());
265  auto idCert = io::load<v1::IdentityCertificate>(certfilePath.string());
266 
267  if (idCert != nullptr) {
268  BOOST_ASSERT(idCert->getName().size() >= 1);
269  m_staticContainer.add(idCert);
270  m_anchors[idCert->getName().getPrefix(-1)] = idCert;
271  }
272  else
273  BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " + certfilePath.native()));
274 
275  return;
276  }
277  else if (boost::iequals(type, "base64")) {
278  // Get trust-anchor.base64-string
279  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "base64-string"))
280  BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.base64-string>!"));
281 
282  std::stringstream ss(propertyIt->second.data());
283  propertyIt++;
284 
285  // Check other stuff
286  if (propertyIt != configSection.end())
287  BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor!"));
288 
289  auto idCert = io::load<v1::IdentityCertificate>(ss);
290 
291  if (idCert != nullptr) {
292  BOOST_ASSERT(idCert->getName().size() >= 1);
293  m_staticContainer.add(idCert);
294  m_anchors[idCert->getName().getPrefix(-1)] = idCert;
295  }
296  else
297  BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from base64-string"));
298 
299  return;
300  }
301  else if (boost::iequals(type, "dir")) {
302  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
303  BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.dir>"));
304 
305  std::string dirString(propertyIt->second.data());
306  propertyIt++;
307 
308  if (propertyIt != configSection.end()) {
309  if (boost::iequals(propertyIt->first, "refresh")) {
310  using namespace boost::filesystem;
311 
312  time::nanoseconds refresh = getRefreshPeriod(propertyIt->second.data());
313  propertyIt++;
314 
315  if (propertyIt != configSection.end())
316  BOOST_THROW_EXCEPTION(Error("Expect the end of trust-anchor"));
317 
318  path dirPath = absolute(dirString, path(filename).parent_path());
319 
320  m_dynamicContainers.push_back(DynamicTrustAnchorContainer(dirPath, true, refresh));
321 
322  m_dynamicContainers.rbegin()->setLastRefresh(time::system_clock::now() - refresh);
323 
324  return;
325  }
326  else
327  BOOST_THROW_EXCEPTION(Error("Expect <trust-anchor.refresh>!"));
328  }
329  else {
330  using namespace boost::filesystem;
331 
332  path dirPath = absolute(dirString, path(filename).parent_path());
333 
334  directory_iterator end;
335 
336  for (directory_iterator it(dirPath); it != end; it++) {
337  auto idCert = io::load<v1::IdentityCertificate>(it->path().string());
338 
339  if (idCert != nullptr)
340  m_staticContainer.add(idCert);
341  }
342 
343  return;
344  }
345  }
346  else if (boost::iequals(type, "any")) {
347  m_shouldValidate = false;
348  }
349  else
350  BOOST_THROW_EXCEPTION(Error("Unsupported trust-anchor.type: " + type));
351 }
352 
353 void
355 {
356  if (m_certificateCache != nullptr)
357  m_certificateCache->reset();
358  m_interestRules.clear();
359  m_dataRules.clear();
360 
361  m_anchors.clear();
362 
363  m_staticContainer = TrustAnchorContainer();
364 
365  m_dynamicContainers.clear();
366 }
367 
368 bool
370 {
371  return ((m_certificateCache == nullptr || m_certificateCache->isEmpty()) &&
372  m_interestRules.empty() && m_dataRules.empty() && m_anchors.empty());
373 }
374 
375 time::nanoseconds
376 ValidatorConfig::getRefreshPeriod(std::string inputString)
377 {
378  char unit = inputString[inputString.size() - 1];
379  std::string refreshString = inputString.substr(0, inputString.size() - 1);
380 
381  uint32_t refreshPeriod = 0;
382 
383  try {
384  refreshPeriod = boost::lexical_cast<uint32_t>(refreshString);
385  }
386  catch (const boost::bad_lexical_cast&) {
387  BOOST_THROW_EXCEPTION(Error("Bad number: " + refreshString));
388  }
389 
390  if (refreshPeriod == 0)
391  return getDefaultRefreshPeriod();
392 
393  switch (unit) {
394  case 'h':
395  return time::duration_cast<time::nanoseconds>(time::hours(refreshPeriod));
396  case 'm':
397  return time::duration_cast<time::nanoseconds>(time::minutes(refreshPeriod));
398  case 's':
399  return time::duration_cast<time::nanoseconds>(time::seconds(refreshPeriod));
400  default:
401  BOOST_THROW_EXCEPTION(Error(std::string("Wrong time unit: ") + unit));
402  }
403 }
404 
405 time::nanoseconds
406 ValidatorConfig::getDefaultRefreshPeriod()
407 {
408  return time::duration_cast<time::nanoseconds>(time::seconds(3600));
409 }
410 
411 void
412 ValidatorConfig::refreshAnchors()
413 {
415 
416  bool isRefreshed = false;
417 
418  for (auto cIt = m_dynamicContainers.begin();
419  cIt != m_dynamicContainers.end() && cIt->getLastRefresh() + cIt->getRefreshPeriod() < now;
420  cIt++) {
421  isRefreshed = true;
422  cIt->refresh();
423  cIt->setLastRefresh(now);
424  }
425 
426  if (isRefreshed) {
427  m_anchors.clear();
428 
429  for (const auto& cert : m_staticContainer.getAll()) {
430  m_anchors[cert->getName().getPrefix(-1)] = cert;
431  }
432 
433  for (const auto& container : m_dynamicContainers) {
434  const CertificateList& certList = container.getAll();
435 
436  for (const auto& cert :certList) {
437  m_anchors[cert->getName().getPrefix(-1)] = cert;
438  }
439  }
440  m_dynamicContainers.sort(ValidatorConfig::compareDynamicContainer);
441  }
442 }
443 
444 void
446  int nSteps,
447  const OnDataValidated& onValidated,
448  const OnDataValidationFailed& onValidationFailed,
449  std::vector<shared_ptr<ValidationRequest>>& nextSteps)
450 {
451  if (!m_shouldValidate)
452  return onValidated(data.shared_from_this());
453 
454  bool isMatched = false;
455  int8_t checkResult = -1;
456 
457  for (const auto& dataRule : m_dataRules) {
458  if (dataRule->match(data)) {
459  isMatched = true;
460  checkResult = dataRule->check(data, onValidated, onValidationFailed);
461  break;
462  }
463  }
464 
465  if (!isMatched)
466  return onValidationFailed(data.shared_from_this(), "No rule matched!");
467 
468  if (checkResult == 0) {
469  const Signature& signature = data.getSignature();
470  checkSignature(data, signature, nSteps,
471  onValidated, onValidationFailed, nextSteps);
472  }
473 }
474 
475 void
477  int nSteps,
478  const OnInterestValidated& onValidated,
479  const OnInterestValidationFailed& onValidationFailed,
480  std::vector<shared_ptr<ValidationRequest>>& nextSteps)
481 {
482  if (!m_shouldValidate)
483  return onValidated(interest.shared_from_this());
484 
485  // If interestName has less than 4 name components,
486  // it is definitely not a signed interest.
487  if (interest.getName().size() < signed_interest::MIN_LENGTH)
488  return onValidationFailed(interest.shared_from_this(),
489  "Interest is not signed: " + interest.getName().toUri());
490 
491  try {
492  const Name& interestName = interest.getName();
493  Signature signature(interestName[signed_interest::POS_SIG_INFO].blockFromValue(),
494  interestName[signed_interest::POS_SIG_VALUE].blockFromValue());
495 
496  if (!signature.hasKeyLocator())
497  return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
498 
499  const KeyLocator& keyLocator = signature.getKeyLocator();
500 
501  if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
502  return onValidationFailed(interest.shared_from_this(), "Key Locator is not a name");
503 
505 
506  bool isMatched = false;
507  int8_t checkResult = -1;
508 
509  for (const auto& interestRule : m_interestRules) {
510  if (interestRule->match(interest)) {
511  isMatched = true;
512  checkResult = interestRule->check(interest,
513  bind(&ValidatorConfig::checkTimestamp, this, _1,
514  keyName, onValidated, onValidationFailed),
515  onValidationFailed);
516  break;
517  }
518  }
519 
520  if (!isMatched)
521  return onValidationFailed(interest.shared_from_this(), "No rule matched!");
522 
523  if (checkResult == 0) {
524  checkSignature<Interest, OnInterestValidated, OnInterestValidationFailed>
525  (interest, signature, nSteps,
526  bind(&ValidatorConfig::checkTimestamp, this, _1,
527  keyName, onValidated, onValidationFailed),
528  onValidationFailed,
529  nextSteps);
530  }
531  }
532  catch (const Signature::Error& e) {
533  return onValidationFailed(interest.shared_from_this(), "No valid signature");
534  }
535  catch (const KeyLocator::Error& e){
536  return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
537  }
538  catch (const v1::IdentityCertificate::Error& e){
539  return onValidationFailed(interest.shared_from_this(), "Cannot determine the signing key");
540  }
541  catch (const tlv::Error& e){
542  return onValidationFailed(interest.shared_from_this(), "Cannot decode signature");
543  }
544 }
545 
546 void
547 ValidatorConfig::checkTimestamp(const shared_ptr<const Interest>& interest,
548  const Name& keyName,
549  const OnInterestValidated& onValidated,
550  const OnInterestValidationFailed& onValidationFailed)
551 {
552  const Name& interestName = interest->getName();
553  time::system_clock::TimePoint interestTime;
554 
555  try {
556  interestTime =
557  time::fromUnixTimestamp(time::milliseconds(interestName.get(-signed_interest::MIN_LENGTH).toNumber()));
558  }
559  catch (const tlv::Error& e) {
560  return onValidationFailed(interest,
561  "Cannot decode signature related TLVs");
562  }
563 
565 
566  LastTimestampMap::iterator timestampIt = m_lastTimestamp.find(keyName);
567  if (timestampIt == m_lastTimestamp.end()) {
568  if (!(currentTime - m_graceInterval <= interestTime &&
569  interestTime <= currentTime + m_graceInterval))
570  return onValidationFailed(interest,
571  "The command is not in grace interval: " + interest->getName().toUri());
572  }
573  else {
574  if (interestTime <= timestampIt->second)
575  return onValidationFailed(interest,
576  "The command is outdated: " + interest->getName().toUri());
577  }
578 
579  // Update timestamp
580  if (timestampIt == m_lastTimestamp.end()) {
581  cleanOldKeys();
582  m_lastTimestamp[keyName] = interestTime;
583  }
584  else {
585  timestampIt->second = interestTime;
586  }
587 
588  return onValidated(interest);
589 }
590 
591 void
592 ValidatorConfig::cleanOldKeys()
593 {
594  if (m_lastTimestamp.size() < m_maxTrackedKeys)
595  return;
596 
597  LastTimestampMap::iterator timestampIt = m_lastTimestamp.begin();
599 
601  LastTimestampMap::iterator oldestKeyIt = m_lastTimestamp.begin();
602  time::system_clock::TimePoint oldestTimestamp = oldestKeyIt->second;
603 
604  while (timestampIt != end) {
605  if (now - timestampIt->second > m_keyTimestampTtl) {
606  LastTimestampMap::iterator toDelete = timestampIt;
607  timestampIt++;
608  m_lastTimestamp.erase(toDelete);
609  continue;
610  }
611 
612  if (timestampIt->second < oldestTimestamp) {
613  oldestTimestamp = timestampIt->second;
614  oldestKeyIt = timestampIt;
615  }
616 
617  timestampIt++;
618  }
619 
620  if (m_lastTimestamp.size() >= m_maxTrackedKeys)
621  m_lastTimestamp.erase(oldestKeyIt);
622 }
623 
624 void
625 ValidatorConfig::DynamicTrustAnchorContainer::refresh()
626 {
627  using namespace boost::filesystem;
628 
629  m_certificates.clear();
630 
631  if (m_isDir) {
632  directory_iterator end;
633 
634  for (directory_iterator it(m_path); it != end; it++) {
635  auto idCert = io::load<v1::IdentityCertificate>(it->path().string());
636 
637  if (idCert != nullptr)
638  m_certificates.push_back(idCert);
639  }
640  }
641  else {
642  auto idCert = io::load<v1::IdentityCertificate>(m_path.string());
643 
644  if (idCert != nullptr)
645  m_certificates.push_back(idCert);
646  }
647 }
648 
649 template<class Packet, class OnValidated, class OnFailed>
650 void
651 ValidatorConfig::checkSignature(const Packet& packet,
652  const Signature& signature,
653  size_t nSteps,
654  const OnValidated& onValidated,
655  const OnFailed& onValidationFailed,
656  std::vector<shared_ptr<ValidationRequest>>& nextSteps)
657 {
658  if (signature.getType() == tlv::DigestSha256) {
659  DigestSha256 sigSha256(signature);
660 
661  if (verifySignature(packet, sigSha256))
662  return onValidated(packet.shared_from_this());
663  else
664  return onValidationFailed(packet.shared_from_this(), "Sha256 Signature cannot be verified!");
665  }
666 
667  try {
668  switch (signature.getType()) {
671  if (!signature.hasKeyLocator()) {
672  return onValidationFailed(packet.shared_from_this(),
673  "Missing KeyLocator in SignatureInfo");
674  }
675  break;
676  }
677  default:
678  return onValidationFailed(packet.shared_from_this(), "Unsupported signature type");
679  }
680  }
681  catch (const KeyLocator::Error& e) {
682  return onValidationFailed(packet.shared_from_this(),
683  "Cannot decode KeyLocator in public key signature");
684  }
685  catch (const tlv::Error& e) {
686  return onValidationFailed(packet.shared_from_this(), "Cannot decode public key signature");
687  }
688 
689  if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name) {
690  return onValidationFailed(packet.shared_from_this(), "Unsupported KeyLocator type");
691  }
692 
693  const Name& keyLocatorName = signature.getKeyLocator().getName();
694 
695  shared_ptr<const v1::Certificate> trustedCert;
696 
697  refreshAnchors();
698 
699  AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
700  if (m_anchors.end() == it && m_certificateCache != nullptr)
701  trustedCert = m_certificateCache->getCertificate(keyLocatorName);
702  else if (m_anchors.end() != it)
703  trustedCert = it->second;
704 
705  if (trustedCert != nullptr) {
706  if (verifySignature(packet, signature, trustedCert->getPublicKeyInfo()))
707  return onValidated(packet.shared_from_this());
708  else
709  return onValidationFailed(packet.shared_from_this(), "Cannot verify signature");
710  }
711  else {
712  if (m_stepLimit == nSteps)
713  return onValidationFailed(packet.shared_from_this(), "Maximum steps of validation reached");
714 
715  OnDataValidated onCertValidated =
716  bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
717  this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
718 
719  OnDataValidationFailed onCertValidationFailed =
720  bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
721  this, _1, _2, packet.shared_from_this(), onValidationFailed);
722 
723  Interest certInterest(keyLocatorName);
724 
725  auto nextStep = make_shared<ValidationRequest>(certInterest,
726  onCertValidated,
727  onCertValidationFailed,
728  1, nSteps + 1);
729 
730  nextSteps.push_back(nextStep);
731  return;
732  }
733  return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type");
734 }
735 
736 template<class Packet, class OnValidated, class OnFailed>
737 void
738 ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
739  const shared_ptr<const Packet>& packet,
740  const OnValidated& onValidated,
741  const OnFailed& onValidationFailed)
742 {
743  if (signCertificate->getContentType() != tlv::ContentType_Key)
744  return onValidationFailed(packet,
745  "Cannot retrieve signer's cert: " +
746  signCertificate->getName().toUri());
747 
748  shared_ptr<v1::IdentityCertificate> certificate;
749  try {
750  certificate = make_shared<v1::IdentityCertificate>(*signCertificate);
751  }
752  catch (const tlv::Error&) {
753  return onValidationFailed(packet,
754  "Cannot decode signer's cert: " +
755  signCertificate->getName().toUri());
756  }
757 
758  if (!certificate->isTooLate() && !certificate->isTooEarly()) {
759  if (m_certificateCache != nullptr)
760  m_certificateCache->insertCertificate(certificate);
761 
762  if (verifySignature(*packet, certificate->getPublicKeyInfo()))
763  return onValidated(packet);
764  else
765  return onValidationFailed(packet,
766  "Cannot verify signature: " + packet->getName().toUri());
767  }
768  else {
769  return onValidationFailed(packet,
770  "Signing certificate " +
771  signCertificate->getName().toUri() + " is no longer valid.");
772  }
773 }
774 
775 template<class Packet, class OnFailed>
776 void
777 ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
778  const std::string& failureInfo,
779  const shared_ptr<const Packet>& packet,
780  const OnFailed& onValidationFailed)
781 {
782  onValidationFailed(packet, failureInfo);
783 }
784 
785 } // namespace security
786 } // namespace ndn
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestValidationFailed
Callback to report a failed Interest validation.
static Name certificateNameToPublicKeyName(const Name &certificateName)
Get the public key name from the full certificate name.
Copyright (c) 2011-2015 Regents of the University of California.
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:171
void load(const std::string &filename)
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:411
Represent a SHA256 digest.
const Name & getName() const
get Name element
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:45
ValidatorConfig(Face *face=nullptr, const shared_ptr< CertificateCache > &certificateCache=DEFAULT_CERTIFICATE_CACHE, const time::milliseconds &graceInterval=DEFAULT_GRACE_INTERVAL, const size_t stepLimit=10, const size_t maxTrackedKeys=1000, const time::system_clock::Duration &keyTimestampTtl=DEFAULT_KEY_TIMESTAMP_TTL)
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataValidationFailed
Callback to report a failed Data validation.
static const time::milliseconds DEFAULT_GRACE_INTERVAL
bool hasKeyLocator() const
Check if SignatureInfo block has a KeyLocator.
Definition: signature.hpp:132
function< void(const shared_ptr< const Data > &)> OnDataValidated
Callback to report a successful Data validation.
Table::const_iterator iterator
Definition: cs-internal.hpp:41
TrustAnchorContainer m_staticContainer
function< void(const shared_ptr< const Interest > &)> OnInterestValidated
Callback to report a successful Interest validation.
const size_t MIN_LENGTH
minimal number of components for Command Interest
static const shared_ptr< CertificateCache > DEFAULT_CERTIFICATE_CACHE
shared_ptr< CertificateCache > m_certificateCache
std::list< shared_ptr< v1::IdentityCertificate > > CertificateList
provides the interfaces for packet validation.
Definition: validator.hpp:42
Provide a communication channel with local or remote NDN forwarder.
Definition: face.hpp:125
Name abstraction to represent an absolute name.
Definition: name.hpp:46
virtual void checkPolicy(const Data &data, int nSteps, const OnDataValidated &onValidated, const OnDataValidationFailed &onValidationFailed, std::vector< shared_ptr< ValidationRequest >> &nextSteps) override
Check the Data against policy and return the next validation step if necessary.
const ssize_t POS_SIG_VALUE
boost::asio::io_service & getIoService()
Return nullptr (cannot use IoService in simulations), preserved for API compatibility.
Definition: face.hpp:690
const time::system_clock::Duration & m_keyTimestampTtl
size_t size() const
Get the number of components.
Definition: name.hpp:400
uint64_t toNumber() const
Interpret this name component as nonNegativeInteger.
time_point TimePoint
Definition: time.hpp:90
boost::property_tree::ptree ConfigSection
Definition: common.hpp:35
system_clock::TimePoint fromUnixTimestamp(const milliseconds &duration)
Convert UNIX timestamp to system_clock::TimePoint.
Definition: time.cpp:124
const ssize_t POS_SIG_INFO
Type getType() const
static const time::system_clock::Duration DEFAULT_KEY_TIMESTAMP_TTL
indicates content is a public key
Definition: tlv.hpp:130
uint32_t getType() const
Get signature type.
Definition: signature.hpp:123
static bool verifySignature(const Data &data, const v1::PublicKey &publicKey)
Verify the data using the publicKey.
Definition: validator.cpp:105
const Signature & getSignature() const
Definition: data.hpp:348
bool m_shouldValidate
gives whether validation should be preformed
const KeyLocator & getKeyLocator() const
Get KeyLocator.
Definition: signature.hpp:143
represents a Data packet
Definition: data.hpp:37
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
const Name & getName() const
Definition: interest.hpp:215
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33