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