/// <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"); } var 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 == 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) { var 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 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> /// 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 ) { var 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> /// 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 (IExpression arg in ApplyDefinition.Arguments) { if (arg is 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. var childApply = new Apply((ApplyElement)arg); // Evaluate the Apply EvaluationValue retVal = childApply.Evaluate(context); return(retVal); } else if (arg is FunctionElementReadWrite) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (arg is VariableReferenceElement) { var variableRef = arg as VariableReferenceElement; var variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; Debug.Assert(variableDef != null, "variableDef != null"); if (!variableDef.IsEvaluated) { return(variableDef.Evaluate(context)); } else { return(variableDef.Value); } } else if (arg is AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); var attributeValue = new AttributeValueElement(((AttributeValueElementReadWrite)arg).DataType, ((AttributeValueElementReadWrite)arg).Contents, ((AttributeValueElementReadWrite)arg).SchemaVersion); return(new EvaluationValue( attributeValue.GetTypedValue(attributeValue.GetType(context), 0), attributeValue.GetType(context))); } else if (arg is AttributeDesignatorBase) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace("Processing attribute designator: {0}", arg.ToString()); var attrDes = (AttributeDesignatorBase)arg; var bag = new BagValue(EvaluationEngine.GetDataType(attrDes.DataType)); return(new EvaluationValue(bag, bag.GetType(context))); } else if (arg is AttributeSelectorElement) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace("Attribute selector"); var attrSel = (AttributeSelectorElement)arg; var 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> /// 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 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 == null ? string.Empty : evaluationValue.ToString()); } }
/// <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> /// 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 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((ApplyElement)_variableDefinition.Expression); // Evaluate the Apply _value = childApply.Evaluate(context); context.TraceContextValues(); return(_value); } else if (_variableDefinition.Expression is FunctionElement) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (_variableDefinition.Expression is VariableReferenceElement) { var variableRef = _variableDefinition.Expression as VariableReferenceElement; var 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 AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", _variableDefinition.Expression.ToString()); var att = (AttributeValueElementReadWrite)_variableDefinition.Expression; var attributeValue = new 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 AttributeDesignatorBase) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", _variableDefinition.Expression.ToString()); var attrDes = (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 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 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 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 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 AttributeSelectorElement) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { var attributeSelector = (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> /// 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 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 == null ? string.Empty : evaluationValue.ToString()); } }
/// <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) { var 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 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> /// 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> /// 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> /// 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 (IExpression arg in ApplyDefinition.Arguments) { if (arg is 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. var childApply = new Apply((ApplyElement)arg); // Evaluate the Apply EvaluationValue retVal = childApply.Evaluate(context); return retVal; } else if (arg is FunctionElementReadWrite) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (arg is VariableReferenceElement) { var variableRef = arg as VariableReferenceElement; var variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; Debug.Assert(variableDef != null, "variableDef != null"); if (!variableDef.IsEvaluated) { return variableDef.Evaluate(context); } else { return variableDef.Value; } } else if (arg is AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); var attributeValue = new AttributeValueElement(((AttributeValueElementReadWrite)arg).DataType, ((AttributeValueElementReadWrite)arg).Contents, ((AttributeValueElementReadWrite)arg).SchemaVersion); return new EvaluationValue( attributeValue.GetTypedValue(attributeValue.GetType(context), 0), attributeValue.GetType(context)); } else if (arg is AttributeDesignatorBase) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace("Processing attribute designator: {0}", arg.ToString()); var attrDes = (AttributeDesignatorBase)arg; var bag = new BagValue(EvaluationEngine.GetDataType(attrDes.DataType)); return new EvaluationValue(bag, bag.GetType(context)); } else if (arg is AttributeSelectorElement) { // Returning an empty bag, since the condition is not supposed to work with a bag context.Trace("Attribute selector"); var attrSel = (AttributeSelectorElement)arg; var 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> /// 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"); var 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 == 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> /// 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) { var 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 == 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> /// 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 FunctionParameterCollection ProcessArguments(EvaluationContext context, ExpressionCollection arguments) { context.Trace("Processing arguments"); context.AddIndent(); // Create a list to return the processed values. var processedArguments = new FunctionParameterCollection(); // Iterate through the arguments, the IExpressionType is a mark interface foreach (IExpression arg in arguments) { var apply = arg as ApplyElement; if (apply != null) { 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. var childApply = new Apply(apply); // 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 { var write = arg as FunctionElementReadWrite; if (write != null) { // Search for the function and place it in the processed arguments. var functionId = new FunctionElement(write.FunctionId, write.SchemaVersion); context.Trace("Function {0}", functionId.FunctionId); 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 VariableReferenceElement) { var variableRef = arg as VariableReferenceElement; var variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; context.TraceContextValues(); Debug.Assert(variableDef != null, "variableDef != null"); processedArguments.Add(!variableDef.IsEvaluated ? variableDef.Evaluate(context) : variableDef.Value); } else { var readWrite = arg as AttributeValueElementReadWrite; if (readWrite != null) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); processedArguments.Add(new AttributeValueElement(readWrite.DataType, readWrite.Contents, readWrite.SchemaVersion)); } else { var des = arg as AttributeDesignatorBase; if (des != null) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", arg.ToString()); var attrDes = des; 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 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 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 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 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 { var @base = arg as AttributeSelectorElement; if (@base != null) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { BagValue bag = EvaluationEngine.Resolve(context, @base); if (bag.Elements.Count == 0 && @base.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(@base); } else { processedArguments.Add(bag); } } catch (EvaluationException e) { context.Trace("ERR: {0}", e.Message); processedArguments.Add(EvaluationValue.Indeterminate); context.ProcessingError = true; } } } } } } } context.RemoveIndent(); return(processedArguments); }
/// <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 FunctionParameterCollection ProcessArguments(EvaluationContext context, ExpressionCollection arguments) { context.Trace("Processing arguments"); context.AddIndent(); // Create a list to return the processed values. var processedArguments = new FunctionParameterCollection(); // Iterate through the arguments, the IExpressionType is a mark interface foreach (IExpression arg in arguments) { var apply = arg as ApplyElement; if (apply != null) { 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. var childApply = new Apply(apply); // 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 { var write = arg as FunctionElementReadWrite; if (write != null) { // Search for the function and place it in the processed arguments. var functionId = new FunctionElement(write.FunctionId, write.SchemaVersion); context.Trace("Function {0}", functionId.FunctionId); 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 VariableReferenceElement) { var variableRef = arg as VariableReferenceElement; var variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; context.TraceContextValues(); Debug.Assert(variableDef != null, "variableDef != null"); processedArguments.Add(!variableDef.IsEvaluated ? variableDef.Evaluate(context) : variableDef.Value); } else { var readWrite = arg as AttributeValueElementReadWrite; if (readWrite != null) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); processedArguments.Add(new AttributeValueElement(readWrite.DataType, readWrite.Contents, readWrite.SchemaVersion)); } else { var des = arg as AttributeDesignatorBase; if (des != null) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", arg.ToString()); var attrDes = des; 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 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 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 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 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 { var @base = arg as AttributeSelectorElement; if (@base != null) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { BagValue bag = EvaluationEngine.Resolve(context, @base); if (bag.Elements.Count == 0 && @base.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(@base); } else { processedArguments.Add(bag); } } catch (EvaluationException e) { context.Trace("ERR: {0}", e.Message); processedArguments.Add(EvaluationValue.Indeterminate); context.ProcessingError = true; } } } } } } } context.RemoveIndent(); return processedArguments; }
/// <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 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) { var 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 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> /// 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 == 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 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 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((ApplyElement)_variableDefinition.Expression); // Evaluate the Apply _value = childApply.Evaluate(context); context.TraceContextValues(); return _value; } else if (_variableDefinition.Expression is FunctionElement) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (_variableDefinition.Expression is VariableReferenceElement) { var variableRef = _variableDefinition.Expression as VariableReferenceElement; var 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 AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", _variableDefinition.Expression.ToString()); var att = (AttributeValueElementReadWrite)_variableDefinition.Expression; var attributeValue = new 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 AttributeDesignatorBase) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", _variableDefinition.Expression.ToString()); var attrDes = (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 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 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 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 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 AttributeSelectorElement) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { var attributeSelector = (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(); } }