add policy checker

Change-Id: I90c50d15b1d9d97832c66ce90e39524729f12a0f
diff --git a/core/conf/checker.cpp b/core/conf/checker.cpp
new file mode 100644
index 0000000..8c63458
--- /dev/null
+++ b/core/conf/checker.cpp
@@ -0,0 +1,176 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014,  Regents of the University of California
+ *
+ * This file is part of NSL (NDN Signature Logger).
+ * See AUTHORS.md for complete list of NSL authors and contributors.
+ *
+ * NSL is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NSL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NSL, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of nsl authors and contributors.
+ */
+
+#include "checker.hpp"
+
+#include <boost/algorithm/string.hpp>
+
+namespace nsl {
+namespace conf {
+
+Checker::~Checker()
+{
+}
+
+CustomizedChecker::CustomizedChecker(uint32_t sigType,
+                                     shared_ptr<KeyLocatorChecker> keyLocatorChecker)
+  : m_sigType(sigType)
+  , m_keyLocatorChecker(keyLocatorChecker)
+{
+  switch (sigType) {
+  case tlv::SignatureSha256WithRsa:
+  case tlv::SignatureSha256WithEcdsa:
+    {
+      if (!static_cast<bool>(m_keyLocatorChecker))
+        throw Error("Strong signature requires KeyLocatorChecker");
+
+      return;
+    }
+  case tlv::DigestSha256:
+    return;
+  default:
+    throw Error("Unsupported signature type");
+  }
+}
+
+bool
+CustomizedChecker::check(const Data& data)
+{
+  const Signature signature = data.getSignature();
+  if (m_sigType != signature.getType())
+    return false;
+
+  if (signature.getType() == tlv::DigestSha256)
+    return true;
+
+  try {
+    switch (signature.getType()) {
+    case tlv::SignatureSha256WithRsa:
+    case tlv::SignatureSha256WithEcdsa:
+      {
+        if (!signature.hasKeyLocator())
+          return false;
+        break;
+      }
+    default:
+      return false;
+    }
+  }
+  catch (KeyLocator::Error&) {
+    return false;
+  }
+  catch (tlv::Error& e) {
+    return false;
+  }
+
+  std::string failInfo;
+  return m_keyLocatorChecker->check(data, signature.getKeyLocator(), failInfo);
+}
+
+HierarchicalChecker::HierarchicalChecker(uint32_t sigType)
+  : CustomizedChecker(sigType,
+      make_shared<HyperKeyLocatorNameChecker>("^(<>*)$", "\\1",
+                                              "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
+                                              "\\1\\2",
+                                              KeyLocatorChecker::RELATION_IS_PREFIX_OF))
+{
+}
+
+shared_ptr<Checker>
+CheckerFactory::create(const ConfigSection& configSection)
+{
+  ConfigSection::const_iterator propertyIt = configSection.begin();
+
+  // Get checker.type
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "type"))
+    throw Error("Expect <checker.type>");
+
+  std::string type = propertyIt->second.data();
+
+  if (boost::iequals(type, "customized"))
+    return createCustomizedChecker(configSection);
+  else if (boost::iequals(type, "hierarchical"))
+    return createHierarchicalChecker(configSection);
+  else
+    throw Error("Unsupported checker type: " + type);
+}
+
+shared_ptr<Checker>
+CheckerFactory::createCustomizedChecker(const ConfigSection& configSection)
+{
+  ConfigSection::const_iterator propertyIt = configSection.begin();
+  propertyIt++;
+
+  // Get checker.sig-type
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
+    throw Error("Expect <checker.sig-type>");
+
+  std::string sigType = propertyIt->second.data();
+  propertyIt++;
+
+  // Get checker.key-locator
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "key-locator"))
+    throw Error("Expect <checker.key-locator>");
+
+  shared_ptr<KeyLocatorChecker> keyLocatorChecker =
+    KeyLocatorCheckerFactory::create(propertyIt->second);
+  propertyIt++;
+
+  if (propertyIt != configSection.end())
+    throw Error("Expect the end of checker");
+
+  return make_shared<CustomizedChecker>(getSigType(sigType), keyLocatorChecker);
+}
+
+shared_ptr<Checker>
+CheckerFactory::createHierarchicalChecker(const ConfigSection& configSection)
+{
+  ConfigSection::const_iterator propertyIt = configSection.begin();
+  propertyIt++;
+
+  // Get checker.sig-type
+  if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "sig-type"))
+    throw Error("Expect <checker.sig-type>");
+
+  std::string sigType = propertyIt->second.data();
+  propertyIt++;
+
+  if (propertyIt != configSection.end())
+    throw Error("Expect the end of checker");
+
+  return make_shared<HierarchicalChecker>(getSigType(sigType));
+}
+
+uint32_t
+CheckerFactory::getSigType(const std::string& sigType)
+{
+  if (boost::iequals(sigType, "rsa-sha256"))
+    return tlv::SignatureSha256WithRsa;
+  else if (boost::iequals(sigType, "ecdsa-sha256"))
+    return tlv::SignatureSha256WithEcdsa;
+  else if (boost::iequals(sigType, "sha256"))
+    return tlv::DigestSha256;
+  else
+    throw Error("Unsupported signature type");
+}
+
+} // namespace conf
+} // namespace nsl