NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: 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 "../v1/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 
70  virtual int8_t
71  check(const Data& data) = 0;
72 
81  virtual int8_t
82  check(const Interest& interest) = 0;
83 };
84 
85 class CustomizedChecker : public Checker
86 {
87 public:
88  CustomizedChecker(uint32_t sigType,
89  shared_ptr<KeyLocatorChecker> keyLocatorChecker)
90  : m_sigType(sigType)
91  , m_keyLocatorChecker(keyLocatorChecker)
92  {
93  switch (sigType) {
96  if (!static_cast<bool>(m_keyLocatorChecker))
97  BOOST_THROW_EXCEPTION(Error("Strong signature requires KeyLocatorChecker"));
98  return;
99  }
100  case tlv::DigestSha256:
101  return;
102  default:
103  BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
104  }
105  }
106 
107  virtual int8_t
108  check(const Data& data) override
109  {
110  return check(data, data.getSignature());
111  }
112 
113  virtual int8_t
114  check(const Interest& interest) override
115  {
116  try {
117  const Name& interestName = interest.getName();
118  Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
119  interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
120  return check(interest, signature);
121  }
122  catch (const Signature::Error& e) {
123  // Invalid signature
124  return -1;
125  }
126  catch (const tlv::Error& e) {
127  // Cannot decode signature related TLVs
128  return -1;
129  }
130  }
131 
132 private:
133  template<class Packet>
134  int8_t
135  check(const Packet& packet, const Signature& signature)
136  {
137  if (m_sigType != signature.getType()) {
138  // Signature type does not match
139  return -1;
140  }
141 
142  if (signature.getType() == tlv::DigestSha256)
143  return 0;
144 
145  try {
146  switch (signature.getType()) {
149  if (!signature.hasKeyLocator()) {
150  // Missing KeyLocator in SignatureInfo
151  return -1;
152  }
153  break;
154  }
155  default: {
156  // Unsupported signature type
157  return -1;
158  }
159  }
160  }
161  catch (const KeyLocator::Error& e) {
162  // Cannot decode KeyLocator
163  return -1;
164  }
165  catch (const tlv::Error& e) {
166  // Cannot decode signature
167  return -1;
168  }
169 
170  std::string failInfo;
171  if (m_keyLocatorChecker->check(packet, signature.getKeyLocator(), failInfo))
172  return 0;
173  else {
174  return -1;
175  }
176  }
177 
178 private:
179  uint32_t m_sigType;
180  shared_ptr<KeyLocatorChecker> m_keyLocatorChecker;
181 };
182 
184 {
185 public:
186  explicit
187  HierarchicalChecker(uint32_t sigType)
188  : CustomizedChecker(sigType,
189  make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
190  "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
191  "\\1\\2",
192  KeyLocatorChecker::RELATION_IS_PREFIX_OF))
193  {
194  }
195 };
196 
198 {
199 public:
200  FixedSignerChecker(uint32_t sigType,
201  const std::vector<shared_ptr<v1::IdentityCertificate>>& signers)
202  : m_sigType(sigType)
203  {
204  for (std::vector<shared_ptr<v1::IdentityCertificate>>::const_iterator it = signers.begin();
205  it != signers.end(); it++)
206  m_signers[(*it)->getName().getPrefix(-1)] = (*it);
207 
208  if (sigType != tlv::SignatureSha256WithRsa &&
209  sigType != tlv::SignatureSha256WithEcdsa) {
210  BOOST_THROW_EXCEPTION(Error("FixedSigner is only meaningful for strong signature type"));
211  }
212  }
213 
214  virtual int8_t
215  check(const Data& data) override
216  {
217  return check(data, data.getSignature());
218  }
219 
220  virtual int8_t
221  check(const Interest& interest) override
222  {
223  try {
224  const Name& interestName = interest.getName();
225  Signature signature(interestName[Checker::INTEREST_SIG_INFO].blockFromValue(),
226  interestName[Checker::INTEREST_SIG_VALUE].blockFromValue());
227  return check(interest, signature);
228  }
229  catch (const Signature::Error& e) {
230  // Invalid signature
231  return -1;
232  }
233  catch (const tlv::Error& e) {
234  // Cannot decode signature related TLVs
235  return -1;
236  }
237  }
238 
239 private:
240  template<class Packet>
241  int8_t
242  check(const Packet& packet, const Signature& signature)
243  {
244  if (m_sigType != signature.getType()) {
245  // Signature type does not match
246  return -1;
247  }
248 
249  if (signature.getType() == tlv::DigestSha256) {
250  // FixedSigner does not allow Sha256 signature type
251  return -1;
252  }
253 
254  try {
255  switch (signature.getType()) {
258  if (!signature.hasKeyLocator()) {
259  // Missing KeyLocator in SignatureInfo
260  return -1;
261  }
262  break;
263  }
264 
265  default: {
266  // Unsupported signature type
267  return -1;
268  }
269  }
270 
271  const Name& keyLocatorName = signature.getKeyLocator().getName();
272 
273  if (m_signers.find(keyLocatorName) == m_signers.end()) {
274  // Signer is not in the fixed signer list
275  return -1;
276  }
277 
278  if (Validator::verifySignature(packet, signature,
279  m_signers[keyLocatorName]->getPublicKeyInfo())) {
280  return 1;
281  }
282  else {
283  // Signature cannot be validated
284  return -1;
285  }
286  }
287  catch (const KeyLocator::Error& e) {
288  // KeyLocator does not have name
289  return -1;
290  }
291  catch (const tlv::Error& e) {
292  // Cannot decode signature
293  return -1;
294  }
295  }
296 
297 private:
298  typedef std::map<Name, shared_ptr<v1::IdentityCertificate>> SignerList;
299  uint32_t m_sigType;
300  SignerList m_signers;
301 };
302 
304 {
305 public:
313  static shared_ptr<Checker>
314  create(const ConfigSection& configSection, const std::string& configFilename)
315  {
316  ConfigSection::const_iterator propertyIt = configSection.begin();
317 
318  // Get checker.type
319  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
320  BOOST_THROW_EXCEPTION(Error("Expect <checker.type>"));
321 
322  std::string type = propertyIt->second.data();
323 
324  if (boost::iequals(type, "customized"))
325  return createCustomizedChecker(configSection, configFilename);
326  else if (boost::iequals(type, "hierarchical"))
327  return createHierarchicalChecker(configSection, configFilename);
328  else if (boost::iequals(type, "fixed-signer"))
329  return createFixedSignerChecker(configSection, configFilename);
330  else
331  BOOST_THROW_EXCEPTION(Error("Unsupported checker type: " + type));
332  }
333 
334 private:
335  static shared_ptr<Checker>
336  createCustomizedChecker(const ConfigSection& configSection,
337  const std::string& configFilename)
338  {
339  ConfigSection::const_iterator propertyIt = configSection.begin();
340  propertyIt++;
341 
342  // Get checker.sig-type
343  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
344  BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
345 
346  std::string sigType = propertyIt->second.data();
347  propertyIt++;
348 
349  // Get checker.key-locator
350  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
351  BOOST_THROW_EXCEPTION(Error("Expect <checker.key-locator>"));
352 
353  shared_ptr<KeyLocatorChecker> keyLocatorChecker =
354  KeyLocatorCheckerFactory::create(propertyIt->second, configFilename);
355  propertyIt++;
356 
357  if (propertyIt != configSection.end())
358  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
359 
360  return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
361  }
362 
363  static shared_ptr<Checker>
364  createHierarchicalChecker(const ConfigSection& configSection,
365  const std::string& configFilename)
366  {
367  ConfigSection::const_iterator propertyIt = configSection.begin();
368  propertyIt++;
369 
370  // Get checker.sig-type
371  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
372  BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
373 
374  std::string sigType = propertyIt->second.data();
375  propertyIt++;
376 
377  if (propertyIt != configSection.end())
378  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
379 
380  return make_shared<HierarchicalChecker>(getSigType(sigType));
381  }
382 
383  static shared_ptr<Checker>
384  createFixedSignerChecker(const ConfigSection& configSection,
385  const std::string& configFilename)
386  {
387  ConfigSection::const_iterator propertyIt = configSection.begin();
388  propertyIt++;
389 
390  // Get checker.sig-type
391  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
392  BOOST_THROW_EXCEPTION(Error("Expect <checker.sig-type>"));
393 
394  std::string sigType = propertyIt->second.data();
395  propertyIt++;
396 
397  std::vector<shared_ptr<v1::IdentityCertificate>> signers;
398  for (; propertyIt != configSection.end(); propertyIt++) {
399  if (!boost::iequals(propertyIt->first, "signer"))
400  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer> but get <checker." +
401  propertyIt->first + ">"));
402 
403  signers.push_back(getSigner(propertyIt->second, configFilename));
404  }
405 
406  if (propertyIt != configSection.end())
407  BOOST_THROW_EXCEPTION(Error("Expect the end of checker"));
408 
409  return shared_ptr<FixedSignerChecker>(new FixedSignerChecker(getSigType(sigType),
410  signers));
411  }
412 
413  static shared_ptr<v1::IdentityCertificate>
414  getSigner(const ConfigSection& configSection, const std::string& configFilename)
415  {
416  using namespace boost::filesystem;
417 
418  ConfigSection::const_iterator propertyIt = configSection.begin();
419 
420  // Get checker.signer.type
421  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
422  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.type>"));
423 
424  std::string type = propertyIt->second.data();
425  propertyIt++;
426 
427  if (boost::iequals(type, "file")) {
428  // Get checker.signer.file-name
429  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "file-name"))
430  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.file-name>"));
431 
432  path certfilePath = absolute(propertyIt->second.data(),
433  path(configFilename).parent_path());
434  propertyIt++;
435 
436  if (propertyIt != configSection.end())
437  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
438 
439  shared_ptr<v1::IdentityCertificate> idCert
440  = io::load<v1::IdentityCertificate>(certfilePath.c_str());
441 
442  if (static_cast<bool>(idCert))
443  return idCert;
444  else
445  BOOST_THROW_EXCEPTION(Error("Cannot read certificate from file: " +
446  certfilePath.native()));
447  }
448  else if (boost::iequals(type, "base64")) {
449  // Get checker.signer.base64-string
450  if (propertyIt == configSection.end() ||
451  !boost::iequals(propertyIt->first, "base64-string"))
452  BOOST_THROW_EXCEPTION(Error("Expect <checker.signer.base64-string>"));
453 
454  std::stringstream ss(propertyIt->second.data());
455  propertyIt++;
456 
457  if (propertyIt != configSection.end())
458  BOOST_THROW_EXCEPTION(Error("Expect the end of checker.signer"));
459 
460  shared_ptr<v1::IdentityCertificate> idCert = io::load<v1::IdentityCertificate>(ss);
461 
462  if (static_cast<bool>(idCert))
463  return idCert;
464  else
465  BOOST_THROW_EXCEPTION(Error("Cannot decode certificate from string"));
466  }
467  else
468  BOOST_THROW_EXCEPTION(Error("Unsupported checker.signer type: " + type));
469  }
470 
471  static uint32_t
472  getSigType(const std::string& sigType)
473  {
474  if (boost::iequals(sigType, "rsa-sha256"))
476  else if (boost::iequals(sigType, "ecdsa-sha256"))
478  else if (boost::iequals(sigType, "sha256"))
479  return tlv::DigestSha256;
480  else
481  BOOST_THROW_EXCEPTION(Error("Unsupported signature type"));
482  }
483 };
484 
485 } // namespace conf
486 } // namespace security
487 } // namespace ndn
488 
489 #endif // NDN_SECURITY_CONF_CHECKER_HPP
Copyright (c) 2011-2015 Regents of the University of California.
function< void(const shared_ptr< const Interest > &, const std::string &)> OnInterestCheckFailed
Definition: checker.hpp:47
virtual int8_t check(const Interest &interest) override
check if interest satisfies condition defined in the specific checker implementation ...
Definition: checker.hpp:221
const Name & getName() const
get Name element
represents an Interest packet
Definition: interest.hpp:42
virtual int8_t check(const Interest &interest) override
check if interest satisfies condition defined in the specific checker implementation ...
Definition: checker.hpp:114
bool hasKeyLocator() const
Check if SignatureInfo block has a KeyLocator.
Definition: signature.hpp:132
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 Data &data)=0
check if data satisfies condition defined in the specific checker implementation
static shared_ptr< KeyLocatorChecker > create(const ConfigSection &configSection, const std::string &filename)
virtual int8_t check(const Data &data) override
check if data satisfies condition defined in the specific checker implementation
Definition: checker.hpp:108
Name abstraction to represent an absolute name.
Definition: name.hpp:46
CustomizedChecker(uint32_t sigType, shared_ptr< KeyLocatorChecker > keyLocatorChecker)
Definition: checker.hpp:88
FixedSignerChecker(uint32_t sigType, const std::vector< shared_ptr< v1::IdentityCertificate >> &signers)
Definition: checker.hpp:200
boost::property_tree::ptree ConfigSection
Definition: common.hpp:35
function< void(const shared_ptr< const Data > &)> OnDataChecked
Definition: checker.hpp:48
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
static shared_ptr< Checker > create(const ConfigSection &configSection, const std::string &configFilename)
create a checker from configuration file.
Definition: checker.hpp:314
const Signature & getSignature() const
Definition: data.hpp:348
const KeyLocator & getKeyLocator() const
Get KeyLocator.
Definition: signature.hpp:143
represents a Data packet
Definition: data.hpp:37
function< void(const shared_ptr< const Data > &, const std::string &)> OnDataCheckFailed
Definition: checker.hpp:49
virtual int8_t check(const Data &data) override
check if data satisfies condition defined in the specific checker implementation
Definition: checker.hpp:215
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