security: Add configuration based validator

configuration file format can be found at: http://redmine.named-data.net/projects/ndn-cpp-dev/wiki/CommandValidatorConf

Change-Id: Icc2725f349aed7513f35f2cccdcd4463fadeef31
diff --git a/src/security/validator-config.hpp b/src/security/validator-config.hpp
new file mode 100644
index 0000000..acc85f5
--- /dev/null
+++ b/src/security/validator-config.hpp
@@ -0,0 +1,224 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_SECURITY_VALIDATOR_CONFIG_HPP
+#define NDN_SECURITY_VALIDATOR_CONFIG_HPP
+
+#include "validator.hpp"
+#include "certificate-cache.hpp"
+#include "conf/rule.hpp"
+#include "conf/common.hpp"
+
+namespace ndn {
+
+class ValidatorConfig : public Validator
+{
+public:
+  class Error : public Validator::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : Validator::Error(what)
+    {
+    }
+  };
+
+  static const shared_ptr<CertificateCache> DEFAULT_CERTIFICATE_CACHE;
+
+  ValidatorConfig(shared_ptr<Face> face,
+                  shared_ptr<CertificateCache> certificateCache = DEFAULT_CERTIFICATE_CACHE,
+                  const int stepLimit = 10);
+
+  virtual
+  ~ValidatorConfig()
+  {
+  }
+
+  void
+  load(const std::string& filename);
+
+  void
+  load(const std::string& input, const std::string& filename);
+
+  void
+  load(std::istream& input, const std::string& filename);
+
+protected:
+  virtual void
+  checkPolicy(const Data& data,
+              int stepCount,
+              const OnDataValidated& onValidated,
+              const OnDataValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+  virtual void
+  checkPolicy(const Interest& interest,
+              int stepCount,
+              const OnInterestValidated& onValidated,
+              const OnInterestValidationFailed& onValidationFailed,
+              std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+private:
+  template<class Packet, class OnValidated, class OnFailed>
+  void
+  checkSignature(const Packet& packet,
+                 const Signature& signature,
+                 int stepCount,
+                 const OnValidated& onValidated,
+                 const OnFailed& onValidationFailed,
+                 std::vector<shared_ptr<ValidationRequest> >& nextSteps);
+
+  template<class Packet, class OnValidated, class OnFailed>
+  void
+  onCertValidated(const shared_ptr<const Data>& signCertificate,
+                  const shared_ptr<const Packet>& packet,
+                  const OnValidated& onValidated,
+                  const OnFailed& onValidationFailed);
+
+  template<class Packet, class OnFailed>
+  void
+  onCertFailed(const shared_ptr<const Data>& signCertificate,
+               const std::string& failureInfo,
+               const shared_ptr<const Packet>& packet,
+               const OnFailed& onValidationFailed);
+
+  void
+  process(const security::conf::ConfigSection& configSection,
+          const std::string& filename);
+
+  void
+  onConfigRule(const security::conf::ConfigSection& section,
+               const std::string& filename);
+
+  void
+  onConfigTrustAnchor(const security::conf::ConfigSection& section,
+                      const std::string& filename);
+
+private:
+  typedef security::conf::Rule<Interest> InterestRule;
+  typedef security::conf::Rule<Data>     DataRule;
+  typedef std::vector<shared_ptr<InterestRule> > InterestRuleList;
+  typedef std::vector<shared_ptr<DataRule> >     DataRuleList;
+  typedef std::map<Name, shared_ptr<IdentityCertificate> > AnchorList;
+
+  int m_stepLimit;
+  shared_ptr<CertificateCache> m_certificateCache;
+
+  InterestRuleList m_interestRules;
+  DataRuleList m_dataRules;
+  AnchorList m_anchors;
+};
+
+template<class Packet, class OnValidated, class OnFailed>
+void
+ValidatorConfig::checkSignature(const Packet& packet,
+                                const Signature& signature,
+                                int stepCount,
+                                const OnValidated& onValidated,
+                                const OnFailed& onValidationFailed,
+                                std::vector<shared_ptr<ValidationRequest> >& nextSteps)
+{
+  if (signature.getType() == Signature::Sha256)
+    {
+      SignatureSha256 sigSha256(signature);
+
+      if (verifySignature(packet, sigSha256))
+        return onValidated(packet.shared_from_this());
+      else
+        return onValidationFailed(packet.shared_from_this(),
+                                  "Sha256 Signature cannot be verified!");
+    }
+
+  if (signature.getType() == Signature::Sha256WithRsa)
+    {
+      SignatureSha256WithRsa sigSha256Rsa(signature);
+      Name keyLocatorName = sigSha256Rsa.getKeyLocator().getName();
+
+      shared_ptr<const Certificate> trustedCert;
+
+      AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
+      if (m_anchors.end() == it)
+        trustedCert = m_certificateCache->getCertificate(keyLocatorName);
+      else
+        trustedCert = it->second;
+
+      if (static_cast<bool>(trustedCert))
+        {
+          if (verifySignature(packet, sigSha256Rsa, trustedCert->getPublicKeyInfo()))
+            return onValidated(packet.shared_from_this());
+          else
+            return onValidationFailed(packet.shared_from_this(),
+                                      "Cannot verify signature");
+        }
+      else
+        {
+          OnDataValidated onCertValidated =
+            bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
+                 this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
+
+          OnDataValidationFailed onCertValidationFailed =
+            bind(&ValidatorConfig::onCertFailed<Packet, OnFailed>,
+                 this, _1, _2, packet.shared_from_this(), onValidationFailed);
+
+          Interest certInterest(keyLocatorName);
+
+          shared_ptr<ValidationRequest> nextStep =
+            make_shared<ValidationRequest>(boost::cref(certInterest),
+                                           onCertValidated,
+                                           onCertValidationFailed,
+                                           1, stepCount + 1);
+
+          nextSteps.push_back(nextStep);
+          return;
+        }
+    }
+  return onValidationFailed(packet.shared_from_this(), "Unsupported Signature Type!");
+}
+
+template<class Packet, class OnValidated, class OnFailed>
+void
+ValidatorConfig::onCertValidated(const shared_ptr<const Data>& signCertificate,
+                                 const shared_ptr<const Packet>& packet,
+                                 const OnValidated& onValidated,
+                                 const OnFailed& onValidationFailed)
+{
+  shared_ptr<IdentityCertificate> certificate =
+    make_shared<IdentityCertificate>(boost::cref(*signCertificate));
+
+  if (!certificate->isTooLate() && !certificate->isTooEarly())
+    {
+      m_certificateCache->insertCertificate(certificate);
+
+      if (verifySignature(*packet, certificate->getPublicKeyInfo()))
+        return onValidated(packet);
+      else
+        return onValidationFailed(packet,
+                                  "Cannot verify signature: " +
+                                  packet->getName().toUri());
+    }
+  else
+    {
+      return onValidationFailed(packet,
+                                "Signing certificate " +
+                                signCertificate->getName().toUri() +
+                                " is no longer valid.");
+    }
+}
+
+template<class Packet, class OnFailed>
+void
+ValidatorConfig::onCertFailed(const shared_ptr<const Data>& signCertificate,
+                              const std::string& failureInfo,
+                              const shared_ptr<const Packet>& packet,
+                              const OnFailed& onValidationFailed)
+{
+  onValidationFailed(packet, failureInfo);
+}
+
+} // namespace ndn
+
+#endif // NDN_SECURITY_VALIDATOR_CONFIG_HPP