security: Add appropriate hooks in Validator
This commit add three hooks in validation process, so that sub-classes can extend the process
1. preCertificateValidation: process received certificate before validation.
2. onTimeout: process interest timeout
3. afterCheckPolicy: process validation requests.
Change-Id: I23d9eae7087ff6c69639b332a424636ca7bc2841
diff --git a/src/security/validation-request.hpp b/src/security/validation-request.hpp
index b141e02..d9aae80 100644
--- a/src/security/validation-request.hpp
+++ b/src/security/validation-request.hpp
@@ -41,18 +41,26 @@
typedef function<void(const shared_ptr<const Data>&,
const std::string&)> OnDataValidationFailed;
-
+/**
+ * @brief ValidationRequest contains information related to further validation.
+ *
+ * During a validation process, validator may not have retrieved the corresponding public
+ * key of the signature in a packet. ValidationRequest contains the interest for the
+ * certificate that carries the public key and also contains the context for the certificate
+ * including how to proceed when the public key is authenticated or not, the number of
+ * validation steps that have been performed, and how to handle interest timeout.
+ */
class ValidationRequest
{
public:
ValidationRequest(const Interest& interest,
- const OnDataValidated& onValidated,
- const OnDataValidationFailed& onDataValidated,
- int nRetrials, int nSteps)
+ const OnDataValidated& onDataValidated,
+ const OnDataValidationFailed& onDataValidationFailed,
+ int nRetries, int nSteps)
: m_interest(interest)
- , m_onValidated(onValidated)
, m_onDataValidated(onDataValidated)
- , m_nRetrials(nRetrials)
+ , m_onDataValidationFailed(onDataValidationFailed)
+ , m_nRetries(nRetries)
, m_nSteps(nSteps)
{
}
@@ -62,11 +70,16 @@
{
}
- Interest m_interest; // Interest for the requested data.
- OnDataValidated m_onValidated; // Callback function on validated certificate.
- OnDataValidationFailed m_onDataValidated; // Callback function on validation failure.
- int m_nRetrials; // The number of retrials when interest timeout.
- int m_nSteps; // The stepCount of next step.
+ /// @brief the Interest for the requested data/certificate.
+ Interest m_interest;
+ /// @brief callback when the retrieved certificate is authenticated.
+ OnDataValidated m_onDataValidated;
+ /// @brief callback when the retrieved certificate cannot be authenticated.
+ OnDataValidationFailed m_onDataValidationFailed;
+ /// @brief the number of retries when the interest times out.
+ int m_nRetries;
+ /// @brief the number of validation steps that have been performed.
+ int m_nSteps;
};
} // namespace ndn
diff --git a/src/security/validator.cpp b/src/security/validator.cpp
index df7b0e6..1b9d92a 100644
--- a/src/security/validator.cpp
+++ b/src/security/validator.cpp
@@ -55,31 +55,23 @@
std::vector<shared_ptr<ValidationRequest> > nextSteps;
checkPolicy(interest, nSteps, onValidated, onValidationFailed, nextSteps);
- if (!nextSteps.empty())
- {
- if (!m_hasFace)
- {
- onValidationFailed(interest.shared_from_this(),
- "Require more information to validate the interest!");
- return;
- }
-
- std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
- OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
- for (; it != nextSteps.end(); it++)
- m_face.expressInterest((*it)->m_interest,
- bind(&Validator::onData, this, _1, _2, *it),
- bind(&Validator::onTimeout,
- this, _1, (*it)->m_nRetrials,
- onFailure,
- *it));
- }
- else
+ if (nextSteps.empty())
{
// If there is no nextStep,
// that means InterestPolicy has already been able to verify the Interest.
// No more further processes.
+ return;
}
+
+ if (!m_hasFace)
+ {
+ onValidationFailed(interest.shared_from_this(),
+ "Require more information to validate the interest!");
+ return;
+ }
+
+ OnFailure onFailure = bind(onValidationFailed, interest.shared_from_this(), _1);
+ afterCheckPolicy(nextSteps, onFailure);
}
void
@@ -91,30 +83,23 @@
std::vector<shared_ptr<ValidationRequest> > nextSteps;
checkPolicy(data, nSteps, onValidated, onValidationFailed, nextSteps);
- if (!nextSteps.empty())
- {
- if (!m_hasFace)
- {
- onValidationFailed(data.shared_from_this(),
- "Require more information to validate the data!");
- }
-
- std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
- OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
- for (; it != nextSteps.end(); it++)
- m_face.expressInterest((*it)->m_interest,
- bind(&Validator::onData, this, _1, _2, *it),
- bind(&Validator::onTimeout,
- this, _1, (*it)->m_nRetrials,
- onFailure,
- *it));
- }
- else
+ if (nextSteps.empty())
{
// If there is no nextStep,
// that means Data Policy has already been able to verify the Interest.
// No more further processes.
+ return;
}
+
+ if (!m_hasFace)
+ {
+ onValidationFailed(data.shared_from_this(),
+ "Require more information to validate the data!");
+ return;
+ }
+
+ OnFailure onFailure = bind(onValidationFailed, data.shared_from_this(), _1);
+ afterCheckPolicy(nextSteps, onFailure);
}
void
@@ -122,23 +107,15 @@
const Data& data,
const shared_ptr<ValidationRequest>& nextStep)
{
- validate(data, nextStep->m_onValidated, nextStep->m_onDataValidated, nextStep->m_nSteps);
-}
+ shared_ptr<const Data> certificateData = preCertificateValidation(data);
-void
-Validator::onTimeout(const Interest& interest,
- int nRetrials,
- const OnFailure& onFailure,
- const shared_ptr<ValidationRequest>& nextStep)
-{
- if (nRetrials > 0)
- // Issue the same expressInterest except decrement nRetrials.
- m_face.expressInterest(interest,
- bind(&Validator::onData, this, _1, _2, nextStep),
- bind(&Validator::onTimeout, this, _1,
- nRetrials - 1, onFailure, nextStep));
- else
- onFailure("Cannot fetch cert: " + interest.getName().toUri());
+ if (!static_cast<bool>(certificateData))
+ return nextStep->m_onDataValidationFailed(data.shared_from_this(),
+ "Cannot decode cert: " + data.getName().toUri());
+
+ validate(*certificateData,
+ nextStep->m_onDataValidated, nextStep->m_onDataValidationFailed,
+ nextStep->m_nSteps);
}
bool
@@ -352,4 +329,37 @@
}
}
+void
+Validator::onTimeout(const Interest& interest,
+ int remainingRetries,
+ const OnFailure& onFailure,
+ const shared_ptr<ValidationRequest>& validationRequest)
+{
+ if (remainingRetries > 0)
+ // Issue the same expressInterest except decrement nRetrials.
+ m_face.expressInterest(interest,
+ bind(&Validator::onData, this, _1, _2, validationRequest),
+ bind(&Validator::onTimeout, this, _1,
+ remainingRetries - 1, onFailure, validationRequest));
+ else
+ onFailure("Cannot fetch cert: " + interest.getName().toUri());
+}
+
+
+void
+Validator::afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
+ const OnFailure& onFailure)
+{
+ for (std::vector<shared_ptr<ValidationRequest> >::const_iterator it = nextSteps.begin();
+ it != nextSteps.end(); it++)
+ {
+ m_face.expressInterest((*it)->m_interest,
+ bind(&Validator::onData, this, _1, _2, *it),
+ bind(&Validator::onTimeout,
+ this, _1, (*it)->m_nRetries,
+ onFailure,
+ *it));
+ }
+}
+
} // namespace ndn
diff --git a/src/security/validator.hpp b/src/security/validator.hpp
index 87c2bfd..b95c5ad 100644
--- a/src/security/validator.hpp
+++ b/src/security/validator.hpp
@@ -236,13 +236,6 @@
const Data& data,
const shared_ptr<ValidationRequest>& nextStep);
- /// @brief Re-express the interest if it times out.
- void
- onTimeout(const Interest& interest,
- int retry,
- const OnFailure& onFailure,
- const shared_ptr<ValidationRequest>& nextStep);
-
void
validate(const Data& data,
const OnDataValidated& onValidated,
@@ -255,6 +248,57 @@
const OnInterestValidationFailed& onValidationFailed,
int nSteps);
+ /// Hooks
+
+ /**
+ * @brief trigger before validating requested certificate.
+ *
+ * The Data:
+ * - matches the interest in the validation-request.
+ * - may be certificate or a data encapsulating certificate.
+ *
+ * This method returns a data (actually certificate) that is will be passed as Data into:
+ * Validator::validate(const Data& data,
+ * const OnDataValidated& onValidated,
+ * const OnDataValidationFailed& onValidationFailed,
+ * int nSteps);
+ */
+ virtual shared_ptr<const Data>
+ preCertificateValidation(const Data& data)
+ {
+ return data.shared_from_this();
+ }
+
+ /**
+ * @brief trigger when interest for certificate times out.
+ *
+ * Validator can decide how to handle the timeout, either call onFailure, or retry.
+ *
+ * @param interest The interest that times out.
+ * @param nRemainingRetries The number of retries left.
+ * @param onFailure Failure callback when there is no more retries remaining.
+ * @param validationRequest The validationRequest containing the context of the interest.
+ */
+
+ virtual void
+ onTimeout(const Interest& interest,
+ int nRemainingRetries,
+ const OnFailure& onFailure,
+ const shared_ptr<ValidationRequest>& validationRequest);
+
+ /**
+ * @brief trigger after checkPolicy is done.
+ *
+ * Validator can decide how to handle the set of validation requests according to
+ * the trust model.
+ *
+ * @param nextSteps A set of validation request made by checkPolicy.
+ * @param onFailure Failure callback when errors happen in processing nextSteps.
+ */
+ virtual void
+ afterCheckPolicy(const std::vector<shared_ptr<ValidationRequest> >& nextSteps,
+ const OnFailure& onFailure);
+
protected:
bool m_hasFace;
Face& m_face;