helpers: Several optimizations with command interest helpers
Both command interest helpers are now header only. TestCommandInterest
is combined with TestSignedInterest as a second test case under the same
test suite.
Change-Id: Ieb80b24d76ded516a3d40770b65fcc1afd3e00a5
diff --git a/src/helper/command-interest-generator.cpp b/src/helper/command-interest-generator.cpp
deleted file mode 100644
index 006d440..0000000
--- a/src/helper/command-interest-generator.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * See COPYING for copyright and distribution information.
- */
-
-#include "command-interest-generator.hpp"
-#include "../util/time.hpp"
-#include "../util/random.hpp"
-
-#include <unistd.h>
-
-namespace ndn
-{
-const Name CommandInterestGenerator::DEFAULT_CERTIFICATE_NAME = Name();
-
-CommandInterestGenerator::CommandInterestGenerator()
- : m_lastTimestamp(time::now() / 1000000)
-{}
-
-void
-CommandInterestGenerator::generate(Interest& interest,
- const Name& certificateName /*= DEFAULT_CERTIFICATE_NAME*/)
-{
- int64_t timestamp = time::now() / 1000000;
- while(timestamp == m_lastTimestamp)
- {
- usleep(1000); //Guarantee unqiueness of timestamp
- timestamp = time::now();
- }
-
- Name commandInterestName = interest.getName();
- commandInterestName
- .append(name::Component::fromNumber(timestamp))
- .append(name::Component::fromNumber(random::generateWord64()));
- interest.setName(commandInterestName);
-
- if(certificateName == DEFAULT_CERTIFICATE_NAME)
- m_keyChain.sign(interest);
- else
- m_keyChain.sign(interest, certificateName);
-
- m_lastTimestamp = timestamp;
-}
-
-void
-CommandInterestGenerator::generateWithIdentity(Interest& interest, const Name& identity)
-{
- int64_t timestamp = time::now() / 1000000;
- if(timestamp <= m_lastTimestamp)
- timestamp = m_lastTimestamp + 1;
-
- Name commandInterestName = interest.getName();
- commandInterestName
- .append(name::Component::fromNumber(timestamp))
- .append(name::Component::fromNumber(random::generateWord64()));
- interest.setName(commandInterestName);
-
- m_keyChain.signByIdentity(interest, identity);
-
- m_lastTimestamp = timestamp;
-}
-
-}//ndn
diff --git a/src/helper/command-interest-generator.hpp b/src/helper/command-interest-generator.hpp
deleted file mode 100644
index 70208f2..0000000
--- a/src/helper/command-interest-generator.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * See COPYING for copyright and distribution information.
- */
-
-#ifndef NDN_COMMAND_INTEREST_GENERATOR_HPP
-#define NDN_COMMAND_INTEREST_GENERATOR_HPP
-
-#include "../interest.hpp"
-#include "../security/key-chain.hpp"
-
-
-namespace ndn
-{
-
-class CommandInterestGenerator
-{
-public:
- static const Name DEFAULT_CERTIFICATE_NAME;
-
- CommandInterestGenerator();
-
- virtual
- ~CommandInterestGenerator() {}
-
- void
- generate(Interest& interest, const Name& certificateName = DEFAULT_CERTIFICATE_NAME);
-
- void
- generateWithIdentity(Interest& interest, const Name& identity);
-
-private:
- int64_t m_lastTimestamp;
- KeyChain m_keyChain;
-};
-
-}//ndn
-
-#endif
diff --git a/src/helper/command-interest-validator.cpp b/src/helper/command-interest-validator.cpp
deleted file mode 100644
index 396ee8f..0000000
--- a/src/helper/command-interest-validator.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * See COPYING for copyright and distribution information.
- */
-
-#include "command-interest-validator.hpp"
-
-namespace ndn
-{
-const ssize_t CommandInterestValidator::POS_SIG_VALUE = -1;
-const ssize_t CommandInterestValidator::POS_SIG_INFO = -2;
-const ssize_t CommandInterestValidator::POS_RANDOM_VAL = -3;
-const ssize_t CommandInterestValidator::POS_TIMESTAMP = -4;
-const int64_t CommandInterestValidator::GRACE_INTERVAL = 3000;
-
-void
-CommandInterestValidator::checkPolicy (const Interest& interest,
- int stepCount,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps)
-{
- try{
- Name interestName = interest.getName();
-
- Signature signature(interestName.get(POS_SIG_INFO).blockFromValue(),
- interestName.get(POS_SIG_VALUE).blockFromValue());
-
- SignatureSha256WithRsa sig(signature);
- const Name & keyLocatorName = sig.getKeyLocator().getName();
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
-
- //Check if command is in the trusted scope
- bool inScope = false;
- std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
- for(; scopeIt != m_trustScopeForInterest.end(); scopeIt++)
- {
- if(scopeIt->satisfy(interestName, keyName))
- {
- inScope = true;
- break;
- }
- }
- if(inScope == false)
- {
- onValidationFailed(interest.shared_from_this());
- return;
- }
-
- //Check if timestamp is valid
- uint64_t timestamp = interestName.get(POS_TIMESTAMP).toNumber();
- uint64_t current = static_cast<uint64_t>(time::now()/1000000);
- std::map<Name, uint64_t>::const_iterator timestampIt = m_lastTimestamp.find(keyName);
- if(timestampIt == m_lastTimestamp.end())
- {
- if(timestamp > (current + m_graceInterval) || (timestamp + m_graceInterval) < current)
- {
- onValidationFailed(interest.shared_from_this());
- return;
- }
- }
- else if(m_lastTimestamp[keyName] >= timestamp)
- {
- onValidationFailed(interest.shared_from_this());
- return;
- }
-
- //Check if signature can be verified
- Name signedName = interestName.getPrefix(-1);
- Buffer signedBlob = Buffer(signedName.wireEncode().value(), signedName.wireEncode().value_size()); //These two lines could be optimized
- if(!Validator::verifySignature(signedBlob.buf(), signedBlob.size(), sig, m_trustAnchorsForInterest[keyName]))
- {
- onValidationFailed(interest.shared_from_this());
- return;
- }
-
- m_lastTimestamp[keyName] = timestamp;
- onValidated(interest.shared_from_this());
- return;
-
- }catch(...){
- onValidationFailed(interest.shared_from_this());
- }
-}
-
-}//ndn
diff --git a/src/helper/command-interest-validator.hpp b/src/helper/command-interest-validator.hpp
deleted file mode 100644
index 7021a78..0000000
--- a/src/helper/command-interest-validator.hpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
-/**
- * Copyright (C) 2013 Regents of the University of California.
- * See COPYING for copyright and distribution information.
- */
-
-#ifndef NDN_COMMAND_INTEREST_VALIDATOR_HPP
-#define NDN_COMMAND_INTEREST_VALIDATOR_HPP
-
-#include "../security/validator.hpp"
-#include "../security/identity-certificate.hpp"
-#include "../security/sec-rule-specific.hpp"
-
-
-namespace ndn
-{
-
-class CommandInterestValidator : public Validator
-{
-public:
- static const ssize_t POS_SIG_VALUE;
- static const ssize_t POS_SIG_INFO;
- static const ssize_t POS_RANDOM_VAL;
- static const ssize_t POS_TIMESTAMP;
- static const int64_t GRACE_INTERVAL;
-
- CommandInterestValidator(int64_t graceInterval = GRACE_INTERVAL)
- { m_graceInterval = (graceInterval < 0 ? GRACE_INTERVAL : graceInterval); }
-
- virtual
- ~CommandInterestValidator() {}
-
- inline void
- addInterestRule(const std::string& regex, const IdentityCertificate& certificate);
-
- inline void
- addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey);
-
-protected:
- virtual void
- checkPolicy (const Data& data,
- int stepCount,
- const OnDataValidated &onValidated,
- const OnDataValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps)
- { onValidationFailed(data.shared_from_this()); }
-
- virtual void
- checkPolicy (const Interest& interest,
- int stepCount,
- const OnInterestValidated &onValidated,
- const OnInterestValidationFailed &onValidationFailed,
- std::vector<shared_ptr<ValidationRequest> > &nextSteps);
-private:
- int64_t m_graceInterval; //ms
- std::map<Name, PublicKey> m_trustAnchorsForInterest;
- std::list<SecRuleSpecific> m_trustScopeForInterest;
- std::map<Name, uint64_t> m_lastTimestamp;
-};
-
-void
-CommandInterestValidator::addInterestRule(const std::string& regex, const IdentityCertificate& certificate)
-{
- Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
- addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
-}
-
-void
-CommandInterestValidator::addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey)
-{
- m_trustAnchorsForInterest[keyName] = publicKey;
- shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
- shared_ptr<Regex> signerRegex = Regex::fromName(keyName, true);
- m_trustScopeForInterest.push_back(SecRuleSpecific(interestRegex, signerRegex));
-}
-
-}//ndn
-
-#endif
diff --git a/src/helpers/command-interest-generator.hpp b/src/helpers/command-interest-generator.hpp
new file mode 100644
index 0000000..8b4d796
--- /dev/null
+++ b/src/helpers/command-interest-generator.hpp
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_HELPERS_COMMAND_INTEREST_GENERATOR_HPP
+#define NDN_HELPERS_COMMAND_INTEREST_GENERATOR_HPP
+
+#include "../interest.hpp"
+#include "../security/key-chain.hpp"
+#include "../util/time.hpp"
+#include "../util/random.hpp"
+
+namespace ndn {
+
+/**
+ * @brief Helper class to generate CommandInterests
+ *
+ * @see http://redmine.named-data.net/projects/nfd/wiki/Command_Interests
+ */
+class CommandInterestGenerator
+{
+public:
+ static const Name DEFAULT_CERTIFICATE_NAME;
+
+ CommandInterestGenerator()
+ : m_lastTimestamp(time::now() / 1000000)
+ {
+ }
+
+ virtual
+ ~CommandInterestGenerator()
+ {
+ }
+
+ void
+ generate(Interest& interest, const Name& certificateName = Name());
+
+ void
+ generateWithIdentity(Interest& interest, const Name& identity);
+
+private:
+ int64_t m_lastTimestamp;
+ KeyChain m_keyChain;
+};
+
+
+inline void
+CommandInterestGenerator::generate(Interest& interest,
+ const Name& certificateName /*= Name()*/)
+{
+ int64_t timestamp = time::now() / 1000000;
+ while(timestamp == m_lastTimestamp)
+ {
+ usleep(1000); //Guarantee unqiueness of timestamp
+ timestamp = time::now();
+ }
+
+ Name commandInterestName = interest.getName();
+ commandInterestName
+ .append(name::Component::fromNumber(timestamp))
+ .append(name::Component::fromNumber(random::generateWord64()));
+ interest.setName(commandInterestName);
+
+ if(certificateName.empty())
+ m_keyChain.sign(interest);
+ else
+ m_keyChain.sign(interest, certificateName);
+
+ m_lastTimestamp = timestamp;
+}
+
+inline void
+CommandInterestGenerator::generateWithIdentity(Interest& interest, const Name& identity)
+{
+ int64_t timestamp = time::now() / 1000000;
+ if(timestamp <= m_lastTimestamp)
+ timestamp = m_lastTimestamp + 1;
+
+ Name commandInterestName = interest.getName();
+ commandInterestName
+ .append(name::Component::fromNumber(timestamp))
+ .append(name::Component::fromNumber(random::generateWord64()));
+ interest.setName(commandInterestName);
+
+ m_keyChain.signByIdentity(interest, identity);
+
+ m_lastTimestamp = timestamp;
+}
+
+
+} // namespace ndn
+
+#endif // NDN_HELPERS_COMMAND_INTEREST_GENERATOR_HPP
diff --git a/src/helpers/command-interest-validator.hpp b/src/helpers/command-interest-validator.hpp
new file mode 100644
index 0000000..3c8764e
--- /dev/null
+++ b/src/helpers/command-interest-validator.hpp
@@ -0,0 +1,163 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
+#define NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP
+
+#include "../security/validator.hpp"
+#include "../security/identity-certificate.hpp"
+#include "../security/sec-rule-specific.hpp"
+
+namespace ndn {
+
+class CommandInterestValidator : public Validator
+{
+public:
+ enum {
+ POS_SIG_VALUE = -1,
+ POS_SIG_INFO = -2,
+ POS_RANDOM_VAL = -3,
+ POS_TIMESTAMP = -4,
+
+ GRACE_INTERVAL = 3000 // ms
+ };
+
+ CommandInterestValidator(int64_t graceInterval = GRACE_INTERVAL/*ms*/)
+ {
+ m_graceInterval = (graceInterval < 0 ? GRACE_INTERVAL : graceInterval);
+ }
+
+ virtual
+ ~CommandInterestValidator()
+ {
+ }
+
+ void
+ addInterestRule(const std::string& regex, const IdentityCertificate& certificate);
+
+ void
+ addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey);
+
+protected:
+ virtual void
+ checkPolicy (const Data& data,
+ int stepCount,
+ const OnDataValidated &onValidated,
+ const OnDataValidationFailed &onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> > &nextSteps)
+ {
+ onValidationFailed(data.shared_from_this());
+ }
+
+ virtual void
+ checkPolicy (const Interest& interest,
+ int stepCount,
+ const OnInterestValidated &onValidated,
+ const OnInterestValidationFailed &onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> > &nextSteps);
+private:
+ int64_t m_graceInterval; //ms
+ std::map<Name, PublicKey> m_trustAnchorsForInterest;
+ std::list<SecRuleSpecific> m_trustScopeForInterest;
+ std::map<Name, uint64_t> m_lastTimestamp;
+};
+
+inline void
+CommandInterestValidator::addInterestRule(const std::string& regex, const IdentityCertificate& certificate)
+{
+ Name keyName = IdentityCertificate::certificateNameToPublicKeyName(certificate.getName());
+ addInterestRule(regex, keyName, certificate.getPublicKeyInfo());
+}
+
+inline void
+CommandInterestValidator::addInterestRule(const std::string& regex, const Name& keyName, const PublicKey& publicKey)
+{
+ m_trustAnchorsForInterest[keyName] = publicKey;
+ shared_ptr<Regex> interestRegex = make_shared<Regex>(regex);
+ shared_ptr<Regex> signerRegex = Regex::fromName(keyName, true);
+ m_trustScopeForInterest.push_back(SecRuleSpecific(interestRegex, signerRegex));
+}
+
+inline void
+CommandInterestValidator::checkPolicy (const Interest& interest,
+ int stepCount,
+ const OnInterestValidated &onValidated,
+ const OnInterestValidationFailed &onValidationFailed,
+ std::vector<shared_ptr<ValidationRequest> > &nextSteps)
+{
+ try
+ {
+ const Name& interestName = interest.getName();
+
+ if (interestName.size() < 4)
+ return onValidationFailed(interest.shared_from_this());
+
+ Signature signature(interestName[POS_SIG_INFO].blockFromValue(),
+ interestName[POS_SIG_VALUE].blockFromValue());
+
+ SignatureSha256WithRsa sig(signature);
+ const Name& keyLocatorName = sig.getKeyLocator().getName();
+ Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
+
+ //Check if command is in the trusted scope
+ bool inScope = false;
+ for(std::list<SecRuleSpecific>::iterator scopeIt = m_trustScopeForInterest.begin();
+ scopeIt != m_trustScopeForInterest.end();
+ ++scopeIt)
+ {
+ if(scopeIt->satisfy(interestName, keyName))
+ {
+ inScope = true;
+ break;
+ }
+ }
+ if(inScope == false)
+ {
+ onValidationFailed(interest.shared_from_this());
+ return;
+ }
+
+ //Check if timestamp is valid
+ uint64_t timestamp = interestName.get(POS_TIMESTAMP).toNumber();
+ uint64_t current = static_cast<uint64_t>(time::now()/1000000);
+ std::map<Name, uint64_t>::const_iterator timestampIt = m_lastTimestamp.find(keyName);
+ if(timestampIt == m_lastTimestamp.end())
+ {
+ if(timestamp > (current + m_graceInterval) || (timestamp + m_graceInterval) < current)
+ {
+ onValidationFailed(interest.shared_from_this());
+ return;
+ }
+ }
+ else if(m_lastTimestamp[keyName] >= timestamp)
+ {
+ onValidationFailed(interest.shared_from_this());
+ return;
+ }
+
+ if(!Validator::verifySignature(interestName.wireEncode().value(),
+ interestName.wireEncode().value_size() - interestName[-1].size(),
+ sig, m_trustAnchorsForInterest[keyName]))
+ {
+ onValidationFailed(interest.shared_from_this());
+ return;
+ }
+
+ m_lastTimestamp[keyName] = timestamp;
+ onValidated(interest.shared_from_this());
+ return;
+
+ }
+ catch(...)
+ {
+ onValidationFailed(interest.shared_from_this());
+ }
+}
+
+
+} // namespace ndn
+
+#endif // NDN_HELPERS_COMMAND_INTEREST_VALIDATOR_HPP