Source: security/v2/interest-validation-state.js

/**
 * Copyright (C) 2018 Regents of the University of California.
 * @author: Jeff Thompson <[email protected]>
 * @author: From ndn-cxx security https://github.com/named-data/ndn-cxx/blob/master/src/security/v2/validation-state.hpp
 *
 * This program 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.
 *
 * This program 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 a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * A copy of the GNU Lesser General Public License is in the file COPYING.
 */

/** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var Interest = require('../../interest.js').Interest; /** @ignore */
var LOG = require('../../log.js').Log.LOG; /** @ignore */
var ValidationError = require('./validation-error.js').ValidationError; /** @ignore */
var ValidationState = require('./validation-state.js').ValidationState; /** @ignore */
var VerificationHelpers = require('../verification-helpers.js').VerificationHelpers; /** @ignore */
var NdnCommon = require('../../util/ndn-common.js').NdnCommon;

/**
 * The InterestValidationState class extends ValidationState to hold the
 * validation state for an Interest packet.
 *
 * Create an InterestValidationState for the Interest packet. The caller must
 * ensure that the state instance is valid until the validation finishes (i.e.,
 * until validateCertificateChain() and validateOriginalPacket() have been
 * called).
 * @param {Interest} interest The Interest packet being validated, which is copied.
 * @param {function} successCallback This calls successCallback(interest) to
 * report a successful Interest validation.
 * @param {function} failureCallback This calls failureCallback(interest, error)
 * to report a failed Interest validation, where error is a ValidationError.
 * @constructor
 */
var InterestValidationState = function InterestValidationState
  (interest, successCallback, failureCallback)
{
  // Call the base constructor.
  ValidationState.call(this);

  // Make a copy.
  this.interest_ = new Interest(interest);
  this.successCallbacks_ = [successCallback]; // of SuccessCallback function
  this.failureCallback_ = failureCallback;

  if (successCallback == null)
    throw new Error("The successCallback is null");
  if (this.failureCallback_ == null)
    throw new Error("The failureCallback is null");
};

InterestValidationState.prototype = new ValidationState();
InterestValidationState.prototype.name = "InterestValidationState";

exports.InterestValidationState = InterestValidationState;

/**
 * Call the failure callback.
 * @param {ValidationError} error
 */
InterestValidationState.prototype.fail = function(error)
{
  if (LOG > 3) console.log("" + error);
  try {
    this.failureCallback_(this.interest_, error);
  } catch (ex) {
    console.log("Error in failureCallback: " + NdnCommon.getErrorWithStackTrace(ex));
  }
  this.setOutcome(false);
};

/**
 * Get the original Interest packet being validated which was given to the
 * constructor.
 * @return {Interest} The original Interest packet.
 */
InterestValidationState.prototype.getOriginalInterest = function()
{
  return this.interest_;
};

/**
 * @param {function} successCallback This calls successCallback(interest).
 */
InterestValidationState.prototype.addSuccessCallback = function(successCallback)
{
  this.successCallbacks_.push(successCallback);
};

/**
 * Override to verify the Interest packet given to the constructor.
 * @param {CertificateV2} trustedCertificate The certificate that signs the
 * original packet.
 * @return {Promise|SyncPromise} A promise that resolves when the success or
 * failure callback has been called.
 */
InterestValidationState.prototype.verifyOriginalPacketPromise_ = function
  (trustedCertificate)
{
  var thisState = this;

  return VerificationHelpers.verifyInterestSignaturePromise
    (this.interest_, trustedCertificate)
  .then(function(verifySuccess) {
    if (verifySuccess) {
      if (LOG > 3) console.log("OK signature for interest `" +
        thisState.interest_.getName().toUri() + "`");
      for (var i = 0; i < thisState.successCallbacks_.length; ++i) {
        try {
          thisState.successCallbacks_[i](thisState.interest_);
        } catch (ex) {
          console.log("Error in successCallback: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
      thisState.setOutcome(true);
    }
    else
      thisState.fail(new ValidationError(ValidationError.INVALID_SIGNATURE,
        "Invalid signature of interest `" +
        thisState.interest_.getName().toUri() + "`"));

    return SyncPromise.resolve();
  });
};

/**
 * Override to call the success callback using the Interest packet given to the
 * constructor.
 */
InterestValidationState.prototype.bypassValidation_ = function()
{
  if (LOG > 3) console.log("Signature verification bypassed for interest `" +
    this.interest_.getName().toUri() + "`");
  for (var i = 0; i < this.successCallbacks_.length; ++i) {
    try {
      this.successCallbacks_[i](this.interest_);
    } catch (ex) {
      console.log("Error in successCallback: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
  this.setOutcome(true);
};