security: Fix certificate loop detection in v2::Validator
Change-Id: I0e55cd6ee9744df07fa13dcd8ee337909c49430f
diff --git a/src/security/v2/validator.cpp b/src/security/v2/validator.cpp
index 4928c67..6dc1f91 100644
--- a/src/security/v2/validator.cpp
+++ b/src/security/v2/validator.cpp
@@ -133,6 +133,12 @@
return;
}
+ if (state->hasSeenCertificateName(certRequest->m_interest.getName())) {
+ state->fail({ValidationError::Code::LOOP_DETECTED,
+ "Validation loop detected for certificate `" + certRequest->m_interest.getName().toUri() + "`"});
+ return;
+ }
+
NDN_LOG_DEBUG_DEPTH("Retrieving " << certRequest->m_interest.getName());
auto cert = findTrustedCert(certRequest->m_interest);
diff --git a/tests/unit-tests/security/v2/validator.t.cpp b/tests/unit-tests/security/v2/validator.t.cpp
index 51ff7fa..73bd23d 100644
--- a/tests/unit-tests/security/v2/validator.t.cpp
+++ b/tests/unit-tests/security/v2/validator.t.cpp
@@ -220,7 +220,7 @@
face.sentInterests.clear();
}
-BOOST_AUTO_TEST_CASE(LoopingCert)
+BOOST_AUTO_TEST_CASE(InfiniteCertChain)
{
processInterest = [this] (const Interest& interest) {
// create another key for the same identity and sign it properly
@@ -263,10 +263,40 @@
validator.setMaxDepth(30);
BOOST_CHECK_EQUAL(validator.getMaxDepth(), 30);
- VALIDATE_FAILURE(data, "Should fail, as certificate should be looped");
+ VALIDATE_FAILURE(data, "Should fail, as certificate chain is infinite");
BOOST_CHECK_EQUAL(face.sentInterests.size(), 30);
}
+BOOST_AUTO_TEST_CASE(LoopedCertChain)
+{
+ auto s1 = addIdentity("/loop");
+ auto k1 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key1")));
+ auto k2 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key2")));
+ auto k3 = m_keyChain.createKey(s1, RsaKeyParams(name::Component("key3")));
+
+ auto makeCert = [this] (Key& key, const Key& signer) {
+ v2::Certificate request = key.getDefaultCertificate();
+ request.setName(Name(key.getName()).append("looper").appendVersion());
+
+ SignatureInfo info;
+ info.setValidityPeriod({time::system_clock::now() - time::days(100),
+ time::system_clock::now() + time::days(100)});
+ m_keyChain.sign(request, signingByKey(signer).setSignatureInfo(info));
+ m_keyChain.addCertificate(key, request);
+
+ cache.insert(request);
+ };
+
+ makeCert(k1, k2);
+ makeCert(k2, k3);
+ makeCert(k3, k1);
+
+ Data data("/loop/Data");
+ m_keyChain.sign(data, signingByKey(k1));
+ VALIDATE_FAILURE(data, "Should fail, as certificate chain loops");
+ BOOST_CHECK_EQUAL(face.sentInterests.size(), 3);
+}
+
BOOST_AUTO_TEST_SUITE_END() // TestValidator
BOOST_AUTO_TEST_SUITE_END() // V2
BOOST_AUTO_TEST_SUITE_END() // Security