security: Add signing and validating process
Change-Id: Ic9edfcf56f044821e167d7e49b75a9023b67fbcd
diff --git a/src/conf-file-processor.cpp b/src/conf-file-processor.cpp
index 214b3a0..a45199b 100644
--- a/src/conf-file-processor.cpp
+++ b/src/conf-file-processor.cpp
@@ -108,6 +108,10 @@
{
ret = processConfSectionAdvertising(SectionAttributeTree);
}
+ else if (section == "security")
+ {
+ ret = processConfSectionSecurity(SectionAttributeTree);
+ }
else
{
std::cerr << "Wrong configuration Command: " << section << std::endl;
@@ -117,7 +121,7 @@
bool
ConfFileProcessor::processConfSectionGeneral(boost::property_tree::ptree
- SectionAttributeTree)
+ SectionAttributeTree)
{
try {
std::string network = SectionAttributeTree.get<string>("network");
@@ -152,7 +156,7 @@
cerr << ex.what() << endl;
return false;
}
-
+
try {
int32_t lsaRefreshTime = SectionAttributeTree.get<int32_t>("lsa-refresh-time");
if (lsaRefreshTime >= LSA_REFRESH_TIME_MIN &&
@@ -170,7 +174,7 @@
std::cerr << ex.what() << std::endl;
return false;
}
-
+
try {
std::string logLevel = SectionAttributeTree.get<string>("log-level");
if ( boost::iequals(logLevel, "info") || boost::iequals(logLevel, "debug")) {
@@ -186,7 +190,7 @@
std::cerr << ex.what() << std::endl;
return false;
}
-
+
try {
std::string logDir = SectionAttributeTree.get<string>("log-dir");
if (boost::filesystem::exists(logDir)) {
@@ -253,6 +257,7 @@
std::cerr << ex.what() << std::endl;
return false;
}
+
return true;
}
@@ -308,7 +313,7 @@
}
for (boost::property_tree::ptree::const_iterator tn =
SectionAttributeTree.begin(); tn != SectionAttributeTree.end(); ++tn) {
-
+
if (tn->first == "neighbor")
{
try {
@@ -362,7 +367,7 @@
std::cerr << ex.what() << std::endl;
return false;
}
-
+
try {
/* Radius and angle is mandatory configuration parameter in hyperbolic section.
* Even if router can have hyperbolic routing calculation off but other router
@@ -382,7 +387,7 @@
return false;
}
}
-
+
return true;
}
@@ -438,4 +443,44 @@
}
return true;
}
+
+bool
+ConfFileProcessor::processConfSectionSecurity(boost::property_tree::ptree section)
+{
+ ConfigSection::const_iterator it = section.begin();
+
+ if (it == section.end() || it->first != "validator")
+ {
+ std::cerr << "Error: Expect validator section!" << std::endl;
+ return false;
+ }
+
+ m_nlsr.loadValidator(it->second, m_confFileName);
+
+ for (; it != section.end(); it++)
+ {
+ using namespace boost::filesystem;
+ if (it->first != "cert-to-publish")
+ {
+ std::cerr << "Error: Expect cert-to-publish!" << std::endl;
+ return false;
+ }
+
+ std::string file = it->second.data();
+ path certfilePath = absolute(file, path(m_confFileName).parent_path());
+ ndn::shared_ptr<ndn::IdentityCertificate> idCert =
+ ndn::io::load<ndn::IdentityCertificate>(certfilePath.string());
+
+ if (!static_cast<bool>(idCert))
+ {
+ std::cerr << "Error: Cannot load cert-to-publish: " << file << "!" << std::endl;
+ return false;
+ }
+
+ m_nlsr.loadCertToPublish(idCert);
+ }
+
+ return true;
+}
+
}//namespace NLSR
diff --git a/src/conf-file-processor.hpp b/src/conf-file-processor.hpp
index f7d8f1e..cc715b0 100644
--- a/src/conf-file-processor.hpp
+++ b/src/conf-file-processor.hpp
@@ -67,7 +67,12 @@
bool
processConfSectionAdvertising(boost::property_tree::ptree SectionAttributeTree);
+ bool
+ processConfSectionSecurity(boost::property_tree::ptree SectionAttributeTree);
+
private:
+ typedef boost::property_tree::ptree ConfigSection;
+
std::string m_confFileName;
Nlsr& m_nlsr;
};
diff --git a/src/hello-protocol.cpp b/src/hello-protocol.cpp
index cd82e27..91b68a9 100644
--- a/src/hello-protocol.cpp
+++ b/src/hello-protocol.cpp
@@ -41,7 +41,7 @@
i.setInterestLifetime(ndn::time::seconds(seconds));
i.setMustBeFresh(true);
m_nlsr.getNlsrFace().expressInterest(i,
- ndn::bind(&HelloProtocol::processContent,
+ ndn::bind(&HelloProtocol::onContent,
this,
_1, _2),
ndn::bind(&HelloProtocol::processInterestTimedOut,
@@ -90,7 +90,7 @@
data.setFreshnessPeriod(ndn::time::seconds(10)); // 10 sec
data.setContent(reinterpret_cast<const uint8_t*>(INFO_COMPONENT.c_str()),
INFO_COMPONENT.size());
- m_keyChain.sign(data);
+ m_nlsr.getKeyChain().sign(data, m_nlsr.getDefaultCertName());
std::cout << ">> D: " << data << std::endl;
_LOG_DEBUG("Sending out data for name: " << data.getName());
m_nlsr.getNlsrFace().put(data);
@@ -148,12 +148,19 @@
}
}
+void
+HelloProtocol::onContent(const ndn::Interest& interest, const ndn::Data& data)
+{
+ m_nlsr.getValidator().validate(data,
+ ndn::bind(&HelloProtocol::onContentValidated, this, _1),
+ ndn::bind(&HelloProtocol::onContentValidationFailed,
+ this, _1, _2));
+}
void
-HelloProtocol::processContent(const ndn::Interest& interest,
- const ndn::Data& data)
+HelloProtocol::onContentValidated(const ndn::shared_ptr<const ndn::Data>& data)
{
- ndn::Name dataName = data.getName();
+ ndn::Name dataName = data->getName();
std::cout << "Data received for name: " << dataName << std::endl;
_LOG_DEBUG("Data received for name: " << dataName);
if (dataName.get(-3).toUri() == INFO_COMPONENT) {
@@ -195,4 +202,11 @@
}
}
+void
+HelloProtocol::onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
+ const std::string& msg)
+{
+ _LOG_DEBUG("Validation Error: " << msg);
+}
+
} //namespace nlsr
diff --git a/src/hello-protocol.hpp b/src/hello-protocol.hpp
index fc84457..ac0433a 100644
--- a/src/hello-protocol.hpp
+++ b/src/hello-protocol.hpp
@@ -58,11 +58,17 @@
processInterestTimedOut(const ndn::Interest& interest);
void
- processContent(const ndn::Interest& interest, const ndn::Data& data);
+ onContent(const ndn::Interest& interest, const ndn::Data& data);
+
+ void
+ onContentValidated(const ndn::shared_ptr<const ndn::Data>& data);
+
+ void
+ onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data,
+ const std::string& msg);
private:
Nlsr& m_nlsr;
- ndn::KeyChain m_keyChain;
static const std::string INFO_COMPONENT;
};
diff --git a/src/lsdb.cpp b/src/lsdb.cpp
index e3d3dd5..bb1150e 100644
--- a/src/lsdb.cpp
+++ b/src/lsdb.cpp
@@ -755,7 +755,7 @@
interest.setInterestLifetime(ndn::time::seconds(interestLifeTime));
interest.setMustBeFresh(true);
m_nlsr.getNlsrFace().expressInterest(interest,
- ndn::bind(&Lsdb::processContent,
+ ndn::bind(&Lsdb::onContent,
this, _1, _2),
ndn::bind(&Lsdb::processInterestTimedOut,
this, _1, timeoutCount));
@@ -819,8 +819,7 @@
std::string content = nameLsa->getData();
data.setContent(reinterpret_cast<const uint8_t*>(content.c_str()),
content.size());
- m_keyChain.sign(data);
- //std::cout << ">> D: " << data << std::endl;
+ m_nlsr.getKeyChain().sign(data, m_nlsr.getDefaultCertName());
m_nlsr.getNlsrFace().put(data);
}
}
@@ -840,8 +839,7 @@
std::string content = adjLsa->getData();
data.setContent(reinterpret_cast<const uint8_t*>(content.c_str()),
content.size());
- m_keyChain.sign(data);
- //std::cout << ">> D: " << data << std::endl;
+ m_nlsr.getKeyChain().sign(data, m_nlsr.getDefaultCertName());
m_nlsr.getNlsrFace().put(data);
}
}
@@ -861,20 +859,28 @@
std::string content = corLsa->getData();
data.setContent(reinterpret_cast<const uint8_t*>(content.c_str()),
content.size());
- m_keyChain.sign(data);
- //std::cout << ">> D: " << data << std::endl;
+ m_nlsr.getKeyChain().sign(data, m_nlsr.getDefaultCertName());
m_nlsr.getNlsrFace().put(data);
}
}
}
void
-Lsdb::processContent(const ndn::Interest& interest, const ndn::Data& data)
+Lsdb::onContent(const ndn::Interest& interest, const ndn::Data& data)
{
- const ndn::Name& dataName = data.getName();
- std::cout << "Data received for LSA(name): " << dataName << std::endl;
+ m_nlsr.getValidator().validate(data,
+ ndn::bind(&Lsdb::onContentValidated, this, _1),
+ ndn::bind(&Lsdb::onContentValidationFailed, this, _1, _2));
+
+}
+
+void
+Lsdb::onContentValidated(const ndn::shared_ptr<const ndn::Data>& data)
+{
+ const ndn::Name& dataName = data->getName();
+ std::cout << "Data received for name: " << dataName << std::endl;
_LOG_DEBUG("Data received for LSA(name): " << dataName);
- string dataContent(reinterpret_cast<const char*>(data.getContent().value()));
+ string dataContent(reinterpret_cast<const char*>(data->getContent().value()));
string chkString("LSA");
int32_t lsaPosition = util::getNameComponentPosition(dataName, chkString);
if (lsaPosition >= 0) {
@@ -909,6 +915,12 @@
}
void
+Lsdb::onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const std::string& msg)
+{
+ std::cerr << "Validation Error: " << msg << std::endl;
+}
+
+void
Lsdb::processContentNameLsa(const ndn::Name& lsaKey,
uint32_t lsSeqNo, std::string& dataContent)
{
@@ -1003,4 +1015,3 @@
}
}//namespace nlsr
-
diff --git a/src/lsdb.hpp b/src/lsdb.hpp
index 56c4245..79d6e2c 100644
--- a/src/lsdb.hpp
+++ b/src/lsdb.hpp
@@ -183,7 +183,13 @@
uint32_t interestedlsSeqNo);
void
- processContent(const ndn::Interest& interest, const ndn::Data& data);
+ onContent(const ndn::Interest& interest, const ndn::Data& data);
+
+ void
+ onContentValidated(const ndn::shared_ptr<const ndn::Data>& data);
+
+ void
+ onContentValidationFailed(const ndn::shared_ptr<const ndn::Data>& data, const std::string& msg);
void
processContentNameLsa(const ndn::Name& lsaKey,
@@ -208,7 +214,6 @@
cancelScheduleLsaExpiringEvent(ndn::EventId eid);
Nlsr& m_nlsr;
- ndn::KeyChain m_keyChain;
std::list<NameLsa> m_nameLsdb;
std::list<AdjLsa> m_adjLsdb;
std::list<CoordinateLsa> m_corLsdb;
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index 833b650..02a366b 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -89,7 +89,7 @@
(*it).getConnectingFaceUri(), (*it).getLinkCost(), 31536000);
m_fib.setStrategy((*it).getName(), strategy);
}
-
+
m_fib.setStrategy(m_confParam.getChronosyncPrefix(), strategy);
m_fib.setStrategy(m_confParam.getLsaPrefix(), strategy);
}
@@ -123,6 +123,70 @@
m_syncLogicHandler.createSyncSocket(boost::ref(*this));
//m_interestManager.scheduleInfoInterest(10);
m_helloProtocol.scheduleInterest(10);
+
+ intializeKey();
+ registerKeyPrefix();
+}
+
+void
+Nlsr::intializeKey()
+{
+ m_defaultIdentity = m_confParam.getRouterPrefix();
+ m_defaultIdentity.append("NLSR");
+
+ ndn::Name keyName = m_keyChain.generateRsaKeyPairAsDefault(m_defaultIdentity);
+
+ ndn::shared_ptr<ndn::IdentityCertificate> certificate = m_keyChain.selfSign(keyName);
+ m_keyChain.signByIdentity(*certificate, m_confParam.getRouterPrefix());
+
+ m_keyChain.addCertificateAsIdentityDefault(*certificate);
+ loadCertToPublish(certificate);
+
+ m_defaultCertName = certificate->getName();
+}
+
+void
+Nlsr::registerKeyPrefix()
+{
+ ndn::Name keyPrefix = DEFAULT_BROADCAST_PREFIX;
+ keyPrefix.append("KEYS");
+ m_nlsrFace.setInterestFilter(keyPrefix,
+ ndn::bind(&Nlsr::onKeyInterest,
+ this, _1, _2),
+ ndn::bind(&Nlsr::onKeyPrefixRegSuccess, this, _1),
+ ndn::bind(&Nlsr::registrationFailed, this, _1));
+
+}
+
+void
+Nlsr::onKeyInterest(const ndn::Name& name, const ndn::Interest& interest)
+{
+ const ndn::Name& interestName = interest.getName();
+
+ ndn::Name certName = interestName.getSubName(name.size());
+
+ if (certName[-2].toUri() == "ID-CERT")
+ {
+ certName = certName.getPrefix(-1);
+ }
+ else if (certName[-1].toUri() != "ID-CERT")
+ return; //Wrong key interest.
+
+ ndn::shared_ptr<const ndn::IdentityCertificate> cert = getCertificate(certName);
+
+ if (!static_cast<bool>(cert))
+ return; // cert is not found
+
+ Data data(interestName);
+ data.setContent(cert->wireEncode());
+ m_keyChain.signWithSha256(data);
+
+ m_nlsrFace.put(data);
+}
+
+void
+Nlsr::onKeyPrefixRegSuccess(const ndn::Name& name)
+{
}
void
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index 8db25c2..b0d5126 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -28,6 +28,7 @@
#include <ndn-cxx/face.hpp>
#include <ndn-cxx/security/key-chain.hpp>
+#include <ndn-cxx/security/certificate-cache-ttl.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include "conf-parameter.hpp"
@@ -41,9 +42,13 @@
#include "communication/sync-logic-handler.hpp"
#include "hello-protocol.hpp"
+#include "validator.hpp"
+
namespace nlsr {
+static ndn::Name DEFAULT_BROADCAST_PREFIX("/ndn/broadcast");
+
class Nlsr
{
class Error : public std::runtime_error
@@ -75,6 +80,9 @@
, m_namePrefixTable(*this)
, m_syncLogicHandler(m_nlsrFace.getIoService())
, m_helloProtocol(*this)
+
+ , m_certificateCache(new ndn::CertificateCacheTtl(m_nlsrFace.getIoService()))
+ , m_validator(m_nlsrFace, DEFAULT_BROADCAST_PREFIX, m_certificateCache)
{}
void
@@ -255,11 +263,71 @@
void
initialize();
+ void
+ intializeKey();
+
+ void
+ loadValidator(boost::property_tree::ptree section,
+ const std::string& filename)
+ {
+ m_validator.load(section, filename);
+ }
+
+ Validator&
+ getValidator()
+ {
+ return m_validator;
+ }
+
+ void
+ loadCertToPublish(ndn::shared_ptr<ndn::IdentityCertificate> certificate)
+ {
+ if (static_cast<bool>(certificate))
+ m_certToPublish[certificate->getName().getPrefix(-1)] = certificate; // key is cert name
+ // without version
+ }
+
+ ndn::shared_ptr<const ndn::IdentityCertificate>
+ getCertificate(const ndn::Name& certificateNameWithoutVersion)
+ {
+ CertMap::iterator it = m_certToPublish.find(certificateNameWithoutVersion);
+
+ if (it != m_certToPublish.end())
+ {
+ return it->second;
+ }
+
+ return m_certificateCache->getCertificate(certificateNameWithoutVersion);
+ }
+
+ ndn::KeyChain&
+ getKeyChain()
+ {
+ return m_keyChain;
+ }
+
+ const ndn::Name&
+ getDefaultCertName()
+ {
+ return m_defaultCertName;
+ }
+
private:
void
registerPrefixes();
+ void
+ registerKeyPrefix();
+
+ void
+ onKeyInterest(const ndn::Name& name, const ndn::Interest& interest);
+
+ void
+ onKeyPrefixRegSuccess(const ndn::Name& name);
+
private:
+ typedef std::map<ndn::Name, ndn::shared_ptr<ndn::IdentityCertificate> > CertMap;
+
ndn::Face m_nlsrFace;
ndn::Scheduler m_scheduler;
ConfParameter m_confParam;
@@ -279,6 +347,13 @@
SyncLogicHandler m_syncLogicHandler;
int32_t m_apiPort;
HelloProtocol m_helloProtocol;
+
+ ndn::shared_ptr<ndn::CertificateCacheTtl> m_certificateCache;
+ CertMap m_certToPublish;
+ Validator m_validator;
+ ndn::KeyChain m_keyChain;
+ ndn::Name m_defaultIdentity;
+ ndn::Name m_defaultCertName;
};
} //namespace nlsr
diff --git a/src/validator.hpp b/src/validator.hpp
new file mode 100644
index 0000000..fd4bac8
--- /dev/null
+++ b/src/validator.hpp
@@ -0,0 +1,134 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014 The University of Memphis,
+ * Regents of the University of California
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NLSR, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author Yingdi Yu <yingdi@cs.ucla.edu>
+ **/
+
+#ifndef NLSR_VALIDATOR_HPP
+#define NLSR_VALIDATOR_HPP
+
+#include <ndn-cxx/security/validator-config.hpp>
+
+namespace nlsr {
+
+class Validator : public ndn::ValidatorConfig
+{
+public:
+ class Error : public ndn::ValidatorConfig::Error
+ {
+ public:
+ explicit
+ Error(const std::string& what)
+ : ndn::ValidatorConfig::Error(what)
+ {
+ }
+ };
+
+ explicit
+ Validator(ndn::Face& face,
+ const ndn::Name broadcastPrefix,
+ const ndn::shared_ptr<ndn::CertificateCache>& cache,
+ const int stepLimit = 10)
+ : ndn::ValidatorConfig(face, cache, stepLimit)
+ , m_broadcastPrefix(broadcastPrefix)
+ {
+ m_broadcastPrefix.append("KEYS");
+ }
+
+ virtual
+ ~Validator()
+ {
+ }
+
+ const ndn::Name&
+ getBroadcastPrefix()
+ {
+ return m_broadcastPrefix;
+ }
+
+ void
+ setBroadcastPrefix(const ndn::Name& broadcastPrefix)
+ {
+ m_broadcastPrefix = broadcastPrefix;
+ }
+
+protected:
+ typedef std::vector<ndn::shared_ptr<ndn::ValidationRequest> > NextSteps;
+
+ virtual void
+ checkPolicy(const ndn::Data& data,
+ int nSteps,
+ const ndn::OnDataValidated& onValidated,
+ const ndn::OnDataValidationFailed& onValidationFailed,
+ NextSteps& nextSteps)
+ {
+ ndn::ValidatorConfig::checkPolicy(data, nSteps,
+ onValidated, onValidationFailed,
+ nextSteps);
+
+ for (NextSteps::iterator it = nextSteps.begin(); it != nextSteps.end(); it++)
+ {
+ ndn::Name broadcastName = m_broadcastPrefix;
+ broadcastName.append((*it)->m_interest.getName());
+
+ (*it)->m_interest.setName(broadcastName);
+ }
+ }
+
+ virtual void
+ checkPolicy(const ndn::Interest& interest,
+ int nSteps,
+ const ndn::OnInterestValidated& onValidated,
+ const ndn::OnInterestValidationFailed& onValidationFailed,
+ NextSteps& nextSteps)
+ {
+ ndn::ValidatorConfig::checkPolicy(interest, nSteps,
+ onValidated, onValidationFailed,
+ nextSteps);
+
+ for (NextSteps::iterator it = nextSteps.begin(); it != nextSteps.end(); it++)
+ {
+ ndn::Name broadcastName = m_broadcastPrefix;
+ broadcastName.append((*it)->m_interest.getName());
+
+ (*it)->m_interest.setName(broadcastName);
+ }
+
+ }
+
+ void
+ onData(const ndn::Interest& interest,
+ const ndn::Data& data,
+ const ndn::shared_ptr<ndn::ValidationRequest>& nextStep)
+ {
+
+ ndn::shared_ptr<ndn::Data> internalData = ndn::make_shared<ndn::Data>();
+ internalData->wireDecode(data.getContent().blockFromValue());
+ validate(*internalData,
+ nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_nSteps);
+ }
+
+private:
+ ndn::Name m_broadcastPrefix;
+};
+
+
+} // namespace nlsr
+
+#endif // NLSR_VALIDATOR_HPP