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/cert-publisher.cpp b/tools/pib/cert-publisher.cpp
new file mode 100644
index 0000000..abcd5a2
--- /dev/null
+++ b/tools/pib/cert-publisher.cpp
@@ -0,0 +1,128 @@
+/* -*- 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 "cert-publisher.hpp"
+
+namespace ndn {
+namespace pib {
+
+CertPublisher::CertPublisher(Face& face, PibDb& db)
+ : m_face(face)
+ , m_db(db)
+{
+ startPublishAll();
+
+ m_certDeletedConnection =
+ m_db.certificateDeleted.connect(bind(&CertPublisher::stopPublish, this, _1));
+ m_certInsertedConnection =
+ m_db.certificateInserted.connect(bind(&CertPublisher::startPublish, this, _1));
+}
+
+CertPublisher::~CertPublisher()
+{
+ for (const auto& it : m_registeredPrefixes)
+ m_face.unsetInterestFilter(it.second);
+}
+
+void
+CertPublisher::startPublishAll()
+{
+ // For now we have to register the prefix of certificates separately.
+ // The reason is that certificates do not share the same prefix that
+ // can aggregate the certificates publishing without attracting interests
+ // for non-PIB data.
+
+ std::vector<Name> identities = m_db.listIdentities();
+
+ for (const auto& identity : identities) {
+ std::vector<Name> keyNames = m_db.listKeyNamesOfIdentity(identity);
+
+ for (const auto& key : keyNames) {
+ std::vector<Name> certNames = m_db.listCertNamesOfKey(key);
+
+ for (const auto& certName : certNames)
+ startPublish(certName);
+ }
+ }
+}
+
+void
+CertPublisher::registerCertPrefix(const Name& certName)
+{
+ BOOST_ASSERT(!certName.empty());
+
+ const Name& prefix = certName.getPrefix(-1);
+
+ if (m_registeredPrefixes.find(prefix) == m_registeredPrefixes.end()) {
+ m_registeredPrefixes[prefix] =
+ m_face.setInterestFilter(certName.getPrefix(-1),
+ bind(&CertPublisher::processInterest, this, _1, _2),
+ [] (const Name& name) {},
+ [=] (const Name& name, const std::string& msg) {
+ if (m_registeredPrefixes.erase(prefix) == 0) {
+ // registration no longer needed - certificates deleted
+ return;
+ }
+ // retry
+ registerCertPrefix(certName);
+ });
+
+ }
+}
+
+void
+CertPublisher::processInterest(const InterestFilter& interestFilter,
+ const Interest& interest)
+{
+ shared_ptr<const Data> certificate = m_responseCache.find(interest);
+ if (certificate != nullptr) {
+ m_face.put(*certificate);
+ }
+}
+
+void
+CertPublisher::startPublish(const Name& certName)
+{
+ m_responseCache.insert(*m_db.getCertificate(certName));
+ registerCertPrefix(certName);
+}
+
+void
+CertPublisher::stopPublish(const Name& certName)
+{
+ BOOST_ASSERT(!certName.empty());
+
+ m_responseCache.erase(certName);
+
+ // clear the listener if this is the only cert using the prefix
+ const Name& prefix = certName.getPrefix(-1); // strip version component
+
+ if (m_responseCache.find(prefix) != nullptr)
+ return;
+
+ auto it = m_registeredPrefixes.find(prefix);
+ BOOST_ASSERT(it != m_registeredPrefixes.end());
+ m_face.unsetInterestFilter(it->second);
+ m_registeredPrefixes.erase(it);
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/cert-publisher.hpp b/tools/pib/cert-publisher.hpp
new file mode 100644
index 0000000..052895c
--- /dev/null
+++ b/tools/pib/cert-publisher.hpp
@@ -0,0 +1,99 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_CERT_PUBLISHER_HPP
+#define NDN_PIB_CERT_PUBLISHER_HPP
+
+#include "pib-db.hpp"
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/util/in-memory-storage-persistent.hpp>
+
+namespace ndn {
+namespace pib {
+
+/// @brief implements the certificate publisher
+class CertPublisher : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param face The face pib used to receive queries and serve certificates.
+ * @param pibDb Database which holds the certificates.
+ */
+ CertPublisher(Face& face, PibDb& pibDb);
+
+ ~CertPublisher();
+
+private:
+ void
+ startPublishAll();
+
+ /**
+ * @brief add an interest filter for the certificate
+ */
+ void
+ registerCertPrefix(const Name& certName);
+
+ void
+ processInterest(const InterestFilter& interestFilter,
+ const Interest& interest);
+
+ void
+ startPublish(const Name& certName);
+
+ /**
+ * @brief callback when a certificate is deleted
+ *
+ * The method will remove the cert from in-memory storage
+ * and also unset interest filter if the removed cert
+ * is the only one with the registered prefix.
+ *
+ * @param certName removed certificate name
+ */
+ void
+ stopPublish(const Name& certName);
+
+private:
+ Face& m_face;
+ PibDb& m_db;
+ util::InMemoryStoragePersistent m_responseCache;
+ std::map<Name, const RegisteredPrefixId*> m_registeredPrefixes;
+
+ util::signal::ScopedConnection m_certDeletedConnection;
+ util::signal::ScopedConnection m_certInsertedConnection;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_CERT_PUBLISHER_HPP
diff --git a/tools/pib/default-query-processor.cpp b/tools/pib/default-query-processor.cpp
new file mode 100644
index 0000000..4909ea2
--- /dev/null
+++ b/tools/pib/default-query-processor.cpp
@@ -0,0 +1,199 @@
+/* -*- 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 "default-query-processor.hpp"
+#include "encoding/pib-encoding.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+using std::string;
+
+const size_t DefaultQueryProcessor::DEFAULT_QUERY_LENGTH = 5;
+
+DefaultQueryProcessor::DefaultQueryProcessor(PibDb& db)
+ : m_db(db)
+{
+}
+
+std::pair<bool, Block>
+DefaultQueryProcessor::operator()(const Interest& interest)
+{
+ const Name& interestName = interest.getName();
+
+ // handle pib query: /localhost/pib/[UserName]/default/param
+ if (interestName.size() != DEFAULT_QUERY_LENGTH) {
+ // malformed interest, discard
+ return std::make_pair(false, Block());
+ }
+
+ DefaultParam param;
+
+ try {
+ param.wireDecode(interestName.get(OFFSET_PARAM).blockFromValue());
+ }
+ catch (const tlv::Error& e) {
+ PibError error(ERR_WRONG_PARAM, "error in parsing param: " + string(e.what()));
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ switch (param.getTargetType()) {
+ case TYPE_ID:
+ return processDefaultIdQuery(param);
+ case TYPE_KEY:
+ return processDefaultKeyQuery(param);
+ case TYPE_CERT:
+ return processDefaultCertQuery(param);
+ default:
+ {
+ PibError error(ERR_WRONG_PARAM,
+ "target type is not supported: " +
+ boost::lexical_cast<string>(param.getTargetType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+}
+
+std::pair<bool, Block>
+DefaultQueryProcessor::processDefaultIdQuery(const DefaultParam& param)
+{
+ if (param.getOriginType() == TYPE_USER) {
+ try {
+ PibIdentity result(m_db.getDefaultIdentity());
+ return std::make_pair(true, result.wireEncode());
+ }
+ catch (PibDb::Error&) {
+ PibError error(ERR_NO_DEFAULT_ID, "default identity does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+ else {
+ PibError error(ERR_WRONG_PARAM,
+ "origin type of id target must be USER(0), but gets: " +
+ boost::lexical_cast<string>(param.getOriginType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+}
+
+std::pair<bool, Block>
+DefaultQueryProcessor::processDefaultKeyQuery(const DefaultParam& param)
+{
+ Name identity;
+ if (param.getOriginType() == TYPE_ID)
+ identity = param.getOriginName();
+ else if (param.getOriginType() == TYPE_USER) {
+ try {
+ identity = m_db.getDefaultIdentity();
+ }
+ catch (PibDb::Error&) {
+ PibError error(ERR_NO_DEFAULT_ID, "default identity does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+ else {
+ PibError error(ERR_WRONG_PARAM,
+ "origin type of key target must be ID(1) or USER(0), but gets: " +
+ boost::lexical_cast<string>(param.getOriginType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ try {
+ Name keyName = m_db.getDefaultKeyNameOfIdentity(identity);
+ shared_ptr<PublicKey> key = m_db.getKey(keyName);
+
+ if (key == nullptr) {
+ PibError error(ERR_NO_DEFAULT_KEY, "default key does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ PibPublicKey result(keyName, *key);
+ return std::make_pair(true, result.wireEncode());
+ }
+ catch (PibDb::Error& e) {
+ PibError error(ERR_NO_DEFAULT_KEY,
+ "default key does not exist: " + string(e.what()));
+ return std::make_pair(true, error.wireEncode());
+ }
+}
+
+std::pair<bool, Block>
+DefaultQueryProcessor::processDefaultCertQuery(const DefaultParam& param)
+{
+ Name identity;
+ if (param.getOriginType() == TYPE_USER) {
+ try {
+ identity = m_db.getDefaultIdentity();
+ }
+ catch (PibDb::Error&) {
+ PibError error(ERR_NO_DEFAULT_ID, "default identity does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+ else if (param.getOriginType() == TYPE_ID)
+ identity = param.getOriginName();
+ else if (param.getOriginType() != TYPE_KEY) {
+ PibError error(ERR_WRONG_PARAM,
+ "origin type of cert target must be KEY(2), ID(1) or USER(0), but gets: " +
+ boost::lexical_cast<string>(param.getOriginType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ Name keyName;
+ if (param.getOriginType() == TYPE_KEY) {
+ keyName = param.getOriginName();
+ if (keyName.size() < 1) {
+ PibError error(ERR_WRONG_PARAM,
+ "key name must contain key id component");
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+ else {
+ try {
+ keyName = m_db.getDefaultKeyNameOfIdentity(identity);
+ }
+ catch (PibDb::Error&) {
+ PibError error(ERR_NO_DEFAULT_KEY, "default key does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+
+ try {
+ Name certName = m_db.getDefaultCertNameOfKey(keyName);
+ shared_ptr<IdentityCertificate> certificate = m_db.getCertificate(certName);
+
+ if (certificate == nullptr) {
+ PibError error (ERR_NO_DEFAULT_CERT, "default cert does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ PibCertificate result(*certificate);
+ return std::make_pair(true, result.wireEncode());
+ }
+ catch (PibDb::Error&) {
+ PibError error(ERR_NO_DEFAULT_CERT, "default cert does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/default-query-processor.hpp b/tools/pib/default-query-processor.hpp
new file mode 100644
index 0000000..1938074
--- /dev/null
+++ b/tools/pib/default-query-processor.hpp
@@ -0,0 +1,76 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_DEFAULT_QUERY_PROCESSOR_HPP
+#define NDN_PIB_DEFAULT_QUERY_PROCESSOR_HPP
+
+#include "pib-db.hpp"
+#include "encoding/default-param.hpp"
+#include <ndn-cxx/interest.hpp>
+#include <utility>
+
+namespace ndn {
+namespace pib {
+
+class DefaultQueryProcessor : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param db The pib database.
+ */
+ explicit
+ DefaultQueryProcessor(PibDb& db);
+
+ std::pair<bool, Block>
+ operator()(const Interest& interest);
+
+private:
+ std::pair<bool, Block>
+ processDefaultIdQuery(const DefaultParam& param);
+
+ std::pair<bool, Block>
+ processDefaultKeyQuery(const DefaultParam& param);
+
+ std::pair<bool, Block>
+ processDefaultCertQuery(const DefaultParam& param);
+
+private:
+ static const size_t DEFAULT_QUERY_LENGTH;
+
+ const PibDb& m_db;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_DEFAULT_QUERY_PROCESSOR_HPP
diff --git a/tools/pib/delete-query-processor.cpp b/tools/pib/delete-query-processor.cpp
new file mode 100644
index 0000000..9174784
--- /dev/null
+++ b/tools/pib/delete-query-processor.cpp
@@ -0,0 +1,205 @@
+/* -*- 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 "delete-query-processor.hpp"
+#include "encoding/pib-encoding.hpp"
+#include "pib.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+using std::string;
+
+const size_t DeleteQueryProcessor::DELETE_QUERY_LENGTH = 9;
+const Name DeleteQueryProcessor::PIB_PREFIX("/localhost/pib");
+
+DeleteQueryProcessor::DeleteQueryProcessor(PibDb& db)
+ : m_db(db)
+{
+}
+
+std::pair<bool, Block>
+DeleteQueryProcessor::operator()(const Interest& interest)
+{
+ const Name& interestName = interest.getName();
+
+ // handle pib query: /localhost/pib/[UserName]/delete/param/<signed_interest_related_components>
+ if (interestName.size() != DELETE_QUERY_LENGTH) {
+ // malformed interest, discard
+ return std::make_pair(false, Block());
+ }
+
+ try {
+ DeleteParam param;
+ param.wireDecode(interestName.get(OFFSET_PARAM).blockFromValue());
+
+ SignatureInfo sigInfo;
+ sigInfo.wireDecode(interestName.get(OFFSET_SIG_INFO).blockFromValue());
+
+ // sigInfo must have KeyLocator.Name if the interest passed validation.
+ Name signerName;
+ signerName = sigInfo.getKeyLocator().getName();
+
+ switch (param.getTargetType()) {
+ case TYPE_USER:
+ return std::make_pair(true, PibError(ERR_WRONG_PARAM, "not allowed to delete user").wireEncode());
+ case TYPE_ID:
+ return processDeleteIdQuery(param, signerName);
+ case TYPE_KEY:
+ return processDeleteKeyQuery(param, signerName);
+ case TYPE_CERT:
+ return processDeleteCertQuery(param, signerName);
+ default:
+ {
+ PibError error(ERR_WRONG_PARAM,
+ "target type is not supported: " +
+ boost::lexical_cast<string>(param.getTargetType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+ }
+ catch (const PibDb::Error& e) {
+ PibError error(ERR_INTERNAL_ERROR, e.what());
+ return std::make_pair(true, error.wireEncode());
+ }
+ catch (const tlv::Error& e) {
+ PibError error(ERR_WRONG_PARAM, "error in parsing param: " + string(e.what()));
+ return std::make_pair(true, error.wireEncode());
+ }
+}
+
+std::pair<bool, Block>
+DeleteQueryProcessor::processDeleteIdQuery(const DeleteParam& param, const Name& signerName)
+{
+ Name identity = param.getTargetName();
+ if (!isDeleteAllowed(TYPE_ID, identity, signerName)) {
+ PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ m_db.deleteIdentity(identity);
+
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+}
+
+std::pair<bool, Block>
+DeleteQueryProcessor::processDeleteKeyQuery(const DeleteParam& param, const Name& signerName)
+{
+ const Name& keyName = param.getTargetName();
+ if (!isDeleteAllowed(TYPE_KEY, keyName, signerName)) {
+ PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ m_db.deleteKey(keyName);
+
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+}
+
+std::pair<bool, Block>
+DeleteQueryProcessor::processDeleteCertQuery(const DeleteParam& param, const Name& signerName)
+{
+ const Name& certName = param.getTargetName();
+ if (!isDeleteAllowed(TYPE_CERT, certName, signerName)) {
+ PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ m_db.deleteCertificate(certName);
+
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+}
+
+bool
+DeleteQueryProcessor::isDeleteAllowed(const pib::Type targetType,
+ const Name& targetName,
+ const Name& signer) const
+{
+ // sanity checking, user cannot be deleted.
+ if (targetType == TYPE_USER)
+ return false;
+
+ // Any identity with prefix /localhost/pib is reserved. Any operation with a targetName under
+ // that prefix will be rejected.
+ if (PIB_PREFIX.isPrefixOf(targetName))
+ return false;
+
+ // Rules for other items:
+ //
+ // signer | deleting privilege
+ // =========================+===============================================
+ // local mgmt key | any id, key, and cert
+ // -------------------------+-----------------------------------------------
+ // default key of an id | any id, key, and cert under the id's namespace
+ // -------------------------+-----------------------------------------------
+ // non-default key of an id | any cert of the key
+
+ const Name& signerKeyName = IdentityCertificate::certificateNameToPublicKeyName(signer);
+ const Name& signerId = signerKeyName.getPrefix(-1);
+
+ bool hasSignerDefaultKey = true;
+ Name signerDefaultKeyName;
+ try {
+ signerDefaultKeyName = m_db.getDefaultKeyNameOfIdentity(signerId);
+ }
+ catch (PibDb::Error&) {
+ hasSignerDefaultKey = false;
+ }
+
+ Name mgmtCertName;
+ try {
+ mgmtCertName = m_db.getMgmtCertificate()->getName().getPrefix(-1);
+ }
+ catch (PibDb::Error&) {
+ return false;
+ }
+
+ if (signer == mgmtCertName) {
+ // signer is current management key, anything is allowed.
+ return true;
+ }
+ else if (hasSignerDefaultKey && signerDefaultKeyName == signerKeyName) {
+ // signer is an identity's default key
+ if (!signerId.isPrefixOf(targetName))
+ return false;
+ else
+ return true;
+ }
+ else {
+ // non-default key
+ if (targetType == TYPE_CERT) {
+ // check if it is for the key's cert
+ if (IdentityCertificate::certificateNameToPublicKeyName(targetName) == signerKeyName)
+ return true;
+ }
+ else if (targetType == TYPE_KEY) {
+ // check if it is for the key itself
+ if (targetName == signerKeyName)
+ return true;
+ }
+ return false;
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/delete-query-processor.hpp b/tools/pib/delete-query-processor.hpp
new file mode 100644
index 0000000..3336deb
--- /dev/null
+++ b/tools/pib/delete-query-processor.hpp
@@ -0,0 +1,93 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_DELETE_QUERY_PROCESSOR_HPP
+#define NDN_PIB_DELETE_QUERY_PROCESSOR_HPP
+
+#include "pib-db.hpp"
+#include "encoding/delete-param.hpp"
+#include <ndn-cxx/interest.hpp>
+#include <utility>
+
+namespace ndn {
+namespace pib {
+
+class Pib;
+
+/// @brief Processing unit for PIB delete query
+class DeleteQueryProcessor : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param db The pib database.
+ */
+ explicit
+ DeleteQueryProcessor(PibDb& db);
+
+ std::pair<bool, Block>
+ operator()(const Interest& interest);
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Determine if a delete command is allowed.
+ *
+ * @param targetType The type of the target that will be deleted.
+ * @param targetName The name of the target that will be deleted.
+ * @param signer The name of the command signer.
+ */
+ bool
+ isDeleteAllowed(const pib::Type targetType,
+ const Name& targetName,
+ const Name& signer) const;
+
+private:
+ std::pair<bool, Block>
+ processDeleteIdQuery(const DeleteParam& param, const Name& signerName);
+
+ std::pair<bool, Block>
+ processDeleteKeyQuery(const DeleteParam& param, const Name& signerName);
+
+ std::pair<bool, Block>
+ processDeleteCertQuery(const DeleteParam& param, const Name& signerName);
+
+private:
+ static const size_t DELETE_QUERY_LENGTH;
+ static const Name PIB_PREFIX;
+
+ PibDb& m_db;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_DELETE_QUERY_PROCESSOR_HPP
diff --git a/tools/pib/encoding/default-param.cpp b/tools/pib/encoding/default-param.cpp
new file mode 100644
index 0000000..015bf19
--- /dev/null
+++ b/tools/pib/encoding/default-param.cpp
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "default-param.hpp"
+#include <ndn-cxx/encoding/block-helpers.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+static_assert(std::is_base_of<tlv::Error, DefaultParam::Error>::value,
+ "DefaultParam::Error must inherit from tlv::Error");
+
+const std::string DefaultParam::VERB("default");
+
+DefaultParam::DefaultParam()
+ : m_targetType(TYPE_DEFAULT)
+ , m_originType(TYPE_DEFAULT)
+{
+}
+
+DefaultParam::DefaultParam(const pib::Type targetType,
+ const pib::Type originType,
+ const Name& originName)
+ : m_targetType(targetType)
+ , m_originType(originType)
+ , m_originName(originName)
+{
+}
+
+DefaultParam::DefaultParam(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+const Name&
+DefaultParam::getOriginName() const
+{
+ if (m_originType == TYPE_ID || m_originType == TYPE_KEY || m_originType == TYPE_CERT)
+ return m_originName;
+ else
+ throw Error("DefaultParam::getOriginName: origin name does not exist");
+}
+
+template<bool T>
+size_t
+DefaultParam::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ switch (m_originType) {
+ case TYPE_ID:
+ case TYPE_KEY:
+ case TYPE_CERT:
+ {
+ totalLength += m_originName.wireEncode(block);
+ break;
+ }
+ case TYPE_USER:
+ break;
+ default:
+ throw Error("DefaultParam::wireEncode: unsupported PibType: " +
+ boost::lexical_cast<std::string>(m_originType));
+ }
+
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::Type, m_originType);
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::Type, m_targetType);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::DefaultParam);
+
+ return totalLength;
+}
+
+template size_t
+DefaultParam::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+DefaultParam::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+DefaultParam::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+DefaultParam::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw Error("The supplied block does not contain wire format");
+ }
+
+ m_wire = wire;
+ m_wire.parse();
+
+ if (m_wire.type() != tlv::pib::DefaultParam)
+ throw Error("Unexpected TLV type when decoding DefaultParam");
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ // the first block must be PibType
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Type) {
+ m_targetType = static_cast<pib::Type>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw Error("DefaultParam requires the first sub-TLV to be PibType");
+
+ // the second block must be PibType
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Type) {
+ m_originType = static_cast<pib::Type>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw Error("DefaultParam requires the second sub-TLV to be PibType");
+
+ switch (m_originType) {
+ case TYPE_ID:
+ case TYPE_KEY:
+ case TYPE_CERT:
+ {
+ if (it != m_wire.elements_end()) {
+ // the third block, if exists, must be Name
+ m_originName.wireDecode(*it);
+ return;
+ }
+ else {
+ throw Error("DefaultParam requires the third sub-TLV to be Name");
+ }
+ }
+ case TYPE_USER:
+ return;
+ default:
+ throw Error("DefaultParam::wireDecode: unsupported PibType: " +
+ boost::lexical_cast<std::string>(m_originType));
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/encoding/default-param.hpp b/tools/pib/encoding/default-param.hpp
new file mode 100644
index 0000000..1906954
--- /dev/null
+++ b/tools/pib/encoding/default-param.hpp
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+
+#ifndef NDN_PIB_DEFAULT_PARAM_HPP
+#define NDN_PIB_DEFAULT_PARAM_HPP
+
+#include "pib-common.hpp"
+#include <ndn-cxx/name.hpp>
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief DefaultParam is the abstraction of PIB Default parameter.
+ *
+ * PibDefaultParam := PIB-DEFAULT-PARAM-TYPE TLV-LENGTH
+ * PibType // target type
+ * PibType // origin type
+ * Name? // origin name
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Default-Parameters
+ */
+
+class DefaultParam : noncopyable
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ DefaultParam();
+
+ DefaultParam(const pib::Type targetType,
+ const pib::Type originType,
+ const Name& originName = Name());
+
+ explicit
+ DefaultParam(const Block& wire);
+
+ tlv::pib::ParamType
+ getParamType() const
+ {
+ return tlv::pib::DefaultParam;
+ }
+
+ pib::Type
+ getTargetType() const
+ {
+ return m_targetType;
+ }
+
+ pib::Type
+ getOriginType() const
+ {
+ return m_originType;
+ }
+
+ /**
+ * @brief Get target name
+ *
+ * @throws Error if origin name does not exist
+ */
+ const Name&
+ getOriginName() const;
+
+ /// @brief Encode to a wire format or estimate wire format
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ /**
+ * @brief Encode to a wire format
+ *
+ * @throws Error if encoding fails
+ */
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode GetParam from a wire encoded block
+ *
+ * @throws Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+public:
+ static const std::string VERB;
+
+private:
+ pib::Type m_targetType;
+ pib::Type m_originType;
+ Name m_originName;
+
+ mutable Block m_wire;
+};
+
+} // namespace pib
+} // namespace ndn
+
+
+
+#endif // NDN_PIB_DEFAULT_PARAM_HPP
diff --git a/tools/pib/encoding/delete-param.cpp b/tools/pib/encoding/delete-param.cpp
new file mode 100644
index 0000000..41c8f6a
--- /dev/null
+++ b/tools/pib/encoding/delete-param.cpp
@@ -0,0 +1,129 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "delete-param.hpp"
+#include <ndn-cxx/encoding/block-helpers.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+static_assert(std::is_base_of<tlv::Error, DeleteParam::Error>::value,
+ "DeleteParam::Error must inherit from tlv::Error");
+
+const std::string DeleteParam::VERB("delete");
+
+DeleteParam::DeleteParam()
+ : m_targetType(TYPE_DEFAULT)
+{
+}
+
+DeleteParam::DeleteParam(const Name& name, pib::Type type)
+ : m_targetType(type)
+ , m_targetName(name)
+{
+}
+
+DeleteParam::DeleteParam(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+template<bool T>
+size_t
+DeleteParam::wireEncode(EncodingImpl<T>& block) const
+{
+ if (m_targetType != TYPE_ID &&
+ m_targetType != TYPE_KEY &&
+ m_targetType != TYPE_CERT &&
+ m_targetType != TYPE_USER)
+ throw Error("DeleteParam::wireEncode: Wrong Type value: " +
+ boost::lexical_cast<std::string>(m_targetType));
+
+ size_t totalLength = 0;
+
+ totalLength += m_targetName.wireEncode(block);
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::Type, m_targetType);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::DeleteParam);
+
+ return totalLength;
+}
+
+template size_t
+DeleteParam::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+DeleteParam::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+DeleteParam::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+DeleteParam::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw Error("The supplied block does not contain wire format");
+ }
+
+ m_wire = wire;
+ m_wire.parse();
+
+ if (m_wire.type() != tlv::pib::DeleteParam)
+ throw Error("Unexpected TLV type when decoding DeleteParam");
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ // the first block must be Type
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Type) {
+ m_targetType = static_cast<pib::Type>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw Error("DeleteParam requires the first sub-TLV to be Type");
+
+ // the second block must be Name
+ if (it != m_wire.elements_end() && it->type() == tlv::Name) {
+ m_targetName.wireDecode(*it);
+ it++;
+ }
+ else
+ throw Error("DeleteParam requires the second sub-TLV to be Name");
+
+ if (it != m_wire.elements_end())
+ throw Error("DeleteParam must not contain more than two sub-TLVs");
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/encoding/delete-param.hpp b/tools/pib/encoding/delete-param.hpp
new file mode 100644
index 0000000..14d8392
--- /dev/null
+++ b/tools/pib/encoding/delete-param.hpp
@@ -0,0 +1,114 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_DELETE_PARAM_HPP
+#define NDN_PIB_DELETE_PARAM_HPP
+
+#include "pib-common.hpp"
+#include <ndn-cxx/name.hpp>
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief DeleteParam is the abstraction of PIB Delete parameter.
+ *
+ * PibDeleteParam := PIB-DELETE-PARAM-TYPE TLV-LENGTH
+ * PibType
+ * Name
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Delete-Parameters
+ */
+
+class DeleteParam : noncopyable
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ DeleteParam();
+
+ explicit
+ DeleteParam(const Name& name, const pib::Type type = TYPE_ID);
+
+ explicit
+ DeleteParam(const Block& wire);
+
+ tlv::pib::ParamType
+ getParamType() const
+ {
+ return tlv::pib::DeleteParam;
+ }
+
+ pib::Type
+ getTargetType() const
+ {
+ return m_targetType;
+ }
+
+ const Name&
+ getTargetName() const
+ {
+ return m_targetName;
+ }
+
+ /// @brief Encode to a wire format or estimate wire format
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ /**
+ * @brief Encode to a wire format
+ *
+ * @throws Error if encoding fails
+ */
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode GetParam from a wire encoded block
+ *
+ * @throws Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+public:
+ static const std::string VERB;
+
+private:
+ pib::Type m_targetType;
+ Name m_targetName;
+
+ mutable Block m_wire;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_DELETE_PARAM_HPP
diff --git a/tools/pib/encoding/get-param.cpp b/tools/pib/encoding/get-param.cpp
new file mode 100644
index 0000000..ea076f9
--- /dev/null
+++ b/tools/pib/encoding/get-param.cpp
@@ -0,0 +1,156 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "get-param.hpp"
+#include <boost/lexical_cast.hpp>
+#include <ndn-cxx/encoding/block-helpers.hpp>
+
+namespace ndn {
+namespace pib {
+
+static_assert(std::is_base_of<tlv::Error, GetParam::Error>::value,
+ "GetParam::Error must inherit from tlv::Error");
+
+const std::string GetParam::VERB("get");
+
+GetParam::GetParam()
+ : m_targetType(TYPE_USER)
+{
+}
+
+GetParam::GetParam(const pib::Type targetType, const Name& targetName)
+ : m_targetType(targetType)
+ , m_targetName(targetName)
+{
+}
+
+GetParam::GetParam(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+const Name&
+GetParam::getTargetName() const
+{
+ if (m_targetType == TYPE_ID || m_targetType == TYPE_KEY || m_targetType == TYPE_CERT)
+ return m_targetName;
+ else
+ throw Error("GetParam::getTargetName: target name does not exist");
+}
+
+template<bool T>
+size_t
+GetParam::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ switch (m_targetType) {
+ case TYPE_ID:
+ case TYPE_KEY:
+ case TYPE_CERT:
+ {
+ totalLength += m_targetName.wireEncode(block);
+ break;
+ }
+ case TYPE_USER:
+ break;
+ default:
+ throw Error("GetParam::wireEncode: unsupported PibType: " +
+ boost::lexical_cast<std::string>(m_targetType));
+ }
+
+ // Encode Type
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::Type, m_targetType);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::GetParam);
+
+ return totalLength;
+}
+
+template size_t
+GetParam::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+GetParam::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+GetParam::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+GetParam::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw Error("The supplied block does not contain wire format");
+ }
+
+ m_wire = wire;
+ m_wire.parse();
+
+ if (m_wire.type() != tlv::pib::GetParam)
+ throw Error("Unexpected TLV type when decoding GetParam");
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ // the first block must be Type
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Type) {
+ m_targetType = static_cast<pib::Type>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw Error("GetParam requires the first sub-TLV to be PibType");
+
+ switch (m_targetType) {
+ case TYPE_ID:
+ case TYPE_KEY:
+ case TYPE_CERT:
+ {
+ if (it != m_wire.elements_end()) {
+ // the second block, if exists, must be Name
+ m_targetName.wireDecode(*it);
+ return;
+ }
+ else {
+ throw Error("GetParam requires the second sub-TLV to be Name");
+ }
+ }
+ case TYPE_USER:
+ return;
+ default:
+ throw Error("GetParam::wireDecode: unsupported PibType: " +
+ boost::lexical_cast<std::string>(m_targetType));
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/encoding/get-param.hpp b/tools/pib/encoding/get-param.hpp
new file mode 100644
index 0000000..39a6c0e
--- /dev/null
+++ b/tools/pib/encoding/get-param.hpp
@@ -0,0 +1,115 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_GET_PARAM_HPP
+#define NDN_PIB_GET_PARAM_HPP
+
+#include "pib-common.hpp"
+#include <ndn-cxx/name.hpp>
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief GetParam is the abstraction of PIB Get parameter.
+ *
+ * PibGetParam := PIB-GET-PARAM-TYPE TLV-LENGTH
+ * PibType
+ * Name?
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Get-Parameters
+ */
+
+class GetParam : noncopyable
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ GetParam();
+
+ GetParam(const pib::Type targetType, const Name& targetName);
+
+ explicit
+ GetParam(const Block& wire);
+
+ tlv::pib::ParamType
+ getParamType() const
+ {
+ return tlv::pib::GetParam;
+ }
+
+ pib::Type
+ getTargetType() const
+ {
+ return m_targetType;
+ }
+
+ /**
+ * @brief Get target name
+ *
+ * @throws Error if target name does not exist
+ */
+ const Name&
+ getTargetName() const;
+
+ /// @brief Encode to a wire format or estimate wire format
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ /**
+ * @brief Encode to a wire format
+ *
+ * @throws Error if encoding fails
+ */
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode GetParam from a wire encoded block
+ *
+ * @throws Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+public:
+ static const std::string VERB;
+
+private:
+ pib::Type m_targetType;
+ Name m_targetName;
+
+ mutable Block m_wire;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_GET_PARAM_HPP
diff --git a/tools/pib/encoding/list-param.cpp b/tools/pib/encoding/list-param.cpp
new file mode 100644
index 0000000..cb604e6
--- /dev/null
+++ b/tools/pib/encoding/list-param.cpp
@@ -0,0 +1,155 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "list-param.hpp"
+#include <ndn-cxx/encoding/block-helpers.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+static_assert(std::is_base_of<tlv::Error, ListParam::Error>::value,
+ "ListParam::Error must inherit from tlv::Error");
+
+const std::string ListParam::VERB("list");
+
+ListParam::ListParam()
+ : m_originType(TYPE_USER)
+{
+}
+
+ListParam::ListParam(const pib::Type originType, const Name& originName)
+ : m_originType(originType)
+ , m_originName(originName)
+{
+}
+
+ListParam::ListParam(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+const Name&
+ListParam::getOriginName() const
+{
+ if (m_originType == TYPE_ID || m_originType == TYPE_KEY || m_originType == TYPE_CERT)
+ return m_originName;
+ else
+ throw Error("ListParam::getOriginName: origin name does not exist");
+}
+
+template<bool T>
+size_t
+ListParam::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ switch (m_originType) {
+ case TYPE_ID:
+ case TYPE_KEY:
+ case TYPE_CERT:
+ {
+ totalLength += m_originName.wireEncode(block);
+ break;
+ }
+ case TYPE_USER:
+ break;
+ default:
+ throw Error("ListParam::wireEncode: unsupported PibType: " +
+ boost::lexical_cast<std::string>(m_originType));
+ }
+
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::Type, m_originType);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::ListParam);
+
+ return totalLength;
+}
+
+template size_t
+ListParam::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+ListParam::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+ListParam::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+ListParam::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw Error("The supplied block does not contain wire format");
+ }
+
+ m_wire = wire;
+ m_wire.parse();
+
+ if (m_wire.type() != tlv::pib::ListParam)
+ throw Error("Unexpected TLV type when decoding ListParam");
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ // the first block must be PibType
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Type) {
+ m_originType = static_cast<pib::Type>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw Error("ListParam requires the first sub-TLV to be PibType");
+
+ switch (m_originType) {
+ case TYPE_ID:
+ case TYPE_KEY:
+ case TYPE_CERT:
+ {
+ if (it != m_wire.elements_end()) {
+ // the second block, if exists, must be Name
+ m_originName.wireDecode(*it);
+ return;
+ }
+ else {
+ throw Error("ListParam requires the second sub-TLV to be Name");
+ }
+ }
+ case TYPE_USER:
+ return;
+ default:
+ throw Error("ListParam::wireDecode: unsupported PibType: " +
+ boost::lexical_cast<std::string>(m_originType));
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/encoding/list-param.hpp b/tools/pib/encoding/list-param.hpp
new file mode 100644
index 0000000..f94732e
--- /dev/null
+++ b/tools/pib/encoding/list-param.hpp
@@ -0,0 +1,118 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+
+#ifndef NDN_PIB_LIST_PARAM_HPP
+#define NDN_PIB_LIST_PARAM_HPP
+
+#include "pib-common.hpp"
+#include <ndn-cxx/name.hpp>
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief ListParam is the abstraction of PIB List parameter.
+ *
+ * PibListParam := PIB-LIST-PARAM-TYPE TLV-LENGTH
+ * PibType // origin type
+ * Name? // origin name
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#List-Parameters
+ */
+
+class ListParam : noncopyable
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ ListParam();
+
+ ListParam(const pib::Type originType, const Name& originName);
+
+ explicit
+ ListParam(const Block& wire);
+
+ tlv::pib::ParamType
+ getParamType() const
+ {
+ return tlv::pib::ListParam;
+ }
+
+ pib::Type
+ getOriginType() const
+ {
+ return m_originType;
+ }
+
+ /**
+ * @brief Get target name
+ *
+ * @throws Error if origin name does not exist
+ */
+ const Name&
+ getOriginName() const;
+
+ /// @brief Encode to a wire format or estimate wire format
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ /**
+ * @brief Encode to a wire format
+ *
+ * @throws Error if encoding fails
+ */
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode GetParam from a wire encoded block
+ *
+ * @throws Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+public:
+ static const std::string VERB;
+
+private:
+ pib::Type m_originType;
+ Name m_originName;
+
+ mutable Block m_wire;
+};
+
+} // namespace pib
+} // namespace ndn
+
+
+
+#endif // NDN_PIB_LIST_PARAM_HPP
diff --git a/tools/pib/encoding/pib-common.hpp b/tools/pib/encoding/pib-common.hpp
new file mode 100644
index 0000000..74c5daf
--- /dev/null
+++ b/tools/pib/encoding/pib-common.hpp
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_PIB_COMMON_HPP
+#define NDN_PIB_PIB_COMMON_HPP
+
+namespace ndn {
+namespace pib {
+
+/// @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base
+
+enum {
+ OFFSET_USER = 2,
+ OFFSET_VERB = 3,
+ OFFSET_PARAM = 4,
+ OFFSET_TIMESTAMP = 5,
+ OFFSET_NONCE = 6,
+ OFFSET_SIG_INFO = 7,
+ OFFSET_SIG_VALUE = 8,
+
+ MIN_PIB_INTEREST_SIZE = 5,
+ SIGNED_PIB_INTEREST_SIZE = 9
+};
+
+enum Type {
+ TYPE_USER = 0,
+ TYPE_ID = 1,
+ TYPE_KEY = 2,
+ TYPE_CERT = 3,
+ TYPE_DEFAULT = 255
+};
+
+enum DefaultOpt {
+ DEFAULT_OPT_NO = 0,
+ DEFAULT_OPT_KEY = 1, // 0x01
+ DEFAULT_OPT_ID = 3, // 0x03
+ DEFAULT_OPT_USER = 7 // 0x07
+};
+
+enum DefaultOptMask {
+ DEFAULT_OPT_KEY_MASK = 0x1,
+ DEFAULT_OPT_ID_MASK = 0x2,
+ DEFAULT_OPT_USER_MASK = 0x4
+};
+
+enum ErrCode {
+ ERR_SUCCESS = 0,
+
+ // Invalid query
+ ERR_INCOMPLETE_COMMAND = 1,
+ ERR_WRONG_VERB = 2,
+ ERR_WRONG_PARAM = 3,
+ ERR_WRONG_SIGNER = 4,
+ ERR_INTERNAL_ERROR = 5,
+
+ // Non existing entity
+ ERR_NON_EXISTING_USER = 128,
+ ERR_NON_EXISTING_ID = 129,
+ ERR_NON_EXISTING_KEY = 130,
+ ERR_NON_EXISTING_CERT = 131,
+
+ // No default setting
+ ERR_NO_DEFAULT_ID = 256,
+ ERR_NO_DEFAULT_KEY = 257,
+ ERR_NO_DEFAULT_CERT = 258,
+
+ // Delete default setting
+ ERR_DELETE_DEFAULT_SETTING = 384
+};
+
+} // namespace pib
+
+
+namespace tlv {
+namespace pib {
+
+enum ParamType {
+ GetParam = 128, // 0x80
+ DefaultParam = 129, // 0x81
+ ListParam = 130, // 0x82
+ UpdateParam = 131, // 0x83
+ DeleteParam = 132 // 0x84
+};
+
+enum EntityType {
+ User = 144, // 0x90
+ Identity = 145, // 0x91
+ PublicKey = 146, // 0x92
+ Certificate = 147 // 0x93
+};
+
+// Other
+enum {
+ Bytes = 148, // 0x94
+ DefaultOpt = 149, // 0x95
+ NameList = 150, // 0x96
+ Type = 151, // 0x97
+ Error = 152, // 0x98
+ TpmLocator = 153, // 0x99
+
+ // ErrorCode
+ ErrorCode = 252 // 0xfc
+};
+
+} // namespace pib
+} // namespace tlv
+} // namespace ndn
+
+
+#endif // NDN_PIB_PIB_COMMON_HPP
diff --git a/tools/pib/encoding/pib-encoding.cpp b/tools/pib/encoding/pib-encoding.cpp
new file mode 100644
index 0000000..e7c5ca4
--- /dev/null
+++ b/tools/pib/encoding/pib-encoding.cpp
@@ -0,0 +1,525 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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-encoding.hpp"
+#include <ndn-cxx/encoding/block-helpers.hpp>
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <vector>
+#include <string>
+
+namespace ndn {
+namespace pib {
+
+using std::vector;
+using std::string;
+
+PibIdentity::PibIdentity()
+{
+}
+
+PibIdentity::PibIdentity(const Name& identity)
+ : m_identity(identity)
+{
+}
+
+PibIdentity::PibIdentity(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+template<bool T>
+size_t
+PibIdentity::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = m_identity.wireEncode(block);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::Identity);
+
+ return totalLength;
+}
+
+template size_t
+PibIdentity::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+PibIdentity::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+PibIdentity::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+PibIdentity::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw tlv::Error("The supplied block does not contain wire format");
+ }
+
+ if (wire.type() != tlv::pib::Identity)
+ throw tlv::Error("Unexpected TLV type when decoding PibIdentity");
+
+ m_wire = wire;
+ m_identity.wireDecode(m_wire.blockFromValue());
+}
+
+
+
+PibPublicKey::PibPublicKey()
+ : m_isValueSet(false)
+{
+}
+
+PibPublicKey::PibPublicKey(const Name& keyName, const PublicKey& key)
+ : m_isValueSet(true)
+ , m_keyName(keyName)
+ , m_key(key)
+{
+}
+
+PibPublicKey::PibPublicKey(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+const Name&
+PibPublicKey::getKeyName() const
+{
+ if (m_isValueSet)
+ return m_keyName;
+ else
+ throw tlv::Error("PibPublicKey::getKeyName: keyName is not set");
+}
+
+const PublicKey&
+PibPublicKey::getPublicKey() const
+{
+ if (m_isValueSet)
+ return m_key;
+ else
+ throw tlv::Error("PibPublicKey::getPublicKey: key is not set");
+}
+
+template<bool T>
+size_t
+PibPublicKey::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = prependByteArrayBlock(block, tlv::pib::Bytes,
+ m_key.get().buf(), m_key.get().size());
+ totalLength += m_keyName.wireEncode(block);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::PublicKey);
+
+ return totalLength;
+}
+
+template size_t
+PibPublicKey::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+PibPublicKey::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+PibPublicKey::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+PibPublicKey::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw tlv::Error("The supplied block does not contain wire format");
+ }
+
+ if (wire.type() != tlv::pib::PublicKey)
+ throw tlv::Error("Unexpected TLV type when decoding PibPublicKey");
+
+ m_wire = wire;
+ m_wire.parse();
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+ if (it != m_wire.elements_end() && it->type() == tlv::Name) {
+ m_keyName.wireDecode(*it);
+ it++;
+ }
+ else
+ throw tlv::Error("PibPublicKey requires the first sub-TLV to be Name");
+
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Bytes) {
+ m_key = PublicKey(it->value(), it->value_size());
+ it++;
+ }
+ else
+ throw tlv::Error("PibPublicKey requires the second sub-TLV to be Bytes");
+
+ m_isValueSet = true;
+ if (it != m_wire.elements_end())
+ throw tlv::Error("PibPublicKey must contain only two sub-TLVs");
+}
+
+
+PibCertificate::PibCertificate()
+ : m_isValueSet(false)
+{
+}
+
+PibCertificate::PibCertificate(const IdentityCertificate& certificate)
+ : m_isValueSet(true)
+ , m_certificate(certificate)
+{
+}
+
+PibCertificate::PibCertificate(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+const IdentityCertificate&
+PibCertificate::getCertificate() const
+{
+ if (m_isValueSet)
+ return m_certificate;
+ else
+ throw tlv::Error("PibCertificate::getCertificate: certificate is not set");
+}
+
+template<bool T>
+size_t
+PibCertificate::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = prependBlock(block, m_certificate.wireEncode());
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::Certificate);
+
+ return totalLength;
+}
+
+template size_t
+PibCertificate::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+PibCertificate::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+PibCertificate::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+PibCertificate::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw tlv::Error("The supplied block does not contain wire format");
+ }
+
+ if (wire.type() != tlv::pib::Certificate)
+ throw tlv::Error("Unexpected TLV type when decoding PibCertificate");
+
+ m_wire = wire;
+ m_certificate.wireDecode(m_wire.blockFromValue());
+
+ m_isValueSet = true;
+}
+
+
+PibNameList::PibNameList()
+{
+}
+
+PibNameList::PibNameList(const std::vector<Name>& names)
+ : m_names(names)
+{
+}
+
+PibNameList::PibNameList(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+template<bool T>
+size_t
+PibNameList::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ for (vector<Name>::const_reverse_iterator it = m_names.rbegin();
+ it != m_names.rend(); it++) {
+ totalLength += it->wireEncode(block);
+ }
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::NameList);
+ return totalLength;
+}
+
+template size_t
+PibNameList::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+PibNameList::wireEncode<false>(EncodingImpl<false>& block) const;
+
+
+const Block&
+PibNameList::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+PibNameList::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw tlv::Error("The supplied block does not contain wire format");
+ }
+
+ if (wire.type() != tlv::pib::NameList)
+ throw tlv::Error("Unexpected TLV type when decoding PibNameList");
+
+ m_wire = wire;
+ m_wire.parse();
+ for (Block::element_const_iterator it = m_wire.elements_begin();
+ it != m_wire.elements_end(); it++) {
+ if (it->type() == tlv::Name) {
+ Name name;
+ name.wireDecode(*it);
+ m_names.push_back(name);
+ }
+ }
+}
+
+PibError::PibError()
+ : m_errCode(ERR_SUCCESS)
+{
+}
+
+PibError::PibError(const pib::ErrCode errCode, const std::string& msg)
+ : m_errCode(errCode)
+ , m_msg(msg)
+{
+}
+
+PibError::PibError(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+template<bool T>
+size_t
+PibError::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+ totalLength += prependByteArrayBlock(block, tlv::pib::Bytes,
+ reinterpret_cast<const uint8_t*>(m_msg.c_str()),
+ m_msg.size());
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::ErrorCode, m_errCode);
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::Error);
+ return totalLength;
+}
+
+template size_t
+PibError::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+PibError::wireEncode<false>(EncodingImpl<false>& block) const;
+
+
+const Block&
+PibError::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+PibError::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw tlv::Error("The supplied block does not contain wire format");
+ }
+
+ if (wire.type() != tlv::pib::Error)
+ throw tlv::Error("Unexpected TLV type when decoding Error");
+
+ m_wire = wire;
+ m_wire.parse();
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::ErrorCode) {
+ m_errCode = static_cast<pib::ErrCode>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw tlv::Error("PibError requires the first sub-TLV to be ErrorCode");
+
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::Bytes) {
+ m_msg = string(reinterpret_cast<const char*>(it->value()), it->value_size());
+ it++;
+ }
+ else
+ throw tlv::Error("PibError requires the second sub-TLV to be Bytes");
+}
+
+PibUser::PibUser()
+{
+}
+
+PibUser::PibUser(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+void
+PibUser::setMgmtCert(const IdentityCertificate& mgmtCert)
+{
+ m_wire.reset();
+ m_mgmtCert = mgmtCert;
+}
+
+void
+PibUser::setTpmLocator(const std::string& tpmLocator)
+{
+ m_wire.reset();
+ m_tpmLocator = tpmLocator;
+}
+
+template<bool T>
+size_t
+PibUser::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ if (!m_tpmLocator.empty())
+ totalLength = prependByteArrayBlock(block, tlv::pib::TpmLocator,
+ reinterpret_cast<const uint8_t*>(m_tpmLocator.c_str()),
+ m_tpmLocator.size());
+
+ totalLength += prependBlock(block, m_mgmtCert.wireEncode());
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::User);
+
+ return totalLength;
+}
+
+template size_t
+PibUser::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+PibUser::wireEncode<false>(EncodingImpl<false>& block) const;
+
+
+const Block&
+PibUser::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+PibUser::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw tlv::Error("The supplied block does not contain wire format");
+ }
+
+ if (wire.type() != tlv::pib::User)
+ throw tlv::Error("Unexpected TLV type when decoding Content");
+
+ m_wire = wire;
+ m_wire.parse();
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+ if (it != m_wire.elements_end() && it->type() == tlv::Data) {
+ m_mgmtCert.wireDecode(*it);
+ it++;
+ }
+ else
+ throw tlv::Error("PibError requires the first sub-TLV to be Data");
+
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::TpmLocator) {
+ m_tpmLocator = string(reinterpret_cast<const char*>(it->value()), it->value_size());
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/encoding/pib-encoding.hpp b/tools/pib/encoding/pib-encoding.hpp
new file mode 100644
index 0000000..9ebb4c4
--- /dev/null
+++ b/tools/pib/encoding/pib-encoding.hpp
@@ -0,0 +1,316 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_PIB_ENCODING_HPP
+#define NDN_PIB_PIB_ENCODING_HPP
+
+#include "pib-common.hpp"
+#include <ndn-cxx/security/identity-certificate.hpp>
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief Abstraction of pib::Identity TLV.
+ *
+ * This class is copyable since it is used by a variety of pib parameters
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Query-Responses
+ */
+class PibIdentity
+{
+public:
+ PibIdentity();
+
+ explicit
+ PibIdentity(const Name& identity);
+
+ explicit
+ PibIdentity(const Block& wire);
+
+ const Name&
+ getIdentity() const
+ {
+ return m_identity;
+ }
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode PibIdentity from a wire encoded block
+ *
+ * @throws tlv::Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+private:
+ Name m_identity;
+
+ mutable Block m_wire;
+};
+
+/**
+ * @brief Abstraction of pib::PublicKey TLV.
+ *
+ * This class is copyable since it is used by a variety of pib parameters
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Query-Responses
+ */
+class PibPublicKey
+{
+public:
+ PibPublicKey();
+
+ PibPublicKey(const Name& keyName, const PublicKey& key);
+
+ explicit
+ PibPublicKey(const Block& wire);
+
+ const Name&
+ getKeyName() const;
+
+ const PublicKey&
+ getPublicKey() const;
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode PibPublicKey from a wire encoded block
+ *
+ * @throws tlv::Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+private:
+ bool m_isValueSet;
+ Name m_keyName;
+ PublicKey m_key;
+
+ mutable Block m_wire;
+};
+
+/**
+ * @brief Abstraction of pib::Certificate TLV.
+ *
+ * This class is copyable since it is used by a variety of pib parameters
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Query-Responses
+ */
+class PibCertificate
+{
+public:
+ PibCertificate();
+
+ explicit
+ PibCertificate(const IdentityCertificate& certificate);
+
+ explicit
+ PibCertificate(const Block& wire);
+
+ const IdentityCertificate&
+ getCertificate() const;
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode PibCertificate from a wire encoded block
+ *
+ * @throws tlv::Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+private:
+ bool m_isValueSet;
+ IdentityCertificate m_certificate;
+
+ mutable Block m_wire;
+};
+
+/**
+ * @brief Abstraction of pib::NameList TLV.
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#List-Parameters
+ */
+class PibNameList : noncopyable
+{
+public:
+ PibNameList();
+
+ explicit
+ PibNameList(const std::vector<Name>& names);
+
+ explicit
+ PibNameList(const Block& wire);
+
+ const std::vector<Name>&
+ getNameList() const
+ {
+ return m_names;
+ }
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode PibCertificate from a wire encoded block
+ *
+ * @throws tlv::Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+private:
+ std::vector<Name> m_names;
+
+ mutable Block m_wire;
+};
+
+/**
+ * @brief Abstraction of pib::Error TLV.
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Query-Responses
+ */
+class PibError : noncopyable
+{
+public:
+ PibError();
+
+ explicit
+ PibError(const pib::ErrCode errCode, const std::string& msg = "");
+
+ explicit
+ PibError(const Block& wire);
+
+ pib::ErrCode
+ getErrorCode() const
+ {
+ return m_errCode;
+ }
+
+ const std::string&
+ getErrorMsg() const
+ {
+ return m_msg;
+ }
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode PibCertificate from a wire encoded block
+ *
+ * @throws tlv::Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+private:
+ pib::ErrCode m_errCode;
+ std::string m_msg;
+
+ mutable Block m_wire;
+};
+
+/**
+ * @brief Abstraction of pib::User TLV.
+ *
+ * This class is copyable since it is used by a variety of pib parameters
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Query-Responses
+ */
+class PibUser
+{
+public:
+ PibUser();
+
+ explicit
+ PibUser(const Block& wire);
+
+ void
+ setMgmtCert(const IdentityCertificate& mgmtCert);
+
+ const IdentityCertificate&
+ getMgmtCert() const
+ {
+ return m_mgmtCert;
+ }
+
+ void
+ setTpmLocator(const std::string& tpmLocator);
+
+ const std::string&
+ getTpmLocator() const
+ {
+ return m_tpmLocator;
+ }
+
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode PibCertificate from a wire encoded block
+ *
+ * @throws tlv::Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+private:
+ IdentityCertificate m_mgmtCert;
+ std::string m_tpmLocator;
+
+ mutable Block m_wire;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_PIB_ENCODING_HPP
diff --git a/tools/pib/encoding/update-param.cpp b/tools/pib/encoding/update-param.cpp
new file mode 100644
index 0000000..71a6602
--- /dev/null
+++ b/tools/pib/encoding/update-param.cpp
@@ -0,0 +1,235 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "update-param.hpp"
+#include <ndn-cxx/encoding/block-helpers.hpp>
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+static_assert(std::is_base_of<tlv::Error, UpdateParam::Error>::value,
+ "UpdateParam::Error must inherit from tlv::Error");
+
+const std::string UpdateParam::VERB("update");
+
+UpdateParam::UpdateParam()
+ : m_defaultOpt(DEFAULT_OPT_NO)
+{
+}
+
+UpdateParam::UpdateParam(const PibUser& user)
+ : m_entityType(tlv::pib::User)
+ , m_user(user)
+ , m_defaultOpt(DEFAULT_OPT_NO)
+{
+}
+
+UpdateParam::UpdateParam(const Name& identity, DefaultOpt defaultOpt)
+ : m_entityType(tlv::pib::Identity)
+ , m_identity(identity)
+ , m_defaultOpt(defaultOpt)
+{
+}
+
+UpdateParam::UpdateParam(const Name& keyName, const PublicKey& key, DefaultOpt defaultOpt)
+ : m_entityType(tlv::pib::PublicKey)
+ , m_key(keyName, key)
+ , m_defaultOpt(defaultOpt)
+{
+}
+
+UpdateParam::UpdateParam(const IdentityCertificate& certificate, DefaultOpt defaultOpt)
+ : m_entityType(tlv::pib::Certificate)
+ , m_certificate(certificate)
+ , m_defaultOpt(defaultOpt)
+{
+}
+
+UpdateParam::UpdateParam(const Block& wire)
+{
+ wireDecode(wire);
+}
+
+const PibUser&
+UpdateParam::getUser() const
+{
+ if (m_entityType == tlv::pib::User)
+ return m_user;
+ else
+ throw Error("UpdateParam::getUser: entityType must be User");
+}
+
+const PibIdentity&
+UpdateParam::getIdentity() const
+{
+ if (m_entityType == tlv::pib::Identity)
+ return m_identity;
+ else
+ throw Error("UpdateParam::getIdentity: entityType must be Identity");
+}
+
+const PibPublicKey&
+UpdateParam::getPublicKey() const
+{
+ if (m_entityType == tlv::pib::PublicKey)
+ return m_key;
+ else
+ throw Error("UpdateParam::getPublicKey: entityType must be PublicKey");
+}
+
+const PibCertificate&
+UpdateParam::getCertificate() const
+{
+ if (m_entityType == tlv::pib::Certificate)
+ return m_certificate;
+ else
+ throw Error("UpdateParam::getCertificate: entityType must be Certificate");
+}
+
+template<bool T>
+size_t
+UpdateParam::wireEncode(EncodingImpl<T>& block) const
+{
+ size_t totalLength = 0;
+
+ totalLength += prependNonNegativeIntegerBlock(block, tlv::pib::DefaultOpt, m_defaultOpt);
+
+ // Encode Entity
+ switch (m_entityType) {
+ case tlv::pib::Identity:
+ {
+ totalLength += m_identity.wireEncode(block);
+ break;
+ }
+ case tlv::pib::PublicKey:
+ {
+ totalLength += m_key.wireEncode(block);
+ break;
+ }
+ case tlv::pib::Certificate:
+ {
+ totalLength += m_certificate.wireEncode(block);
+ break;
+ }
+ case tlv::pib::User:
+ {
+ totalLength += m_user.wireEncode(block);
+ break;
+ }
+ default:
+ throw Error("UpdateParam::wireEncode: unsupported entity type: " +
+ boost::lexical_cast<std::string>(m_entityType));
+ }
+
+ totalLength += block.prependVarNumber(totalLength);
+ totalLength += block.prependVarNumber(tlv::pib::UpdateParam);
+
+ return totalLength;
+}
+
+template size_t
+UpdateParam::wireEncode<true>(EncodingImpl<true>& block) const;
+
+template size_t
+UpdateParam::wireEncode<false>(EncodingImpl<false>& block) const;
+
+const Block&
+UpdateParam::wireEncode() const
+{
+ if (m_wire.hasWire())
+ return m_wire;
+
+ EncodingEstimator estimator;
+ size_t estimatedSize = wireEncode(estimator);
+
+ EncodingBuffer buffer(estimatedSize, 0);
+ wireEncode(buffer);
+
+ m_wire = buffer.block();
+ return m_wire;
+}
+
+void
+UpdateParam::wireDecode(const Block& wire)
+{
+ if (!wire.hasWire()) {
+ throw Error("The supplied block does not contain wire format");
+ }
+
+ m_wire = wire;
+ m_wire.parse();
+
+ if (m_wire.type() != tlv::pib::UpdateParam)
+ throw Error("Unexpected TLV type when decoding UpdateParam");
+
+ Block::element_const_iterator it = m_wire.elements_begin();
+
+ // the first block must be Entity
+ if (it != m_wire.elements_end()) {
+ switch (it->type()) {
+ case tlv::pib::Identity:
+ {
+ m_entityType = tlv::pib::Identity;
+ m_identity.wireDecode(*it);
+ break;
+ }
+ case tlv::pib::PublicKey:
+ {
+ m_entityType = tlv::pib::PublicKey;
+ m_key.wireDecode(*it);
+ break;
+ }
+ case tlv::pib::Certificate:
+ {
+ m_entityType = tlv::pib::Certificate;
+ m_certificate.wireDecode(*it);
+ break;
+ }
+ case tlv::pib::User:
+ {
+ m_entityType = tlv::pib::User;
+ m_user.wireDecode(*it);
+ break;
+ }
+ default:
+ throw Error("The first sub-TLV of UpdateParam is not an entity type");
+ }
+
+ it++;
+ }
+ else
+ throw Error("UpdateParam requires the first sub-TLV to be an entity type");
+
+ // the second block must be DefaultOpt
+ if (it != m_wire.elements_end() && it->type() == tlv::pib::DefaultOpt) {
+ m_defaultOpt = static_cast<pib::DefaultOpt>(readNonNegativeInteger(*it));
+ it++;
+ }
+ else
+ throw Error("UpdateParam requires the second sub-TLV to be DefaultOpt");
+
+ if (it != m_wire.elements_end())
+ throw Error("UpdateParam must not contain more than two sub-TLVs");
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/encoding/update-param.hpp b/tools/pib/encoding/update-param.hpp
new file mode 100644
index 0000000..6a6e5ba
--- /dev/null
+++ b/tools/pib/encoding/update-param.hpp
@@ -0,0 +1,136 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_UPDATE_PARAM_HPP
+#define NDN_PIB_UPDATE_PARAM_HPP
+
+#include "pib-common.hpp"
+#include "pib-encoding.hpp"
+#include <ndn-cxx/name.hpp>
+#include <ndn-cxx/security/identity-certificate.hpp>
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief UpdateParam is the abstraction of PIB Update parameter.
+ *
+ * PibUpdateParam := PIB-UPDATE-PARAM-TYPE TLV-LENGTH
+ * (PibIdentity | PibPublicKey | PibCertificate)
+ * PibDefaultOpt
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base#Update-Parameters
+ */
+
+class UpdateParam : noncopyable
+{
+public:
+ class Error : public tlv::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : tlv::Error(what)
+ {
+ }
+ };
+
+ UpdateParam();
+
+ explicit
+ UpdateParam(const PibUser& user);
+
+ explicit
+ UpdateParam(const Name& identity, DefaultOpt defaultOpt = DEFAULT_OPT_NO);
+
+ UpdateParam(const Name& keyName, const PublicKey& key, DefaultOpt defaultOpt = DEFAULT_OPT_NO);
+
+ explicit
+ UpdateParam(const IdentityCertificate& certificate, DefaultOpt defaultOpt = DEFAULT_OPT_NO);
+
+ explicit
+ UpdateParam(const Block& wire);
+
+ tlv::pib::ParamType
+ getParamType() const
+ {
+ return tlv::pib::UpdateParam;
+ }
+
+ tlv::pib::EntityType
+ getEntityType() const
+ {
+ return m_entityType;
+ }
+
+ const PibUser&
+ getUser() const;
+
+ const PibIdentity&
+ getIdentity() const;
+
+ const PibPublicKey&
+ getPublicKey() const;
+
+ const PibCertificate&
+ getCertificate() const;
+
+ pib::DefaultOpt
+ getDefaultOpt() const
+ {
+ return m_defaultOpt;
+ }
+
+ /// @brief Encode to a wire format or estimate wire format
+ template<bool T>
+ size_t
+ wireEncode(EncodingImpl<T>& block) const;
+
+ /// @brief Encode to a wire format
+ const Block&
+ wireEncode() const;
+
+ /**
+ * @brief Decode GetParam from a wire encoded block
+ *
+ * @throws Error if decoding fails
+ */
+ void
+ wireDecode(const Block& wire);
+
+public:
+ static const std::string VERB;
+
+private:
+ tlv::pib::EntityType m_entityType;
+ PibUser m_user;
+ PibIdentity m_identity;
+ PibPublicKey m_key;
+ PibCertificate m_certificate;
+ pib::DefaultOpt m_defaultOpt;
+
+ mutable Block m_wire;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_UPDATE_PARAM_HPP
diff --git a/tools/pib/get-query-processor.cpp b/tools/pib/get-query-processor.cpp
new file mode 100644
index 0000000..bc22747
--- /dev/null
+++ b/tools/pib/get-query-processor.cpp
@@ -0,0 +1,132 @@
+/* -*- 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 "get-query-processor.hpp"
+#include "encoding/pib-encoding.hpp"
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+const Name GetQueryProcessor::PIB_PREFIX("/localhost/pib");
+const size_t GetQueryProcessor::GET_QUERY_LENGTH = 5;
+
+GetQueryProcessor::GetQueryProcessor(PibDb& db)
+ : m_db(db)
+{
+}
+
+std::pair<bool, Block>
+GetQueryProcessor::operator()(const Interest& interest)
+{
+ const Name& interestName = interest.getName();
+
+ // handle pib query: /localhost/pib/[UserName]/get/param
+ if (interestName.size() != GET_QUERY_LENGTH) {
+ // malformed interest, discard
+ return std::make_pair(false, Block());
+ }
+
+ GetParam param;
+
+ try {
+ param.wireDecode(interestName.get(OFFSET_PARAM).blockFromValue());
+ }
+ catch (const tlv::Error& e) {
+ PibError error(ERR_WRONG_PARAM, "error in parsing param: " + std::string(e.what()));
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ switch (param.getTargetType()) {
+ case TYPE_ID:
+ return processGetIdQuery(param);
+ case TYPE_KEY:
+ return processGetKeyQuery(param);
+ case TYPE_CERT:
+ return processGetCertQuery(param);
+ case TYPE_USER:
+ if (interest.getName().get(2).toUri() != m_db.getOwnerName())
+ return std::make_pair(false, Block());
+ else
+ return processGetUserQuery(param);
+ default:
+ {
+ PibError error(ERR_WRONG_PARAM, "requested type is not supported:" +
+ boost::lexical_cast<std::string>(param.getTargetType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+}
+
+std::pair<bool, Block>
+GetQueryProcessor::processGetIdQuery(const GetParam& param)
+{
+ if (!m_db.hasIdentity(param.getTargetName())) {
+ PibError error(ERR_NON_EXISTING_ID, "requested id does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ PibIdentity result(param.getTargetName());
+ return std::make_pair(true, result.wireEncode());
+}
+
+std::pair<bool, Block>
+GetQueryProcessor::processGetKeyQuery(const GetParam& param)
+{
+ if (param.getTargetName().empty()) {
+ PibError error(ERR_WRONG_PARAM, "key name does not have id-component");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ shared_ptr<PublicKey> key = m_db.getKey(param.getTargetName());
+ if (key == nullptr) {
+ PibError error(ERR_NON_EXISTING_KEY, "requested key does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ PibPublicKey result(param.getTargetName(), *key);
+ return std::make_pair(true, result.wireEncode());
+}
+
+std::pair<bool, Block>
+GetQueryProcessor::processGetCertQuery(const GetParam& param)
+{
+ shared_ptr<IdentityCertificate> certificate = m_db.getCertificate(param.getTargetName());
+ if (certificate == nullptr) {
+ PibError error(ERR_NON_EXISTING_CERT, "requested certificate does not exist");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ PibCertificate result(*certificate);
+ return std::make_pair(true, result.wireEncode());
+}
+
+std::pair<bool, Block>
+GetQueryProcessor::processGetUserQuery(const GetParam& param)
+{
+ PibUser result;
+ result.setMgmtCert(*m_db.getMgmtCertificate());
+ result.setTpmLocator(m_db.getTpmLocator());
+ return std::make_pair(true, result.wireEncode());
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/get-query-processor.hpp b/tools/pib/get-query-processor.hpp
new file mode 100644
index 0000000..f4eca40
--- /dev/null
+++ b/tools/pib/get-query-processor.hpp
@@ -0,0 +1,82 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_GET_QUERY_PROCESSOR_HPP
+#define NDN_PIB_GET_QUERY_PROCESSOR_HPP
+
+#include "pib-db.hpp"
+#include "encoding/get-param.hpp"
+#include <ndn-cxx/interest.hpp>
+#include <utility>
+
+namespace ndn {
+namespace pib {
+
+/// @brief implements the PIB service
+class GetQueryProcessor : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param db The pib database.
+ * @param owner Owner of the pib database.
+ */
+ explicit
+ GetQueryProcessor(PibDb& db);
+
+ std::pair<bool, Block>
+ operator()(const Interest& interest);
+
+private:
+ std::pair<bool, Block>
+ processGetUserQuery(const GetParam& param);
+
+ std::pair<bool, Block>
+ processGetIdQuery(const GetParam& param);
+
+ std::pair<bool, Block>
+ processGetKeyQuery(const GetParam& param);
+
+ std::pair<bool, Block>
+ processGetCertQuery(const GetParam& param);
+
+private:
+ static const Name PIB_PREFIX;
+ static const size_t GET_QUERY_LENGTH;
+
+ const PibDb& m_db;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_GET_QUERY_PROCESSOR_HPP
diff --git a/tools/pib/key-cache.cpp b/tools/pib/key-cache.cpp
new file mode 100644
index 0000000..431e635
--- /dev/null
+++ b/tools/pib/key-cache.cpp
@@ -0,0 +1,106 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "key-cache.hpp"
+
+namespace ndn {
+namespace pib {
+
+KeyCacheEntry::KeyCacheEntry(const Name& name, shared_ptr<PublicKey> key)
+ : name(name)
+ , key(key)
+{
+ BOOST_ASSERT(static_cast<bool>(key));
+}
+
+KeyCache::KeyCache(size_t capacity)
+ : m_capacity(capacity)
+{
+}
+
+void
+KeyCache::insert(const Name& name, shared_ptr<PublicKey> key)
+{
+ // check if key exist
+ KeyContainer::index<byName>::type::iterator it = m_keys.get<byName>().find(name);
+ if (it != m_keys.get<byName>().end()) {
+ adjustLru(it);
+ return;
+ }
+
+ // evict key when capacity is reached
+ if (size() >= m_capacity)
+ evictKey();
+
+ // insert entry
+ m_keys.insert(KeyCacheEntry(name, key));
+}
+
+shared_ptr<PublicKey>
+KeyCache::find(const Name& name) const
+{
+ // check if key exist
+ KeyContainer::index<byName>::type::iterator it = m_keys.get<byName>().find(name);
+ if (it == m_keys.get<byName>().end())
+ return shared_ptr<PublicKey>();
+ else {
+ // adjust lru
+ shared_ptr<PublicKey> key = it->key;
+ adjustLru(it);
+ return key;
+ }
+}
+
+void
+KeyCache::erase(const Name& name)
+{
+ // check if key exist
+ KeyContainer::index<byName>::type::iterator it = m_keys.get<byName>().find(name);
+ if (it != m_keys.get<byName>().end()) {
+ m_keys.erase(it);
+ }
+}
+
+size_t
+KeyCache::size() const
+{
+ return m_keys.size();
+}
+
+void
+KeyCache::evictKey()
+{
+ if (!m_keys.get<byUsedTime>().empty()) {
+ KeyContainer::index<byUsedTime>::type::iterator it = m_keys.get<byUsedTime>().begin();
+ m_keys.erase(m_keys.project<0>(it));
+ }
+}
+
+void
+KeyCache::adjustLru(KeyContainer::iterator it) const
+{
+ KeyCacheEntry entry = std::move(*it);
+ m_keys.erase(it);
+ m_keys.insert(entry);
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/key-cache.hpp b/tools/pib/key-cache.hpp
new file mode 100644
index 0000000..5df077a
--- /dev/null
+++ b/tools/pib/key-cache.hpp
@@ -0,0 +1,108 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_KEY_CACHE_HPP
+#define NDN_PIB_KEY_CACHE_HPP
+
+#include <ndn-cxx/name.hpp>
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/security/public-key.hpp>
+
+#include <stack>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index/key_extractors.hpp>
+
+namespace ndn {
+namespace pib {
+
+struct KeyCacheEntry
+{
+ KeyCacheEntry(const Name& name, shared_ptr<PublicKey> key);
+
+ Name name;
+ shared_ptr<PublicKey> key;
+};
+
+class byName;
+class byUsedTime;
+
+typedef boost::multi_index::multi_index_container<
+ KeyCacheEntry,
+ boost::multi_index::indexed_by<
+ boost::multi_index::hashed_unique<
+ boost::multi_index::tag<byName>,
+ boost::multi_index::member<KeyCacheEntry, Name, &KeyCacheEntry::name>,
+ std::hash<Name>
+ >,
+
+ boost::multi_index::sequenced<
+ boost::multi_index::tag<byUsedTime>
+ >
+ >
+> KeyContainer;
+
+class KeyCache : noncopyable
+{
+public:
+ explicit
+ KeyCache(size_t capacity = getDefaultCapacity());
+
+ void
+ insert(const Name& name, shared_ptr<PublicKey> key);
+
+ shared_ptr<PublicKey>
+ find(const Name& name) const;
+
+ void
+ erase(const Name& name);
+
+ size_t
+ size() const;
+
+private:
+ static size_t
+ getDefaultCapacity()
+ {
+ return 100;
+ }
+
+ void
+ evictKey();
+
+ void
+ adjustLru(KeyContainer::iterator it) const;
+
+ void
+ freeEntry(KeyContainer::iterator it);
+
+private:
+ size_t m_capacity;
+ mutable KeyContainer m_keys;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_KEY_CACHE_HPP
diff --git a/tools/pib/list-query-processor.cpp b/tools/pib/list-query-processor.cpp
new file mode 100644
index 0000000..ad4e2d5
--- /dev/null
+++ b/tools/pib/list-query-processor.cpp
@@ -0,0 +1,98 @@
+/* -*- 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 "list-query-processor.hpp"
+#include "encoding/pib-encoding.hpp"
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+using std::string;
+using std::vector;
+
+const size_t ListQueryProcessor::LIST_QUERY_LENGTH = 5;
+
+ListQueryProcessor::ListQueryProcessor(PibDb& db)
+ : m_db(db)
+{
+}
+
+std::pair<bool, Block>
+ListQueryProcessor::operator()(const Interest& interest)
+{
+ const Name& interestName = interest.getName();
+
+ // handle pib query: /localhost/pib/[UserName]/list/param
+ if (interestName.size() != MIN_PIB_INTEREST_SIZE) {
+ // malformed interest, discard
+ return std::make_pair(false, Block());
+ }
+
+ ListParam param;
+
+ try {
+ param.wireDecode(interestName.get(OFFSET_PARAM).blockFromValue());
+ }
+ catch (const tlv::Error& e) {
+ PibError error(ERR_WRONG_PARAM, "error in parsing param: " + string(e.what()));
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ vector<Name> nameList;
+ switch (param.getOriginType()) {
+ case TYPE_USER:
+ {
+ nameList = m_db.listIdentities();
+ break;
+ }
+ case TYPE_ID:
+ {
+ nameList = m_db.listKeyNamesOfIdentity(param.getOriginName());
+ break;
+ }
+ case TYPE_KEY:
+ {
+ const Name& keyName = param.getOriginName();
+ if (keyName.empty()) {
+ PibError error(ERR_WRONG_PARAM,
+ "key name must contain key id component");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ nameList = m_db.listCertNamesOfKey(keyName);
+ break;
+ }
+ default:
+ {
+ PibError error(ERR_WRONG_PARAM,
+ "origin type is not supported: " +
+ boost::lexical_cast<string>(param.getOriginType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+
+ PibNameList result(nameList);
+ return std::make_pair(true, result.wireEncode());
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/list-query-processor.hpp b/tools/pib/list-query-processor.hpp
new file mode 100644
index 0000000..4b814f7
--- /dev/null
+++ b/tools/pib/list-query-processor.hpp
@@ -0,0 +1,66 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_LIST_QUERY_PROCESSOR_HPP
+#define NDN_PIB_LIST_QUERY_PROCESSOR_HPP
+
+#include "pib-db.hpp"
+#include "encoding/list-param.hpp"
+#include <ndn-cxx/interest.hpp>
+#include <utility>
+
+namespace ndn {
+namespace pib {
+
+class ListQueryProcessor : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param db The pib database.
+ */
+ explicit
+ ListQueryProcessor(PibDb& db);
+
+ std::pair<bool, Block>
+ operator()(const Interest& interest);
+
+private:
+ static const size_t LIST_QUERY_LENGTH;
+
+ const PibDb& m_db;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_LIST_QUERY_PROCESSOR_HPP
diff --git a/tools/pib/ndn-pib.cpp b/tools/pib/ndn-pib.cpp
new file mode 100644
index 0000000..4166bd8
--- /dev/null
+++ b/tools/pib/ndn-pib.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.hpp"
+
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/util/config-file.hpp>
+#include <ndn-cxx/security/key-chain.hpp>
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/filesystem.hpp>
+
+namespace ndn {
+namespace pib {
+
+int
+main(int argc, char** argv)
+{
+ namespace po = boost::program_options;
+ namespace fs = boost::filesystem;
+
+ std::string owner;
+ std::string dbDir;
+ std::string tpmLocator;
+ Face face;
+
+ std::cerr << "hello" << std::endl;
+
+ po::options_description description(
+ "General Usage\n"
+ " ndn-pib [-h] -o owner -d database_dir -t tpm_locator\n"
+ "General options");
+
+ description.add_options()
+ ("help,h", "produce help message")
+ ("owner,o", po::value<std::string>(&owner),
+ "Name of the owner, PIB will listen to /localhost/pib/[owner].")
+ ("database,d", po::value<std::string>(&dbDir),
+ "Absolute path to the directory of PIB database, /<database_dir>/pib.db")
+ ("tpm,t", po::value<std::string>(&tpmLocator),
+ "URI of the tpm. e.g., tpm-file:/var")
+ ;
+
+ po::variables_map vm;
+ try {
+ po::store(po::parse_command_line(argc, argv, description), vm);
+ po::notify(vm);
+ }
+ catch (const std::exception& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ std::cerr << description << std::endl;
+ return 1;
+ }
+
+ if (vm.count("help") != 0) {
+ std::cerr << description << std::endl;
+ return 0;
+ }
+
+ try {
+ if (vm.count("owner") == 0 && vm.count("database") == 0 && vm.count("tpm") == 0) {
+ if (std::getenv("HOME")) {
+ fs::path pibDir(std::getenv("HOME"));
+ pibDir /= ".ndn/pib";
+ dbDir = pibDir.string();
+ }
+ else {
+ std::cerr << "ERROR: HOME variable is not set" << std::endl;
+ return 1;
+ }
+
+ tpmLocator = KeyChain::getDefaultTpmLocator();
+
+ if (std::getenv("USER")) {
+ owner = std::string(std::getenv("USER"));
+ }
+ else {
+ std::cerr << "ERROR: HOME variable is not set" << std::endl;
+ return 1;
+ }
+ }
+ else if (vm.count("owner") == 0 || vm.count("database") == 0 ||
+ vm.count("tpm") == 0) {
+ std::cerr << description << std::endl;
+ return 1;
+ }
+
+ Pib pib(face, dbDir, tpmLocator, owner);
+ face.processEvents();
+ }
+ catch (std::runtime_error& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl;
+ return 1;
+ }
+
+
+ return 0;
+}
+
+} // namespace pib
+} // namespace ndn
+
+int
+main(int argc, char** argv)
+{
+ ndn::pib::main(argc, argv);
+}
diff --git a/tools/pib/pib-db.cpp b/tools/pib/pib-db.cpp
new file mode 100644
index 0000000..0e2ce87
--- /dev/null
+++ b/tools/pib/pib-db.cpp
@@ -0,0 +1,825 @@
+/* -*- 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-db.hpp"
+#include <sqlite3.h>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+
+namespace ndn {
+namespace pib {
+
+using std::string;
+using std::vector;
+using std::set;
+
+const Name PibDb::NON_EXISTING_IDENTITY("/localhost/reserved/non-existing-identity");
+const Name PibDb::NON_EXISTING_KEY("/localhost/reserved/non-existing-key");
+const Name PibDb::NON_EXISTING_CERTIFICATE("/localhost/reserved/non-existing-certificate");
+
+const Name PibDb::LOCALHOST_PIB("/localhost/pib");
+const name::Component PibDb::MGMT_LABEL("mgmt");
+
+
+static const string INITIALIZATION =
+ "CREATE TABLE IF NOT EXISTS \n"
+ " mgmt( \n"
+ " id INTEGER PRIMARY KEY,\n"
+ " owner BLOB NOT NULL, \n"
+ " tpm_locator BLOB, \n"
+ " local_management_cert BLOB NOT NULL \n"
+ " ); \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " mgmt_insert_trigger \n"
+ " BEFORE INSERT ON mgmt \n"
+ " FOR EACH ROW \n"
+ " BEGIN \n"
+ " DELETE FROM mgmt; \n"
+ " END; \n"
+ " \n"
+ "CREATE TABLE IF NOT EXISTS \n"
+ " identities( \n"
+ " id INTEGER PRIMARY KEY,\n"
+ " identity BLOB NOT NULL, \n"
+ " is_default INTEGER DEFAULT 0 \n"
+ " ); \n"
+ "CREATE UNIQUE INDEX IF NOT EXISTS \n"
+ " identityIndex ON identities(identity); \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " identity_default_before_insert_trigger \n"
+ " BEFORE INSERT ON identities \n"
+ " FOR EACH ROW \n"
+ " WHEN NEW.is_default=1 \n"
+ " BEGIN \n"
+ " UPDATE identities SET is_default=0; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " identity_default_after_insert_trigger \n"
+ " AFTER INSERT ON identities \n"
+ " FOR EACH ROW \n"
+ " WHEN NOT EXISTS \n"
+ " (SELECT id \n"
+ " FROM identities \n"
+ " WHERE is_default=1) \n"
+ " BEGIN \n"
+ " UPDATE identities \n"
+ " SET is_default=1 \n"
+ " WHERE identity=NEW.identity; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " identity_default_update_trigger \n"
+ " BEFORE UPDATE ON identities \n"
+ " FOR EACH ROW \n"
+ " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
+ " BEGIN \n"
+ " UPDATE identities SET is_default=0; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " identity_delete_trigger \n"
+ " AFTER DELETE ON identities \n"
+ " FOR EACH ROW \n"
+ " BEGIN \n"
+ " SELECT identityDeleted (OLD.identity); \n"
+ " END; \n"
+ " \n"
+ "CREATE TABLE IF NOT EXISTS \n"
+ " keys( \n"
+ " id INTEGER PRIMARY KEY,\n"
+ " identity_id INTEGER NOT NULL, \n"
+ " key_name BLOB NOT NULL, \n"
+ " key_type INTEGER NOT NULL, \n"
+ " key_bits BLOB NOT NULL, \n"
+ " is_default INTEGER DEFAULT 0, \n"
+ " FOREIGN KEY(identity_id) \n"
+ " REFERENCES identities(id) \n"
+ " ON DELETE CASCADE \n"
+ " ON UPDATE CASCADE \n"
+ " ); \n"
+ "CREATE UNIQUE INDEX IF NOT EXISTS \n"
+ " keyIndex ON keys(key_name); \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " key_default_before_insert_trigger \n"
+ " BEFORE INSERT ON keys \n"
+ " FOR EACH ROW \n"
+ " WHEN NEW.is_default=1 \n"
+ " BEGIN \n"
+ " UPDATE keys \n"
+ " SET is_default=0 \n"
+ " WHERE identity_id=NEW.identity_id; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " key_default_after_insert_trigger \n"
+ " AFTER INSERT ON keys \n"
+ " FOR EACH ROW \n"
+ " WHEN NOT EXISTS \n"
+ " (SELECT id \n"
+ " FROM keys \n"
+ " WHERE is_default=1 \n"
+ " AND identity_id=NEW.identity_id) \n"
+ " BEGIN \n"
+ " UPDATE keys \n"
+ " SET is_default=1 \n"
+ " WHERE key_name=NEW.key_name; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " key_default_update_trigger \n"
+ " BEFORE UPDATE ON keys \n"
+ " FOR EACH ROW \n"
+ " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
+ " BEGIN \n"
+ " UPDATE keys \n"
+ " SET is_default=0 \n"
+ " WHERE identity_id=NEW.identity_id; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " key_delete_trigger \n"
+ " AFTER DELETE ON keys \n"
+ " FOR EACH ROW \n"
+ " BEGIN \n"
+ " SELECT keyDeleted (OLD.key_name); \n"
+ " END; \n"
+ " \n"
+ "CREATE TABLE IF NOT EXISTS \n"
+ " certificates( \n"
+ " id INTEGER PRIMARY KEY,\n"
+ " key_id INTEGER NOT NULL, \n"
+ " certificate_name BLOB NOT NULL, \n"
+ " certificate_data BLOB NOT NULL, \n"
+ " is_default INTEGER DEFAULT 0, \n"
+ " FOREIGN KEY(key_id) \n"
+ " REFERENCES keys(id) \n"
+ " ON DELETE CASCADE \n"
+ " ON UPDATE CASCADE \n"
+ " ); \n"
+ "CREATE UNIQUE INDEX IF NOT EXISTS \n"
+ " certIndex ON certificates(certificate_name);\n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " cert_default_before_insert_trigger \n"
+ " BEFORE INSERT ON certificates \n"
+ " FOR EACH ROW \n"
+ " WHEN NEW.is_default=1 \n"
+ " BEGIN \n"
+ " UPDATE certificates \n"
+ " SET is_default=0 \n"
+ " WHERE key_id=NEW.key_id; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " cert_default_after_insert_trigger \n"
+ " AFTER INSERT ON certificates \n"
+ " FOR EACH ROW \n"
+ " WHEN NOT EXISTS \n"
+ " (SELECT id \n"
+ " FROM certificates \n"
+ " WHERE is_default=1 \n"
+ " AND key_id=NEW.key_id) \n"
+ " BEGIN \n"
+ " UPDATE certificates \n"
+ " SET is_default=1 \n"
+ " WHERE certificate_name=NEW.certificate_name;\n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " cert_default_update_trigger \n"
+ " BEFORE UPDATE ON certificates \n"
+ " FOR EACH ROW \n"
+ " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
+ " BEGIN \n"
+ " UPDATE certificates \n"
+ " SET is_default=0 \n"
+ " WHERE key_id=NEW.key_id; \n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " cert_delete_trigger \n"
+ " AFTER DELETE ON certificates \n"
+ " FOR EACH ROW \n"
+ " BEGIN \n"
+ " SELECT certDeleted (OLD.certificate_name);\n"
+ " END; \n"
+ "CREATE TRIGGER IF NOT EXISTS \n"
+ " cert_insert_trigger \n"
+ " AFTER INSERT ON certificates \n"
+ " FOR EACH ROW \n"
+ " BEGIN \n"
+ " SELECT certInserted (NEW.certificate_name);\n"
+ " END; \n";
+
+
+/**
+ * A utility function to call the normal sqlite3_bind_text where the value and length are
+ * value.c_str() and value.size().
+ */
+static int
+sqlite3_bind_string(sqlite3_stmt* statement,
+ int index,
+ const string& value,
+ void(*destructor)(void*))
+{
+ return sqlite3_bind_text(statement, index, value.c_str(), value.size(), destructor);
+}
+
+/**
+ * A utility function to call the normal sqlite3_bind_blob where the value and length are
+ * block.wire() and block.size().
+ */
+static int
+sqlite3_bind_block(sqlite3_stmt* statement,
+ int index,
+ const Block& block,
+ void(*destructor)(void*))
+{
+ return sqlite3_bind_blob(statement, index, block.wire(), block.size(), destructor);
+}
+
+/**
+ * A utility function to generate string by calling the normal sqlite3_column_text.
+ */
+static string
+sqlite3_column_string(sqlite3_stmt* statement, int column)
+{
+ return string(reinterpret_cast<const char*>(sqlite3_column_text(statement, column)),
+ sqlite3_column_bytes(statement, column));
+}
+
+/**
+ * A utility function to generate block by calling the normal sqlite3_column_text.
+ */
+static Block
+sqlite3_column_block(sqlite3_stmt* statement, int column)
+{
+ return Block(sqlite3_column_blob(statement, column), sqlite3_column_bytes(statement, column));
+}
+
+PibDb::PibDb(const string& dbDir)
+{
+ // Determine the path of PIB DB
+ boost::filesystem::path dir;
+ if (dbDir == "") {
+ dir = boost::filesystem::path(getenv("HOME")) / ".ndn";
+ boost::filesystem::create_directories(dir);
+ }
+ else {
+ dir = boost::filesystem::path(dbDir);
+ boost::filesystem::create_directories(dir);
+ }
+ // Open PIB
+ int result = sqlite3_open_v2((dir / "pib.db").c_str(), &m_database,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+#ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
+ "unix-dotfile"
+#else
+ nullptr
+#endif
+ );
+
+ if (result != SQLITE_OK)
+ throw Error("PIB DB cannot be opened/created: " + dbDir);
+
+
+ // enable foreign key
+ sqlite3_exec(m_database, "PRAGMA foreign_keys = ON", nullptr, nullptr, nullptr);
+
+ // initialize PIB specific tables
+ char* errorMessage = nullptr;
+ result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
+ if (result != SQLITE_OK && errorMessage != nullptr) {
+ sqlite3_free(errorMessage);
+ throw Error("PIB DB cannot be initialized");
+ }
+
+ // create delete trigger functions
+ createDbDeleteTrigger();
+
+ getOwnerName();
+}
+
+void
+PibDb::createDbDeleteTrigger()
+{
+ int res = 0;
+
+ res = sqlite3_create_function(m_database, "identityDeleted", -1, SQLITE_UTF8,
+ reinterpret_cast<void*>(this),
+ PibDb::identityDeletedFun, nullptr, nullptr);
+ if (res != SQLITE_OK)
+ throw Error("Cannot create function ``identityDeleted''");
+
+ res = sqlite3_create_function(m_database, "keyDeleted", -1, SQLITE_UTF8,
+ reinterpret_cast<void*>(this),
+ PibDb::keyDeletedFun, nullptr, nullptr);
+ if (res != SQLITE_OK)
+ throw Error("Cannot create function ``keyDeleted''");
+
+ res = sqlite3_create_function(m_database, "certDeleted", -1, SQLITE_UTF8,
+ reinterpret_cast<void*>(this),
+ PibDb::certDeletedFun, nullptr, nullptr);
+ if (res != SQLITE_OK)
+ throw Error("Cannot create function ``certDeleted''");
+
+ res = sqlite3_create_function(m_database, "certInserted", -1, SQLITE_UTF8,
+ reinterpret_cast<void*>(this),
+ PibDb::certInsertedFun, nullptr, nullptr);
+ if (res != SQLITE_OK)
+ throw Error("Cannot create function ``certInserted''");
+}
+
+void
+PibDb::identityDeletedFun(sqlite3_context* context, int argc, sqlite3_value** argv)
+{
+ BOOST_ASSERT(argc == 1);
+
+ PibDb* pibDb = reinterpret_cast<PibDb*>(sqlite3_user_data(context));
+ Name identity(Block(sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0])));
+
+ pibDb->identityDeleted(identity);
+}
+
+void
+PibDb::keyDeletedFun(sqlite3_context* context, int argc, sqlite3_value** argv)
+{
+ BOOST_ASSERT(argc == 1);
+
+ PibDb* pibDb = reinterpret_cast<PibDb*>(sqlite3_user_data(context));
+ Name keyName(Block(sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0])));
+
+ pibDb->keyDeleted(keyName);
+}
+
+void
+PibDb::certDeletedFun(sqlite3_context* context, int argc, sqlite3_value** argv)
+{
+ BOOST_ASSERT(argc == 1);
+
+ PibDb* pibDb = reinterpret_cast<PibDb*>(sqlite3_user_data(context));
+ Name certName(Block(sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0])));
+
+ pibDb->certificateDeleted(certName);
+}
+
+void
+PibDb::certInsertedFun(sqlite3_context* context, int argc, sqlite3_value** argv)
+{
+ BOOST_ASSERT(argc == 1);
+
+ PibDb* pibDb = reinterpret_cast<PibDb*>(sqlite3_user_data(context));
+ Name certName(Block(sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0])));
+
+ pibDb->certificateInserted(certName);
+}
+
+void
+PibDb::updateMgmtCertificate(const IdentityCertificate& certificate)
+{
+ const Name& keyName = certificate.getPublicKeyName();
+
+ // Name of mgmt key should be "/localhost/pib/[UserName]/mgmt/[KeyID]"
+ if (keyName.size() != 5 ||
+ keyName.compare(0, 2, LOCALHOST_PIB) ||
+ keyName.get(3) != MGMT_LABEL)
+ throw Error("PibDb::updateMgmtCertificate: certificate does not follow the naming convention");
+
+ string owner = keyName.get(2).toUri();
+ sqlite3_stmt* statement;
+ if (!m_owner.empty()) {
+ if (m_owner != owner)
+ throw Error("PibDb::updateMgmtCertificate: owner name does not match");
+ else {
+ sqlite3_prepare_v2(m_database,
+ "UPDATE mgmt SET local_management_cert=? WHERE owner=?",
+ -1, &statement, nullptr);
+ }
+ }
+ else {
+ sqlite3_prepare_v2(m_database,
+ "INSERT INTO mgmt (local_management_cert, owner) VALUES (?, ?)",
+ -1, &statement, nullptr);
+ }
+
+ sqlite3_bind_block(statement, 1, certificate.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_bind_string(statement, 2, owner, SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ m_owner = owner;
+
+ mgmtCertificateChanged();
+}
+
+string
+PibDb::getOwnerName() const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database, "SELECT owner FROM mgmt", -1, &statement, nullptr);
+
+ if (sqlite3_step(statement) == SQLITE_ROW) {
+ m_owner = sqlite3_column_string(statement, 0);
+ }
+
+ sqlite3_finalize(statement);
+ return m_owner;
+}
+
+shared_ptr<IdentityCertificate>
+PibDb::getMgmtCertificate() const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database, "SELECT local_management_cert FROM mgmt", -1, &statement, nullptr);
+
+ shared_ptr<IdentityCertificate> certificate;
+ if (sqlite3_step(statement) == SQLITE_ROW) {
+ certificate = make_shared<IdentityCertificate>();
+ certificate->wireDecode(sqlite3_column_block(statement, 0));
+ }
+
+ sqlite3_finalize(statement);
+ return certificate;
+}
+
+void
+PibDb::setTpmLocator(const std::string& tpmLocator)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "UPDATE mgmt SET tpm_locator=? WHERE owner=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_string(statement, 1, tpmLocator, SQLITE_TRANSIENT);
+ sqlite3_bind_string(statement, 2, m_owner, SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+std::string
+PibDb::getTpmLocator() const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database, "SELECT tpm_locator FROM mgmt", -1, &statement, nullptr);
+
+ string tpmLocator;
+ if (sqlite3_step(statement) == SQLITE_ROW) {
+ tpmLocator = sqlite3_column_string(statement, 0);
+ }
+
+ sqlite3_finalize(statement);
+ return tpmLocator;
+}
+
+int64_t
+PibDb::addIdentity(const Name& identity)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "INSERT INTO identities (identity) values (?)",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ return sqlite3_last_insert_rowid(m_database);
+}
+
+void
+PibDb::deleteIdentity(const Name& identity)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "DELETE FROM identities WHERE identity=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+bool
+PibDb::hasIdentity(const Name& identity) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT id FROM identities WHERE identity=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+ int result = sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ if (result == SQLITE_ROW)
+ return true;
+ else
+ return false;
+}
+
+void
+PibDb::setDefaultIdentity(const Name& identity)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "UPDATE identities SET is_default=1 WHERE identity=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+Name
+PibDb::getDefaultIdentity() const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT identity FROM identities WHERE is_default=1",
+ -1, &statement, nullptr);
+
+ Name identity = NON_EXISTING_IDENTITY;
+ if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_bytes(statement, 0) != 0) {
+ identity = Name(sqlite3_column_block(statement, 0));
+ }
+ sqlite3_finalize(statement);
+ return identity;
+}
+
+vector<Name>
+PibDb::listIdentities() const
+{
+ vector<Name> identities;
+
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database, "SELECT identity FROM identities", -1, &statement, nullptr);
+
+ identities.clear();
+ while (sqlite3_step(statement) == SQLITE_ROW) {
+ Name name(sqlite3_column_block(statement, 0));
+ identities.push_back(name);
+ }
+ sqlite3_finalize(statement);
+
+ return identities;
+}
+
+int64_t
+PibDb::addKey(const Name& keyName, const PublicKey& key)
+{
+ if (keyName.empty())
+ return 0;
+
+ Name&& identity = keyName.getPrefix(-1);
+ if (!hasIdentity(identity))
+ addIdentity(identity);
+
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "INSERT INTO keys (identity_id, key_name, key_type, key_bits) \
+ values ((SELECT id FROM identities WHERE identity=?), ?, ?, ?)",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_bind_block(statement, 2, keyName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_bind_int(statement, 3, key.getKeyType());
+ sqlite3_bind_blob(statement, 4, key.get().buf(), key.get().size(), SQLITE_STATIC);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ return sqlite3_last_insert_rowid(m_database);
+}
+
+shared_ptr<PublicKey>
+PibDb::getKey(const Name& keyName) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT key_bits FROM keys WHERE key_name=?"
+ , -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+ shared_ptr<PublicKey> key;
+ if (sqlite3_step(statement) == SQLITE_ROW) {
+ key = make_shared<PublicKey>(static_cast<const uint8_t*>(sqlite3_column_blob(statement, 0)),
+ sqlite3_column_bytes(statement, 0));
+ }
+ sqlite3_finalize(statement);
+ return key;
+}
+
+void
+PibDb::deleteKey(const Name& keyName)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "DELETE FROM keys WHERE key_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+bool
+PibDb::hasKey(const Name& keyName) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT id FROM keys WHERE key_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+ int result = sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ if (result == SQLITE_ROW)
+ return true;
+ else
+ return false;
+}
+
+void
+PibDb::setDefaultKeyNameOfIdentity(const Name& keyName)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "UPDATE keys SET is_default=1 WHERE key_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+Name
+PibDb::getDefaultKeyNameOfIdentity(const Name& identity) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT key_name FROM keys JOIN identities ON keys.identity_id=identities.id\
+ WHERE identities.identity=? AND keys.is_default=1",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+
+ Name keyName = NON_EXISTING_KEY;
+ if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_bytes(statement, 0) != 0) {
+ keyName = Name(sqlite3_column_block(statement, 0));
+ }
+
+ sqlite3_finalize(statement);
+ return keyName;
+}
+
+vector<Name>
+PibDb::listKeyNamesOfIdentity(const Name& identity) const
+{
+ vector<Name> keyNames;
+
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT key_name FROM keys JOIN identities ON keys.identity_id=identities.id\
+ WHERE identities.identity=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, identity.wireEncode(), SQLITE_TRANSIENT);
+
+ keyNames.clear();
+ while (sqlite3_step(statement) == SQLITE_ROW) {
+ Name keyName(sqlite3_column_block(statement, 0));
+ keyNames.push_back(keyName);
+ }
+
+ sqlite3_finalize(statement);
+ return keyNames;
+}
+
+
+int64_t
+PibDb::addCertificate(const IdentityCertificate& certificate)
+{
+ const Name& certName = certificate.getName();
+ const Name& keyName = certificate.getPublicKeyName();
+
+ if (!hasKey(keyName))
+ addKey(keyName, certificate.getPublicKeyInfo());
+
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "INSERT INTO certificates \
+ (key_id, certificate_name, certificate_data) \
+ values ((SELECT id FROM keys WHERE key_name=?), ?, ?)",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_bind_block(statement, 2, certName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_bind_block(statement, 3, certificate.wireEncode(), SQLITE_STATIC);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ return sqlite3_last_insert_rowid(m_database);
+}
+
+shared_ptr<IdentityCertificate>
+PibDb::getCertificate(const Name& certificateName) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT certificate_data FROM certificates WHERE certificate_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, certificateName.wireEncode(), SQLITE_TRANSIENT);
+
+ shared_ptr<IdentityCertificate> certificate;
+ if (sqlite3_step(statement) == SQLITE_ROW) {
+ certificate = make_shared<IdentityCertificate>();
+ certificate->wireDecode(sqlite3_column_block(statement, 0));
+ }
+
+ sqlite3_finalize(statement);
+ return certificate;
+}
+
+void
+PibDb::deleteCertificate(const Name& certificateName)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "DELETE FROM certificates WHERE certificate_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, certificateName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+bool
+PibDb::hasCertificate(const Name& certificateName) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT id FROM certificates WHERE certificate_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, certificateName.wireEncode(), SQLITE_TRANSIENT);
+ int result = sqlite3_step(statement);
+ sqlite3_finalize(statement);
+
+ if (result == SQLITE_ROW)
+ return true;
+ else
+ return false;
+}
+
+void
+PibDb::setDefaultCertNameOfKey(const Name& certificateName)
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "UPDATE certificates SET is_default=1 WHERE certificate_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, certificateName.wireEncode(), SQLITE_TRANSIENT);
+ sqlite3_step(statement);
+ sqlite3_finalize(statement);
+}
+
+Name
+PibDb::getDefaultCertNameOfKey(const Name& keyName) const
+{
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT certificate_name\
+ FROM certificates JOIN keys ON certificates.key_id=keys.id\
+ WHERE keys.key_name=? AND certificates.is_default=1",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+ Name certName = NON_EXISTING_CERTIFICATE;
+ if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_bytes(statement, 0) != 0) {
+ certName = Name(sqlite3_column_block(statement, 0));
+ }
+ sqlite3_finalize(statement);
+ return certName;
+}
+
+vector<Name>
+PibDb::listCertNamesOfKey(const Name& keyName) const
+{
+ vector<Name> certNames;
+
+ sqlite3_stmt* statement;
+ sqlite3_prepare_v2(m_database,
+ "SELECT certificate_name\
+ FROM certificates JOIN keys ON certificates.key_id=keys.id\
+ WHERE keys.key_name=?",
+ -1, &statement, nullptr);
+ sqlite3_bind_block(statement, 1, keyName.wireEncode(), SQLITE_TRANSIENT);
+
+ certNames.clear();
+ while (sqlite3_step(statement) == SQLITE_ROW) {
+ Name name(sqlite3_column_block(statement, 0));
+ certNames.push_back(name);
+ }
+ sqlite3_finalize(statement);
+
+ return certNames;
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/pib-db.hpp b/tools/pib/pib-db.hpp
new file mode 100644
index 0000000..5101e25
--- /dev/null
+++ b/tools/pib/pib-db.hpp
@@ -0,0 +1,265 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_PIB_DB_HPP
+#define NDN_PIB_PIB_DB_HPP
+
+#include "core/common.hpp"
+#include <ndn-cxx/security/identity-certificate.hpp>
+#include <ndn-cxx/util/signal.hpp>
+
+#include <set>
+#include <vector>
+
+struct sqlite3;
+struct sqlite3_context;
+struct Mem;
+typedef Mem sqlite3_value;
+
+namespace ndn {
+namespace pib {
+
+/// @brief Callback to report changes on user info.
+typedef function<void(const std::string&)> UserChangedEventHandler;
+
+/// @brief Callback to report that a key is deleted.
+typedef function<void(const std::string&, const Name&,
+ const name::Component&)> KeyDeletedEventHandler;
+
+/**
+ * @brief PibDb is a class to manage the database of PIB service.
+ *
+ * only public key related information is stored in this database.
+ * Detail information can be found at:
+ * http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base
+ */
+class PibDb : noncopyable
+{
+public:
+ util::signal::Signal<PibDb> mgmtCertificateChanged;
+ util::signal::Signal<PibDb, Name> certificateDeleted;
+ util::signal::Signal<PibDb, Name> keyDeleted;
+ util::signal::Signal<PibDb, Name> identityDeleted;
+ util::signal::Signal<PibDb, Name> certificateInserted;
+
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ explicit
+ PibDb(const std::string& dbDir = "");
+
+public: // Owner management
+ /**
+ * @brief Update owner's management certificate
+ *
+ * Since owner name is encoded in the management certificate,
+ * this method can also set the owner name if it is not set.
+ * If the owner name is set but does not match the one in the
+ * supplied certificate, it throws @p Error.
+ *
+ * @throws Error if supplied certificate is wrong
+ */
+ void
+ updateMgmtCertificate(const IdentityCertificate& certificate);
+
+ /**
+ * @brief Get owner name
+ *
+ * return empty string when owner name is not set.
+ */
+ std::string
+ getOwnerName() const;
+
+ /** @brief Get the management cert
+ *
+ * return nullptr when the management cert is not set
+ */
+ shared_ptr<IdentityCertificate>
+ getMgmtCertificate() const;
+
+ /// @brief Set TPM locator
+ void
+ setTpmLocator(const std::string& tpmLocator);
+
+ /**
+ * @brief Get TPM locator
+ *
+ * return empty string when tpmLocator is not set.
+ */
+ std::string
+ getTpmLocator() const;
+
+public: // Identity management
+
+ /**
+ * @brief Add an identity
+ *
+ * @return row id of the added identity, 0 if insert fails.
+ */
+ int64_t
+ addIdentity(const Name& identity);
+
+ /// @brief Delete an identity
+ void
+ deleteIdentity(const Name& identity);
+
+ /// @brief Check if an identity exists
+ bool
+ hasIdentity(const Name& identity) const;
+
+ /// @brief Get all identities
+ std::vector<Name>
+ listIdentities() const;
+
+ /// @brief Set the default identity
+ void
+ setDefaultIdentity(const Name& identity);
+
+ /**
+ * @brief Get the default identity
+ *
+ * @return default identity or /localhost/reserved/non-existing-identity if no default identity
+ */
+ Name
+ getDefaultIdentity() const;
+
+public: // Key management
+
+ /// @brief Add key
+ int64_t
+ addKey(const Name& keyName, const PublicKey& key);
+
+ /// @brief Delete key
+ void
+ deleteKey(const Name& keyName);
+
+ /// @brief Check if a key exists
+ bool
+ hasKey(const Name& keyName) const;
+
+ /**
+ * @brief Get key
+ *
+ * @return shared pointer to the key, nullptr if the key does not exit
+ */
+ shared_ptr<PublicKey>
+ getKey(const Name& keyName) const;
+
+ /// @brief Get all the key names of an identity
+ std::vector<Name>
+ listKeyNamesOfIdentity(const Name& identity) const;
+
+ /// @brief Set an identity's default key name
+ void
+ setDefaultKeyNameOfIdentity(const Name& keyName);
+
+ /**
+ * @brief Get the default key name of an identity
+ *
+ * @return default key name or /localhost/reserved/non-existing-key if no default key
+ */
+ Name
+ getDefaultKeyNameOfIdentity(const Name& identity) const;
+
+public: // Certificate management
+
+ /// @brief Add a certificate
+ int64_t
+ addCertificate(const IdentityCertificate& certificate);
+
+ /// @brief Delete a certificate
+ void
+ deleteCertificate(const Name& certificateName);
+
+ /// @brief Check if the certificate exist
+ bool
+ hasCertificate(const Name& certificateName) const;
+
+ /**
+ * @brief Get a certificate
+ *
+ * @return shared pointer to the certificate, nullptr if the certificate does not exist
+ */
+ shared_ptr<IdentityCertificate>
+ getCertificate(const Name& certificateName) const;
+
+ /// @brief Get all the cert names of a key
+ std::vector<Name>
+ listCertNamesOfKey(const Name& keyName) const;
+
+ /// @brief Set a key's default certificate name
+ void
+ setDefaultCertNameOfKey(const Name& certificateName);
+
+ /**
+ * @brief Get a key's default certificate name
+ *
+ * @return default certificate name or /localhost/reserved/non-existing-certificate if no default
+ * certificate.
+ */
+ Name
+ getDefaultCertNameOfKey(const Name& keyName) const;
+
+private:
+ void
+ createDbDeleteTrigger();
+
+private:
+ static void
+ identityDeletedFun(sqlite3_context* context, int argc, sqlite3_value** argv);
+
+ static void
+ keyDeletedFun(sqlite3_context* context, int argc, sqlite3_value** argv);
+
+ static void
+ certDeletedFun(sqlite3_context* context, int argc, sqlite3_value** argv);
+
+ static void
+ certInsertedFun(sqlite3_context* context, int argc, sqlite3_value** argv);
+
+public:
+ static const Name NON_EXISTING_IDENTITY;
+ static const Name NON_EXISTING_KEY;
+ static const Name NON_EXISTING_CERTIFICATE;
+
+private:
+ static const Name LOCALHOST_PIB;
+ static const name::Component MGMT_LABEL;
+
+private:
+ sqlite3* m_database;
+
+ mutable std::string m_owner;
+};
+
+} // namespace pib
+} // namespace ndn
+
+
+#endif // NDN_PIB_PIB_DB_HPP
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
diff --git a/tools/pib/pib-validator.hpp b/tools/pib/pib-validator.hpp
new file mode 100644
index 0000000..9d7a3e1
--- /dev/null
+++ b/tools/pib/pib-validator.hpp
@@ -0,0 +1,81 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_PIB_VALIDATOR_HPP
+#define NDN_PIB_PIB_VALIDATOR_HPP
+
+#include "pib-db.hpp"
+#include "key-cache.hpp"
+#include <ndn-cxx/security/validator.hpp>
+#include <unordered_map>
+
+namespace ndn {
+namespace pib {
+
+
+/*
+ * @brief The validator to verify the command interests to PIB service
+ *
+ * @sa http://redmine.named-data.net/projects/ndn-cxx/wiki/PublicKey_Info_Base
+ */
+class PibValidator : public Validator
+{
+ struct UserKeyCache;
+public:
+ explicit
+ PibValidator(const PibDb& pibDb,
+ size_t maxCacheSize = 1000);
+
+ ~PibValidator();
+
+protected:
+ virtual void
+ checkPolicy(const Interest& interest,
+ int nSteps,
+ const OnInterestValidated& onValidated,
+ const OnInterestValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest>>& nextSteps);
+
+ virtual void
+ checkPolicy(const Data& data,
+ int nSteps,
+ const OnDataValidated& onValidated,
+ const OnDataValidationFailed& onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest>>& nextSteps);
+
+private:
+
+ const PibDb& m_db;
+
+ bool m_isMgmtReady;
+ std::string m_owner;
+ shared_ptr<IdentityCertificate> m_mgmtCert;
+
+ KeyCache m_keyCache;
+
+ util::signal::ScopedConnection m_mgmtChangeConnection;
+ util::signal::ScopedConnection m_keyDeletedConnection;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_PIB_VALIDATOR_HPP
diff --git a/tools/pib/pib.cpp b/tools/pib/pib.cpp
new file mode 100644
index 0000000..d5a4e5c
--- /dev/null
+++ b/tools/pib/pib.cpp
@@ -0,0 +1,282 @@
+/* -*- 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.hpp"
+
+#include "encoding/pib-encoding.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/util/crypto.hpp>
+#include <ndn-cxx/util/concepts.hpp>
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+using std::string;
+using std::vector;
+using std::set;
+
+const Name Pib::PIB_PREFIX("/localhost/pib");
+const Name Pib::EMPTY_SIGNER_NAME;
+const name::Component Pib::MGMT_LABEL("mgmt");
+
+// \todo make this a static method in KeyChain
+static inline void
+signWithDigestSha256(Data& data)
+{
+ DigestSha256 sig;
+ data.setSignature(sig);
+ Block sigValue(tlv::SignatureValue,
+ crypto::sha256(data.wireEncode().value(),
+ data.wireEncode().value_size() -
+ data.getSignature().getValue().size()));
+ data.setSignatureValue(sigValue);
+ data.wireEncode();
+}
+
+Pib::Pib(Face& face,
+ const std::string& dbDir,
+ const std::string& tpmLocator,
+ const std::string& owner)
+ : m_db(dbDir)
+ , m_tpm(nullptr)
+ , m_owner(owner)
+ , m_validator(m_db)
+ , m_face(face)
+ , m_certPublisher(m_face, m_db)
+ , m_getProcessor(m_db)
+ , m_defaultProcessor(m_db)
+ , m_listProcessor(m_db)
+ , m_updateProcessor(m_db, *this)
+ , m_deleteProcessor(m_db)
+{
+ if (!m_db.getOwnerName().empty() && m_db.getOwnerName() != owner)
+ throw Error("owner argument differs from OwnerName in database");
+
+ if (!m_db.getTpmLocator().empty() && m_db.getTpmLocator() != tpmLocator)
+ throw Error("tpmLocator argument differs from TpmLocator in database");
+
+ initializeTpm(tpmLocator);
+ initializeMgmtCert();
+ m_db.setTpmLocator(tpmLocator);
+
+ registerPrefix();
+}
+
+Pib::~Pib()
+{
+ m_face.unsetInterestFilter(m_pibMgmtFilterId);
+ m_face.unsetInterestFilter(m_pibGetFilterId);
+ m_face.unsetInterestFilter(m_pibDefaultFilterId);
+ m_face.unsetInterestFilter(m_pibListFilterId);
+ m_face.unsetInterestFilter(m_pibUpdateFilterId);
+ m_face.unsetInterestFilter(m_pibDeleteFilterId);
+
+ m_face.unsetInterestFilter(m_pibPrefixId);
+}
+
+void
+Pib::setMgmtCert(std::shared_ptr<IdentityCertificate> mgmtCert)
+{
+ if (mgmtCert != nullptr)
+ m_mgmtCert = mgmtCert;
+}
+
+void
+Pib::initializeTpm(const string& tpmLocator)
+{
+ m_tpm = KeyChain::createTpm(tpmLocator);
+}
+
+void
+Pib::initializeMgmtCert()
+{
+ shared_ptr<IdentityCertificate> mgmtCert = m_db.getMgmtCertificate();
+
+ if (mgmtCert == nullptr ||
+ !m_tpm->doesKeyExistInTpm(mgmtCert->getPublicKeyName(), KEY_CLASS_PRIVATE)) {
+ // If mgmt cert is set, or corresponding private key of the current mgmt cert is missing,
+ // generate new mgmt cert
+
+ // key name: /localhost/pib/[UserName]/mgmt/dsk-...
+ Name mgmtKeyName = PIB_PREFIX;
+ mgmtKeyName.append(m_owner).append(MGMT_LABEL);
+ std::ostringstream oss;
+ oss << "dsk-" << time::toUnixTimestamp(time::system_clock::now()).count();
+ mgmtKeyName.append(oss.str());
+
+ // self-sign pib root key
+ m_mgmtCert = prepareCertificate(mgmtKeyName, RsaKeyParams(),
+ time::system_clock::now(),
+ time::system_clock::now() + time::days(7300));
+
+ // update management certificate in database
+ m_db.updateMgmtCertificate(*m_mgmtCert);
+ }
+ else
+ m_mgmtCert = mgmtCert;
+}
+
+shared_ptr<IdentityCertificate>
+Pib::prepareCertificate(const Name& keyName, const KeyParams& keyParams,
+ const time::system_clock::TimePoint& notBefore,
+ const time::system_clock::TimePoint& notAfter,
+ const Name& signerName)
+{
+ // Generate mgmt key
+ m_tpm->generateKeyPairInTpm(keyName, keyParams);
+ shared_ptr<PublicKey> publicKey = m_tpm->getPublicKeyFromTpm(keyName);
+
+ // Set mgmt cert
+ auto certificate = make_shared<IdentityCertificate>();
+ Name certName = keyName.getPrefix(-1);
+ certName.append("KEY").append(keyName.get(-1)).append("ID-CERT").appendVersion();
+ certificate->setName(certName);
+ certificate->setNotBefore(notBefore);
+ certificate->setNotAfter(notAfter);
+ certificate->setPublicKeyInfo(*publicKey);
+ CertificateSubjectDescription subjectName(oid::ATTRIBUTE_NAME, keyName.getPrefix(-1).toUri());
+ certificate->addSubjectDescription(subjectName);
+ certificate->encode();
+
+
+ Name signingKeyName;
+ KeyLocator keyLocator;
+ if (signerName == EMPTY_SIGNER_NAME) {
+ // Self-sign mgmt cert
+ keyLocator = KeyLocator(certificate->getName().getPrefix(-1));
+ signingKeyName = keyName;
+ }
+ else {
+ keyLocator = KeyLocator(signerName.getPrefix(-1));
+ signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(signerName);
+ }
+
+ SignatureSha256WithRsa signature(keyLocator);
+ certificate->setSignature(signature);
+ EncodingBuffer encoder;
+ certificate->wireEncode(encoder, true);
+ Block signatureValue = m_tpm->signInTpm(encoder.buf(), encoder.size(),
+ signingKeyName, DIGEST_ALGORITHM_SHA256);
+ certificate->wireEncode(encoder, signatureValue);
+
+ return certificate;
+}
+
+void
+Pib::registerPrefix()
+{
+ // register pib prefix
+ Name pibPrefix = PIB_PREFIX;
+ pibPrefix.append(m_owner);
+ m_pibPrefixId =
+ m_face.registerPrefix(pibPrefix,
+ [] (const Name& name) {},
+ [] (const Name& name, const string& msg) {
+ throw Error("cannot register pib prefix");
+ });
+
+ // set interest filter for management certificate
+ m_pibMgmtFilterId =
+ m_face.setInterestFilter(Name(pibPrefix).append(MGMT_LABEL),
+ [this] (const InterestFilter&, const Interest& interest) {
+ if (m_mgmtCert != nullptr) {
+ m_face.put(*m_mgmtCert);
+ }
+ });
+
+ // set interest filter for get command
+ m_pibGetFilterId = registerProcessor(Name(pibPrefix).append(GetParam::VERB), m_getProcessor);
+
+ // set interest filter for default command
+ m_pibDefaultFilterId = registerProcessor(Name(pibPrefix).append(DefaultParam::VERB),
+ m_defaultProcessor);
+
+ // set interest filter for list command
+ m_pibListFilterId = registerProcessor(Name(pibPrefix).append(ListParam::VERB),
+ m_listProcessor);
+
+ // set interest filter for update command
+ m_pibUpdateFilterId = registerSignedCommandProcessor(Name(pibPrefix).append(UpdateParam::VERB),
+ m_updateProcessor);
+
+ // set interest filter for delete command
+ m_pibDeleteFilterId = registerSignedCommandProcessor(Name(pibPrefix).append(DeleteParam::VERB),
+ m_deleteProcessor);
+}
+
+template<class Processor>
+const InterestFilterId*
+Pib::registerProcessor(const Name& prefix, Processor& process)
+{
+ return m_face.setInterestFilter(prefix,
+ [&] (const InterestFilter&, const Interest& interest) {
+ processCommand(process, interest);
+ });
+}
+
+template<class Processor>
+const InterestFilterId*
+Pib::registerSignedCommandProcessor(const Name& prefix, Processor& process)
+{
+ const InterestFilterId* filterId =
+ m_face.setInterestFilter(prefix,
+ [&] (const InterestFilter&, const Interest& interest) {
+ m_validator.validate(interest,
+ [&] (const shared_ptr<const Interest>& interest) {
+ processCommand(process, *interest);
+ },
+ [] (const shared_ptr<const Interest>&, const string&) {});
+ });
+
+ return filterId;
+}
+
+template<class Processor>
+void
+Pib::processCommand(Processor& process, const Interest& interest)
+{
+ std::pair<bool, Block> result = process(interest);
+ if (result.first)
+ returnResult(Name(interest.getName()).appendVersion(),
+ result.second);
+}
+
+void
+Pib::returnResult(const Name& dataName, const Block& content)
+{
+ shared_ptr<Data> data = make_shared<Data>(dataName);
+
+ data->setFreshnessPeriod(time::milliseconds::zero());
+ data->setContent(content);
+ signWithDigestSha256(*data);
+
+ // Put data into response cache
+ m_responseCache.insert(*data);
+
+ // Put data to face.
+ m_face.put(*data);
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/pib.hpp b/tools/pib/pib.hpp
new file mode 100644
index 0000000..3128191
--- /dev/null
+++ b/tools/pib/pib.hpp
@@ -0,0 +1,178 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_PIB_HPP
+#define NDN_PIB_PIB_HPP
+
+#include "pib-db.hpp"
+#include "pib-validator.hpp"
+#include "cert-publisher.hpp"
+
+#include <ndn-cxx/face.hpp>
+#include <ndn-cxx/util/in-memory-storage-persistent.hpp>
+
+#include "get-query-processor.hpp"
+#include "default-query-processor.hpp"
+#include "list-query-processor.hpp"
+#include "update-query-processor.hpp"
+#include "delete-query-processor.hpp"
+
+#include <ndn-cxx/security/sec-tpm.hpp>
+
+namespace ndn {
+namespace pib {
+
+/// @brief implements the PIB service
+class Pib : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param face The face pib used to receive queries and serve certificates.
+ * @param dbDir Absolute path to the directory of the pib database.
+ * @param tpmLocator URI to locate the TPM for pib service.
+ * @param owner Owner of the pib database.
+ */
+ Pib(Face& face,
+ const std::string& dbDir,
+ const std::string& tpmLocator,
+ const std::string& owner);
+
+ ~Pib();
+
+ void
+ setMgmtCert(std::shared_ptr<IdentityCertificate> mgmtCert);
+
+PUBLIC_WITH_TESTS_ELSE_PROTECTED:
+ PibDb&
+ getDb()
+ {
+ return m_db;
+ }
+
+ SecTpm&
+ getTpm()
+ {
+ return *m_tpm;
+ }
+
+ util::InMemoryStoragePersistent&
+ getResponseCache()
+ {
+ return m_responseCache;
+ }
+
+ const std::string&
+ getOwner() const
+ {
+ return m_owner;
+ }
+
+ const IdentityCertificate&
+ getMgmtCert() const
+ {
+ BOOST_ASSERT(m_mgmtCert != nullptr);
+ return *m_mgmtCert;
+ }
+
+private: // initialization
+ /// @brief initialize the PIB's own TPM.
+ void
+ initializeTpm(const std::string& tpmLocator);
+
+ /// @brief initialize management certificate
+ void
+ initializeMgmtCert();
+
+ std::shared_ptr<IdentityCertificate>
+ prepareCertificate(const Name& keyName, const KeyParams& keyParams,
+ const time::system_clock::TimePoint& notBefore,
+ const time::system_clock::TimePoint& notAfter,
+ const Name& signerName = EMPTY_SIGNER_NAME);
+
+ /// @brief register prefix for PIB query and management certificate
+ void
+ registerPrefix();
+
+ template<class Processor>
+ const InterestFilterId*
+ registerProcessor(const Name& prefix, Processor& process);
+
+ template<class Processor>
+ const InterestFilterId*
+ registerSignedCommandProcessor(const Name& prefix, Processor& process);
+
+ template<class Processor>
+ void
+ processCommand(Processor& process, const Interest& interest);
+
+ void
+ returnResult(const Name& dataName, const Block& content);
+
+private:
+
+ static const Name EMPTY_SIGNER_NAME;
+ static const Name PIB_PREFIX;
+ static const name::Component MGMT_LABEL;
+
+ PibDb m_db;
+ std::unique_ptr<SecTpm> m_tpm;
+ std::string m_owner;
+ std::shared_ptr<IdentityCertificate> m_mgmtCert;
+
+ PibValidator m_validator;
+
+ Face& m_face;
+ CertPublisher m_certPublisher;
+ util::InMemoryStoragePersistent m_responseCache;
+
+ const RegisteredPrefixId* m_pibPrefixId;
+ const InterestFilterId* m_pibMgmtFilterId;
+ const InterestFilterId* m_pibGetFilterId;
+ const InterestFilterId* m_pibDefaultFilterId;
+ const InterestFilterId* m_pibListFilterId;
+ const InterestFilterId* m_pibUpdateFilterId;
+ const InterestFilterId* m_pibDeleteFilterId;
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+
+ GetQueryProcessor m_getProcessor;
+ DefaultQueryProcessor m_defaultProcessor;
+ ListQueryProcessor m_listProcessor;
+ UpdateQueryProcessor m_updateProcessor;
+ DeleteQueryProcessor m_deleteProcessor;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_PIB_HPP
diff --git a/tools/pib/response-cache.cpp b/tools/pib/response-cache.cpp
new file mode 100644
index 0000000..57c211e
--- /dev/null
+++ b/tools/pib/response-cache.cpp
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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 "response-cache.hpp"
+
+namespace ndn {
+namespace pib {
+
+using std::map;
+
+ResponseCache::ResponseCache()
+{
+}
+
+
+shared_ptr<const Data>
+ResponseCache::find(const Name& dataName, bool hasVersion) const
+{
+ if (!hasVersion) {
+ Storage::const_iterator it = m_storage.find(dataName);
+ if (it != m_storage.end())
+ return it->second;
+ else
+ return shared_ptr<const Data>();
+ }
+ else {
+ Storage::const_iterator it = m_storage.find(dataName.getPrefix(-1));
+ if (it != m_storage.end() && it->second->getName() == dataName)
+ return it->second;
+ else
+ return shared_ptr<const Data>();
+ }
+}
+
+void
+ResponseCache::insert(const Data& data)
+{
+ data.getName().at(-1).toVersion(); // ensures last component is version
+ m_storage[data.getName().getPrefix(-1)] = data.shared_from_this();
+}
+
+void
+ResponseCache::erase(const Name& dataNameWithoutVersion)
+{
+ m_storage.erase(dataNameWithoutVersion);
+}
+
+void
+ResponseCache::clear()
+{
+ m_storage.clear();
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/response-cache.hpp b/tools/pib/response-cache.hpp
new file mode 100644
index 0000000..40edd04
--- /dev/null
+++ b/tools/pib/response-cache.hpp
@@ -0,0 +1,74 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2014 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.
+ */
+
+#ifndef NDN_PIB_RESPONSE_CACHE_HPP
+#define NDN_PIB_RESPONSE_CACHE_HPP
+
+#include <ndn-cxx/data.hpp>
+#include <map>
+
+
+namespace ndn {
+namespace pib {
+
+/**
+ * @brief ResponseCache is an abstraction of a cache of response made before
+ *
+ * ResponseCache is used to reduce the number of PibDb lookup and Data signing
+ * operations.
+ *
+ * Eventually, it should be replaced by a formal application level cache. This
+ * one is only a temporary module and is used for test.
+ */
+class ResponseCache : noncopyable
+{
+public:
+ ResponseCache();
+
+ shared_ptr<const Data>
+ find(const Name& dataName, bool hasVersion = false) const;
+
+ /**
+ * @brief Insert a data packet into cache
+ *
+ * Name of the inserted data must end with a version component
+ *
+ * @param data Data to insert. It MUST have been created with make_shared.
+ */
+ void
+ insert(const Data& data);
+
+ void
+ erase(const Name& dataNameWithoutVersion);
+
+ void
+ clear();
+
+private:
+ typedef std::map<Name, shared_ptr<const Data> > Storage;
+
+ Storage m_storage;
+};
+
+} // namespace ndn
+} // namespace pib
+
+#endif // NDN_PIB_RESPONSE_CACHE_HPP
diff --git a/tools/pib/update-query-processor.cpp b/tools/pib/update-query-processor.cpp
new file mode 100644
index 0000000..4ab853d
--- /dev/null
+++ b/tools/pib/update-query-processor.cpp
@@ -0,0 +1,267 @@
+/* -*- 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 "update-query-processor.hpp"
+#include "encoding/pib-encoding.hpp"
+#include "pib.hpp"
+
+#include <boost/lexical_cast.hpp>
+
+namespace ndn {
+namespace pib {
+
+using std::string;
+
+const size_t UpdateQueryProcessor::UPDATE_QUERY_LENGTH = 9;
+const Name UpdateQueryProcessor::PIB_PREFIX("/localhost/pib");
+
+UpdateQueryProcessor::UpdateQueryProcessor(PibDb& db, Pib& pib)
+ : m_db(db)
+ , m_pib(pib)
+{
+}
+
+std::pair<bool, Block>
+UpdateQueryProcessor::operator()(const Interest& interest)
+{
+ const Name& interestName = interest.getName();
+
+ // handle pib query: /localhost/pib/[UserName]/update/param/<signed_interest_related_components>
+ if (interestName.size() != UPDATE_QUERY_LENGTH) {
+ // malformed interest, discard
+ return std::make_pair(false, Block());
+ }
+
+ try {
+ UpdateParam param;
+ param.wireDecode(interestName.get(OFFSET_PARAM).blockFromValue());
+
+ SignatureInfo sigInfo;
+ sigInfo.wireDecode(interestName.get(OFFSET_SIG_INFO).blockFromValue());
+
+ // sigInfo must have KeyLocator.Name if the interest passed validation.
+ Name signerName;
+ signerName = sigInfo.getKeyLocator().getName();
+
+ switch (param.getEntityType()) {
+ case tlv::pib::User:
+ return processUpdateUserQuery(param, signerName);
+ case tlv::pib::Identity:
+ return processUpdateIdQuery(param, signerName);
+ case tlv::pib::PublicKey:
+ return processUpdateKeyQuery(param, signerName);
+ case tlv::pib::Certificate:
+ return processUpdateCertQuery(param, signerName);
+ default:
+ {
+ PibError error(ERR_WRONG_PARAM,
+ "entity type is not supported: " +
+ boost::lexical_cast<string>(param.getEntityType()));
+ return std::make_pair(true, error.wireEncode());
+ }
+ }
+ }
+ catch (const PibDb::Error& e) {
+ PibError error(ERR_INTERNAL_ERROR, e.what());
+ return std::make_pair(true, error.wireEncode());
+ }
+ catch (const tlv::Error& e) {
+ PibError error(ERR_WRONG_PARAM, "error in parsing param: " + string(e.what()));
+ return std::make_pair(true, error.wireEncode());
+ }
+}
+
+std::pair<bool, Block>
+UpdateQueryProcessor::processUpdateUserQuery(const UpdateParam& param, const Name& signerName)
+{
+ Name expectedId = m_db.getMgmtCertificate()->getPublicKeyName().getPrefix(-1);
+ Name targetId = param.getUser().getMgmtCert().getPublicKeyName().getPrefix(-1);
+ Name signerId = IdentityCertificate::certificateNameToPublicKeyName(signerName).getPrefix(-1);
+
+ if (expectedId == targetId && expectedId == signerId) {
+ m_db.updateMgmtCertificate(param.getUser().getMgmtCert());
+ m_pib.setMgmtCert(make_shared<IdentityCertificate>(param.getUser().getMgmtCert()));
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+ }
+
+ PibError error(ERR_WRONG_PARAM, "not allowed to update user");
+ return std::make_pair(true, error.wireEncode());
+}
+
+std::pair<bool, Block>
+UpdateQueryProcessor::processUpdateIdQuery(const UpdateParam& param, const Name& signerName)
+{
+ const Name& identity = param.getIdentity().getIdentity();
+ if (!isUpdateAllowed(TYPE_ID, identity, signerName, param.getDefaultOpt())) {
+ PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ // add the identity
+ m_db.addIdentity(identity);
+
+ // set the identity as user default if it is requested.
+ const pib::DefaultOpt& defaultOpt = param.getDefaultOpt();
+ if (DEFAULT_OPT_USER_MASK & defaultOpt) {
+ m_db.setDefaultIdentity(identity);
+ }
+
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+}
+
+std::pair<bool, Block>
+UpdateQueryProcessor::processUpdateKeyQuery(const UpdateParam& param, const Name& signerName)
+{
+ const Name& keyName = param.getPublicKey().getKeyName();
+ if (!isUpdateAllowed(TYPE_KEY, keyName, signerName, param.getDefaultOpt())) {
+ PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ Name identity = keyName.getPrefix(-1);
+
+ // add the key
+ m_db.addKey(keyName, param.getPublicKey().getPublicKey());
+
+ const pib::DefaultOpt& defaultOpt = param.getDefaultOpt();
+ if (DEFAULT_OPT_ID_MASK & defaultOpt) // set the key as identity default if requested.
+ m_db.setDefaultKeyNameOfIdentity(keyName);
+ if (DEFAULT_OPT_USER_MASK & defaultOpt) // set the identity as user default if requested.
+ m_db.setDefaultIdentity(identity);
+
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+}
+
+std::pair<bool, Block>
+UpdateQueryProcessor::processUpdateCertQuery(const UpdateParam& param, const Name& signerName)
+{
+ const IdentityCertificate& cert = param.getCertificate().getCertificate();
+ const Name& certName = cert.getName();
+ if (!isUpdateAllowed(TYPE_CERT, certName, signerName, param.getDefaultOpt())) {
+ PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
+ return std::make_pair(true, error.wireEncode());
+ }
+
+ const Name& keyName = cert.getPublicKeyName();
+ Name identity = keyName.getPrefix(-1);
+
+ // add certificate
+ m_db.addCertificate(cert);
+
+ const pib::DefaultOpt& defaultOpt = param.getDefaultOpt();
+ if (DEFAULT_OPT_KEY_MASK & defaultOpt) // set the cert as key default if requested.
+ m_db.setDefaultCertNameOfKey(certName);
+ if (DEFAULT_OPT_ID_MASK & defaultOpt) // set the key as identity default if requested.
+ m_db.setDefaultKeyNameOfIdentity(keyName);
+ if (DEFAULT_OPT_USER_MASK & defaultOpt) // set the identity as user default if requested.
+ m_db.setDefaultIdentity(identity);
+
+ return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
+}
+
+bool
+UpdateQueryProcessor::isUpdateAllowed(const pib::Type targetType,
+ const Name& targetName,
+ const Name& signer,
+ const pib::DefaultOpt defaultOpt) const
+{
+ // Any identity with prefix /localhost/pib is reserved. Any operation with a targetName under
+ // that prefix will be rejected.
+ if (PIB_PREFIX.isPrefixOf(targetName))
+ return false;
+
+ // A request is wrong if
+ // 1) it wants to change the default setting of an identity, but the target is not key nor cert
+ // 2) it wants to change the default setting of a key, but the target is not cert
+ if ((defaultOpt == DEFAULT_OPT_ID && (targetType != TYPE_KEY && targetType != TYPE_CERT)) ||
+ (defaultOpt == DEFAULT_OPT_KEY && targetType != TYPE_CERT))
+ return false;
+
+
+ // Rules for other items:
+ //
+ // signer | adding privilege | default setting privilege
+ // ================+==========================+============================================
+ // local mgmt key | any id, key, and cert | the default id,
+ // | | the default key of any id,
+ // | | the default cert of any key of any id
+ // ----------------+--------------------------+--------------------------------------------
+ // default key of | any id, key, and cert | the default key of the id and its sub ids,
+ // an id | under the id's namespace | the default cert of any key of the id
+ // | | and its sub ids
+ // ----------------+--------------------------+--------------------------------------------
+ // non-default key | any cert of the key | the default cert of the key
+ // of an id
+
+ const Name& signerKeyName = IdentityCertificate::certificateNameToPublicKeyName(signer);
+ const Name& signerId = signerKeyName.getPrefix(-1);
+
+ bool hasSignerDefaultKey = true;
+ Name signerDefaultKeyName;
+ try {
+ signerDefaultKeyName = m_db.getDefaultKeyNameOfIdentity(signerId);
+ }
+ catch (PibDb::Error&) {
+ hasSignerDefaultKey = false;
+ }
+
+ Name mgmtCertName;
+ try {
+ mgmtCertName = m_db.getMgmtCertificate()->getName().getPrefix(-1);
+ }
+ catch (PibDb::Error&) {
+ return false;
+ }
+
+ if (signer == mgmtCertName) {
+ // signer is current management key, anything is allowed.
+ return true;
+ }
+ else if (hasSignerDefaultKey && signerDefaultKeyName == signerKeyName) {
+ // signer is an identity's default key
+ if (!signerId.isPrefixOf(targetName))
+ return false;
+
+ // check default setting
+ // user default setting is not allowed
+ if (defaultOpt == DEFAULT_OPT_USER)
+ return false;
+ else
+ return true;
+ }
+ else {
+ // non-default key
+ if (targetType != TYPE_CERT)
+ return false;
+
+ // check if it is for the key's cert
+ if (IdentityCertificate::certificateNameToPublicKeyName(targetName) != signerKeyName)
+ return false;
+
+ if (defaultOpt == DEFAULT_OPT_USER || defaultOpt == DEFAULT_OPT_ID)
+ return false;
+ else
+ return true;
+ }
+}
+
+} // namespace pib
+} // namespace ndn
diff --git a/tools/pib/update-query-processor.hpp b/tools/pib/update-query-processor.hpp
new file mode 100644
index 0000000..6c0655b
--- /dev/null
+++ b/tools/pib/update-query-processor.hpp
@@ -0,0 +1,98 @@
+/* -*- 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.
+ */
+
+#ifndef NDN_PIB_UPDATE_QUERY_PROCESSOR_HPP
+#define NDN_PIB_UPDATE_QUERY_PROCESSOR_HPP
+
+#include "pib-db.hpp"
+#include "encoding/update-param.hpp"
+#include <ndn-cxx/interest.hpp>
+#include <utility>
+
+namespace ndn {
+namespace pib {
+
+class Pib;
+
+/// @brief Processing unit for PIB update query
+class UpdateQueryProcessor : noncopyable
+{
+public:
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+ };
+
+ /**
+ * @brief Constructor
+ *
+ * @param db The pib database.
+ */
+ UpdateQueryProcessor(PibDb& db, Pib& pib);
+
+ std::pair<bool, Block>
+ operator()(const Interest& interest);
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+ /**
+ * @brief Determine if an update command is allowed.
+ *
+ * @param targetType The type of the target that will be updated.
+ * @param targetName The name of the target that will be updated.
+ * @param signer The name of the command signer.
+ * @param defaultOpt The default settings that is requested to update.
+ */
+ bool
+ isUpdateAllowed(const pib::Type targetType,
+ const Name& targetName,
+ const Name& signer,
+ const pib::DefaultOpt defaultOpt) const;
+
+private:
+ std::pair<bool, Block>
+ processUpdateUserQuery(const UpdateParam& param, const Name& signerName);
+
+ std::pair<bool, Block>
+ processUpdateIdQuery(const UpdateParam& param, const Name& signerName);
+
+ std::pair<bool, Block>
+ processUpdateKeyQuery(const UpdateParam& param, const Name& signerName);
+
+ std::pair<bool, Block>
+ processUpdateCertQuery(const UpdateParam& param, const Name& signerName);
+
+private:
+ static const size_t UPDATE_QUERY_LENGTH;
+ static const Name PIB_PREFIX;
+
+ PibDb& m_db;
+ Pib& m_pib;
+};
+
+} // namespace pib
+} // namespace ndn
+
+#endif // NDN_PIB_UPDATE_QUERY_PROCESSOR_HPP
diff --git a/tools/pib/wscript b/tools/pib/wscript
new file mode 100644
index 0000000..7a40d5a
--- /dev/null
+++ b/tools/pib/wscript
@@ -0,0 +1,19 @@
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+top = '../..'
+
+def build(bld):
+
+ bld(features=['cxx'],
+ name="pib-objects",
+ target="pib-objects",
+ source=bld.path.ant_glob('**/*.cpp', excl=['ndn-pib.cpp']),
+ use='core-objects',
+ install_path=None,
+ )
+
+
+ bld(features=['cxx', 'cxxprogram'],
+ target='ndn-pib',
+ source='ndn-pib.cpp',
+ use='pib-objects',
+ )