security: Add general interface to chain validation policies
Change-Id: I1a0d47aeb847455a2d7d6d48185f6edd9024d298
Refs: #3920
diff --git a/src/security/v2/validation-policy.cpp b/src/security/v2/validation-policy.cpp
new file mode 100644
index 0000000..6783f80
--- /dev/null
+++ b/src/security/v2/validation-policy.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#include "validation-policy.hpp"
+
+namespace ndn {
+namespace security {
+namespace v2 {
+
+void
+ValidationPolicy::setInnerPolicy(unique_ptr<ValidationPolicy> innerPolicy)
+{
+ if (innerPolicy == nullptr) {
+ BOOST_THROW_EXCEPTION(std::invalid_argument("Inner policy argument cannot be nullptr"));
+ }
+
+ if (m_validator != nullptr) {
+ innerPolicy->setValidator(*m_validator);
+ }
+
+ if (m_innerPolicy == nullptr) {
+ m_innerPolicy = std::move(innerPolicy);
+ }
+ else {
+ m_innerPolicy->setInnerPolicy(std::move(innerPolicy));
+ }
+}
+
+ValidationPolicy&
+ValidationPolicy::getInnerPolicy()
+{
+ return *m_innerPolicy;
+}
+
+void
+ValidationPolicy::setValidator(Validator& validator)
+{
+ m_validator = &validator;
+ if (m_innerPolicy != nullptr) {
+ m_innerPolicy->setValidator(validator);
+ }
+}
+
+} // namespace v2
+} // namespace security
+} // namespace ndn
diff --git a/src/security/v2/validation-policy.hpp b/src/security/v2/validation-policy.hpp
index 7d85803..66216c8 100644
--- a/src/security/v2/validation-policy.hpp
+++ b/src/security/v2/validation-policy.hpp
@@ -40,10 +40,41 @@
using ValidationContinuation = std::function<void(const shared_ptr<CertificateRequest>& certRequest,
const shared_ptr<ValidationState>& state)>;
+ ValidationPolicy()
+ : m_validator(nullptr)
+ {
+ }
+
virtual
~ValidationPolicy() = default;
/**
+ * @brief Set inner policy
+ *
+ * Multiple assignments of the inner policy will create a "chain" of linked policies.
+ * The inner policy from the latest invocation of setInnerPolicy will be at the bottom
+ * of the policy list.
+ *
+ * For example, sequence of `this->setInnerPolicy(policy1)` and
+ * `this->setInnerPolicy(policy2)`, will result in `this->m_innerPolicy == policy1`,
+ * this->m_innerPolicy->m_innerPolicy == policy2', and
+ * `this->m_innerPolicy->m_innerPolicy->m_innerPolicy == nullptr`.
+ *
+ * @throw std::invalid_argument exception, if @p innerPolicy is nullptr.
+ */
+ void
+ setInnerPolicy(unique_ptr<ValidationPolicy> innerPolicy);
+
+ ValidationPolicy&
+ getInnerPolicy();
+
+ /**
+ * @brief Set validator to which the policy is associated
+ */
+ void
+ setValidator(Validator& validator);
+
+ /**
* @brief Check @p data against the policy
*
* Depending on implementation of the policy, this check can be done synchronously or
@@ -101,6 +132,10 @@
{
checkPolicy(static_cast<const Data&>(certificate), state, continueValidation);
}
+
+NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PROTECTED:
+ Validator* m_validator;
+ unique_ptr<ValidationPolicy> m_innerPolicy;
};
} // namespace v2
diff --git a/src/security/v2/validator.cpp b/src/security/v2/validator.cpp
index 6dc1f91..638d12d 100644
--- a/src/security/v2/validator.cpp
+++ b/src/security/v2/validator.cpp
@@ -41,11 +41,24 @@
{
BOOST_ASSERT(m_policy != nullptr);
BOOST_ASSERT(m_certFetcher != nullptr);
+ m_policy->setValidator(*this);
m_certFetcher->setCertificateStorage(*this);
}
Validator::~Validator() = default;
+ValidationPolicy&
+Validator::getPolicy()
+{
+ return *m_policy;
+}
+
+CertificateFetcher&
+Validator::getFetcher()
+{
+ return *m_certFetcher;
+}
+
void
Validator::setMaxDepth(size_t depth)
{
diff --git a/src/security/v2/validator.hpp b/src/security/v2/validator.hpp
index f24499c..6dfe8a8 100644
--- a/src/security/v2/validator.hpp
+++ b/src/security/v2/validator.hpp
@@ -71,6 +71,12 @@
~Validator();
+ ValidationPolicy&
+ getPolicy();
+
+ CertificateFetcher&
+ getFetcher();
+
/**
* @brief Set the maximum depth of the certificate chain
*/
diff --git a/tests/unit-tests/security/v2/validator.t.cpp b/tests/unit-tests/security/v2/validator.t.cpp
index 73bd23d..42bcf2a 100644
--- a/tests/unit-tests/security/v2/validator.t.cpp
+++ b/tests/unit-tests/security/v2/validator.t.cpp
@@ -36,6 +36,19 @@
BOOST_AUTO_TEST_SUITE(V2)
BOOST_FIXTURE_TEST_SUITE(TestValidator, HierarchicalValidatorFixture<ValidationPolicySimpleHierarchy>)
+BOOST_AUTO_TEST_CASE(ConstructorSetValidator)
+{
+ auto middlePolicy = make_unique<ValidationPolicySimpleHierarchy>();
+ auto innerPolicy = make_unique<ValidationPolicySimpleHierarchy>();
+
+ validator.getPolicy().setInnerPolicy(std::move(middlePolicy));
+ validator.getPolicy().setInnerPolicy(std::move(innerPolicy));
+
+ BOOST_CHECK(validator.getPolicy().m_validator != nullptr);
+ BOOST_CHECK(validator.getPolicy().getInnerPolicy().m_validator != nullptr);
+ BOOST_CHECK(validator.getPolicy().getInnerPolicy().getInnerPolicy().m_validator != nullptr);
+}
+
BOOST_AUTO_TEST_CASE(Timeouts)
{
processInterest = nullptr; // no response for all interests