security: Add 'type dir' trust-anchor in ValidatorConfig
Refs: #1483
Change-Id: I4a34947026edc929624b64fe0a996df36d3fb8ed
diff --git a/src/security/validator-config.cpp b/src/security/validator-config.cpp
index b23a47c..a0a35d8 100644
--- a/src/security/validator-config.cpp
+++ b/src/security/validator-config.cpp
@@ -252,6 +252,7 @@
if (static_cast<bool>(idCert))
{
BOOST_ASSERT(idCert->getName().size() >= 1);
+ m_staticContainer.add(idCert);
m_anchors[idCert->getName().getPrefix(-1)] = idCert;
}
else
@@ -278,6 +279,7 @@
if (static_cast<bool>(idCert))
{
BOOST_ASSERT(idCert->getName().size() >= 1);
+ m_staticContainer.add(idCert);
m_anchors[idCert->getName().getPrefix(-1)] = idCert;
}
else
@@ -285,6 +287,57 @@
return;
}
+ else if (boost::iequals(type, "dir"))
+ {
+ if (propertyIt == configSection.end() || !boost::iequals(propertyIt->first, "dir"))
+ throw Error("Expect <trust-anchor.dir>!");
+
+ std::string dirString(propertyIt->second.data());
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ {
+ if (boost::iequals(propertyIt->first, "refresh"))
+ {
+ using namespace boost::filesystem;
+
+ time::nanoseconds refresh = getRefreshPeriod(propertyIt->second.data());
+ propertyIt++;
+
+ if (propertyIt != configSection.end())
+ throw Error("Expect the end of trust-anchor!");
+
+ path dirPath = absolute(dirString, path(filename).parent_path());
+
+ m_dynamicContainers.push_back(DynamicTrustAnchorContainer(dirPath, true, refresh));
+
+ m_dynamicContainers.rbegin()->setLastRefresh(time::system_clock::now() - refresh);
+
+ return;
+ }
+ else
+ throw Error("Expect <trust-anchor.refresh>!");
+ }
+ else
+ {
+ using namespace boost::filesystem;
+
+ path dirPath = absolute(dirString, path(filename).parent_path());
+
+ directory_iterator end;
+
+ for (directory_iterator it(dirPath); it != end; it++)
+ {
+ shared_ptr<IdentityCertificate> idCert =
+ io::load<IdentityCertificate>(it->path().string());
+
+ if (static_cast<bool>(idCert))
+ m_staticContainer.add(idCert);
+ }
+
+ return;
+ }
+ }
else if (boost::iequals(type, "any"))
{
m_shouldValidate = false;
@@ -293,6 +346,84 @@
throw Error("Unsupported trust-anchor.type: " + type);
}
+time::nanoseconds
+ValidatorConfig::getRefreshPeriod(std::string inputString)
+{
+ char unit = inputString[inputString.size() - 1];
+ std::string refreshString = inputString.substr(0, inputString.size() - 1);
+
+ uint32_t number;
+
+ try
+ {
+ number = boost::lexical_cast<uint32_t>(refreshString);
+ }
+ catch (boost::bad_lexical_cast&)
+ {
+ throw Error("Bad number: " + refreshString);
+ }
+
+ if (number == 0)
+ return getDefaultRefreshPeriod();
+
+ switch (unit)
+ {
+ case 'h':
+ return time::duration_cast<time::nanoseconds>(time::hours(number));
+ case 'm':
+ return time::duration_cast<time::nanoseconds>(time::minutes(number));
+ case 's':
+ return time::duration_cast<time::nanoseconds>(time::seconds(number));
+ default:
+ throw Error(std::string("Wrong time unit: ") + unit);
+ }
+}
+
+void
+ValidatorConfig::refreshAnchors()
+{
+ time::system_clock::TimePoint now = time::system_clock::now();
+
+ bool isRefreshed = false;
+
+ for (DynamicContainers::iterator cIt = m_dynamicContainers.begin();
+ cIt != m_dynamicContainers.end(); cIt++)
+ {
+ if (cIt->getLastRefresh() + cIt->getRefreshPeriod() < now)
+ {
+ isRefreshed = true;
+ cIt->refresh();
+ cIt->setLastRefresh(now);
+ }
+ else
+ break;
+ }
+
+ if (isRefreshed)
+ {
+ m_anchors.clear();
+
+ for (CertificateList::const_iterator it = m_staticContainer.getAll().begin();
+ it != m_staticContainer.getAll().end(); it++)
+ {
+ m_anchors[(*it)->getName().getPrefix(-1)] = (*it);
+ }
+
+ for (DynamicContainers::iterator cIt = m_dynamicContainers.begin();
+ cIt != m_dynamicContainers.end(); cIt++)
+ {
+ const CertificateList& certList = cIt->getAll();
+
+ for (CertificateList::const_iterator it = certList.begin();
+ it != certList.end(); it++)
+ {
+ m_anchors[(*it)->getName().getPrefix(-1)] = (*it);
+ }
+ }
+ m_dynamicContainers.sort(ValidatorConfig::compareDynamicContainer);
+ }
+}
+
void
ValidatorConfig::checkPolicy(const Data& data,
int nSteps,
@@ -303,10 +434,6 @@
if (!m_shouldValidate)
return onValidated(data.shared_from_this());
- if (m_stepLimit == nSteps)
- return onValidationFailed(data.shared_from_this(),
- "Maximum steps of validation reached");
-
bool isMatched = false;
int8_t checkResult = -1;
@@ -342,10 +469,6 @@
if (!m_shouldValidate)
return onValidated(interest.shared_from_this());
- if (m_stepLimit == nSteps)
- return onValidationFailed(interest.shared_from_this(),
- "Maximum steps of validation reached");
-
bool isMatched = false;
int8_t checkResult = -1;
@@ -375,5 +498,35 @@
}
}
+void
+ValidatorConfig::DynamicTrustAnchorContainer::refresh()
+{
+ using namespace boost::filesystem;
+
+ m_certificates.clear();
+
+ if (m_isDir)
+ {
+ directory_iterator end;
+
+ for (directory_iterator it(m_path); it != end; it++)
+ {
+ shared_ptr<IdentityCertificate> idCert =
+ io::load<IdentityCertificate>(it->path().string());
+
+ if (static_cast<bool>(idCert))
+ m_certificates.push_back(idCert);
+ }
+ }
+ else
+ {
+ shared_ptr<IdentityCertificate> idCert =
+ io::load<IdentityCertificate>(m_path.string());
+
+ if (static_cast<bool>(idCert))
+ m_certificates.push_back(idCert);
+ }
+}
+
} // namespace ndn
diff --git a/src/security/validator-config.hpp b/src/security/validator-config.hpp
index 6759ee1..a55797a 100644
--- a/src/security/validator-config.hpp
+++ b/src/security/validator-config.hpp
@@ -33,6 +33,7 @@
class ValidatorConfig : public Validator
{
+
public:
class Error : public Validator::Error
{
@@ -122,12 +123,95 @@
onConfigTrustAnchor(const security::conf::ConfigSection& section,
const std::string& filename);
+ time::nanoseconds
+ getRefreshPeriod(std::string refreshString);
+
+ inline time::nanoseconds
+ getDefaultRefreshPeriod();
+
+ void
+ refreshAnchors();
+
+
private:
+
+ class TrustAnchorContainer
+ {
+ public:
+ TrustAnchorContainer()
+ {
+ }
+
+ const std::list<shared_ptr<IdentityCertificate> >&
+ getAll() const
+ {
+ return m_certificates;
+ }
+
+ void
+ add(shared_ptr<IdentityCertificate> certificate)
+ {
+ m_certificates.push_back(certificate);
+ }
+
+ protected:
+ std::list<shared_ptr<IdentityCertificate> > m_certificates;
+ };
+
+ class DynamicTrustAnchorContainer : public TrustAnchorContainer
+ {
+ public:
+ DynamicTrustAnchorContainer(const boost::filesystem::path& path, bool isDir,
+ time::nanoseconds refreshPeriod)
+ : m_path(path)
+ , m_isDir(isDir)
+ , m_refreshPeriod(refreshPeriod)
+ {
+ }
+
+ void
+ setLastRefresh(const time::system_clock::TimePoint& lastRefresh)
+ {
+ m_lastRefresh = lastRefresh;
+ }
+
+ const time::system_clock::TimePoint&
+ getLastRefresh() const
+ {
+ return m_lastRefresh;
+ }
+
+ const time::nanoseconds&
+ getRefreshPeriod() const
+ {
+ return m_refreshPeriod;
+ }
+
+ void
+ refresh();
+
+ private:
+ boost::filesystem::path m_path;
+ bool m_isDir;
+
+ time::system_clock::TimePoint m_lastRefresh;
+ time::nanoseconds m_refreshPeriod;
+ };
+
typedef security::conf::Rule<Interest> InterestRule;
typedef security::conf::Rule<Data> DataRule;
typedef std::vector<shared_ptr<InterestRule> > InterestRuleList;
typedef std::vector<shared_ptr<DataRule> > DataRuleList;
typedef std::map<Name, shared_ptr<IdentityCertificate> > AnchorList;
+ typedef std::list<DynamicTrustAnchorContainer> DynamicContainers; // sorted by m_lastRefresh
+ typedef std::list<shared_ptr<IdentityCertificate> > CertificateList;
+
+ static inline bool
+ compareDynamicContainer(const DynamicTrustAnchorContainer& containerA,
+ const DynamicTrustAnchorContainer& containerB)
+ {
+ return (containerA.getLastRefresh() < containerB.getLastRefresh());
+ }
/**
* @brief gives whether validation should be preformed
@@ -141,7 +225,11 @@
InterestRuleList m_interestRules;
DataRuleList m_dataRules;
+
AnchorList m_anchors;
+ TrustAnchorContainer m_staticContainer;
+ DynamicContainers m_dynamicContainers;
+
};
inline void
@@ -150,7 +238,12 @@
m_certificateCache->reset();
m_interestRules.clear();
m_dataRules.clear();
+
m_anchors.clear();
+
+ m_staticContainer = TrustAnchorContainer();
+
+ m_dynamicContainers.clear();
}
inline bool
@@ -191,6 +284,8 @@
shared_ptr<const Certificate> trustedCert;
+ refreshAnchors();
+
AnchorList::const_iterator it = m_anchors.find(keyLocatorName);
if (m_anchors.end() == it)
trustedCert = m_certificateCache->getCertificate(keyLocatorName);
@@ -207,6 +302,10 @@
}
else
{
+ if (m_stepLimit == nSteps)
+ return onValidationFailed(packet.shared_from_this(),
+ "Maximum steps of validation reached");
+
OnDataValidated onCertValidated =
bind(&ValidatorConfig::onCertValidated<Packet, OnValidated, OnFailed>,
this, _1, packet.shared_from_this(), onValidated, onValidationFailed);
@@ -270,6 +369,12 @@
onValidationFailed(packet, failureInfo);
}
+inline time::nanoseconds
+ValidatorConfig::getDefaultRefreshPeriod()
+{
+ return time::duration_cast<time::nanoseconds>(time::seconds(3600));
+}
+
} // namespace ndn
#endif // NDN_SECURITY_VALIDATOR_CONFIG_HPP