blob: 567ceeb5aea9faf6c0bf191f9e23c4dcf9f2499b [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/**
* @fileoverview Registry for caveats. Provides a mapping between caveat
* UUIDs and validations methods.
* @private
*/
var vdl = require('../vdl');
var vom = require('../vom');
var byteUtil = require('../vdl/byte-util');
var standardCaveats = require('./standard-caveat-validators');
var vdlSecurity = require('../gen-vdl/v.io/v23/security');
var unwrapArg = require('../lib/unwrap-arg');
var InspectableFunction = require('../lib/inspectable-function');
var asyncCall = require('../lib/async-call');
module.exports = CaveatValidatorRegistry;
/**
* @summary CaveatValidatorRegistry is a registry for caveats.
* @description
* It enables registration of caveat validation functions and provides
* provides functionality to perform validation given UUIDs. This constructor
* should not be invoked directly, but rather the
* [singleton]{@link Runtime.caveatRegistry} on {@link Runtime} should be used.
* @constructor
* @inner
* @memberof module:vanadium.security
*/
function CaveatValidatorRegistry() {
this.validators = new Map();
standardCaveats.registerDefaultCaveats(this);
}
/**
* _makeKey generates a key for the given Uint8Array.
* This is needed because ES6 map does === comparison and equivalent arrays
* can be different under ===.
* @private
*/
CaveatValidatorRegistry.prototype._makeKey = function(bytes) {
return byteUtil.bytes2Hex(bytes);
};
/**
* @callback CaveatValidationFunction
* A function to validate caveats on {@link Blessings}
* @param {module:vanadium.context.Context} ctx The context of the call.
* @param {module:vanadium.security~SecurityCall} secCall The security call
* to validate.
* @memberof module:vanadium.security
* @param {*} param Validation-function specific parameter.
* @throws {Error} If validation fails.
*/
/**
* Register a caveat validation function.
* @param {module:vanadium.security.CaveatDescriptor} cavDesc The caveat
* description.
* @param {module:vanadium.security.CaveatValidationFunction} validateFn
* The validation function.
*/
CaveatValidatorRegistry.prototype.register = function(cavDesc, validateFn) {
this.validators.set(
this._makeKey(cavDesc.id),
new CaveatValidator(cavDesc, validateFn)
);
};
/**
* Perform validation on a caveat.
* @param {module:vanadium.context.Context} ctx The context.
* @param {module:vanadium.security.SecurityCall} secCall The security call.
* @param {*} caveat The caveat to validate.
* @param {Function} [cb] Callback after validation is complete.
* See security/types.vdl
* @throws {Error} If validation fails.
* @private
*/
CaveatValidatorRegistry.prototype.validate =
function(ctx, call, caveat, cb) {
var validator = this.validators.get(this._makeKey(caveat.id));
if (validator === undefined) {
return cb(new vdlSecurity.CaveatNotRegisteredError(ctx,
'Unknown caveat id: ' + this._makeKey(caveat.id)));
}
return vom.decode(caveat.paramVom, false, null, function(err, val) {
if (err) {
return cb(err);
}
return validator.validate(ctx, call, val, cb);
});
};
/**
* CaveatValidator is a helper object representing a specific caveat
* description and function pair.
* @private
*/
function CaveatValidator(cavDesc, validateFn) {
this.cavDesc = cavDesc;
this.validateFn = validateFn;
}
/**
* @private
*/
CaveatValidator.prototype.validate = function(ctx, call, paramForValidator,
cb) {
var paramType = this.cavDesc.paramType;
var canonParam = vdl.canonicalize.reduce(paramForValidator, paramType);
var unwrappedParam = unwrapArg(canonParam, paramType);
var inspectableFn = new InspectableFunction(this.validateFn);
asyncCall(ctx, null, inspectableFn, [], [ctx, call, unwrappedParam], cb);
};