security: Add configuration based validator
Change-Id: Ic5837f4b02a613966c0a2e969c974ebd0786f769
diff --git a/src/common.hpp b/src/common.hpp
index 063b82f..650f2de 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -12,6 +12,7 @@
#include <ndn-cpp-dev/face.hpp>
#include <ndn-cpp-dev/security/key-chain.hpp>
+#include <ndn-cpp-dev/security/validator-config.hpp>
#include <ndn-cpp-dev/util/scheduler.hpp>
#include <ndn-cpp-dev/management/nfd-controller.hpp>
diff --git a/src/main.cpp b/src/main.cpp
index ce89f3f..e360e5d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -10,7 +10,10 @@
main(int argc, char** argv)
{
try {
- ndn::nrd::Nrd nrd;
+ // TODO: the configFilename should be obtained from command line arguments.
+ std::string configFilename("nrd.conf");
+
+ ndn::nrd::Nrd nrd(configFilename);
nrd.enableLocalControlHeader();
nrd.listen();
}
diff --git a/src/nrd.cpp b/src/nrd.cpp
index 403a32f..f22c000 100644
--- a/src/nrd.cpp
+++ b/src/nrd.cpp
@@ -38,27 +38,31 @@
Nrd::setInterestFilterFailed(const Name& name, const std::string& msg)
{
std::cerr << "Error in setting interest filter (" << name << "): " << msg << std::endl;
- m_face.shutdown();
+ m_face->shutdown();
}
-Nrd::Nrd()
- : m_nfdController(new nfd::Controller(m_face))
+Nrd::Nrd(const std::string& validatorConfig)
+ : m_face(new Face())
+ , m_validator(m_face)
+ , m_nfdController(new nfd::Controller(*m_face))
, m_verbDispatch(COMMAND_VERBS,
COMMAND_VERBS + (sizeof(COMMAND_VERBS) / sizeof(VerbAndProcessor)))
{
//check whether the components of localhop and localhost prefixes are same
BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
+ m_validator.load(validatorConfig);
+
std::cerr << "Setting interest filter on: " << COMMAND_PREFIX.toUri() << std::endl;
- m_face.setController(m_nfdController);
- m_face.setInterestFilter(COMMAND_PREFIX.toUri(),
- bind(&Nrd::onRibRequest, this, _2),
- bind(&Nrd::setInterestFilterFailed, this, _1, _2));
+ m_face->setController(m_nfdController);
+ m_face->setInterestFilter(COMMAND_PREFIX.toUri(),
+ bind(&Nrd::onRibRequest, this, _2),
+ bind(&Nrd::setInterestFilterFailed, this, _1, _2));
std::cerr << "Setting interest filter on: " << REMOTE_COMMAND_PREFIX.toUri() << std::endl;
- m_face.setInterestFilter(REMOTE_COMMAND_PREFIX.toUri(),
- bind(&Nrd::onRibRequest, this, _2),
- bind(&Nrd::setInterestFilterFailed, this, _1, _2));
+ m_face->setInterestFilter(REMOTE_COMMAND_PREFIX.toUri(),
+ bind(&Nrd::onRibRequest, this, _2),
+ bind(&Nrd::setInterestFilterFailed, this, _1, _2));
}
void
@@ -71,7 +75,7 @@
responseData.setContent(encodedControl);
m_keyChain.sign(responseData);
- m_face.put(responseData);
+ m_face->put(responseData);
}
void
@@ -86,24 +90,15 @@
void
Nrd::onRibRequest(const Interest& request)
{
- const Name& command = request.getName();
- const size_t commandNComps = command.size();
+ m_validator.validate(request,
+ bind(&Nrd::onRibRequestValidated, this, _1),
+ bind(&Nrd::onRibRequestValidationFailed, this, _1, _2));
+}
- if (COMMAND_UNSIGNED_NCOMPS <= commandNComps &&
- commandNComps < COMMAND_SIGNED_NCOMPS)
- {
- std::cerr << "Error: Signature required" << std::endl;
- sendResponse(command, 401, "Signature required");
- return;
- }
- else if (commandNComps < COMMAND_SIGNED_NCOMPS ||
- !(COMMAND_PREFIX.isPrefixOf(command) ||
- REMOTE_COMMAND_PREFIX.isPrefixOf(command)))
- {
- std::cerr << "Error: Malformed Command" << std::endl;
- sendResponse(command, 400, "Malformed command");
- return;
- }
+void
+Nrd::onRibRequestValidated(const shared_ptr<const Interest>& request)
+{
+ const Name& command = request->getName();
//REMOTE_COMMAND_PREFIX number of componenets are same as
// NRD_COMMAND_PREFIX's so no extra checks are required.
@@ -113,7 +108,7 @@
if (verbProcessor != m_verbDispatch.end())
{
PrefixRegOptions options;
- if (!extractOptions(request, options))
+ if (!extractOptions(*request, options))
{
sendResponse(command, 400, "Malformed command");
return;
@@ -122,23 +117,30 @@
/// \todo authorize command
if (false)
{
- sendResponse(request.getName(), 403, "Unauthorized command");
+ sendResponse(request->getName(), 403, "Unauthorized command");
return;
}
// \todo add proper log support
std::cout << "Received options (name, faceid, cost): " << options.getName() <<
- ", " << options.getFaceId() << ", " << options.getCost() << std::endl;
+ ", " << options.getFaceId() << ", " << options.getCost() << std::endl;
nfd::ControlResponse response;
- (verbProcessor->second)(this, request, options);
+ (verbProcessor->second)(this, *request, options);
}
else
{
- sendResponse(request.getName(), 501, "Unsupported command");
+ sendResponse(request->getName(), 501, "Unsupported command");
}
}
+void
+Nrd::onRibRequestValidationFailed(const shared_ptr<const Interest>& request,
+ const std::string& failureInfo)
+{
+ sendResponse(request->getName(), 403, failureInfo);
+}
+
bool
Nrd::extractOptions(const Interest& request,
PrefixRegOptions& extractedOptions)
@@ -202,8 +204,8 @@
response.setBody(options.wireEncode());
std::cout << "Success: Name unregistered (" <<
- options.getName() << ", " <<
- options.getFaceId() << ")" << std::endl;
+ options.getName() << ", " <<
+ options.getFaceId() << ")" << std::endl;
sendResponse(request.getName(), response);
m_managedRib.erase(options);
}
@@ -218,7 +220,7 @@
response.setBody(options.wireEncode());
std::cout << "Success: Name registered (" << options.getName() << ", " <<
- options.getFaceId() << ")" << std::endl;
+ options.getFaceId() << ")" << std::endl;
sendResponse(request.getName(), response);
}
@@ -232,13 +234,12 @@
// will add next hops one by one..
m_managedRib.insert(options);
m_nfdController->start<nfd::FibAddNextHopCommand>(
- nfd::ControlParameters()
- .setName(options.getName())
- .setFaceId(options.getFaceId())
- .setCost(options.getCost()),
- bind(&Nrd::onRegSuccess, this, request, options),
- bind(&Nrd::onCommandError, this, _1, _2, request, options)
- );
+ nfd::ControlParameters()
+ .setName(options.getName())
+ .setFaceId(options.getFaceId())
+ .setCost(options.getCost()),
+ bind(&Nrd::onRegSuccess, this, request, options),
+ bind(&Nrd::onCommandError, this, _1, _2, request, options));
}
@@ -246,12 +247,11 @@
Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
{
m_nfdController->start<nfd::FibRemoveNextHopCommand>(
- nfd::ControlParameters()
- .setName(options.getName())
- .setFaceId(options.getFaceId()),
- bind(&Nrd::onUnRegSuccess, this, request, options),
- bind(&Nrd::onCommandError, this, _1, _2, request, options)
- );
+ nfd::ControlParameters()
+ .setName(options.getName())
+ .setFaceId(options.getFaceId()),
+ bind(&Nrd::onUnRegSuccess, this, request, options),
+ bind(&Nrd::onCommandError, this, _1, _2, request, options));
}
@@ -259,7 +259,7 @@
Nrd::listen()
{
std::cout << "NRD started: listening for incoming interests" << std::endl;
- m_face.processEvents();
+ m_face->processEvents();
}
@@ -275,7 +275,7 @@
{
std::cout << "Error: couldn't enable local control header "
<< "(code: " << code << ", info: " << reason << ")" << std::endl;
- m_face.shutdown();
+ m_face->shutdown();
}
@@ -286,8 +286,7 @@
nfd::ControlParameters()
.setLocalControlFeature(nfd::LOCAL_CONTROL_FEATURE_INCOMING_FACE_ID),
bind(&Nrd::onControlHeaderSuccess, this),
- bind(&Nrd::onControlHeaderError, this, _1, _2)
- );
+ bind(&Nrd::onControlHeaderError, this, _1, _2));
}
} // namespace nrd
diff --git a/src/nrd.hpp b/src/nrd.hpp
index 7e1473e..49df0b5 100644
--- a/src/nrd.hpp
+++ b/src/nrd.hpp
@@ -15,7 +15,8 @@
class Nrd
{
public:
- Nrd();
+ explicit
+ Nrd(const std::string& validatorConfig);
void
onRibRequest(const Interest& request);
@@ -35,6 +36,14 @@
sendResponse(const Name& name,
uint32_t code,
const std::string& text);
+
+ void
+ onRibRequestValidated(const shared_ptr<const Interest>& request);
+
+ void
+ onRibRequestValidationFailed(const shared_ptr<const Interest>& request,
+ const std::string& failureInfo);
+
void
onCommandError(uint32_t code, const std::string& error,
const ndn::Interest& interest,
@@ -66,8 +75,9 @@
PrefixRegOptions& extractedOptions);
private:
Rib m_managedRib;
- ndn::Face m_face;
+ ndn::shared_ptr<ndn::Face> m_face;
ndn::KeyChain m_keyChain;
+ ndn::ValidatorConfig m_validator;
shared_ptr<nfd::Controller> m_nfdController;
typedef boost::function<void(Nrd*,
diff --git a/validator.conf.sample b/validator.conf.sample
new file mode 100644
index 0000000..224d3d8
--- /dev/null
+++ b/validator.conf.sample
@@ -0,0 +1,40 @@
+rule
+{
+ id "NRD Prefix Registration Command Rule"
+ for interest
+ filter
+ {
+ type name
+ regex ^<localhost><nrd>[<register><unregister>]<>{3}$
+ }
+ checker
+ {
+ type customized
+ sig-type rsa-sha256
+ key-locator
+ {
+ type name
+ regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT>$
+ }
+ }
+}
+rule
+{
+ id "Testbed Hierarchy Rule"
+ for data
+ filter
+ {
+ type name
+ regex ^[^<KEY>]*<KEY><>*<ksk-.*><ID-CERT><>$
+ }
+ checker
+ {
+ type hierarchical
+ sig-type rsa-sha256
+ }
+}
+trust-anchor
+{
+ type file
+ file-name "trust-anchor.cert"
+}
\ No newline at end of file