/// <summary> /// Match the target of this policy. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The retult evaluation of the policy target.</returns> public TargetEvaluationValue Match(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } TargetEvaluationValue targetEvaluationValue = TargetEvaluationValue.Indeterminate; context.Trace("Evaluating Target..."); context.AddIndent(); try { // Evaluate the policy target targetEvaluationValue = TargetEvaluationValue.Match; if (_target != null) { targetEvaluationValue = _target.Evaluate(context); } return(targetEvaluationValue); } finally { context.TraceContextValues(); context.RemoveIndent(); context.Trace("Target: {0}", targetEvaluationValue); } }
/// <summary> /// Evaluates the policy set. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The decission result for this policy set.</returns> public Decision Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.Trace("Evaluating policySet: {0}", _policySet.Description); context.CurrentPolicySet = this; try { context.Trace("Evaluating Target..."); context.AddIndent(); // Evaluate the policy target TargetEvaluationValue targetEvaluationValue = Match(context); context.RemoveIndent(); context.Trace("Target: {0}", targetEvaluationValue); ProcessTargetEvaluationValue(context, targetEvaluationValue); context.Trace("PolicySet: {0}", _evaluationValue); // If the policy evaluated to Deny or Permit add the obligations depending on its fulfill value. ProcessObligations(context); return(_evaluationValue); } finally { context.CurrentPolicySet = null; } }
/// <summary> /// Evaluates the rule contents. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>A decission for this evalauation.</returns> public Decision Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.Trace("Evaluating rule: {0}", _rule.Description); context.AddIndent(); context.CurrentRule = this; try { // Validate the Target element TargetEvaluationValue targetEvaluation = Match(context); // If the target matches the conditions ar evaluated EvaluationValue conditionEvaluation = EvaluationValue.True; if (_rule.HasCondition) { // Evaluate the condition conditionEvaluation = _condition.Evaluate(context); } else { context.Trace("Rule does not have a condition"); } // Decite the final rule evaluation value if (targetEvaluation == TargetEvaluationValue.Indeterminate || conditionEvaluation.IsIndeterminate) { _evaluationValue = Decision.Indeterminate; } else if (targetEvaluation == TargetEvaluationValue.Match && conditionEvaluation.BoolValue) { _evaluationValue = ((_rule.Effect == pol.Effect.Permit) ? Decision.Permit : Decision.Deny); } else if ((targetEvaluation == TargetEvaluationValue.NoMatch) || (targetEvaluation == TargetEvaluationValue.Match && !conditionEvaluation.BoolValue)) { _evaluationValue = Decision.NotApplicable; } // Return the value context.Trace("Rule: {0}", _evaluationValue); return(_evaluationValue); } finally { context.RemoveIndent(); context.CurrentRule = null; } }
/// <summary> /// The evaluation implementation in the pseudo-code described in the specification. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="rules">The policies that must be evaluated.</param> /// <returns>The final decission for the combination of the rule evaluation.</returns> public Decision Evaluate(EvaluationContext context, RuleCollection rules) { Decision decision = Decision.Indeterminate; context.Trace("Evaluating rules..."); context.AddIndent(); try { foreach (Rule rule in rules) { decision = rule.Evaluate(context); context.TraceContextValues(); if (decision == Decision.Deny) { decision = Decision.Deny; return(decision); } if (decision == Decision.Permit) { decision = Decision.Permit; return(decision); } if (decision == Decision.NotApplicable) { continue; } if (decision == Decision.Indeterminate) { decision = Decision.Indeterminate; return(decision); } } return(Decision.NotApplicable); } finally { context.Trace("Rule combination algorithm: {0}", decision.ToString()); context.RemoveIndent(); } }
/// <summary> /// Process the match result. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="targetEvaluationValue">The match evaluation result.</param> private void ProcessTargetEvaluationValue(EvaluationContext context, TargetEvaluationValue targetEvaluationValue) { if (targetEvaluationValue == TargetEvaluationValue.Match) { try { context.Trace("Evaluating policies..."); context.AddIndent(); context.Trace("Policy combination algorithm: {0}", _policySet.PolicyCombiningAlgorithm); // Evaluate all policies and apply rule combination inf.IPolicyCombiningAlgorithm pca = EvaluationEngine.CreatePolicyCombiningAlgorithm(_policySet.PolicyCombiningAlgorithm); if (pca == null) { throw new EvaluationException("the policy combining algorithm does not exists."); //TODO: resources } _evaluationValue = pca.Evaluate(context, _policies); // Update the flags for general evaluation status. context.TraceContextValues(); context.Trace("Policy combination algorithm: {0}", _evaluationValue.ToString()); } finally { context.RemoveIndent(); } } else if (targetEvaluationValue == TargetEvaluationValue.NoMatch) { _evaluationValue = Decision.NotApplicable; } else if (targetEvaluationValue == TargetEvaluationValue.Indeterminate) { _evaluationValue = Decision.Indeterminate; } }
/// <summary> /// Main evaluation method which is divided in two phases: Argument processing and /// Function evaluation. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The result of the evaluation in an EvaluationValue instance.</returns> public virtual EvaluationValue Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } // Validate the function exists context.Trace("Calling function: {0}", _applyBase.FunctionId); inf.IFunction function = EvaluationEngine.GetFunction(_applyBase.FunctionId); if (function == null) { context.Trace("ERR: function not found {0}", _applyBase.FunctionId); context.ProcessingError = true; return(EvaluationValue.Indeterminate); } // Process the arguments. IFunctionParameterCollection arguments = ProcessArguments(context, new pol.IExpressionCollection((pol.IExpressionReadWriteCollection)_applyBase.Arguments)); // Call the function with the arguments processed. EvaluationValue returnValue = EvaluationEngine.EvaluateFunction(context, function, arguments.ToArray()); return(returnValue); }
/// <summary> /// The evaluation implementation in the pseudo-code described in the specification. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="rules">The policies that must be evaluated.</param> /// <returns>The final decission for the combination of the rule evaluation.</returns> public Decision Evaluate( EvaluationContext context, RuleCollection rules ) { Decision decision = Decision.Indeterminate; context.Trace( "Evaluating rules..." ); context.AddIndent(); try { foreach( Rule rule in rules ) { decision = rule.Evaluate( context ); context.TraceContextValues(); if( decision == Decision.Deny ) { decision = Decision.Deny; return decision; } if( decision == Decision.Permit ) { decision = Decision.Permit; return decision; } if( decision == Decision.NotApplicable ) { continue; } if( decision == Decision.Indeterminate ) { decision = Decision.Indeterminate; return decision; } } return Decision.NotApplicable; } finally { context.Trace( "Rule combination algorithm: {0}", decision.ToString() ); context.RemoveIndent(); } }
/// <summary> /// Process the obligations for the policy. /// </summary> /// <param name="context">The evaluation context instance.</param> private void ProcessObligations(EvaluationContext context) { _obligations = new pol.ObligationCollection(); if (_evaluationValue != Decision.Indeterminate && _evaluationValue != Decision.NotApplicable && _policySet.Obligations != null && _policySet.Obligations.Count != 0) { foreach (pol.ObligationElement obl in _policySet.Obligations) { if ((obl.FulfillOn == pol.Effect.Deny && _evaluationValue == Decision.Deny) || (obl.FulfillOn == pol.Effect.Permit && _evaluationValue == Decision.Permit)) { context.Trace("Adding obligation: {0} ", obl.ObligationId); _obligations.Add(obl); } } // Get all obligations from child policies foreach (IMatchEvaluable child in _policies) { IObligationsContainer oblig = child as IObligationsContainer; if (oblig != null && oblig.Obligations != null) { foreach (pol.ObligationElement childObligation in oblig.Obligations) { if ((childObligation.FulfillOn == pol.Effect.Deny && _evaluationValue == Decision.Deny) || (childObligation.FulfillOn == pol.Effect.Permit && _evaluationValue == Decision.Permit)) { _obligations.Add(childObligation); } } } } } }
/// <summary> /// Resolves the attribute reference defined within the given match. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="match">The target item match.</param> /// <param name="contextTargetItem">The context target item.</param> /// <returns>The context attribute.</returns> public static ctx.AttributeElement Resolve( EvaluationContext context, pol.TargetMatchBaseReadWrite match, ctx.TargetItemBase contextTargetItem ) { ctx.AttributeElementReadWrite attribute = null; if( match.AttributeReference is pol.AttributeDesignatorBase ) { pol.AttributeDesignatorBase attrDesig = (pol.AttributeDesignatorBase)match.AttributeReference; context.Trace( "Looking for attribute: {0}", attrDesig.AttributeId ); foreach( ctx.AttributeElementReadWrite tempAttribute in contextTargetItem.Attributes ) { if( tempAttribute.Match( attrDesig ) ) { attribute = tempAttribute; break; } } if( attribute == null ) { context.Trace( "Attribute not found, loading searching an external repository" ); attribute = GetAttribute( context, attrDesig ); } } else if( match.AttributeReference is pol.AttributeSelectorElement ) { pol.AttributeSelectorElement attrSelec = (pol.AttributeSelectorElement)match.AttributeReference; ctx.ResourceContentElement content = (ctx.ResourceContentElement)((ctx.ResourceElement)contextTargetItem).ResourceContent; if( content != null ) { XmlDocument doc = context.ContextDocument.XmlDocument; if( context.ContextDocument.XmlNamespaceManager == null ) { context.ContextDocument.AddNamespaces( context.PolicyDocument.Namespaces ); } string xpath = attrSelec.RequestContextPath; try { XmlNode node = doc.DocumentElement.SelectSingleNode( xpath, context.ContextDocument.XmlNamespaceManager ); if( node != null ) { attribute = new ctx.AttributeElement( null, attrSelec.DataType, null, null, node.InnerText, attrSelec.SchemaVersion ); } } catch( XPathException e ) { context.Trace( Resource.TRACE_ERROR, e.Message ); context.ProcessingError = true; } } } if( attribute == null && match.AttributeReference.MustBePresent ) { context.IsMissingAttribute = true; context.AddMissingAttribute( match.AttributeReference ); } if( attribute != null ) { return new ctx.AttributeElement( attribute.AttributeId, attribute.DataType, attribute.Issuer, attribute.IssueInstant, attribute.Value, attribute.SchemaVersion); } return null; }
/// <summary> /// Search for the attribute in the context target item using the attribute designator specified. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="attributeDesignator">The attribute designator instance.</param> /// <param name="targetItem">The target item to search in.</param> /// <returns>A bag value with the values of the attributes found.</returns> public static BagValue FindAttribute( EvaluationContext context, pol.AttributeDesignatorBase attributeDesignator, ctx.TargetItemBase targetItem ) { BagValue bag = new BagValue( GetDataType( attributeDesignator.DataType ) ); foreach( ctx.AttributeElement attribute in targetItem.Attributes ) { if( attribute.Match( attributeDesignator ) ) { context.Trace( "Adding target item attribute designator: {0}", attribute.ToString() ); bag.Add( attribute ); } } return bag; }
/// <summary> /// Evaluates the rule contents. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>A decission for this evalauation.</returns> public Decision Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); context.Trace( "Evaluating rule: {0}", _rule.Description ); context.AddIndent(); context.CurrentRule = this; try { // Validate the Target element TargetEvaluationValue targetEvaluation = Match( context ); // If the target matches the conditions ar evaluated EvaluationValue conditionEvaluation = EvaluationValue.True; if( _rule.HasCondition ) { // Evaluate the condition conditionEvaluation = _condition.Evaluate( context ); } else { context.Trace( "Rule does not have a condition" ); } // Decite the final rule evaluation value if( targetEvaluation == TargetEvaluationValue.Indeterminate || conditionEvaluation.IsIndeterminate ) { _evaluationValue = Decision.Indeterminate; } else if( targetEvaluation == TargetEvaluationValue.Match && conditionEvaluation.BoolValue ) { _evaluationValue = ((_rule.Effect == pol.Effect.Permit) ? Decision.Permit : Decision.Deny); } else if( ( targetEvaluation == TargetEvaluationValue.NoMatch ) || ( targetEvaluation == TargetEvaluationValue.Match && !conditionEvaluation.BoolValue ) ) { _evaluationValue = Decision.NotApplicable; } // Return the value context.Trace( "Rule: {0}", _evaluationValue ); return _evaluationValue; } finally { context.RemoveIndent(); context.CurrentRule = null; } }
/// <summary> /// Evaluates the target items and return wether the target applies to the context or not. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="targetItem">The target item in the context document.</param> /// <returns></returns> public TargetEvaluationValue Evaluate(EvaluationContext context, ctx.TargetItemBase targetItem) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (_targetItems.IsAny) { context.Trace("IsAny"); return(TargetEvaluationValue.Match); } _evaluationValue = TargetEvaluationValue.NoMatch; //Match TargetItem foreach (pol.TargetItemBase polItem in _targetItems.ItemsList) { foreach (pol.TargetMatchBase match in polItem.Match) { _evaluationValue = TargetEvaluationValue.NoMatch; context.Trace("Using function: {0}", match.MatchId); inf.IFunction matchFunction = EvaluationEngine.GetFunction(match.MatchId); if (matchFunction == null) { context.Trace("ERR: function not found {0}", match.MatchId); context.ProcessingError = true; return(TargetEvaluationValue.Indeterminate); } if (matchFunction.Returns == null) { // Validates the function return value context.Trace("ERR: The function '{0}' does not defines it's return value", match.MatchId); context.ProcessingError = true; return(TargetEvaluationValue.Indeterminate); } if (matchFunction.Returns != DataTypeDescriptor.Boolean) { context.Trace("ERR: Function does not return Boolean a value"); context.ProcessingError = true; return(TargetEvaluationValue.Indeterminate); } ctx.AttributeElement attribute = EvaluationEngine.Resolve(context, match, targetItem); if (attribute != null) { context.Trace("Attribute found, evaluating match function"); try { EvaluationValue returnValue = EvaluationEngine.EvaluateFunction(context, matchFunction, match.AttributeValue, attribute); _evaluationValue = returnValue.BoolValue ? TargetEvaluationValue.Match : TargetEvaluationValue.NoMatch; } catch (EvaluationException e) { context.Trace(Resource.TRACE_ERROR, e.Message); _evaluationValue = TargetEvaluationValue.Indeterminate; } } // Validate MustBePresent if (match.AttributeReference.MustBePresent) { if (context.IsMissingAttribute) { context.Trace("Attribute not found and must be present"); _evaluationValue = TargetEvaluationValue.Indeterminate; } } // Do not iterate if the value was found if (_evaluationValue != TargetEvaluationValue.Match) { break; } } // Do not iterate if the value was found if (_evaluationValue == TargetEvaluationValue.Match) { return(_evaluationValue); } } return(_evaluationValue); }
/// <summary> /// Evaluates the variable into a value. /// </summary> /// <param name="context">The contex of the evaluation.</param> /// <returns>The value of the function.</returns> public EvaluationValue Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); context.Trace( "Evaluating variable" ); context.AddIndent(); try { if( _variableDefinition.Expression is pol.ApplyElement ) { context.Trace( "Apply within condition." ); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply( (pol.ApplyElement)_variableDefinition.Expression ); // Evaluate the Apply _value = _childApply.Evaluate( context ); context.TraceContextValues(); return _value; } else if( _variableDefinition.Expression is pol.FunctionElement ) { throw new NotImplementedException( "FunctionElement" ); //TODO: } else if( _variableDefinition.Expression is pol.VariableReferenceElement ) { pol.VariableReferenceElement variableRef = _variableDefinition.Expression as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[ variableRef.VariableId ] as VariableDefinition; context.TraceContextValues(); if( !variableDef.IsEvaluated ) { return variableDef.Evaluate( context ); } else { return variableDef.Value; } } else if( _variableDefinition.Expression is pol.AttributeValueElementReadWrite ) { // The AttributeValue does not need to be processed context.Trace( "Attribute value {0}", _variableDefinition.Expression.ToString() ); pol.AttributeValueElementReadWrite att = (pol.AttributeValueElementReadWrite)_variableDefinition.Expression; pol.AttributeValueElement attributeValue = new pol.AttributeValueElement( att.DataType, att.Contents, att.SchemaVersion ); _value = new EvaluationValue( attributeValue.GetTypedValue( attributeValue.GetType( context ), 0 ), attributeValue.GetType( context ) ); return _value; } else if( _variableDefinition.Expression is pol.AttributeDesignatorBase ) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace( "Processing attribute designator: {0}", _variableDefinition.Expression.ToString() ); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)_variableDefinition.Expression; BagValue bag = EvaluationEngine.Resolve( context, attrDes ); // If the attribute was not resolved by the EvaluationEngine search the // attribute in the context document, also using the EvaluationEngine public // methods. if( bag.BagSize == 0 ) { if( _variableDefinition.Expression is pol.SubjectAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding subject attribute designator: {0}", attrib.ToString() ); bag.Add( attrib ); } } else if( _variableDefinition.Expression is pol.ResourceAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding resource attribute designator {0}", attrib.ToString() ); bag.Add( attrib ); } } else if( _variableDefinition.Expression is pol.ActionAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding action attribute designator {0}", attrib.ToString() ); bag.Add( attrib ); } } else if( _variableDefinition.Expression is pol.EnvironmentAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding environment attribute designator {0}", attrib.ToString() ); bag.Add( attrib ); } } } // If the argument was not found and the attribute must be present this is // a MissingAttribute situation so set the flag. Otherwise add the attribute // to the processed arguments. if( bag.BagSize == 0 && attrDes.MustBePresent ) { context.Trace( "Attribute is missing" ); context.IsMissingAttribute = true; context.AddMissingAttribute( attrDes ); _value = EvaluationValue.Indeterminate; } else { _value = new EvaluationValue( bag, bag.GetType( context ) ); } return _value; } else if( _variableDefinition.Expression is pol.AttributeSelectorElement ) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace( "Attribute selector" ); try { pol.AttributeSelectorElement attributeSelector = (pol.AttributeSelectorElement)_variableDefinition.Expression; BagValue bag = EvaluationEngine.Resolve( context, attributeSelector ); if( bag.Elements.Count == 0 && attributeSelector.MustBePresent ) { context.Trace( "Attribute is missing" ); context.IsMissingAttribute = true; context.AddMissingAttribute( attributeSelector ); _value = EvaluationValue.Indeterminate; } else { _value = new EvaluationValue( bag, bag.GetType( context ) ); } } catch( EvaluationException e ) { context.Trace( "ERR: {0}", e.Message ); context.ProcessingError = true; _value = EvaluationValue.Indeterminate; } return _value; } throw new NotSupportedException( "internal error" ); } finally { _isEvaluated = true; context.RemoveIndent(); } }
/// <summary> /// Main evaluation method which is divided in two phases: Argument processing and /// Function evaluation. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The result of the evaluation in an EvaluationValue instance.</returns> public virtual EvaluationValue Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); // Validate the function exists context.Trace( "Calling function: {0}", _applyBase.FunctionId ); inf.IFunction function = EvaluationEngine.GetFunction( _applyBase.FunctionId ); if( function == null ) { context.Trace( "ERR: function not found {0}", _applyBase.FunctionId ); context.ProcessingError = true; return EvaluationValue.Indeterminate; } // Process the arguments. IFunctionParameterCollection arguments = ProcessArguments( context, new pol.IExpressionCollection( (pol.IExpressionReadWriteCollection)_applyBase.Arguments ) ); // Call the function with the arguments processed. EvaluationValue returnValue = EvaluationEngine.EvaluateFunction( context, function, arguments.ToArray() ); return returnValue; }
/// <summary> /// Evaluates the target items and return wether the target applies to the context or not. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="targetItem">The target item in the context document.</param> /// <returns></returns> public TargetEvaluationValue Evaluate( EvaluationContext context, ctx.TargetItemBase targetItem ) { if (context == null) throw new ArgumentNullException(nameof(context)); if (_targetItems.IsAny) { context.Trace("IsAny"); return TargetEvaluationValue.Match; } _evaluationValue = TargetEvaluationValue.NoMatch; //Match TargetItem foreach( pol.TargetItemBase polItem in _targetItems.ItemsList ) { foreach( pol.TargetMatchBase match in polItem.Match ) { _evaluationValue = TargetEvaluationValue.NoMatch; context.Trace( "Using function: {0}", match.MatchId ); inf.IFunction matchFunction = EvaluationEngine.GetFunction( match.MatchId ); if( matchFunction == null ) { context.Trace( "ERR: function not found {0}", match.MatchId ); context.ProcessingError = true; return TargetEvaluationValue.Indeterminate; } if( matchFunction.Returns == null ) { // Validates the function return value context.Trace( "ERR: The function '{0}' does not defines it's return value", match.MatchId ); context.ProcessingError = true; return TargetEvaluationValue.Indeterminate; } if( matchFunction.Returns != DataTypeDescriptor.Boolean ) { context.Trace( "ERR: Function does not return Boolean a value" ); context.ProcessingError = true; return TargetEvaluationValue.Indeterminate; } ctx.AttributeElement attribute = EvaluationEngine.Resolve( context, match, targetItem ); if( attribute != null ) { context.Trace( "Attribute found, evaluating match function" ); try { EvaluationValue returnValue = EvaluationEngine.EvaluateFunction( context, matchFunction, match.AttributeValue, attribute ); _evaluationValue = returnValue.BoolValue ? TargetEvaluationValue.Match : TargetEvaluationValue.NoMatch; } catch( EvaluationException e ) { context.Trace( Resource.TRACE_ERROR, e.Message ); _evaluationValue = TargetEvaluationValue.Indeterminate; } } // Validate MustBePresent if( match.AttributeReference.MustBePresent ) { if( context.IsMissingAttribute ) { context.Trace( "Attribute not found and must be present" ); _evaluationValue = TargetEvaluationValue.Indeterminate; } } // Do not iterate if the value was found if( _evaluationValue != TargetEvaluationValue.Match ) { break; } } // Do not iterate if the value was found if( _evaluationValue == TargetEvaluationValue.Match ) { return _evaluationValue; } } return _evaluationValue; }
/// <summary> /// THe argument processing method resolves all the attribute designators, attribute /// selectors. If there is an internal Apply it will be evaulated within this method. /// </summary> /// <remarks>All the processed arguments are converted into an IFunctionParameter instance /// because this is the only value that can be used to call a function.</remarks> /// <param name="context">The evaluation context instance.</param> /// <param name="arguments">The arguments to process.</param> /// <returns>A list of arguments ready to be used by a function.</returns> private IFunctionParameterCollection ProcessArguments(EvaluationContext context, pol.IExpressionCollection arguments) { context.Trace("Processing arguments"); context.AddIndent(); // Create a list to return the processed values. IFunctionParameterCollection processedArguments = new IFunctionParameterCollection(); // Iterate through the arguments, the IExpressionType is a mark interface foreach (inf.IExpression arg in arguments) { if (arg is pol.ApplyElement) { context.Trace("Nested apply"); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply((pol.ApplyElement)arg); // Evaluate the Apply EvaluationValue retVal = _childApply.Evaluate(context); context.TraceContextValues(); // If the results were Indeterminate the Indeterminate value will be placed in // the processed arguments, later another method will validate the parameters // and cancel the evaluation propperly. if (!retVal.IsIndeterminate) { if (!context.IsMissingAttribute) { processedArguments.Add(retVal); } } else { processedArguments.Add(retVal); } } else if (arg is pol.FunctionElementReadWrite) { // Search for the function and place it in the processed arguments. pol.FunctionElement functionId = new pol.FunctionElement(((pol.FunctionElementReadWrite)arg).FunctionId, ((pol.FunctionElementReadWrite)arg).SchemaVersion); context.Trace("Function {0}", functionId.FunctionId); inf.IFunction function = EvaluationEngine.GetFunction(functionId.FunctionId); if (function == null) { context.Trace("ERR: function not found {0}", _applyBase.FunctionId); context.ProcessingError = true; processedArguments.Add(EvaluationValue.Indeterminate); } else { processedArguments.Add(function); } } else if (arg is pol.VariableReferenceElement) { pol.VariableReferenceElement variableRef = arg as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; context.TraceContextValues(); if (!variableDef.IsEvaluated) { processedArguments.Add(variableDef.Evaluate(context)); } else { processedArguments.Add(variableDef.Value); } } else if (arg is pol.AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); processedArguments.Add(new pol.AttributeValueElement(((pol.AttributeValueElementReadWrite)arg).DataType, ((pol.AttributeValueElementReadWrite)arg).Contents, ((pol.AttributeValueElementReadWrite)arg).SchemaVersion)); } else if (arg is pol.AttributeDesignatorBase) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", arg.ToString()); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)arg; BagValue bag = EvaluationEngine.Resolve(context, attrDes); // If the attribute was not resolved by the EvaluationEngine search the // attribute in the context document, also using the EvaluationEngine public // methods. if (bag.BagSize == 0) { if (arg is pol.SubjectAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding subject attribute designator: {0}", attrib.ToString()); bag.Add(attrib); break; } } else if (arg is pol.ResourceAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding resource attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (arg is pol.ActionAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding action attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (arg is pol.EnvironmentAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding environment attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } } // If the argument was not found and the attribute must be present this is // a MissingAttribute situation so set the flag. Otherwise add the attribute // to the processed arguments. if (bag.BagSize == 0 && attrDes.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(attrDes); } else { processedArguments.Add(bag); } } else if (arg is pol.AttributeSelectorElement) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { BagValue bag = EvaluationEngine.Resolve(context, (pol.AttributeSelectorElement)arg); if (bag.Elements.Count == 0 && ((pol.AttributeSelectorElement)arg).MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute((pol.AttributeReferenceBase)arg); } else { processedArguments.Add(bag); } } catch (EvaluationException e) { context.Trace(Resource.TRACE_ERROR, e.Message); processedArguments.Add(EvaluationValue.Indeterminate); context.ProcessingError = true; } } } context.RemoveIndent(); return(processedArguments); }
/// <summary> /// This method overrides the ApplyBase method in order to provide extra validations /// required in the condition evaluation, for example the final return value should be a /// boolean value. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The EvaluationValue with the results of the condition evaluation.</returns> public override EvaluationValue Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.Trace("Evaluating condition"); context.AddIndent(); try { // Iterate through the arguments, the IExpressionType is a mark interface foreach (inf.IExpression arg in ApplyDefinition.Arguments) { if (arg is pol.ApplyElement) { context.Trace("Apply within condition."); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply((pol.ApplyElement)arg); // Evaluate the Apply EvaluationValue retVal = _childApply.Evaluate(context); return(retVal); } else if (arg is pol.FunctionElementReadWrite) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (arg is pol.VariableReferenceElement) { pol.VariableReferenceElement variableRef = arg as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; if (!variableDef.IsEvaluated) { return(variableDef.Evaluate(context)); } else { return(variableDef.Value); } } else if (arg is pol.AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); pol.AttributeValueElement attributeValue = new pol.AttributeValueElement(((pol.AttributeValueElementReadWrite)arg).DataType, ((pol.AttributeValueElementReadWrite)arg).Contents, ((pol.AttributeValueElementReadWrite)arg).SchemaVersion); return(new EvaluationValue( attributeValue.GetTypedValue(attributeValue.GetType(context), 0), attributeValue.GetType(context))); } else if (arg is pol.AttributeDesignatorBase) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace("Processing attribute designator: {0}", arg.ToString()); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)arg; BagValue bag = new BagValue(EvaluationEngine.GetDataType(attrDes.DataType)); return(new EvaluationValue(bag, bag.GetType(context))); } else if (arg is pol.AttributeSelectorElement) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace("Attribute selector"); pol.AttributeSelectorElement attrSel = (pol.AttributeSelectorElement)arg; BagValue bag = new BagValue(EvaluationEngine.GetDataType(attrSel.DataType)); return(new EvaluationValue(bag, bag.GetType(context))); } } throw new NotSupportedException("internal error"); } finally { context.TraceContextValues(); context.RemoveIndent(); } }
/// <summary> /// Evaluates the policy set. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The decission result for this policy set.</returns> public Decision Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); context.Trace( "Evaluating policySet: {0}", _policySet.Description ); context.CurrentPolicySet = this; try { context.Trace( "Evaluating Target..." ); context.AddIndent(); // Evaluate the policy target TargetEvaluationValue targetEvaluationValue = Match( context ); context.RemoveIndent(); context.Trace( "Target: {0}", targetEvaluationValue ); ProcessTargetEvaluationValue(context, targetEvaluationValue); context.Trace( "PolicySet: {0}", _evaluationValue ); // If the policy evaluated to Deny or Permit add the obligations depending on its fulfill value. ProcessObligations(context); return _evaluationValue; } finally { context.CurrentPolicySet = null; } }
/// <summary> /// Evaluates a function and also validates it's return value and parameter data types /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="functionInstance">The function to call</param> /// <param name="arguments">The function arguments</param> /// <returns>The return value of the function</returns> public static EvaluationValue EvaluateFunction( EvaluationContext context, inf.IFunction functionInstance, params inf.IFunctionParameter[] arguments ) { if (context == null) throw new ArgumentNullException("context"); // If the caller is in a missing attribute state the function should not be called if( context.IsMissingAttribute ) { context.Trace( "There's a missing attribute in the parameters" ); //TODO: resources return EvaluationValue.Indeterminate; } else { // Validate function defined arguments int functionArgumentIdx; for( functionArgumentIdx = 0; functionArgumentIdx < functionInstance.Arguments.Length; functionArgumentIdx++ ) { // Validate the value is not an Indeterminate value if( arguments[ functionArgumentIdx ] is EvaluationValue && ((EvaluationValue)arguments[ functionArgumentIdx ]).IsIndeterminate ) { if( !context.IsMissingAttribute ) { context.ProcessingError = true; } context.Trace( "There's a parameter with Indeterminate value" ); return EvaluationValue.Indeterminate; } // Compare the function and the value data type if( ( ( functionInstance.Arguments[ functionArgumentIdx ] != arguments[ functionArgumentIdx ].GetType( context ) ) && ( ( functionInstance.Arguments[ functionArgumentIdx ] != DataTypeDescriptor.Bag ) && (arguments[ functionArgumentIdx ] is BagValue) ) ) ) { context.ProcessingError = true; context.Trace( "There's a parameter with an invalid datatype" ); //TODO: resources return EvaluationValue.Indeterminate; } } //If the function supports variable arguments, the last datatype is used to validate the //rest of the parameters if( functionInstance.VarArgs ) { functionArgumentIdx--; for( int argumentValueIdx = functionArgumentIdx; argumentValueIdx < arguments.Length; argumentValueIdx++ ) { // Validate the value is not an Indeterminate value if( arguments[ argumentValueIdx ] is EvaluationValue && ((EvaluationValue)arguments[ argumentValueIdx ]).IsIndeterminate ) { if( !context.IsMissingAttribute ) { context.ProcessingError = true; } context.Trace( "There's a parameter with Indeterminate value" ); //TODO: resources return EvaluationValue.Indeterminate; } // Compare the function and the value data type if( ( functionInstance.Arguments[ functionArgumentIdx ] != arguments[ argumentValueIdx ].GetType( context ) ) && ( (arguments[ argumentValueIdx ] is BagValue) && ( functionInstance.Arguments[ functionArgumentIdx ] != DataTypeDescriptor.Bag ) ) ) { context.ProcessingError = true; context.Trace( "There's a parameter with an invalid datatype" ); //TODO: resources return EvaluationValue.Indeterminate; } } } StringBuilder sb = new StringBuilder(); // Call the function in a controlled evironment to capture any exception try { sb.Append( functionInstance.Id ); sb.Append( "( " ); bool isFirst = true; foreach( inf.IFunctionParameter param in arguments ) { if( isFirst ) { isFirst = false; } else { sb.Append( ", " ); } sb.Append( param.ToString() ); } sb.Append( " )" ); sb.Append( " = " ); EvaluationValue returnValue = functionInstance.Evaluate( context, arguments ); sb.Append( returnValue.ToString() ); context.Trace( sb.ToString() ); return returnValue; } catch( EvaluationException e ) { context.Trace( sb.ToString() ); context.ProcessingError = true; context.Trace( "Error: {0}", e.Message ); //TODO: resources return EvaluationValue.Indeterminate; } } }
/// <summary> /// THe argument processing method resolves all the attribute designators, attribute /// selectors. If there is an internal Apply it will be evaulated within this method. /// </summary> /// <remarks>All the processed arguments are converted into an IFunctionParameter instance /// because this is the only value that can be used to call a function.</remarks> /// <param name="context">The evaluation context instance.</param> /// <param name="arguments">The arguments to process.</param> /// <returns>A list of arguments ready to be used by a function.</returns> private IFunctionParameterCollection ProcessArguments( EvaluationContext context, pol.IExpressionCollection arguments ) { context.Trace( "Processing arguments" ); context.AddIndent(); // Create a list to return the processed values. IFunctionParameterCollection processedArguments = new IFunctionParameterCollection(); // Iterate through the arguments, the IExpressionType is a mark interface foreach( inf.IExpression arg in arguments ) { if( arg is pol.ApplyElement ) { context.Trace( "Nested apply" ); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply( (pol.ApplyElement)arg ); // Evaluate the Apply EvaluationValue retVal = _childApply.Evaluate( context ); context.TraceContextValues(); // If the results were Indeterminate the Indeterminate value will be placed in // the processed arguments, later another method will validate the parameters // and cancel the evaluation propperly. if( !retVal.IsIndeterminate ) { if( !context.IsMissingAttribute ) { processedArguments.Add( retVal ); } } else { processedArguments.Add( retVal ); } } else if( arg is pol.FunctionElementReadWrite ) { // Search for the function and place it in the processed arguments. pol.FunctionElement functionId = new pol.FunctionElement( ((pol.FunctionElementReadWrite)arg).FunctionId, ((pol.FunctionElementReadWrite)arg).SchemaVersion ); context.Trace( "Function {0}", functionId.FunctionId ); inf.IFunction function = EvaluationEngine.GetFunction( functionId.FunctionId ); if( function == null ) { context.Trace( "ERR: function not found {0}", _applyBase.FunctionId ); context.ProcessingError = true; processedArguments.Add( EvaluationValue.Indeterminate ); } else { processedArguments.Add( function ); } } else if( arg is pol.VariableReferenceElement ) { pol.VariableReferenceElement variableRef = arg as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[ variableRef.VariableId ] as VariableDefinition; context.TraceContextValues(); if( !variableDef.IsEvaluated ) { processedArguments.Add( variableDef.Evaluate( context ) ); } else { processedArguments.Add( variableDef.Value ); } } else if( arg is pol.AttributeValueElementReadWrite ) { // The AttributeValue does not need to be processed context.Trace( "Attribute value {0}", arg.ToString() ); processedArguments.Add( new pol.AttributeValueElement( ((pol.AttributeValueElementReadWrite)arg).DataType, ((pol.AttributeValueElementReadWrite)arg).Contents, ((pol.AttributeValueElementReadWrite)arg).SchemaVersion )); } else if( arg is pol.AttributeDesignatorBase ) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace( "Processing attribute designator: {0}", arg.ToString() ); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)arg; BagValue bag = EvaluationEngine.Resolve( context, attrDes ); // If the attribute was not resolved by the EvaluationEngine search the // attribute in the context document, also using the EvaluationEngine public // methods. if( bag.BagSize == 0 ) { if( arg is pol.SubjectAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding subject attribute designator: {0}", attrib.ToString() ); bag.Add( attrib ); break; } } else if( arg is pol.ResourceAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding resource attribute designator {0}", attrib.ToString() ); bag.Add( attrib ); } } else if( arg is pol.ActionAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding action attribute designator {0}", attrib.ToString() ); bag.Add( attrib ); } } else if( arg is pol.EnvironmentAttributeDesignatorElement ) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute( context, attrDes ); if( attrib != null ) { context.Trace( "Adding environment attribute designator {0}", attrib.ToString() ); bag.Add( attrib ); } } } // If the argument was not found and the attribute must be present this is // a MissingAttribute situation so set the flag. Otherwise add the attribute // to the processed arguments. if( bag.BagSize == 0 && attrDes.MustBePresent ) { context.Trace( "Attribute is missing" ); context.IsMissingAttribute = true; context.AddMissingAttribute( attrDes ); } else { processedArguments.Add( bag ); } } else if( arg is pol.AttributeSelectorElement ) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace( "Attribute selector" ); try { BagValue bag = EvaluationEngine.Resolve( context, (pol.AttributeSelectorElement)arg ); if( bag.Elements.Count == 0 && ((pol.AttributeSelectorElement)arg).MustBePresent ) { context.Trace( "Attribute is missing" ); context.IsMissingAttribute = true; context.AddMissingAttribute( (pol.AttributeReferenceBase)arg ); } else { processedArguments.Add( bag ); } } catch( EvaluationException e ) { context.Trace( Resource.TRACE_ERROR, e.Message ); processedArguments.Add( EvaluationValue.Indeterminate ); context.ProcessingError = true; } } } context.RemoveIndent(); return processedArguments; }
/// <summary> /// This method overrides the ApplyBase method in order to provide extra validations /// required in the condition evaluation, for example the final return value should be a /// boolean value. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The EvaluationValue with the results of the condition evaluation.</returns> public override EvaluationValue Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); EvaluationValue _evaluationValue = null; context.Trace( "Evaluating condition..." ); context.AddIndent(); try { // Get the function instance inf.IFunction function = EvaluationEngine.GetFunction( ApplyDefinition.FunctionId ); if( function == null ) { context.Trace( "ERR: function not found {0}", ApplyDefinition.FunctionId ); context.ProcessingError = true; return EvaluationValue.Indeterminate; } // Validates the function return value if( function.Returns == null ) { context.Trace( "The function '{0}' does not defines it's return value", ApplyDefinition.FunctionId ); _evaluationValue = EvaluationValue.Indeterminate; context.ProcessingError = true; } else if( function.Returns != DataTypeDescriptor.Boolean ) { context.Trace( "Function does not return Boolean a value" ); _evaluationValue = EvaluationValue.Indeterminate; context.ProcessingError = true; } else { // Call the ApplyBase method to perform the evaluation. _evaluationValue = base.Evaluate( context ); } // Validate the results of the evaluation if( _evaluationValue.IsIndeterminate ) { context.Trace( "condition evaluated into {0}", _evaluationValue.ToString() ); return _evaluationValue; } if( !(_evaluationValue.Value is bool) ) { context.Trace( "condition evaluated into {0}", _evaluationValue.ToString() ); return EvaluationValue.Indeterminate; } if( _evaluationValue.BoolValue ) { context.Trace( "condition evaluated into {0}", _evaluationValue.ToString() ); return EvaluationValue.True; } else { // If the evaluation was false, validate if there was a missin attribute during // evaluation and return an Indeterminate, otherwise return the False value. if( context.IsMissingAttribute ) { context.Trace( "condition evaluated into {0}", _evaluationValue.ToString() ); return EvaluationValue.Indeterminate; } else { context.Trace( "condition evaluated into {0}", _evaluationValue.ToString() ); return EvaluationValue.False; } } } finally { context.TraceContextValues(); context.RemoveIndent(); context.Trace( "Condition: {0}", _evaluationValue.ToString() ); } }
/// <summary> /// The evaluation implementation in the pseudo-code described in the specification. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="rules">The policies that must be evaluated.</param> /// <returns>The final decission for the combination of the rule evaluation.</returns> public Decision Evaluate(EvaluationContext context, RuleCollection rules) { if (context == null) { throw new ArgumentNullException("context"); } if (rules == null) { throw new ArgumentNullException("rules"); } Decision decision = Decision.Indeterminate; bool atLeastOneError = false; bool potentialPermit = false; bool atLeastOneDeny = false; context.Trace("Evaluating rules..."); context.AddIndent(); try { foreach (Rule rule in rules) { decision = rule.Evaluate(context); context.TraceContextValues(); if (decision == Decision.Deny) { atLeastOneDeny = true; continue; } if (decision == Decision.Permit) { decision = Decision.Permit; return(decision); } if (decision == Decision.NotApplicable) { continue; } if (decision == Decision.Indeterminate) { atLeastOneError = true; if (rule.RuleDefinition.Effect == pol.Effect.Permit) { potentialPermit = true; } continue; } } if (potentialPermit) { decision = Decision.Indeterminate; return(decision); } if (atLeastOneDeny) { decision = Decision.Deny; return(decision); } if (atLeastOneError) { decision = Decision.Indeterminate; return(decision); } decision = Decision.NotApplicable; return(decision); } finally { context.Trace("Rule combination algorithm: {0}", decision.ToString()); context.RemoveIndent(); } }
/// <summary> /// This method overrides the ApplyBase method in order to provide extra validations /// required in the condition evaluation, for example the final return value should be a /// boolean value. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The EvaluationValue with the results of the condition evaluation.</returns> public override EvaluationValue Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); context.Trace( "Evaluating condition" ); context.AddIndent(); try { // Iterate through the arguments, the IExpressionType is a mark interface foreach( inf.IExpression arg in ApplyDefinition.Arguments ) { if( arg is pol.ApplyElement ) { context.Trace( "Apply within condition." ); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply( (pol.ApplyElement)arg ); // Evaluate the Apply EvaluationValue retVal = _childApply.Evaluate( context ); return retVal; } else if( arg is pol.FunctionElementReadWrite ) { throw new NotImplementedException( "FunctionElement" ); //TODO: } else if( arg is pol.VariableReferenceElement ) { pol.VariableReferenceElement variableRef = arg as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[ variableRef.VariableId ] as VariableDefinition; if( !variableDef.IsEvaluated ) { return variableDef.Evaluate( context ); } else { return variableDef.Value; } } else if( arg is pol.AttributeValueElementReadWrite ) { // The AttributeValue does not need to be processed context.Trace( "Attribute value {0}", arg.ToString() ); pol.AttributeValueElement attributeValue = new pol.AttributeValueElement( ((pol.AttributeValueElementReadWrite)arg).DataType, ((pol.AttributeValueElementReadWrite)arg).Contents, ((pol.AttributeValueElementReadWrite)arg).SchemaVersion ); return new EvaluationValue( attributeValue.GetTypedValue( attributeValue.GetType( context ), 0 ), attributeValue.GetType( context ) ); } else if( arg is pol.AttributeDesignatorBase ) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace( "Processing attribute designator: {0}", arg.ToString() ); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)arg; BagValue bag = new BagValue( EvaluationEngine.GetDataType( attrDes.DataType ) ); return new EvaluationValue( bag, bag.GetType( context ) ); } else if( arg is pol.AttributeSelectorElement ) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace( "Attribute selector" ); pol.AttributeSelectorElement attrSel = (pol.AttributeSelectorElement)arg; BagValue bag = new BagValue( EvaluationEngine.GetDataType( attrSel.DataType ) ); return new EvaluationValue( bag, bag.GetType( context ) ); } } throw new NotSupportedException( "internal error" ); } finally { context.TraceContextValues(); context.RemoveIndent(); } }
/// <summary> /// Evaluates the policy. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The decission result for this policy.</returns> public Decision Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.Trace("Evaluating policy: {0}", _policy.Description); context.AddIndent(); context.CurrentPolicy = this; try { // Evaluate the variables if (this._policy.SchemaVersion == XacmlVersion.Version20) { if (_variables == null) { context.Trace("Evaluating variables..."); _variables = new Hashtable(); foreach (pol.VariableDefinitionElement variableDef in _policy.VariableDefinitions.Values) { VariableDefinition variable = new VariableDefinition(variableDef); _variables.Add(variableDef.Id, variable); } } } // Matches the target. TargetEvaluationValue targetEvaluationValue = Match(context); // If the target matches. if (targetEvaluationValue == TargetEvaluationValue.Match) { context.Trace("Rule combination algorithm: {0}", _policy.RuleCombiningAlgorithm); // Evaluate all rules and apply rule combination inf.IRuleCombiningAlgorithm rca = EvaluationEngine.CreateRuleCombiningAlgorithm(_policy.RuleCombiningAlgorithm); _evaluationValue = rca.Evaluate(context, _rules); } else if (targetEvaluationValue == TargetEvaluationValue.NoMatch) { _evaluationValue = Decision.NotApplicable; } else if (targetEvaluationValue == TargetEvaluationValue.Indeterminate) { _evaluationValue = Decision.Indeterminate; } context.Trace("Policy: {0}", _evaluationValue); // Copy all the obligations. _obligations = new pol.ObligationCollection(); if (_evaluationValue != Decision.Indeterminate && _evaluationValue != Decision.NotApplicable && _policy.Obligations != null && _policy.Obligations.Count != 0) { foreach (pol.ObligationElement obl in _policy.Obligations) { if ((obl.FulfillOn == pol.Effect.Deny && _evaluationValue == Decision.Deny) || (obl.FulfillOn == pol.Effect.Permit && _evaluationValue == Decision.Permit)) { context.Trace("Adding obligation: {0} ", obl.ObligationId); _obligations.Add(obl); } } } return(_evaluationValue); } finally { context.RemoveIndent(); context.CurrentPolicy = null; } }
/// <summary> /// This method overrides the ApplyBase method in order to provide extra validations /// required in the condition evaluation, for example the final return value should be a /// boolean value. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The EvaluationValue with the results of the condition evaluation.</returns> public override EvaluationValue Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } EvaluationValue _evaluationValue = null; context.Trace("Evaluating condition..."); context.AddIndent(); try { // Get the function instance inf.IFunction function = EvaluationEngine.GetFunction(ApplyDefinition.FunctionId); if (function == null) { context.Trace("ERR: function not found {0}", ApplyDefinition.FunctionId); context.ProcessingError = true; return(EvaluationValue.Indeterminate); } // Validates the function return value if (function.Returns == null) { context.Trace("The function '{0}' does not defines it's return value", ApplyDefinition.FunctionId); _evaluationValue = EvaluationValue.Indeterminate; context.ProcessingError = true; } else if (function.Returns != DataTypeDescriptor.Boolean) { context.Trace("Function does not return Boolean a value"); _evaluationValue = EvaluationValue.Indeterminate; context.ProcessingError = true; } else { // Call the ApplyBase method to perform the evaluation. _evaluationValue = base.Evaluate(context); } // Validate the results of the evaluation if (_evaluationValue.IsIndeterminate) { context.Trace("condition evaluated into {0}", _evaluationValue.ToString()); return(_evaluationValue); } if (!(_evaluationValue.Value is bool)) { context.Trace("condition evaluated into {0}", _evaluationValue.ToString()); return(EvaluationValue.Indeterminate); } if (_evaluationValue.BoolValue) { context.Trace("condition evaluated into {0}", _evaluationValue.ToString()); return(EvaluationValue.True); } else { // If the evaluation was false, validate if there was a missin attribute during // evaluation and return an Indeterminate, otherwise return the False value. if (context.IsMissingAttribute) { context.Trace("condition evaluated into {0}", _evaluationValue.ToString()); return(EvaluationValue.Indeterminate); } else { context.Trace("condition evaluated into {0}", _evaluationValue.ToString()); return(EvaluationValue.False); } } } finally { context.TraceContextValues(); context.RemoveIndent(); context.Trace("Condition: {0}", _evaluationValue.ToString()); } }
/// <summary> /// Matches this target instance using the context document. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The results of the evaluation of this target.</returns> public TargetEvaluationValue Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); // Set the default value. _evaluationValue = TargetEvaluationValue.NoMatch; // Resource context.Trace( "Evaluating Resource..." ); context.AddIndent(); TargetEvaluationValue resourceEval = _resources.Evaluate( context, context.CurrentResource ); context.TraceContextValues(); context.Trace( "Target item result: {0}", resourceEval ); context.RemoveIndent(); // Action context.Trace( "Evaluating Action..." ); context.AddIndent(); TargetEvaluationValue actionEval = _actions.Evaluate( context, context.ContextDocument.Request.Action ); context.TraceContextValues(); context.Trace( "Target item result: {0}", actionEval ); context.RemoveIndent(); context.Trace( "Evaluating Subjects..." ); context.AddIndent(); if( actionEval == TargetEvaluationValue.Match && resourceEval == TargetEvaluationValue.Match ) { // Subjects foreach( ctx.SubjectElement ctxSubject in context.ContextDocument.Request.Subjects ) { context.Trace( "Evaluating Subject: {0}", ctxSubject.SubjectCategory ); // Subject TargetEvaluationValue subjectEval = _subjects.Evaluate( context, ctxSubject ); context.TraceContextValues(); if( subjectEval == TargetEvaluationValue.Indeterminate ) { _evaluationValue = TargetEvaluationValue.Indeterminate; } else if( subjectEval == TargetEvaluationValue.Match ) { _evaluationValue = TargetEvaluationValue.Match; context.RemoveIndent(); context.Trace( "Target item result: {0}", _evaluationValue ); return _evaluationValue; } } context.RemoveIndent(); context.Trace( "Target item result: {0}", _evaluationValue ); return _evaluationValue; } else { context.Trace( "Actions or Resources does not Match so Subjects will not be evaluated" ); if( resourceEval == TargetEvaluationValue.Indeterminate || actionEval == TargetEvaluationValue.Indeterminate ) { context.RemoveIndent(); return TargetEvaluationValue.Indeterminate; } else { context.RemoveIndent(); return TargetEvaluationValue.NoMatch; } } }
/// <summary> /// Evaluates the function. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="args">The function arguments.</param> /// <returns>The result value of the function evaluation.</returns> public override EvaluationValue Evaluate( EvaluationContext context, params inf.IFunctionParameter[] args ) { if (context == null) throw new ArgumentNullException("context"); if (args == null) throw new ArgumentNullException("args"); try { if( GetAnyUriArgument( args, 0 ).Equals( GetAnyUriArgument( args, 1 ) ) ) { return EvaluationValue.True; } else { return EvaluationValue.False; } } catch( EvaluationException e ) { context.Trace( Resource.TRACE_ERROR, e.Message ); return EvaluationValue.False; } }
/// <summary> /// Evaluates the policy. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The decission result for this policy.</returns> public Decision Evaluate( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); context.Trace( "Evaluating policy: {0}", _policy.Description ); context.AddIndent(); context.CurrentPolicy = this; try { // Evaluate the variables if( this._policy.SchemaVersion == XacmlVersion.Version20 ) { if( _variables == null ) { context.Trace( "Evaluating variables..." ); _variables = new Hashtable(); foreach( pol.VariableDefinitionElement variableDef in _policy.VariableDefinitions.Values ) { VariableDefinition variable = new VariableDefinition( variableDef ); _variables.Add( variableDef.Id, variable ); } } } // Matches the target. TargetEvaluationValue targetEvaluationValue = Match( context ); // If the target matches. if( targetEvaluationValue == TargetEvaluationValue.Match ) { context.Trace( "Rule combination algorithm: {0}", _policy.RuleCombiningAlgorithm ); // Evaluate all rules and apply rule combination inf.IRuleCombiningAlgorithm rca = EvaluationEngine.CreateRuleCombiningAlgorithm( _policy.RuleCombiningAlgorithm ); _evaluationValue = rca.Evaluate( context, _rules ); } else if( targetEvaluationValue == TargetEvaluationValue.NoMatch ) { _evaluationValue = Decision.NotApplicable; } else if( targetEvaluationValue == TargetEvaluationValue.Indeterminate ) { _evaluationValue = Decision.Indeterminate; } context.Trace( "Policy: {0}", _evaluationValue ); // Copy all the obligations. _obligations = new pol.ObligationCollection(); if( _evaluationValue != Decision.Indeterminate && _evaluationValue != Decision.NotApplicable && _policy.Obligations != null && _policy.Obligations.Count != 0 ) { foreach( pol.ObligationElement obl in _policy.Obligations ) { if( ( obl.FulfillOn == pol.Effect.Deny && _evaluationValue == Decision.Deny ) || ( obl.FulfillOn == pol.Effect.Permit && _evaluationValue == Decision.Permit ) ) { context.Trace( "Adding obligation: {0} ", obl.ObligationId ); _obligations.Add( obl ); } } } return _evaluationValue; } finally { context.RemoveIndent(); context.CurrentPolicy = null; } }
/// <summary> /// The evaluation implementation in the pseudo-code described in the specification. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="rules">The policies that must be evaluated.</param> /// <returns>The final decission for the combination of the rule evaluation.</returns> public Decision Evaluate( EvaluationContext context, RuleCollection rules ) { Decision decision = Decision.Indeterminate; bool atLeastOneError = false; bool potentialDeny = false; bool atLeastOnePermit = false; context.Trace( "Evaluating rules..." ); context.AddIndent(); try { foreach( Rule rule in rules ) { decision = rule.Evaluate( context ); context.TraceContextValues(); if( decision == Decision.Deny ) { decision = Decision.Deny; return decision; } if( decision == Decision.Permit ) { atLeastOnePermit = true; continue; } if( decision == Decision.NotApplicable ) { continue; } if( decision == Decision.Indeterminate ) { atLeastOneError = true; if( rule.RuleDefinition.Effect == pol.Effect.Deny ) { potentialDeny = true; } continue; } } if( potentialDeny ) { decision = Decision.Indeterminate; return decision; } if( atLeastOnePermit ) { decision = Decision.Permit; return decision; } if( atLeastOneError ) { decision = Decision.Indeterminate; return decision; } decision = Decision.NotApplicable; return decision; } finally { context.Trace( "Rule combination algorithm: {0}", decision.ToString() ); context.RemoveIndent(); } }
/// <summary> /// Evaluates the variable into a value. /// </summary> /// <param name="context">The contex of the evaluation.</param> /// <returns>The value of the function.</returns> public EvaluationValue Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.Trace("Evaluating variable"); context.AddIndent(); try { if (_variableDefinition.Expression is pol.ApplyElement) { context.Trace("Apply within condition."); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply((pol.ApplyElement)_variableDefinition.Expression); // Evaluate the Apply _value = _childApply.Evaluate(context); context.TraceContextValues(); return(_value); } else if (_variableDefinition.Expression is pol.FunctionElement) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (_variableDefinition.Expression is pol.VariableReferenceElement) { pol.VariableReferenceElement variableRef = _variableDefinition.Expression as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; context.TraceContextValues(); if (!variableDef.IsEvaluated) { return(variableDef.Evaluate(context)); } else { return(variableDef.Value); } } else if (_variableDefinition.Expression is pol.AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", _variableDefinition.Expression.ToString()); pol.AttributeValueElementReadWrite att = (pol.AttributeValueElementReadWrite)_variableDefinition.Expression; pol.AttributeValueElement attributeValue = new pol.AttributeValueElement(att.DataType, att.Contents, att.SchemaVersion); _value = new EvaluationValue( attributeValue.GetTypedValue(attributeValue.GetType(context), 0), attributeValue.GetType(context)); return(_value); } else if (_variableDefinition.Expression is pol.AttributeDesignatorBase) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", _variableDefinition.Expression.ToString()); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)_variableDefinition.Expression; BagValue bag = EvaluationEngine.Resolve(context, attrDes); // If the attribute was not resolved by the EvaluationEngine search the // attribute in the context document, also using the EvaluationEngine public // methods. if (bag.BagSize == 0) { if (_variableDefinition.Expression is pol.SubjectAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding subject attribute designator: {0}", attrib.ToString()); bag.Add(attrib); } } else if (_variableDefinition.Expression is pol.ResourceAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding resource attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (_variableDefinition.Expression is pol.ActionAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding action attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (_variableDefinition.Expression is pol.EnvironmentAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding environment attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } } // If the argument was not found and the attribute must be present this is // a MissingAttribute situation so set the flag. Otherwise add the attribute // to the processed arguments. if (bag.BagSize == 0 && attrDes.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(attrDes); _value = EvaluationValue.Indeterminate; } else { _value = new EvaluationValue(bag, bag.GetType(context)); } return(_value); } else if (_variableDefinition.Expression is pol.AttributeSelectorElement) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { pol.AttributeSelectorElement attributeSelector = (pol.AttributeSelectorElement)_variableDefinition.Expression; BagValue bag = EvaluationEngine.Resolve(context, attributeSelector); if (bag.Elements.Count == 0 && attributeSelector.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(attributeSelector); _value = EvaluationValue.Indeterminate; } else { _value = new EvaluationValue(bag, bag.GetType(context)); } } catch (EvaluationException e) { context.Trace("ERR: {0}", e.Message); context.ProcessingError = true; _value = EvaluationValue.Indeterminate; } return(_value); } throw new NotSupportedException("internal error"); } finally { _isEvaluated = true; context.RemoveIndent(); } }
/// <summary> /// Evaluate the context document using a specified policy /// </summary> /// <param name="contextDocument">The context document instance</param> /// <returns>The response document.</returns> public ctx.ResponseElement Evaluate( ctx.ContextDocument contextDocument ) { EvaluationContext context = new EvaluationContext( this, null, contextDocument ); try { // Validates the configuration file was found. if( ConfigurationRoot.Config != null ) { // Search all the policies repositories to find a policy that matches the // context document pol.PolicyDocument policyDocument = null; foreach( inf.IPolicyRepository policyRep in ConfigurationRoot.Config.PolicyRepositories ) { if( policyDocument == null ) { policyDocument = policyRep.Match( context ); } else { throw new EvaluationException( Resource.ResourceManager[ Resource.MessageKey.exc_duplicated_policy_in_repository ] ); } } // If the policy was found evaluate the context document, otherwise use the // Evaluate method to generate a Response context document. if( policyDocument != null ) { return Evaluate( policyDocument, contextDocument ); } return Evaluate(null, null); } throw new EvaluationException(Resource.ResourceManager[ Resource.MessageKey.exc_configuration_file_not_found]); } catch( EvaluationException e ) { context.Trace( Resource.TRACE_ERROR, e.Message ); } return Evaluate(null, null); }
/// <summary> /// Verifies if the rule target matches /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The result of the Match process.</returns> public TargetEvaluationValue Match( EvaluationContext context ) { if (context == null) throw new ArgumentNullException("context"); TargetEvaluationValue targetEvaluationValue = TargetEvaluationValue.Indeterminate; context.Trace( "Evaluating rule target" ); context.AddIndent(); try { // Evaluate the policy target targetEvaluationValue = TargetEvaluationValue.Match; if( _target != null ) { targetEvaluationValue = _target.Evaluate( context ); context.TraceContextValues(); } return targetEvaluationValue; } finally { context.RemoveIndent(); context.Trace( "Target: {0}", targetEvaluationValue ); } }
/// <summary> /// Evaluate the context document using a specified policy /// </summary> /// <param name="policyDocument">The policy instance</param> /// <param name="contextDocument">The context document instance</param> /// <returns>The response document</returns> public ctx.ResponseElement Evaluate( pol.PolicyDocument policyDocument, ctx.ContextDocument contextDocument ) { if (policyDocument == null) throw new ArgumentNullException("policyDocument"); if (contextDocument == null) throw new ArgumentNullException("contextDocument"); EvaluationContext context = new EvaluationContext( this, policyDocument, (ctx.ContextDocument)contextDocument ) ; context.Trace( "Start evaluation" ); context.AddIndent(); if ( policyDocument == null || contextDocument == null ) { // If a validation error was found a response is created with the syntax error message ctx.ResponseElement response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement( StatusCodes.ProcessingError, null, policyDocument.Version ), null, null, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version ); return response; } // Check if both documents are valid if( !policyDocument.IsValidDocument || !contextDocument.IsValidDocument ) { // If a validation error was found a response is created with the syntax error message ctx.ResponseElement response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement( StatusCodes.SyntaxError, null, policyDocument.Version ), null, null, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version ); return response; } // Create a new response contextDocument.Response = new ctx.ResponseElement( (ctx.ResultElement[])null, policyDocument.Version ); try { // Create the evaluable policy intance IMatchEvaluable policy = null; if( policyDocument.PolicySet != null ) { policy = new PolicySet( this, (pol.PolicySetElement)policyDocument.PolicySet ); } else if( policyDocument.Policy != null ) { policy = new Policy( (pol.PolicyElement)policyDocument.Policy ); } // Evaluate the policy or policy set if( policy != null ) { // Creates the evaluable policy set if( policy.AllResources.Count == 0 ) { policy.AllResources.Add( "" ); } string requestedResourceString = String.Empty; Uri requestedResource = null; foreach( ctx.ResourceElement resource in contextDocument.Request.Resources ) { // Keep the requested resource if( resource.IsHierarchical ) { foreach( ctx.AttributeElement attribute in resource.Attributes ) { if( attribute.AttributeId == ResourceElement.ResourceId ) { if( context.PolicyDocument.Version == XacmlVersion.Version10 || context.PolicyDocument.Version == XacmlVersion.Version11 ) { requestedResourceString = attribute.AttributeValues[0].Contents; } else { if( attribute.AttributeValues.Count > 1 ) { throw new NotSupportedException( "resources contains a bag of values" ); } requestedResourceString = attribute.AttributeValues[0].Contents; } } } if( !string.IsNullOrEmpty(requestedResourceString) ) { requestedResource = new Uri( requestedResourceString ); } } // Iterate through the policy resources evaluating each resource in the context document request foreach( string resourceName in policy.AllResources ) { bool mustEvaluate; if( resource.IsHierarchical ) { //Validate if the resource is hierarchically desdendant or children //of the requested resource Uri policyResource = new Uri( resourceName ); if( !(mustEvaluate = requestedResource.Equals( policyResource ) ) ) { // Perform the hierarchical evaluation if( resource.ResourceScopeValue == ctx.ResourceScope.Children ) { mustEvaluate = typ.AnyUri.IsChildrenOf( requestedResource, policyResource ); } else if( resource.ResourceScopeValue == ctx.ResourceScope.Descendants ) { mustEvaluate = typ.AnyUri.IsDescendantOf( requestedResource, policyResource ); } } if( mustEvaluate ) { foreach( ctx.AttributeElementReadWrite attribute in context.CurrentResource.Attributes ) { if( attribute.AttributeId == ResourceElement.ResourceId ) { attribute.AttributeValues[0].Contents = resourceName; break; } } } } else { context.CurrentResource = resource; mustEvaluate = true; } if( mustEvaluate ) { // Evaluates the policy set Decision decision = policy.Evaluate( context ); // Create a status code using the policy execution state ctx.StatusCodeElement scode; if( context.IsMissingAttribute ) { scode = new ctx.StatusCodeElement( StatusCodes.MissingAttribute, null, policyDocument.Version ); } else if( context.ProcessingError ) { scode = new ctx.StatusCodeElement( StatusCodes.ProcessingError, null, policyDocument.Version ); } else { scode = new ctx.StatusCodeElement( StatusCodes.OK, null, policyDocument.Version ); } //Stop the iteration if there is not a hierarchical request if( !resource.IsHierarchical ) { // Ussually when a single resource is requested the ResourceId is not specified in the result IObligationsContainer oblig = policy as IObligationsContainer; contextDocument.Response.Results.Add( new ctx.ResultElement( "", decision, new ctx.StatusElement( scode, "", "", policyDocument.Version ), oblig.Obligations, policyDocument.Version ) ); break; } else { // Adding a resource for each requested resource, using the resourceName as the resourceId of the result IObligationsContainer oblig = policy as IObligationsContainer; contextDocument.Response.Results.Add( new ctx.ResultElement( resourceName, decision, new ctx.StatusElement( scode, "", "", policyDocument.Version ), oblig.Obligations, policyDocument.Version ) ); } } // if( mustEvaluate ) } // foreach( string resourceName in policy.AllResources ) } } //if( policy != null ) } catch( EvaluationException e ) { // If a validation error was found a response is created with the syntax error message contextDocument.Response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement( StatusCodes.ProcessingError, null, policyDocument.Version ), e.Message, e.StackTrace, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version ); } return contextDocument.Response; }
/// <summary> /// Matches this target instance using the context document. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <returns>The results of the evaluation of this target.</returns> public TargetEvaluationValue Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } // Set the default value. _evaluationValue = TargetEvaluationValue.NoMatch; // Resource context.Trace("Evaluating Resource..."); context.AddIndent(); TargetEvaluationValue resourceEval = _resources.Evaluate(context, context.CurrentResource); context.TraceContextValues(); context.Trace("Target item result: {0}", resourceEval); context.RemoveIndent(); // Action context.Trace("Evaluating Action..."); context.AddIndent(); TargetEvaluationValue actionEval = _actions.Evaluate(context, context.ContextDocument.Request.Action); context.TraceContextValues(); context.Trace("Target item result: {0}", actionEval); context.RemoveIndent(); context.Trace("Evaluating Subjects..."); context.AddIndent(); if (actionEval == TargetEvaluationValue.Match && resourceEval == TargetEvaluationValue.Match) { // Subjects foreach (ctx.SubjectElement ctxSubject in context.ContextDocument.Request.Subjects) { context.Trace("Evaluating Subject: {0}", ctxSubject.SubjectCategory); // Subject TargetEvaluationValue subjectEval = _subjects.Evaluate(context, ctxSubject); context.TraceContextValues(); if (subjectEval == TargetEvaluationValue.Indeterminate) { _evaluationValue = TargetEvaluationValue.Indeterminate; } else if (subjectEval == TargetEvaluationValue.Match) { _evaluationValue = TargetEvaluationValue.Match; context.RemoveIndent(); context.Trace("Target item result: {0}", _evaluationValue); return(_evaluationValue); } } context.RemoveIndent(); context.Trace("Target item result: {0}", _evaluationValue); return(_evaluationValue); } else { context.Trace("Actions or Resources does not Match so Subjects will not be evaluated"); if (resourceEval == TargetEvaluationValue.Indeterminate || actionEval == TargetEvaluationValue.Indeterminate) { context.RemoveIndent(); return(TargetEvaluationValue.Indeterminate); } else { context.RemoveIndent(); return(TargetEvaluationValue.NoMatch); } } }
/// <summary> /// Resolves the AttributeSelector in the context document using the XPath sentence. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="attributeSelector">The attribute selector.</param> /// <returns>A bag of values with the contents of the node.</returns> public static BagValue Resolve( EvaluationContext context, pol.AttributeSelectorElement attributeSelector ) { BagValue bagValue = new BagValue( GetDataType( attributeSelector.DataType ) ); ctx.ResourceContentElement content = (ctx.ResourceContentElement)context.CurrentResource.ResourceContent; if( content != null ) { XmlDocument doc = context.ContextDocument.XmlDocument; if( context.ContextDocument.XmlNamespaceManager == null ) { context.ContextDocument.AddNamespaces( context.PolicyDocument.Namespaces ); } try { string xpath = attributeSelector.RequestContextPath; XmlNodeList nodeList = doc.DocumentElement.SelectNodes( xpath, context.ContextDocument.XmlNamespaceManager ); if( nodeList != null ) { foreach( XmlNode node in nodeList ) { pol.AttributeValueElement ave = new pol.AttributeValueElement( attributeSelector.DataType, node.InnerText, attributeSelector.SchemaVersion ); bagValue.Add( ave ); } } } catch( XPathException e ) { context.Trace( Resource.TRACE_ERROR, e.Message ); bagValue = new BagValue( GetDataType( attributeSelector.DataType ) ); } } return bagValue; }