Project

General

Profile

Task #3289

Validator Refactoring

Added by Yingdi Yu almost 5 years ago. Updated over 3 years ago.

Status:
Closed
Priority:
Normal
Category:
Security
Target version:
Start date:
10/26/2015
Due date:
% Done:

100%

Estimated time:
(Total: 0.00 h)

Description

We have several features and issues about Validator, which is more or less coupled.

We can take this opportunity to refactor Validator to make it simple and modular.

An ideal Validator should consists of three parts:

  • a policy checker which determine if a packet complies with the trust model;
  • key/cert retrieval from cache, trust anchor and network.
  • a list of active validation instances of which each tracks the validation of an original packet.

The top-level class Validator defines the inter-operations between these modules, and virtual interface for others to implement detailed features.

class Validator {
public:
  /** @brief Construct a Validator using @p face
   *    
   *  The policy checking module is implemented as checkPolicy method
   *  The instance management is internally managed by InstancePool
   *  @param enableLoopDetection Enable loop detection if true
   */
  Validator(Face* face, bool enableLoopDetection = false);

  /// @brief Validate data, invoke @p succeed if validated, otherwise invoke @p fail
  void
  validate(const Data& data, const SuccessCallback& succeed, const FailureCallback& fail) 
  {
    auto instance = m_instancePool.allocate(data, succeed, fail);
    reqs = validate(data, instance.succeed, instance.fail, instance.id);
  }

  /// @brief Validate interest, invoke @p succeed if validated, otherwise invoke @p fail
  void
  validate(const Interest& interest, const SuccessCallback& succeed, const FailureCallback& fail)
  {
    auto instance = m_instancePool.allocate(interest, succeed, fail);
    reqs = validate(interest, instance.succeed, instance.fail, instance.id);
  }

protected:
  /** @brief Validate data, invoke @p succeed if validated, otherwise invoke @p fail, 
   *  @param id The id of validation instance.
   */
  template<typename Packet> void
  validate(const Packet& packet, const SuccessCallback& succeed, const FailureCallback& fail, uint32_t id)
  {
    list<KeyRequest> reqs = checkPolicy(packet, succeed, fail, id);

    // retrieve keys
    for (const auto& req : reqs)
      if (m_enableLoopDetection && m_instancePool.isLoopDetected(id, req)) 
        req.FailureCallback();
      else {
        // retrieve keys...
        auto cert = RetrieveTrustedKey(req);
        if (cert != nullptr)
          RetrievalSuccessCallback(cert);
        else
          RetrieveCertificate(req);
      }
  }

private:
  virtual list<KeyRequest>
  checkPolicy(const Data& data, const SuccessCallback& succeed, const FailureCallback& fail) = 0;

  virtual list<KeyRequest>
  checkPolicy(const Data& data, const SuccessCallback& succeed, const FailureCallback& fail) = 0;

protected: 
  // key management;
  TrustAnchorContainer m_anchorCache;
  CertificateCache m_verifiedKeyCache;
  Cache m_unVerifiedKeyCache;

private:
  Face* m_face;

  // loop detection mode
  bool m_enableLoopDetection;

  // instance management;
  InstancePool m_instancePool;
};

Subtasks

Task #3292: Design and Implement TrustAnchorContainerClosedAlex Afanasyev10/26/2015

Actions
Task #3317: Design and Implement validator::CertificateCacheClosedAlex Afanasyev11/04/2015

Actions

Related issues

Related to ndn-cxx - Task #3920: Convert existing validator implementations to v2::ValidatorClosedZhiyi Zhang

Actions
Blocks NFD - Feature #2237: Remote prefix registration: fetch certificates from requesterClosedZhiyi Zhang

Actions
#1

Updated by Yingdi Yu almost 5 years ago

  • Description updated (diff)
#2

Updated by Yingdi Yu almost 5 years ago

  • Category set to Security
#3

Updated by Junxiao Shi almost 5 years ago

What is loop detection?


What's the benefit of having a pool for validation instances?
If it's just "memory allocation", a benchmark is needed.

#4

Updated by Qiuhan Ding almost 5 years ago

  • Description updated (diff)
  • Status changed from New to Code review
  • Assignee changed from Yingdi Yu to Qiuhan Ding
#5

Updated by Alex Afanasyev almost 5 years ago

  • Target version set to v0.5
#7

Updated by Alex Afanasyev over 3 years ago

  • Assignee changed from Qiuhan Ding to Alex Afanasyev
  • Target version changed from v0.5 to v0.6

In my latest implementation, the design has been adjusted: Validator is split from the ValidationPolicy. ValidationPolicy determines whether data/interest can be signed by the key name specified in the KeyLocator field, Validator performs actual signature verification, key retrieval, etc.

Here is the high-level interface:

/**
 * @brief Abstraction that implements validation policy for Data and Interest packets
 */
class ValidationPolicy
{
public:
  using ValidationContinuation = std::function<void(const shared_ptr<ValidationState>& state,
                                                    const shared_ptr<KeyRequest>& keyRequest)>;

  /**
   * @brief Check @p data against the policy
   *
   * Semantics of checkPolicy has changed from v1::Validator
   * - If packet violates policy, the policy should call `state.fail` with appropriate error
   *   code and error description.
   * - If packet conforms to the policy and no further key retrievals are necessary,
   *   the policy should call continueValidation(state, nullptr)
   * - If packet conforms to the policy and key needs to be fetched, the policy should call
   *   continueValidation(state, <appropriate-key-request-instance>)
   */
  virtual void
  checkPolicy(const Data& data, const shared_ptr<ValidationState>& state,
              const ValidationContinuation& continueValidation) = 0;

  /**
   * @brief Check @p interest against the policy
   *
   * Semantics of checkPolicy has changed from v1::Validator
   * - If packet violates policy, the policy should call `state.fail` with appropriate error
   *   code and error description.
   * - If packet conforms to the policy and no further key retrievals are necessary,
   *   the policy should call continueValidation(state, nullptr)
   * - If packet conforms to the policy and key needs to be fetched, the policy should call
   *   continueValidation(state, <appropriate-key-request-instance>)
   */
  virtual void
  checkPolicy(const Interest& interest, const shared_ptr<ValidationState>& state,
              const ValidationContinuation& continueValidation) = 0;
};
/**
 * @brief Interface for validating data and interest packets.
 *
 * A validator can either operate in online mode or offline mode:
 * - In online mode (a pointer to a valid Face instance passed to the constructor): certificates
 *   missing in the local cache will be retrieved from the network
 * - In offline mode (nullptr passed to the constructor): only local cache will be used, failing
 *   validation if some certificates are missing.
 *
 * Every time a validation process initiated, it creates a ValidationState that exist until
 * validation finishes either with success of failure.  This instance ensures that each key is
 * requested no more than once.
 *
 * A validator has a trust anchor cache to save static and dynamic trust anchors, a verified
 * key cache for saving keys that is already verified and an unverified key cache for saving
 * prefetched but not yet verified keys.
 */
class Validator : noncopyable
{
public:
  /**
   * @brief Validator constructor.
   *
   * @param policy Validation policy to be associated with the validator
   * @param face Pointer to face for fetching keys from network.  If provided, the Validator
   *             operates in online mode; otherwise, the Validator operates in offline mode.
   */
  explicit
  Validator(unique_ptr<ValidationPolicy> policy, Face* face = nullptr);

  /**
   * @brief Validate Data and trigger either success callback or failure callback.
   *
   * @param data       Data to check.
   * @param successCb  Callback when @p data is validated.
   * @param failureCb  Callback when @p data is not validated.
   */
  void
  validate(const Data& data,
           const DataValidationSuccessCallback& successCb,
           const DataValidationFailureCallback& failureCb);

  /**
   * @brief Validate Interest and trigger either success callback or failure callback.
   *
   * @param interest   Interest to check.
   * @param successCb  Callback when @p interest is validated.
   * @param failureCb  Callback when @p interest is not validated.
   */
  void
  validate(const Interest& interest,
           const InterestValidationSuccessCallback& successCb,
           const InterestValidationFailureCallback& failureCb);
};
#8

Updated by Zhiyi Zhang over 3 years ago

  • Blocks Feature #2237: Remote prefix registration: fetch certificates from requester added
#9

Updated by Zhiyi Zhang over 3 years ago

  • Related to Task #3920: Convert existing validator implementations to v2::Validator added
#10

Updated by Junxiao Shi over 3 years ago

  • Status changed from Code review to Closed

There is no open Change on Gerrit for this issue. Further ValidationPolicy work is being performed in #3920.

Also available in: Atom PDF