Move pib service from ndn-cxx to ndn-tools

Code is copied from ndn-cxx:commit:e1c8c4cfffb33dca13c8ca7d7ef04c7401a7cbef,
(gerrit change-id Ieea485c0ebdce9fb9c876cad005cb95fd8e0c899)
with minor changes for changing include paths and building script.

Change-Id: I77b94fe69b20f04c338e7be7387125f709fa9e1a
Refs: #3018
diff --git a/tools/pib/pib-validator.cpp b/tools/pib/pib-validator.cpp
new file mode 100644
index 0000000..cc34645
--- /dev/null
+++ b/tools/pib/pib-validator.cpp
@@ -0,0 +1,163 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2015 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "pib-validator.hpp"
+#include "encoding/pib-common.hpp"
+#include "encoding/update-param.hpp"
+#include <set>
+#include <string>
+
+namespace ndn {
+namespace pib {
+
+using std::set;
+using std::string;
+
+PibValidator::PibValidator(const PibDb& db, size_t maxCacheSize)
+  : m_db(db)
+  , m_isMgmtReady(false)
+{
+  m_owner = m_db.getOwnerName();
+  m_mgmtCert = m_db.getMgmtCertificate();
+
+  if (!m_owner.empty() && m_mgmtCert != nullptr)
+    m_isMgmtReady = true;
+
+  m_mgmtChangeConnection =
+    const_cast<PibDb&>(m_db).mgmtCertificateChanged.connect([this] () {
+        m_owner = m_db.getOwnerName();
+        m_mgmtCert = m_db.getMgmtCertificate();
+        if (!m_owner.empty() && m_mgmtCert != nullptr)
+          m_isMgmtReady = true;
+      });
+
+  m_keyDeletedConnection =
+    const_cast<PibDb&>(m_db).keyDeleted.connect([this] (Name keyName) {
+        m_keyCache.erase(keyName);
+      });
+}
+
+PibValidator::~PibValidator()
+{
+}
+
+void
+PibValidator::checkPolicy(const Interest& interest,
+                          int nSteps,
+                          const OnInterestValidated& onValidated,
+                          const OnInterestValidationFailed& onValidationFailed,
+                          std::vector<shared_ptr<ValidationRequest>>& nextSteps)
+{
+  if (!m_isMgmtReady)
+    return onValidationFailed(interest.shared_from_this(), "PibDb is not initialized");
+
+  const Name& interestName = interest.getName();
+
+  if (interestName.size() != SIGNED_PIB_INTEREST_SIZE) {
+    return onValidationFailed(interest.shared_from_this(),
+                              "Interest is not signed: " + interest.getName().toUri());
+  }
+
+  // Check if the user exists in PIB
+  string user = interestName.get(OFFSET_USER).toUri();
+  if (user != m_owner)
+    return onValidationFailed(interest.shared_from_this(), "Wrong user: " + user);
+
+  // Verify signature
+  try {
+    Signature signature(interestName[OFFSET_SIG_INFO].blockFromValue(),
+                        interestName[OFFSET_SIG_VALUE].blockFromValue());
+    // KeyLocator is required to contain the name of signing certificate (w/o version)
+    if (!signature.hasKeyLocator())
+      return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
+
+    const KeyLocator& keyLocator = signature.getKeyLocator();
+    if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
+      return onValidationFailed(interest.shared_from_this(), "Key Locator is not a name");
+
+    // Check if PIB has the corresponding public key
+    shared_ptr<PublicKey> publicKey;
+
+    if (keyLocator.getName() == m_mgmtCert->getName().getPrefix(-1)) {
+      // the signing key is mgmt key.
+      publicKey = make_shared<PublicKey>(m_mgmtCert->getPublicKeyInfo());
+    }
+    else {
+      // the signing key is normal key.
+      Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());
+
+      shared_ptr<PublicKey> key = m_keyCache.find(keyName);
+      if (key != nullptr) {
+        // the signing key is cached.
+        publicKey = key;
+      }
+      else {
+        // the signing key is not cached.
+        publicKey = m_db.getKey(keyName);
+        if (publicKey == nullptr) {
+          // the signing key does not exist in PIB.
+          return onValidationFailed(interest.shared_from_this(), "Public key is not trusted");
+        }
+        else {
+          // the signing key is retrieved from PIB.
+          m_keyCache.insert(keyName, publicKey);
+        }
+      }
+    }
+
+    if (verifySignature(interest, signature, *publicKey))
+      onValidated(interest.shared_from_this());
+    else
+      onValidationFailed(interest.shared_from_this(), "Cannot verify signature");
+
+  }
+  catch (KeyLocator::Error&) {
+    return onValidationFailed(interest.shared_from_this(),
+                              "No valid KeyLocator");
+  }
+  catch (Signature::Error&) {
+    return onValidationFailed(interest.shared_from_this(),
+                              "No valid signature");
+  }
+  catch (IdentityCertificate::Error&) {
+    return onValidationFailed(interest.shared_from_this(),
+                              "Cannot determine the signing key");
+  }
+  catch (tlv::Error&) {
+    return onValidationFailed(interest.shared_from_this(),
+                              "Cannot decode signature");
+  }
+}
+
+void
+PibValidator::checkPolicy(const Data& data,
+                          int nSteps,
+                          const OnDataValidated& onValidated,
+                          const OnDataValidationFailed& onValidationFailed,
+                          std::vector<shared_ptr<ValidationRequest>>& nextSteps)
+{
+  // Pib does not express any interest, therefor should not validate any data.
+  onValidationFailed(data.shared_from_this(),
+                     "PibValidator should not receive data packet");
+}
+
+} // namespace pib
+} // namespace ndn