mgmt, main: add support for authorized commands
refs: #1227
Change-Id: I907d1fa6e78775470c5376fcdfe898be4c311001
diff --git a/daemon/mgmt/command-validator.cpp b/daemon/mgmt/command-validator.cpp
new file mode 100644
index 0000000..9028ba2
--- /dev/null
+++ b/daemon/mgmt/command-validator.cpp
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "command-validator.hpp"
+#include <ndn-cpp-dev/util/io.hpp>
+#include <ndn-cpp-dev/security/identity-certificate.hpp>
+
+namespace nfd {
+
+NFD_LOG_INIT("CommandValidator");
+
+CommandValidator::CommandValidator()
+{
+
+}
+
+CommandValidator::~CommandValidator()
+{
+
+}
+
+void
+CommandValidator::setConfigFile(ConfigFile& configFile)
+{
+ configFile.addSectionHandler("authorizations",
+ bind(&CommandValidator::onConfig, this, _1, _2));
+}
+
+static inline void
+aggregateErrors(std::stringstream& ss, const std::string& msg)
+{
+ if (!ss.str().empty())
+ {
+ ss << "\n";
+ }
+ ss << msg;
+}
+
+void
+CommandValidator::onConfig(const ConfigSection& section,
+ bool isDryRun)
+{
+ const ConfigSection EMPTY_SECTION;
+
+ if (section.begin() == section.end())
+ {
+ throw ConfigFile::Error("No authorize sections found");
+ }
+
+ std::stringstream dryRunErrors;
+ ConfigSection::const_iterator authIt;
+ for (authIt = section.begin(); authIt != section.end(); authIt++)
+ {
+ std::string keyfile;
+ try
+ {
+ keyfile = authIt->second.get<std::string>("keyfile");
+ }
+ catch (const std::runtime_error& e)
+ {
+ std::string msg = "No keyfile specified";
+ if (!isDryRun)
+ {
+ throw ConfigFile::Error(msg);
+ }
+ aggregateErrors(dryRunErrors, msg);
+ continue;
+ }
+
+ std::ifstream in;
+ in.open(keyfile.c_str());
+ if (!in.is_open())
+ {
+ std::string msg = "Unable to open key file " + keyfile;
+ if (!isDryRun)
+ {
+ throw ConfigFile::Error(msg);
+ }
+ aggregateErrors(dryRunErrors, msg);
+ continue;
+ }
+
+ shared_ptr<ndn::IdentityCertificate> id;
+ try
+ {
+ id = ndn::io::load<ndn::IdentityCertificate>(in);
+ }
+ catch(const std::runtime_error& error)
+ {
+ std::string msg = "Malformed key file " + keyfile;
+ if (!isDryRun)
+ {
+ throw ConfigFile::Error(msg);
+ }
+ aggregateErrors(dryRunErrors, msg);
+ continue;
+ }
+
+ in.close();
+
+ const ConfigSection* privileges = 0;
+
+ try
+ {
+ privileges = &authIt->second.get_child("privileges");
+ }
+ catch (const std::runtime_error& error)
+ {
+ std::string msg = "No privileges section found for key file " +
+ keyfile + " (" + id->getPublicKeyName().toUri() + ")";
+ if (!isDryRun)
+ {
+ throw ConfigFile::Error(msg);
+ }
+ aggregateErrors(dryRunErrors, msg);
+ continue;
+ }
+
+ if (privileges->begin() == privileges->end())
+ {
+ NFD_LOG_WARN("No privileges specified for key file " << keyfile + " (" << id->getPublicKeyName().toUri() << ")");
+ }
+
+ ConfigSection::const_iterator privIt;
+ for (privIt = privileges->begin(); privIt != privileges->end(); privIt++)
+ {
+ const std::string& privilegeName = privIt->first;
+ if (m_supportedPrivileges.find(privilegeName) != m_supportedPrivileges.end())
+ {
+ NFD_LOG_INFO("Giving privilege \"" << privilegeName
+ << "\" to key " << id->getPublicKeyName());
+ if (!isDryRun)
+ {
+ const std::string regex = "^<localhost><nfd><" + privilegeName + ">";
+ m_validator.addInterestRule(regex, *id);
+ }
+ }
+ else
+ {
+ // Invalid configuration
+ std::string msg = "Invalid privilege \"" + privilegeName + "\" for key file " +
+ keyfile + " (" + id->getPublicKeyName().toUri() + ")";
+ if (!isDryRun)
+ {
+ throw ConfigFile::Error(msg);
+ }
+ aggregateErrors(dryRunErrors, msg);
+ }
+ }
+ }
+
+ if (!dryRunErrors.str().empty())
+ {
+ throw ConfigFile::Error(dryRunErrors.str());
+ }
+}
+
+void
+CommandValidator::addSupportedPrivilege(const std::string& privilege)
+{
+ if (m_supportedPrivileges.find(privilege) != m_supportedPrivileges.end())
+ {
+ throw CommandValidator::Error("Duplicated privivilege: " + privilege);
+ }
+ m_supportedPrivileges.insert(privilege);
+}
+
+} // namespace nfd
+
diff --git a/daemon/mgmt/command-validator.hpp b/daemon/mgmt/command-validator.hpp
new file mode 100644
index 0000000..466bb70
--- /dev/null
+++ b/daemon/mgmt/command-validator.hpp
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (C) 2014 Named Data Networking Project
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NFD_MGMT_COMMAND_VALIDATOR_HPP
+#define NFD_MGMT_COMMAND_VALIDATOR_HPP
+
+#include "config-file.hpp"
+#include <ndn-cpp-dev/util/command-interest-validator.hpp>
+
+namespace nfd {
+
+class CommandValidator
+{
+public:
+
+ class Error : public std::runtime_error
+ {
+ public:
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+
+ }
+ };
+
+ CommandValidator();
+
+ ~CommandValidator();
+
+ void
+ setConfigFile(ConfigFile& configFile);
+
+ /**
+ * \param section "authorizations" section to parse
+ * \param isDryRun true if performing a dry run of configuration, false otherwise
+ * \throws ConfigFile::Error on parse error
+ */
+ void
+ onConfig(const ConfigSection& section, bool isDryRun);
+
+ /**
+ * \param privilege name of privilege to add
+ * \throws CommandValidator::Error on duplicated privilege
+ */
+ void
+ addSupportedPrivilege(const std::string& privilege);
+
+ void
+ addInterestRule(const std::string& regex,
+ const ndn::IdentityCertificate& certificate);
+
+ void
+ addInterestRule(const std::string& regex,
+ const Name& keyName,
+ const ndn::PublicKey& publicKey);
+
+ void
+ validate(const Interest& interest,
+ const ndn::OnInterestValidated& onValidated,
+ const ndn::OnInterestValidationFailed& onValidationFailed);
+
+private:
+ ndn::CommandInterestValidator m_validator;
+ std::set<std::string> m_supportedPrivileges;
+};
+
+inline void
+CommandValidator::addInterestRule(const std::string& regex,
+ const ndn::IdentityCertificate& certificate)
+{
+ m_validator.addInterestRule(regex, certificate);
+}
+
+inline void
+CommandValidator::addInterestRule(const std::string& regex,
+ const Name& keyName,
+ const ndn::PublicKey& publicKey)
+{
+ m_validator.addInterestRule(regex, keyName, publicKey);
+}
+
+inline void
+CommandValidator::validate(const Interest& interest,
+ const ndn::OnInterestValidated& onValidated,
+ const ndn::OnInterestValidationFailed& onValidationFailed)
+{
+ m_validator.validate(interest, onValidated, onValidationFailed);
+}
+
+} // namespace nfd
+
+#endif // NFD_MGMT_COMMAND_VALIDATOR_HPP
diff --git a/daemon/mgmt/config-file.cpp b/daemon/mgmt/config-file.cpp
index a55650e..8018310 100644
--- a/daemon/mgmt/config-file.cpp
+++ b/daemon/mgmt/config-file.cpp
@@ -34,7 +34,7 @@
{
std::string msg = "Failed to read configuration file: ";
msg += filename;
- throw Error(filename);
+ throw Error(msg);
}
parse(inputFile, isDryRun, filename);
inputFile.close();
diff --git a/daemon/mgmt/face-manager.cpp b/daemon/mgmt/face-manager.cpp
index 30e3abd..9874176 100644
--- a/daemon/mgmt/face-manager.cpp
+++ b/daemon/mgmt/face-manager.cpp
@@ -34,7 +34,7 @@
const size_t FaceManager::COMMAND_SIGNED_NCOMPS =
FaceManager::COMMAND_UNSIGNED_NCOMPS +
- 0; // No signed Interest support in mock, otherwise 4 (timestamp, nonce, signed info tlv, signature tlv)
+ 4; // (timestamp, nonce, signed info tlv, signature tlv)
const FaceManager::VerbAndProcessor FaceManager::COMMAND_VERBS[] =
{
@@ -52,8 +52,8 @@
FaceManager::FaceManager(FaceTable& faceTable,
- shared_ptr<AppFace> face)
- : ManagerBase(face)
+ shared_ptr<InternalFace> face)
+ : ManagerBase(face, FACE_MANAGER_PRIVILEGE)
, m_faceTable(faceTable)
, m_verbDispatch(COMMAND_VERBS,
COMMAND_VERBS +
@@ -411,7 +411,9 @@
return;
}
- onValidatedFaceRequest(request.shared_from_this());
+ validate(request,
+ bind(&FaceManager::onValidatedFaceRequest, this, _1),
+ bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
}
void
@@ -430,14 +432,6 @@
return;
}
- /// \todo authorize command
- if (false)
- {
- NFD_LOG_INFO("command result: unauthorized verb: " << command);
- sendResponse(command, 403, "Unauthorized command");
- return;
- }
-
NFD_LOG_INFO("command result: processing verb: " << verb);
(verbProcessor->second)(this, command, options);
}
diff --git a/daemon/mgmt/face-manager.hpp b/daemon/mgmt/face-manager.hpp
index 87574cd..316af2a 100644
--- a/daemon/mgmt/face-manager.hpp
+++ b/daemon/mgmt/face-manager.hpp
@@ -35,7 +35,7 @@
*/
FaceManager(FaceTable& faceTable,
- shared_ptr<AppFace> face);
+ shared_ptr<InternalFace> face);
/** \brief Subscribe to a face management section(s) for the config file
*/
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 8e27114..dee765b 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -17,18 +17,18 @@
NFD_LOG_INIT("FibManager");
-const Name FibManager::FIB_MANAGER_COMMAND_PREFIX = "/localhost/nfd/fib";
+const Name FibManager::COMMAND_PREFIX = "/localhost/nfd/fib";
-const size_t FibManager::FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS =
- FibManager::FIB_MANAGER_COMMAND_PREFIX.size() +
+const size_t FibManager::COMMAND_UNSIGNED_NCOMPS =
+ FibManager::COMMAND_PREFIX.size() +
1 + // verb
1; // verb options
-const size_t FibManager::FIB_MANAGER_COMMAND_SIGNED_NCOMPS =
- FibManager::FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS +
- 0; // No signed Interest support in mock, otherwise 3 (timestamp, signed info tlv, signature tlv)
+const size_t FibManager::COMMAND_SIGNED_NCOMPS =
+ FibManager::COMMAND_UNSIGNED_NCOMPS +
+ 4; // (timestamp, nonce, signed info tlv, signature tlv)
-const FibManager::VerbAndProcessor FibManager::FIB_MANAGER_COMMAND_VERBS[] =
+const FibManager::VerbAndProcessor FibManager::COMMAND_VERBS[] =
{
VerbAndProcessor(
Name::Component("insert"),
@@ -45,8 +45,6 @@
&FibManager::addNextHop
),
-
-
VerbAndProcessor(
Name::Component("remove-nexthop"),
&FibManager::removeNextHop
@@ -56,13 +54,13 @@
FibManager::FibManager(Fib& fib,
function<shared_ptr<Face>(FaceId)> getFace,
- shared_ptr<AppFace> face)
- : ManagerBase(face),
+ shared_ptr<InternalFace> face)
+ : ManagerBase(face, FIB_PRIVILEGE),
m_managedFib(fib),
m_getFace(getFace),
- m_verbDispatch(FIB_MANAGER_COMMAND_VERBS,
- FIB_MANAGER_COMMAND_VERBS +
- (sizeof(FIB_MANAGER_COMMAND_VERBS) / sizeof(VerbAndProcessor)))
+ m_verbDispatch(COMMAND_VERBS,
+ COMMAND_VERBS +
+ (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
{
face->setInterestFilter("/localhost/nfd/fib",
bind(&FibManager::onFibRequest, this, _2));
@@ -74,56 +72,56 @@
const Name& command = request.getName();
const size_t commandNComps = command.size();
-
-
- if (FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
- commandNComps < FIB_MANAGER_COMMAND_SIGNED_NCOMPS)
+ if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
+ commandNComps < COMMAND_SIGNED_NCOMPS)
{
NFD_LOG_INFO("command result: unsigned verb: " << command);
sendResponse(command, 401, "Signature required");
return;
}
- else if (commandNComps < FIB_MANAGER_COMMAND_SIGNED_NCOMPS ||
- !FIB_MANAGER_COMMAND_PREFIX.isPrefixOf(command))
+ else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
+ !COMMAND_PREFIX.isPrefixOf(command))
{
NFD_LOG_INFO("command result: malformed");
sendResponse(command, 400, "Malformed command");
return;
}
- const Name::Component& verb = command.get(FIB_MANAGER_COMMAND_PREFIX.size());
+ validate(request,
+ bind(&FibManager::onValidatedFibRequest,
+ this, _1),
+ bind(&ManagerBase::onCommandValidationFailed,
+ this, _1, _2));
+}
+
+void
+FibManager::onValidatedFibRequest(const shared_ptr<const Interest>& request)
+{
+ const Name& command = request->getName();
+ const Name::Component& verb = command.get(COMMAND_PREFIX.size());
VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find (verb);
if (verbProcessor != m_verbDispatch.end())
{
FibManagementOptions options;
- if (!extractOptions(request, options))
+ if (!extractOptions(*request, options))
{
+ NFD_LOG_INFO("command result: malformed verb: " << verb);
sendResponse(command, 400, "Malformed command");
return;
}
- /// \todo authorize command
- if (false)
- {
- NFD_LOG_INFO("command result: unauthorized verb: " << command);
- sendResponse(request.getName(), 403, "Unauthorized command");
- return;
- }
-
NFD_LOG_INFO("command result: processing verb: " << verb);
ControlResponse response;
(verbProcessor->second)(this, options, response);
-
sendResponse(command, response);
}
else
{
NFD_LOG_INFO("command result: unsupported verb: " << verb);
- sendResponse(request.getName(), 501, "Unsupported command");
+ sendResponse(command, 501, "Unsupported command");
}
-
}
bool
@@ -131,8 +129,7 @@
FibManagementOptions& extractedOptions)
{
const Name& command = request.getName();
- const size_t optionCompIndex =
- FIB_MANAGER_COMMAND_PREFIX.size() + 1;
+ const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
try
{
@@ -220,7 +217,7 @@
void
FibManager::removeNextHop(const FibManagementOptions& options,
- ControlResponse &response)
+ ControlResponse& response)
{
NFD_LOG_DEBUG("remove-nexthop prefix: " << options.getName()
<< " faceid: " << options.getFaceId());
diff --git a/daemon/mgmt/fib-manager.hpp b/daemon/mgmt/fib-manager.hpp
index c7b7793..43b410e 100644
--- a/daemon/mgmt/fib-manager.hpp
+++ b/daemon/mgmt/fib-manager.hpp
@@ -22,13 +22,15 @@
class Forwarder;
class Fib;
+const std::string FIB_PRIVILEGE = "fib"; // config file privilege name
+
class FibManager : public ManagerBase
{
public:
FibManager(Fib& fib,
function<shared_ptr<Face>(FaceId)> getFace,
- shared_ptr<AppFace> face);
+ shared_ptr<InternalFace> face);
void
onFibRequest(const Interest& request);
@@ -36,9 +38,13 @@
private:
void
+ onValidatedFibRequest(const shared_ptr<const Interest>& request);
+
+ void
insertEntry(const FibManagementOptions& options,
ControlResponse& response);
+
void
deleteEntry(const FibManagementOptions& options,
ControlResponse& response);
@@ -55,9 +61,6 @@
extractOptions(const Interest& request,
FibManagementOptions& extractedOptions);
- // void
- // onConfig(ConfigFile::Node section, bool isDryRun);
-
private:
Fib& m_managedFib;
@@ -75,17 +78,17 @@
const VerbDispatchTable m_verbDispatch;
- static const Name FIB_MANAGER_COMMAND_PREFIX; // /localhost/nfd/fib
+ static const Name COMMAND_PREFIX; // /localhost/nfd/fib
// number of components in an invalid, but not malformed, unsigned command.
// (/localhost/nfd/fib + verb + options) = 5
- static const size_t FIB_MANAGER_COMMAND_UNSIGNED_NCOMPS;
+ static const size_t COMMAND_UNSIGNED_NCOMPS;
// number of components in a valid signed Interest.
- // 5 in mock (see UNSIGNED_NCOMPS), 8 with signed Interest support.
- static const size_t FIB_MANAGER_COMMAND_SIGNED_NCOMPS;
+ // UNSIGNED_NCOMPS + 4 command Interest components = 9
+ static const size_t COMMAND_SIGNED_NCOMPS;
- static const VerbAndProcessor FIB_MANAGER_COMMAND_VERBS[];
+ static const VerbAndProcessor COMMAND_VERBS[];
};
diff --git a/daemon/mgmt/internal-face.hpp b/daemon/mgmt/internal-face.hpp
index 8d5805c..3ce32e3 100644
--- a/daemon/mgmt/internal-face.hpp
+++ b/daemon/mgmt/internal-face.hpp
@@ -10,6 +10,8 @@
#include "face/face.hpp"
#include "app-face.hpp"
+#include "command-validator.hpp"
+
namespace nfd {
class InternalFace : public Face, public AppFace
@@ -25,6 +27,12 @@
InternalFace();
+ CommandValidator&
+ getValidator();
+
+ virtual
+ ~InternalFace();
+
// Overridden Face methods for forwarder
virtual void
@@ -45,17 +53,19 @@
virtual void
put(const Data& data);
- virtual
- ~InternalFace();
-
private:
- // void
- // onConfig(ConfigFile::Node section, bool isDryRun);
-
std::map<Name, OnInterest> m_interestFilters;
+ CommandValidator m_validator;
};
+inline CommandValidator&
+InternalFace::getValidator()
+{
+ return m_validator;
+}
+
+
} // namespace nfd
#endif //NFD_MGMT_INTERNAL_FACE_HPP
diff --git a/daemon/mgmt/local-control-header-manager.cpp b/daemon/mgmt/local-control-header-manager.cpp
index 5717f54..aae1d0c 100644
--- a/daemon/mgmt/local-control-header-manager.cpp
+++ b/daemon/mgmt/local-control-header-manager.cpp
@@ -6,6 +6,7 @@
#include "local-control-header-manager.hpp"
#include "face/local-face.hpp"
+#include "mgmt/internal-face.hpp"
namespace nfd {
@@ -20,26 +21,23 @@
const size_t LocalControlHeaderManager::COMMAND_SIGNED_NCOMPS =
LocalControlHeaderManager::COMMAND_UNSIGNED_NCOMPS +
- 0; // No signed Interest support in mock
+ 4; // (timestamp, nonce, signed info tlv, signature tlv)
LocalControlHeaderManager::LocalControlHeaderManager(function<shared_ptr<Face>(FaceId)> getFace,
- shared_ptr<AppFace> face)
- : ManagerBase(face),
+ shared_ptr<InternalFace> face)
+ : ManagerBase(face, CONTROL_HEADER_PRIVILEGE),
m_getFace(getFace)
{
face->setInterestFilter("/localhost/nfd/control-header",
bind(&LocalControlHeaderManager::onLocalControlHeaderRequest, this, _2));
}
+
+
void
LocalControlHeaderManager::onLocalControlHeaderRequest(const Interest& request)
{
- static const Name::Component MODULE_IN_FACEID("in-faceid");
- static const Name::Component MODULE_NEXTHOP_FACEID("nexthop-faceid");
- static const Name::Component VERB_ENABLE("enable");
- static const Name::Component VERB_DISABLE("disable");
-
const Name& command = request.getName();
const size_t commandNComps = command.size();
@@ -59,35 +57,53 @@
return;
}
+ validate(request,
+ bind(&LocalControlHeaderManager::onCommandValidated,
+ this, _1),
+ bind(&ManagerBase::onCommandValidationFailed,
+ this, _1, _2));
+
+
+}
+
+void
+LocalControlHeaderManager::onCommandValidated(const shared_ptr<const Interest>& command)
+{
+ static const Name::Component MODULE_IN_FACEID("in-faceid");
+ static const Name::Component MODULE_NEXTHOP_FACEID("nexthop-faceid");
+ static const Name::Component VERB_ENABLE("enable");
+ static const Name::Component VERB_DISABLE("disable");
+
shared_ptr<LocalFace> face =
- dynamic_pointer_cast<LocalFace>(m_getFace(request.getIncomingFaceId()));
+ dynamic_pointer_cast<LocalFace>(m_getFace(command->getIncomingFaceId()));
if (!static_cast<bool>(face))
{
- NFD_LOG_INFO("command result: request to enable control header on non-local face");
- sendResponse(command, 400, "Command not supported on the requested face");
+ NFD_LOG_INFO("command result: command to enable control header on non-local face");
+ sendResponse(command->getName(), 400, "Command not supported on the requested face");
return;
}
- const Name::Component& module = command.get(COMMAND_PREFIX.size());
- const Name::Component& verb = command.get(COMMAND_PREFIX.size() + 1);
+ const Name& commandName = command->getName();
+ const Name::Component& module = commandName[COMMAND_PREFIX.size()];
+ const Name::Component& verb = commandName[COMMAND_PREFIX.size() + 1];
if (module == MODULE_IN_FACEID)
{
if (verb == VERB_ENABLE)
{
face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID, true);
- sendResponse(command, 200, "Success");
+ sendResponse(commandName, 200, "Success");
}
else if (verb == VERB_DISABLE)
{
face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_IN_FACEID, false);
- sendResponse(command, 200, "Success");
+ sendResponse(commandName, 200, "Success");
}
else
{
NFD_LOG_INFO("command result: unsupported verb: " << verb);
- sendResponse(command, 501, "Unsupported");
+ sendResponse(commandName, 501, "Unsupported");
}
}
else if (module == MODULE_NEXTHOP_FACEID)
@@ -95,23 +111,23 @@
if (verb == VERB_ENABLE)
{
face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID, true);
- sendResponse(command, 200, "Success");
+ sendResponse(commandName, 200, "Success");
}
else if (verb == VERB_DISABLE)
{
face->setLocalControlHeaderFeature(LOCAL_CONTROL_HEADER_FEATURE_NEXTHOP_FACEID, false);
- sendResponse(command, 200, "Success");
+ sendResponse(commandName, 200, "Success");
}
else
{
NFD_LOG_INFO("command result: unsupported verb: " << verb);
- sendResponse(command, 501, "Unsupported");
+ sendResponse(commandName, 501, "Unsupported");
}
}
else
{
NFD_LOG_INFO("command result: unsupported module: " << module);
- sendResponse(command, 501, "Unsupported");
+ sendResponse(commandName, 501, "Unsupported");
}
}
diff --git a/daemon/mgmt/local-control-header-manager.hpp b/daemon/mgmt/local-control-header-manager.hpp
index 8c03e4e..0aa5d63 100644
--- a/daemon/mgmt/local-control-header-manager.hpp
+++ b/daemon/mgmt/local-control-header-manager.hpp
@@ -14,26 +14,31 @@
namespace nfd {
+const std::string CONTROL_HEADER_PRIVILEGE = "control-header"; // config file privilege name
+
class LocalControlHeaderManager : public ManagerBase
{
public:
LocalControlHeaderManager(function<shared_ptr<Face>(FaceId)> getFace,
- shared_ptr<AppFace> face);
+ shared_ptr<InternalFace> face);
void
onLocalControlHeaderRequest(const Interest& request);
+ void
+ onCommandValidated(const shared_ptr<const Interest>& command);
+
private:
function<shared_ptr<Face>(FaceId)> m_getFace;
static const Name COMMAND_PREFIX; // /localhost/nfd/control-header
// number of components in an invalid, but not malformed, unsigned command.
- // (/localhost/nfd/control-headeer + control-module + verb) = 5
+ // (/localhost/nfd/control-header + control-module + verb) = 5
static const size_t COMMAND_UNSIGNED_NCOMPS;
// number of components in a valid signed Interest.
- // 5 in mock (see UNSIGNED_NCOMPS)
+ // UNSIGNED_NCOMPS + 4 command Interest components = 9
static const size_t COMMAND_SIGNED_NCOMPS;
};
diff --git a/daemon/mgmt/manager-base.cpp b/daemon/mgmt/manager-base.cpp
index 1994416..bd94b18 100644
--- a/daemon/mgmt/manager-base.cpp
+++ b/daemon/mgmt/manager-base.cpp
@@ -5,16 +5,15 @@
*/
#include "manager-base.hpp"
-#include "mgmt/app-face.hpp"
namespace nfd {
NFD_LOG_INIT("ManagerBase");
-ManagerBase::ManagerBase(shared_ptr<AppFace> face)
+ManagerBase::ManagerBase(shared_ptr<InternalFace> face, const std::string& privilege)
: m_face(face)
{
-
+ face->getValidator().addSupportedPrivilege(privilege);
}
ManagerBase::~ManagerBase()
@@ -49,5 +48,13 @@
m_face->put(*responseData);
}
+void
+ManagerBase::onCommandValidationFailed(const shared_ptr<const Interest>& command,
+ const std::string& error)
+{
+ NFD_LOG_INFO("command result: unauthorized verb: " << command);
+ sendResponse(command->getName(), 403, "Unauthorized command");
+}
+
} // namespace nfd
diff --git a/daemon/mgmt/manager-base.hpp b/daemon/mgmt/manager-base.hpp
index 78c6efe..9522812 100644
--- a/daemon/mgmt/manager-base.hpp
+++ b/daemon/mgmt/manager-base.hpp
@@ -10,25 +10,34 @@
#include "common.hpp"
#include <ndn-cpp-dev/management/nfd-control-response.hpp>
+#include "mgmt/command-validator.hpp"
+#include "mgmt/internal-face.hpp"
+
+
namespace nfd {
using ndn::nfd::ControlResponse;
-class AppFace;
+class InternalFace;
class ManagerBase
{
public:
+
struct Error : public std::runtime_error
{
Error(const std::string& what) : std::runtime_error(what) {}
};
- ManagerBase(shared_ptr<AppFace> face);
+ ManagerBase(shared_ptr<InternalFace> face, const std::string& privilege);
virtual
~ManagerBase();
+ void
+ onCommandValidationFailed(const shared_ptr<const Interest>& command,
+ const std::string& error);
+
protected:
void
@@ -50,8 +59,23 @@
uint32_t code,
const std::string& text);
+PUBLIC_WITH_TESTS_ELSE_PROTECTED:
+ void
+ addInterestRule(const std::string& regex,
+ const ndn::IdentityCertificate& certificate);
+
+ void
+ addInterestRule(const std::string& regex,
+ const Name& keyName,
+ const ndn::PublicKey& publicKey);
+
+ void
+ validate(const Interest& interest,
+ const ndn::OnInterestValidated& onValidated,
+ const ndn::OnInterestValidationFailed& onValidationFailed);
+
protected:
- shared_ptr<AppFace> m_face;
+ shared_ptr<InternalFace> m_face;
};
inline void
@@ -73,6 +97,29 @@
response.setBody(body);
}
+inline void
+ManagerBase::addInterestRule(const std::string& regex,
+ const ndn::IdentityCertificate& certificate)
+{
+ m_face->getValidator().addInterestRule(regex, certificate);
+}
+
+inline void
+ManagerBase::addInterestRule(const std::string& regex,
+ const Name& keyName,
+ const ndn::PublicKey& publicKey)
+{
+ m_face->getValidator().addInterestRule(regex, keyName, publicKey);
+}
+
+inline void
+ManagerBase::validate(const Interest& interest,
+ const ndn::OnInterestValidated& onValidated,
+ const ndn::OnInterestValidationFailed& onValidationFailed)
+{
+ m_face->getValidator().validate(interest, onValidated, onValidationFailed);
+}
+
} // namespace nfd
diff --git a/daemon/mgmt/strategy-choice-manager.cpp b/daemon/mgmt/strategy-choice-manager.cpp
index 00761dd..665f4a8 100644
--- a/daemon/mgmt/strategy-choice-manager.cpp
+++ b/daemon/mgmt/strategy-choice-manager.cpp
@@ -21,11 +21,11 @@
const size_t StrategyChoiceManager::COMMAND_SIGNED_NCOMPS =
StrategyChoiceManager::COMMAND_UNSIGNED_NCOMPS +
- 0; // No signed Interest support in mock, otherwise 4 (timestamp, nonce, signed info tlv, signature tlv)
+ 4; // (timestamp, nonce, signed info tlv, signature tlv)
StrategyChoiceManager::StrategyChoiceManager(StrategyChoice& strategyChoice,
- shared_ptr<AppFace> face)
- : ManagerBase(face)
+ shared_ptr<InternalFace> face)
+ : ManagerBase(face, STRATEGY_CHOICE_PRIVILEGE)
, m_strategyChoice(strategyChoice)
{
face->setInterestFilter("/localhost/nfd/strategy-choice",
@@ -59,7 +59,9 @@
return;
}
- onValidatedStrategyChoiceRequest(request.shared_from_this());
+ validate(request,
+ bind(&StrategyChoiceManager::onValidatedStrategyChoiceRequest, this, _1),
+ bind(&ManagerBase::onCommandValidationFailed, this, _1, _2));
}
void
diff --git a/daemon/mgmt/strategy-choice-manager.hpp b/daemon/mgmt/strategy-choice-manager.hpp
index 34046ac..6313fbb 100644
--- a/daemon/mgmt/strategy-choice-manager.hpp
+++ b/daemon/mgmt/strategy-choice-manager.hpp
@@ -21,7 +21,7 @@
{
public:
StrategyChoiceManager(StrategyChoice& strategyChoice,
- shared_ptr<AppFace> face);
+ shared_ptr<InternalFace> face);
virtual
~StrategyChoiceManager();