NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
checker.hpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
24 #ifndef NDN_SECURITY_CONF_CHECKER_HPP
25 #define NDN_SECURITY_CONF_CHECKER_HPP
26 
27 #include "common.hpp"
28 
29 #include "key-locator-checker.hpp"
30 #include "../../util/io.hpp"
31 #include "../validator.hpp"
32 #include "../identity-certificate.hpp"
33 
34 #include <boost/algorithm/string.hpp>
35 #include <boost/filesystem.hpp>
36 #include <boost/lexical_cast.hpp>
37 
38 namespace ndn {
39 namespace security {
40 namespace conf {
41 
42 class Checker
43 {
44 public:
45  typedef function<void(const shared_ptr<const Interest>&)> OnInterestChecked;
46  typedef function<void(const shared_ptr<const Interest>&,
47  const std::string&)> OnInterestCheckFailed;
48  typedef function<void(const shared_ptr<const Data>&)> OnDataChecked;
49  typedef function<void(const shared_ptr<const Data>&, const std::string&)> OnDataCheckFailed;
50 
51  enum {
54  };
55 
56 
57  virtual
59  {
60  }
61 
72  virtual int8_t
73  check(const Data& data,
74  const OnDataChecked& onValidated,
75  const OnDataCheckFailed& onValidationFailed) = 0;
76 
87  virtual int8_t
88  check(const Interest& interest,
89  const OnInterestChecked& onValidated,
90  const OnInterestCheckFailed& onValidationFailed) = 0;
91 };
92 
93 class CustomizedChecker : public Checker
94 {
95 public:
96  CustomizedChecker(uint32_t sigType,
97  shared_ptr<KeyLocatorChecker> keyLocatorChecker)
98  : m_sigType(sigType)
99  , m_keyLocatorChecker(keyLocatorChecker)
100  {
101  switch (sigType)
102  {
105  {
106  if (!static_cast<bool>(m_keyLocatorChecker))
107  BOOST_THROW_EXCEPTION(Error("Strong signature requires KeyLocatorChecker"));
108 
109  return;
110  }
111  case tlv::DigestSha256:
112  return;
113  default:
114  BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
115  }
116  }
117 
118  virtual int8_t
119  check(const Data& data,
120  const OnDataChecked& onValidated,
121  const OnDataCheckFailed& onValidationFailed)
122  {
123  return check(data, data.getSignature(), onValidated, onValidationFailed);
124  }
125 
126  virtual int8_t
127  check(const Interest& interest,
128  const OnInterestChecked& onValidated,
129  const OnInterestCheckFailed& onValidationFailed)
130  {
131  try
132  {
133  const Name& interestName = interest.getName();
134  Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
135  interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
136  return check(interest, signature, onValidated, onValidationFailed);
137  }
138  catch (Signature::Error& e)
139  {
140  onValidationFailed(interest.shared_from_this(), "Invalid signature");
141  return -1;
142  }
143  catch (tlv::Error& e)
144  {
145  onValidationFailed(interest.shared_from_this(), "Cannot decode signature related TLVs");
146  return -1;
147  }
148  }
149 
150 private:
151  template<class Packet, class OnValidated, class OnFailed>
152  int8_t
153  check(const Packet& packet, const Signature& signature,
154  const OnValidated& onValidated,
155  const OnFailed& onValidationFailed)
156  {
157  if (m_sigType != signature.getType())
158  {
159  onValidationFailed(packet.shared_from_this(),
160  "Signature type does not match: " +
161  boost::lexical_cast<std::string>(m_sigType) +
162  "!=" +
163  boost::lexical_cast<std::string>(signature.getType()));
164  return -1;
165  }
166 
167  if (signature.getType() == tlv::DigestSha256)
168  return 0;
169 
170  try
171  {
172  switch (signature.getType())
173  {
176  {
177  if (!signature.hasKeyLocator()) {
178  onValidationFailed(packet.shared_from_this(),
179  "Missing KeyLocator in SignatureInfo");
180  }
181  break;
182  }
183  default:
184  {
185  onValidationFailed(packet.shared_from_this(),
186  "Unsupported signature type: " +
187  boost::lexical_cast<std::string>(signature.getType()));
188  return -1;
189  }
190  }
191  }
192  catch (KeyLocator::Error& e)
193  {
194  onValidationFailed(packet.shared_from_this(),
195  "Cannot decode KeyLocator");
196  return -1;
197  }
198  catch (tlv::Error& e)
199  {
200  onValidationFailed(packet.shared_from_this(),
201  "Cannot decode signature");
202  return -1;
203  }
204 
205  std::string failInfo;
206  if (m_keyLocatorChecker->check(packet, signature.getKeyLocator(), failInfo))
207  return 0;
208  else
209  {
210  onValidationFailed(packet.shared_from_this(), failInfo);
211  return -1;
212  }
213  }
214 
215 private:
216  uint32_t m_sigType;
217  shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
218 };
219 
221 {
222 public:
223  explicit
224  HierarchicalChecker(uint32_t sigType)
225  : CustomizedChecker(sigType,
226  make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
227  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
228  "\\1\\2",
229  KeyLocatorChecker::RELATION_IS_PREFIX_OF))
230  {
231  }
232 };
233 
235 {
236 public:
237  FixedSignerChecker(uint32_t sigType,
238  const std::vector<shared_ptr<IdentityCertificate> >& signers)
239  : m_sigType(sigType)
240  {
241  for (std::vector<shared_ptr<IdentityCertificate> >::const_iterator it = signers.begin();
242  it != signers.end(); it++)
243  m_signers[(*it)->getName().getPrefix(-1)] = (*it);
244 
245  if (sigType != tlv::SignatureSha256WithRsa &&
247  {
248  BOOST_THROW_EXCEPTION(Error("FixedSigner is only meaningful for strong signature type"));
249  }
250 
251  }
252 
253  virtual int8_t
254  check(const Data& data,
255  const OnDataChecked& onValidated,
256  const OnDataCheckFailed& onValidationFailed)
257  {
258  return check(data, data.getSignature(), onValidated, onValidationFailed);
259  }
260 
261  virtual int8_t
262  check(const Interest& interest,
263  const OnInterestChecked& onValidated,
264  const OnInterestCheckFailed& onValidationFailed)
265  {
266  try
267  {
268  const Name& interestName = interest.getName();
269  Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
270  interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
271  return check(interest, signature, onValidated, onValidationFailed);
272  }
273  catch (Signature::Error& e)
274  {
275  onValidationFailed(interest.shared_from_this(), "Invalid signature");
276  return -1;
277  }
278  catch (tlv::Error& e)
279  {
280  onValidationFailed(interest.shared_from_this(), "Cannot decode signature related TLVs");
281  return -1;
282  }
283  }
284 
285 private:
286  template<class Packet, class OnValidated, class OnFailed>
287  int8_t
288  check(const Packet& packet, const Signature& signature,
289  const OnValidated& onValidated,
290  const OnFailed& onValidationFailed)
291  {
292  if (m_sigType != signature.getType())
293  {
294  onValidationFailed(packet.shared_from_this(),
295  "Signature type does not match: " +
296  boost::lexical_cast<std::string>(m_sigType) +
297  "!=" +
298  boost::lexical_cast<std::string>(signature.getType()));
299  return -1;
300  }
301 
302  if (signature.getType() == tlv::DigestSha256)
303  {
304  onValidationFailed(packet.shared_from_this(),
305  "FixedSigner does not allow Sha256 signature type");
306  return -1;
307  }
308 
309  try
310  {
311  switch (signature.getType())
312  {
315  {
316  if (!signature.hasKeyLocator()) {
317  onValidationFailed(packet.shared_from_this(),
318  "Missing KeyLocator in SignatureInfo");
319  }
320  break;
321  }
322  default:
323  {
324  onValidationFailed(packet.shared_from_this(),
325  "Unsupported signature type: " +
326  boost::lexical_cast<std::string>(signature.getType()));
327  return -1;
328  }
329  }
330 
331  const Name& keyLocatorName = signature.getKeyLocator().getName();
332 
333  if (m_signers.find(keyLocatorName) == m_signers.end())
334  {
335  onValidationFailed(packet.shared_from_this(),
336  "Signer is not in the fixed signer list: " +
337  keyLocatorName.toUri());
338  return -1;
339  }
340 
341  if (Validator::verifySignature(packet, signature,
342  m_signers[keyLocatorName]->getPublicKeyInfo()))
343  {
344  onValidated(packet.shared_from_this());
345  return 1;
346  }
347  else
348  {
349  onValidationFailed(packet.shared_from_this(),
350  "Signature cannot be validated");
351  return -1;
352  }
353  }
354  catch (KeyLocator::Error& e)
355  {
356  onValidationFailed(packet.shared_from_this(),
357  "KeyLocator does not have name");
358  return -1;
359  }
360  catch (tlv::Error& e)
361  {
362  onValidationFailed(packet.shared_from_this(),
363  "Cannot decode signature");
364  return -1;
365  }
366  }
367 
368 private:
369  typedef std::map<Name, shared_ptr<IdentityCertificate> > SignerList;
370 
371  uint32_t m_sigType;
372  SignerList m_signers;
373 };
374 
376 {
377 public:
385  static shared_ptr<Checker>
386  create(const ConfigSection& configSection, const std::string& configFilename)
387  {
388  ConfigSection::const_iterator propertyIt = configSection.begin();
389 
390  // Get checker.type
391  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
392  BOOST_THROW_EXCEPTION(Error("Expect <checker.type>"));
393 
394  std::string type = propertyIt->second.data();
395 
396  if (boost::iequals(type, "customized"))
397  return createCustomizedChecker(configSection, configFilename);
398  else if (boost::iequals(type, "hierarchical"))
399  return createHierarchicalChecker(configSection, configFilename);
400  else if (boost::iequals(type, "fixed-signer"))
401  return createFixedSignerChecker(configSection, configFilename);
402  else
403  BOOST_THROW_EXCEPTION(Error("Unsupported checker type: " + type));
404  }
405 
406 private:
407  static shared_ptr<Checker>
408  createCustomizedChecker(const ConfigSection& configSection,
409  const std::string& configFilename)
410  {
411  ConfigSection::const_iterator propertyIt = configSection.begin();
412  propertyIt++;
413 
414  // Get checker.sig-type
415  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
416  BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
417 
418  std::string sigType = propertyIt->second.data();
419  propertyIt++;
420 
421  // Get checker.key-locator
422  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
423  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator>"));
424 
425  shared_ptr<KeyLocatorChecker> keyLocatorChecker =
426  KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
427  propertyIt++;
428 
429  if (propertyIt != configSection.end())
430  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
431 
432  return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
433  }
434 
435  static shared_ptr<Checker>
436  createHierarchicalChecker(const ConfigSection& configSection,
437  const std::string& configFilename)
438  {
439  ConfigSection::const_iterator propertyIt = configSection.begin();
440  propertyIt++;
441 
442  // Get checker.sig-type
443  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
444  BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
445 
446  std::string sigType = propertyIt->second.data();
447  propertyIt++;
448 
449  if (propertyIt != configSection.end())
450  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
451 
452  return make_shared<HierarchicalChecker>(getSigType(sigType));
453  }
454 
455  static shared_ptr<Checker>
456  createFixedSignerChecker(const ConfigSection& configSection,
457  const std::string& configFilename)
458  {
459  ConfigSection::const_iterator propertyIt = configSection.begin();
460  propertyIt++;
461 
462  // Get checker.sig-type
463  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
464  BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
465 
466  std::string sigType = propertyIt->second.data();
467  propertyIt++;
468 
469  std::vector<shared_ptr<IdentityCertificate> > signers;
470  for (; propertyIt != configSection.end(); propertyIt++)
471  {
472  if (!boost::iequals(propertyIt->first, "signer"))
473  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer> but get <checker." +
474  propertyIt->first + ">"));
475 
476  signers.push_back(getSigner(propertyIt->second, configFilename));
477  }
478 
479  if (propertyIt != configSection.end())
480  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
481 
482  return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
483  signers));
484  }
485 
486  static shared_ptr<IdentityCertificate>
487  getSigner(const ConfigSection& configSection, const std::string& configFilename)
488  {
489  using namespace boost::filesystem;
490 
491  ConfigSection::const_iterator propertyIt = configSection.begin();
492 
493  // Get checker.signer.type
494  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
495  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.type>"));
496 
497  std::string type = propertyIt->second.data();
498  propertyIt++;
499 
500  if (boost::iequals(type, "file"))
501  {
502  // Get checker.signer.file-name
503  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
504  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.file-name>"));
505 
506  path certfilePath = absolute(propertyIt->second.data(),
507  path(configFilename).parent_path());
508  propertyIt++;
509 
510  if (propertyIt != configSection.end())
511  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
512 
513  shared_ptr<IdentityCertificate> idCert
514  = io::load<IdentityCertificate>(certfilePath.c_str());
515 
516  if (static_cast<bool>(idCert))
517  return idCert;
518  else
519  BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " +
520  certfilePath.native()));
521  }
522  else if (boost::iequals(type, "base64"))
523  {
524  // Get checker.signer.base64-string
525  if (propertyIt == configSection.end() ||
526  !boost::iequals(propertyIt->first, "base64-string"))
527  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.base64-string>"));
528 
529  std::stringstream ss(propertyIt->second.data());
530  propertyIt++;
531 
532  if (propertyIt != configSection.end())
533  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
534 
535  shared_ptr<IdentityCertificate> idCert = io::load<IdentityCertificate>(ss);
536 
537  if (static_cast<bool>(idCert))
538  return idCert;
539  else
540  BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from string"));
541  }
542  else
543  BOOST_THROW_EXCEPTION(Error("Unsupported checker.signer type: " + type));
544  }
545 
546  static uint32_t
547  getSigType(const std::string& sigType)
548  {
549  if (boost::iequals(sigType, "rsa-sha256"))
551  else if (boost::iequals(sigType, "ecdsa-sha256"))
553  else if (boost::iequals(sigType, "sha256"))
554  return tlv::DigestSha256;
555  else
556  BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
557  }
558 };
559 
560 } // namespace conf
561 } // namespace security
562 } // namespace ndn
563 
564 #endif // NDN_SECURITY_CONF_CHECKER_HPP
Copyright (c) 2011-2015 Regents of the University of California.
std::string toUri() const
Encode this name as a URI.
Definition: name.cpp:183
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestCheckFailed
Definition: checker.hpp:47
FixedSignerChecker(uint32_t sigType, const std::vector< shared_ptr< IdentityCertificate > > &signers)
Definition: checker.hpp:237
virtual int8_t check(const Data &data, const OnDataChecked &onValidated, const OnDataCheckFailed &onValidationFailed)
check if data satisfies condition defined in the specific checker implementation
Definition: checker.hpp:254
const Name & getName() const
get Name element
represents an Interest packet
Definition: interest.hpp:45
virtual int8_t check(const Data &data, const OnDataChecked &onValidated, const OnDataCheckFailed &onValidationFailed)=0
check if data satisfies condition defined in the specific checker implementation
bool hasKeyLocator() const
Check if SignatureInfo block has a KeyLocator.
Definition: signature.hpp:123
virtual int8_t check(const Interest &interest, const OnInterestChecked &onValidated, const OnInterestCheckFailed &onValidationFailed)
check if interest satisfies condition defined in the specific checker implementation ...
Definition: checker.hpp:262
KeyLocatorChecker is one of the classes used by ValidatorConfig.
function< void(const shared_ptr< const Interest > &)> OnInterestChecked
Definition: checker.hpp:45
virtual int8_t check(const Interest &interest, const OnInterestChecked &onValidated, const OnInterestCheckFailed &onValidationFailed)
check if interest satisfies condition defined in the specific checker implementation ...
Definition: checker.hpp:127
static shared_ptr< KeyLocatorChecker > create(const ConfigSection &configSection, const std::string &filename)
Name abstraction to represent an absolute name.
Definition: name.hpp:46
CustomizedChecker(uint32_t sigType, shared_ptr< KeyLocatorChecker > keyLocatorChecker)
Definition: checker.hpp:96
virtual int8_t check(const Data &data, const OnDataChecked &onValidated, const OnDataCheckFailed &onValidationFailed)
check if data satisfies condition defined in the specific checker implementation
Definition: checker.hpp:119
boost::property_tree::ptree ConfigSection
Definition: common.hpp:35
static bool verifySignature(const Data &data, const PublicKey &publicKey)
Verify the data using the publicKey.
Definition: validator.cpp:106
function< void(const shared_ptr< const Data > &)> OnDataChecked
Definition: checker.hpp:48
uint32_t getType() const
Get signature type.
Definition: signature.hpp:114
static shared_ptr< Checker > create(const ConfigSection &configSection, const std::string &configFilename)
create a checker from configuration file.
Definition: checker.hpp:386
const Signature & getSignature() const
Definition: data.hpp:390
const KeyLocator & getKeyLocator() const
Get KeyLocator.
Definition: signature.hpp:134
represents a Data packet
Definition: data.hpp:39
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataCheckFailed
Definition: checker.hpp:49
represents an error in TLV encoding or decoding
Definition: tlv.hpp:50
const Name & getName() const
Definition: interest.hpp:218
A Signature is storage for the signature-related information (info and value) in a Data packet...
Definition: signature.hpp:33