Commit 2eb7b1ee authored by Cyril Dangerville's avatar Cyril Dangerville
Browse files

Merge remote-tracking branch 'origin/release-3.5.3'

parents c6de2f82 5717a11d
This diff is collapsed.
......@@ -61,6 +61,7 @@ import com.sun.xacml.combine.CombiningAlgorithm;
import com.sun.xacml.combine.PolicyCombiningAlgorithm;
import com.sun.xacml.combine.RuleCombiningAlgorithm;
import com.sun.xacml.xacmlv3.Target;
import com.thalesgroup.authzforce.BindingUtility;
/**
* Represents an instance of an XACML policy.
......
......@@ -66,6 +66,7 @@ import com.sun.xacml.attr.xacmlv3.AttributeDesignator;
import com.sun.xacml.attr.xacmlv3.AttributeValue;
import com.sun.xacml.cond.xacmlv3.EvaluationResult;
import com.sun.xacml.finder.AttributeFinder;
import com.thalesgroup.authzforce.BindingUtility;
import com.thalesgroup.authzforce.xacml.schema.XACMLCategory;
/**
......@@ -882,6 +883,9 @@ public class BasicEvaluationCtx implements EvaluationCtx
*/
try
{
/*
* FIXME: We need to use the getContent() method to retrieve attributeValues
*/
attributeValues = getAttributeValues(attrSet, issuerStr, typeStr);
} catch (ParsingException e)
{
......@@ -917,7 +921,7 @@ public class BasicEvaluationCtx implements EvaluationCtx
if (resultAttrVal instanceof BagAttribute)
{
BagAttribute bagAttribute = (BagAttribute) resultAttrVal;
Iterator iter = bagAttribute.getValue().iterator();
Iterator iter = bagAttribute.getValues().iterator();
while (iter.hasNext())
{
AttributeValueType attributeValue = (AttributeValueType) iter.next();
......
......@@ -35,7 +35,6 @@ package com.sun.xacml;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
......@@ -44,15 +43,11 @@ import java.util.List;
import javax.xml.bind.Marshaller;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignment;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ExpressionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.FunctionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpression;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -61,13 +56,13 @@ import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.xacmlv3.AttributeDesignator;
import com.sun.xacml.attr.BagAttribute;
import com.sun.xacml.attr.xacmlv3.AttributeValue;
import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.xacmlv3.EvaluationResult;
import com.sun.xacml.cond.xacmlv3.ExpressionTools;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.Result;
import com.thalesgroup.authzforce.xacml.schema.XACMLDatatypes;
import com.thalesgroup.authzforce.BindingUtility;
/**
* Represents the ObligationType XML type in XACML. This also stores all the AttriubteAssignmentType
......@@ -107,7 +102,7 @@ public class Obligation extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Obli
* @param assignments
* a <code>List</code> of <code>Attribute</code>s
*/
public Obligation(String id, int fulfillOn, List assignments)
public Obligation(String id, int fulfillOn, List<AttributeAssignment> assignments)
{
this(id, fulfillOn, assignments, false);
}
......@@ -125,11 +120,11 @@ public class Obligation extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Obli
* a <code>List</code> of <code>Attribute</code>s
* @param isIndeterminate
*/
public Obligation(String id, int fulfillOn, List assignments, boolean isIndeterminate)
public Obligation(String id, int fulfillOn, List<AttributeAssignment> assignments, boolean isIndeterminate)
{
this.obligationId = id;
this.fulfillOn = fulfillOn;
this.attributeAssignments = Collections.unmodifiableList(new ArrayList(assignments));
this.attributeAssignments = Collections.unmodifiableList(assignments);
this.isIndeterminate = isIndeterminate;
}
......@@ -148,7 +143,7 @@ public class Obligation extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Obli
{
String id;
int fulfillOn = -1;
List assignments = new ArrayList();
List<AttributeAssignment> assignments = new ArrayList<>();
AttributeFactory attrFactory = AttributeFactory.getInstance();
NamedNodeMap attrs = root.getAttributes();
......@@ -191,8 +186,16 @@ public class Obligation extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Obli
try
{
URI attrId = new URI(node.getAttributes().getNamedItem("AttributeId").getNodeValue());
String cat = node.getAttributes().getNamedItem("Category").getNodeValue();
String issuer = node.getAttributes().getNamedItem("Issuer").getNodeValue();
AttributeValue attrValue = attrFactory.createValue(node);
assignments.add(new Attribute(attrId, null, null, attrValue, PolicyMetaData.XACML_VERSION_3_0));
AttributeAssignment assignt = new AttributeAssignment();
assignt.setAttributeId(attrId.toASCIIString());
assignt.setCategory(cat);
assignt.setIssuer(issuer);
assignt.setDataType(attrValue.getDataType());
assignt.getContent().addAll(attrValue.getContent());
assignments.add(assignt);
} catch (URISyntaxException use)
{
throw new ParsingException("Error parsing URI", use);
......@@ -223,95 +226,85 @@ public class Obligation extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Obli
*/
public static Obligation getInstance(ObligationExpression root, EvaluationCtx context) throws ParsingException
{
String id;
int fulfillOn = -1;
List<AttributeAssignment> assignments = new ArrayList<>();
int fulfillOn = root.getFulfillOn().ordinal();
boolean indeterminate = false;
EvaluationResult result = null;
id = root.getObligationId();
fulfillOn = root.getFulfillOn().ordinal();
for (AttributeAssignmentExpression attrsAssignment : root.getAttributeAssignmentExpressions())
String id = root.getObligationId();
final List<AttributeAssignment> assignments = new ArrayList<>();
for (AttributeAssignmentExpression attrAssignmentExpr : root.getAttributeAssignmentExpressions())
{
URI attrId = URI.create(attrsAssignment.getAttributeId());
String issuer = attrsAssignment.getIssuer();
String attrId = attrAssignmentExpr.getAttributeId();
String issuer = attrAssignmentExpr.getIssuer();
ExpressionType myExpr = ExpressionTools.getInstance(attrsAssignment.getExpression().getValue(), null, null);
ExpressionType myExpr = ExpressionTools.getInstance(attrAssignmentExpr.getExpression().getValue(), null, null);
// Check what type of expression this is
if (myExpr instanceof ApplyType)
if (myExpr instanceof FunctionType)
{
// TODO: Not Implemented
throw new ParsingException("Obligation with Apply not implemented yet");
} else if (myExpr instanceof AttributeSelectorType)
{
// TODO: Not Implemented
throw new ParsingException("Obligation with AttributeSelector not implemented yet");
// Not implemented yet
} else if (myExpr instanceof AttributeValueType)
throw new ParsingException(
"<Function> NOT allowed as <AttributeAssignmentExpression> of <ObligationExpression> BUT only as child of an <Apply> element");
}
if (!(myExpr instanceof Evaluatable))
{
AttributeValueType attrValue = (AttributeValueType) myExpr;
URI datatype = URI.create(XACMLDatatypes.XACML_DATATYPE_STRING.value());
if (attrValue.getDataType() != null)
{
datatype = URI.create(attrValue.getDataType());
}
/*
* Evaluation
*/
result = ((AttributeValue) attrValue).evaluate(context);
if (result.indeterminate())
{
indeterminate = true;
}
// an AD/AS will always return a bag
// BagAttribute bag = (BagAttribute) (result.getAttributeValue());
AttributeValueType bag = result.getAttributeValue();
for (Serializable attributeAssignmentType : bag.getContent())
{
AttributeAssignment attrAsgnType = new AttributeAssignment();
attrAsgnType.getContent().add(attributeAssignmentType);
attrAsgnType.setAttributeId(attrId.toASCIIString());
attrAsgnType.setCategory(attrsAssignment.getCategory());
attrAsgnType.setDataType(datatype.toASCIIString());
attrAsgnType.setIssuer(issuer);
assignments.add(attrAsgnType);
}
} else if (myExpr instanceof FunctionType)
throw new ParsingException(myExpr.getClass().getSimpleName()
+ " element NOT supported as <AttributeAssignmentExpression> of <ObligationExpression>");
}
// Expression is Evaluatable
final Evaluatable evaluatable = (Evaluatable) myExpr;
final EvaluationResult result = evaluatable.evaluate(context);
/*
* According to XACML 3.0 spec, if result is empty bag, no AttributeAssignment; if
* non-empty bag, one <AttributeAssignment> per value in the bag.
*/
if (result.indeterminate())
{
// TODO: Not Implemented
throw new ParsingException("Obligation with FunctionType not implemented yet");
} else if (myExpr instanceof VariableReferenceType)
LOGGER.error(
"Evaluation of {} element as <AttributeAssignmentExpression> (id='{}') of <ObligationExpression> (id='{}') returned Indeterminate",
new Object[] {myExpr.getClass().getSimpleName(), attrId, id});
indeterminate = true;
// assignments remains an empty list
} else
{
// TODO: Not Implemented
throw new ParsingException("Obligation with VariableReference not implemented yet");
} else if (myExpr instanceof AttributeDesignator)
assignments.addAll(toAssignments(id, attrAssignmentExpr.getCategory(), attrId, issuer, result.getAttributeValue(), true));
}
}
return new Obligation(id, fulfillOn, assignments, indeterminate);
}
private static List<AttributeAssignment> toAssignments(String obligationId, String category, String attrId, String issuer,
AttributeValue attrVal, boolean isRootBag) throws ParsingException
{
final List<AttributeAssignment> assignts = new ArrayList<>();
if (attrVal.isBag())
{
// nested bags (not the root bag in attribute value) not allowed
if (!isRootBag)
{
AttributeDesignator attrExpression = (AttributeDesignator) myExpr;
/*
* Evaluation
*/
result = attrExpression.evaluate(context);
if (result.indeterminate())
{
indeterminate = true;
}
throw new ParsingException(
String.format(
"Evaluation of <AttributeAssignmentExpression> (id='%s') of <ObligationExpression> (id='%s') resulted in bag with nested bags, which is not allowed",
attrId, obligationId));
}
/*
* FIXME: something is missing! Create/add new attributes assignments to 'assignments' variable.
* NOTA BENE: according to spec, if result empty bag, no AttributeAssignment; if
* non-empty bag, one <AttributeAssignment> per value in the bag.
* Make at least 3 unit tests:
* 1) If <AttributeAssignmentExpression> is static <AttributeValue>;
* 2) If <AttributeAssignmentExpression> evaluates to empty bag (-> no <AttributeAssignment>);
* 3) If <AttributeAssignmentExpression> evaluates to non-empty bag.
*/
// If bag, create one assignment per value
for (final AttributeValue childVal : ((BagAttribute) attrVal).getValues())
{
assignts.addAll(toAssignments(obligationId, category, attrId, issuer, childVal, false));
}
} else
{
final AttributeAssignment attrAssignt = new AttributeAssignment();
attrAssignt.setCategory(category);
attrAssignt.setAttributeId(attrId);
attrAssignt.setIssuer(issuer);
attrAssignt.setDataType(attrVal.getDataType());
attrAssignt.getContent().addAll(attrVal.getContent());
assignts.add(attrAssignt);
}
return new Obligation(id, fulfillOn, assignments, indeterminate);
return assignts;
}
/**
......
......@@ -30,6 +30,8 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.thalesgroup.authzforce.BindingUtility;
/**
* @author Romain Ferrari
*
......
......@@ -65,6 +65,7 @@ import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.xacmlv3.IPolicy;
import com.sun.xacml.xacmlv3.Policy;
import com.sun.xacml.xacmlv3.Target;
import com.thalesgroup.authzforce.BindingUtility;
/**
* Represents one of the two top-level constructs in XACML, the PolicySetType. This can contain
......@@ -523,7 +524,7 @@ public class PolicySet extends AbstractPolicySet implements IPolicy
paramHandlerList = parameters.get(policySetIdRef);
} else
{
paramHandlerList = new ArrayList<CombinerParameter>();
paramHandlerList = new ArrayList<>();
parameters.put(policySetIdRef, paramHandlerList);
}
......
......@@ -66,6 +66,7 @@ import com.sun.xacml.ctx.Result;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.xacmlv3.AdviceExpressions;
import com.sun.xacml.xacmlv3.Target;
import com.thalesgroup.authzforce.BindingUtility;
import com.thalesgroup.authzforce.audit.annotations.Audit;
/**
......@@ -325,7 +326,8 @@ public class Rule extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Rule
* Since a rule is always a leaf in a policy tree because it can have no children, this always
* returns an empty <code>List</code>.
*
* FIXME: This statement is misleading, since Rule can have child nodes: Condition, ObligationExpressions, etc.
* FIXME: This statement is misleading, since Rule can have child nodes: Condition,
* ObligationExpressions, etc.
*
* @return a <code>List</code> with no elements
*/
......@@ -381,126 +383,139 @@ public class Rule extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Rule
List<Attributes> includeInResult = context.getIncludeInResults();
MatchResult match = null;
Result returnResult = null;
// If the Target is null then it's supposed to inherit from the
// parent policy, so we skip the matching step assuming we wouldn't
// be here unless the parent matched
if (target != null)
try
{
match = ((Target) target).match(context);
int result = match.getResult();
// if the target didn't match, then this Rule doesn't apply
if (result == MatchResult.NO_MATCH)
{
return new Result(DecisionType.NOT_APPLICABLE, null, context.getResourceId().encode(), null, includeInResult);
}
// if the target was indeterminate, we can't go on
if (result == MatchResult.INDETERMINATE)
// If the Target is null then it's supposed to inherit from the
// parent policy, so we skip the matching step assuming we wouldn't
// be here unless the parent matched
if (target != null)
{
return new Result(DecisionType.INDETERMINATE, match.getStatus(), context.getResourceId().encode(), null, includeInResult);
}
}
// LOGGER.debug("Found a rule that match the request");
// LOGGER.debug("RuleId: "+idAttr);
// AuditLogs audit = AuditLogs.getInstance();
// audit.setRuleId(idAttr.toString());
match = ((Target) target).match(context);
LOGGER.debug("{} - {}", this, match);
int result = match.getResult();
// if there's no condition, then we just return the effect...
if (condition == null)
{
LOGGER.info("Rule doesn't contain condition, so result is '{}' for rule '{}'", this.effect.value(), this.ruleId);
returnResult = new Result(DecisionType.fromValue(this.effect.value()), null, context.getResourceId().encode(), null, includeInResult);
} else
{
// ...otherwise we evaluate the condition
EvaluationResult result = ((Condition) condition).evaluate(context);
if (result.indeterminate())
{
// if it was INDETERMINATE, then that's what we return
return new Result(DecisionType.INDETERMINATE, result.getStatus(), context.getResourceId().encode(), null, includeInResult);
// if the target didn't match, then this Rule doesn't apply
if (result == MatchResult.NO_MATCH)
{
returnResult = new Result(DecisionType.NOT_APPLICABLE, null, context.getResourceId().encode(), null, includeInResult);
return returnResult;
}
// if the target was indeterminate, we can't go on
if (result == MatchResult.INDETERMINATE)
{
returnResult = new Result(DecisionType.INDETERMINATE, match.getStatus(), context.getResourceId().encode(), null, includeInResult);
return returnResult;
}
}
// otherwise we return the effect on tue, and NA on false
BooleanAttribute bool = (BooleanAttribute) (result.getAttributeValue());
if (bool.getValue())
{
returnResult = new Result(DecisionType.valueOf(effect.name()), null, context.getResourceId().encode(), null, includeInResult);
// LOGGER.debug("Found a rule that match the request");
// LOGGER.debug("RuleId: "+idAttr);
// AuditLogs audit = AuditLogs.getInstance();
// audit.setRuleId(idAttr.toString());
// if there's no condition, then we just return the effect...
if (condition == null)
{
LOGGER.info("Rule doesn't contain condition, so result is '{}' for rule '{}'", this.effect.value(), this.ruleId);
returnResult = new Result(DecisionType.fromValue(this.effect.value()), null, context.getResourceId().encode(), null, includeInResult);
} else
{
return new Result(DecisionType.NOT_APPLICABLE, null, context.getResourceId().encode(), null, includeInResult);
}
}
// ...otherwise we evaluate the condition
EvaluationResult result = ((Condition) condition).evaluate(context);
// Adding Obligations and Advice to the result
if (obligationExpressions != null && !obligationExpressions.getObligationExpressions().isEmpty())
{
// now, see if we should add any obligations to the set
int returnEffect = returnResult.getDecision().ordinal();
if (result.indeterminate())
{
// if it was INDETERMINATE, then that's what we return
returnResult = new Result(DecisionType.INDETERMINATE, result.getStatus(), context.getResourceId().encode(), null, includeInResult);
return returnResult;
}
if ((returnEffect == DecisionType.INDETERMINATE.ordinal()) || (returnEffect == DecisionType.NOT_APPLICABLE.ordinal()))
{
// we didn't permit/deny, so we never return
// obligations
return returnResult;
}
// otherwise we return the effect on tue, and NA on false
BooleanAttribute bool = (BooleanAttribute) (result.getAttributeValue());
for (oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpression myObligation : obligationExpressions.getObligationExpressions())
{
if (myObligation.getFulfillOn().ordinal() == returnEffect)
if (bool.getValue())
{
returnResult = new Result(DecisionType.valueOf(effect.name()), null, context.getResourceId().encode(), null, includeInResult);
} else
{
returnResult.addObligation(myObligation, context);
returnResult = new Result(DecisionType.NOT_APPLICABLE, null, context.getResourceId().encode(), null, includeInResult);
return returnResult;
}
}
}
if (adviceExpressions != null && !adviceExpressions.getAdviceExpressions().isEmpty())
{
int returnEffect = returnResult.getDecision().ordinal();
if ((returnEffect == DecisionType.INDETERMINATE.ordinal()) || (returnEffect == DecisionType.NOT_APPLICABLE.ordinal()))
// Adding Obligations and Advice to the result
if (obligationExpressions != null && !obligationExpressions.getObligationExpressions().isEmpty())
{
// we didn't permit/deny, so we never return advices
return returnResult;
}
final AssociatedAdvice returnAssociatedAdvice = returnResult.getAssociatedAdvice();
final AssociatedAdvice newAssociatedAdvice;
if(returnAssociatedAdvice == null) {
newAssociatedAdvice = new AssociatedAdvice();
returnResult.setAssociatedAdvice(newAssociatedAdvice);
} else {
newAssociatedAdvice = returnAssociatedAdvice;
// now, see if we should add any obligations to the set
int returnEffect = returnResult.getDecision().ordinal();
if ((returnEffect == DecisionType.INDETERMINATE.ordinal()) || (returnEffect == DecisionType.NOT_APPLICABLE.ordinal()))
{
// we didn't permit/deny, so we never return
// obligations
return returnResult;
}
for (oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpression myObligation : obligationExpressions.getObligationExpressions())
{
if (myObligation.getFulfillOn().ordinal() == returnEffect)
{
returnResult.addObligation(myObligation, context);
}
}
}
for (AdviceExpression adviceExpr : adviceExpressions.getAdviceExpressions())
if (adviceExpressions != null && !adviceExpressions.getAdviceExpressions().isEmpty())
{
if (adviceExpr.getAppliesTo().ordinal() == returnEffect)
int returnEffect = returnResult.getDecision().ordinal();
if ((returnEffect == DecisionType.INDETERMINATE.ordinal()) || (returnEffect == DecisionType.NOT_APPLICABLE.ordinal()))
{
Advice advice = new Advice();
advice.setAdviceId(adviceExpr.getAdviceId());
for (AttributeAssignmentExpression attrExpr : adviceExpr.getAttributeAssignmentExpressions())
// we didn't permit/deny, so we never return advices
return returnResult;
}
final AssociatedAdvice returnAssociatedAdvice = returnResult.getAssociatedAdvice();
final AssociatedAdvice newAssociatedAdvice;
if (returnAssociatedAdvice == null)
{
newAssociatedAdvice = new AssociatedAdvice();
returnResult.setAssociatedAdvice(newAssociatedAdvice);
} else
{
newAssociatedAdvice = returnAssociatedAdvice;
}
for (AdviceExpression adviceExpr : adviceExpressions.getAdviceExpressions())
{
if (adviceExpr.getAppliesTo().ordinal() == returnEffect)
{
AttributeAssignment myAttrAssType = new AttributeAssignment();
myAttrAssType.setAttributeId(attrExpr.getAttributeId());
myAttrAssType.setCategory(attrExpr.getCategory());
myAttrAssType.setIssuer(attrExpr.getIssuer());
if ((attrExpr.getExpression().getDeclaredType() == AttributeValueType.class))
Advice advice = new Advice();
advice.setAdviceId(adviceExpr.getAdviceId());
for (AttributeAssignmentExpression attrExpr : adviceExpr.getAttributeAssignmentExpressions())
{
myAttrAssType.setDataType(((AttributeValueType) attrExpr.getExpression().getValue()).getDataType());
myAttrAssType.getContent().addAll(((AttributeValueType) attrExpr.getExpression().getValue()).getContent());
AttributeAssignment myAttrAssType = new AttributeAssignment();
myAttrAssType.setAttributeId(attrExpr.getAttributeId());
myAttrAssType.setCategory(attrExpr.getCategory());
myAttrAssType.setIssuer(attrExpr.getIssuer());
if ((attrExpr.getExpression().getDeclaredType() == AttributeValueType.class))
{
myAttrAssType.setDataType(((AttributeValueType) attrExpr.getExpression().getValue()).getDataType());
myAttrAssType.getContent().addAll(((AttributeValueType) attrExpr.getExpression().getValue()).getContent());
}
advice.getAttributeAssignments().add(myAttrAssType);
}
advice.getAttributeAssignments().add(myAttrAssType);
newAssociatedAdvice.getAdvices().add(advice);
}
newAssociatedAdvice.getAdvices().add(advice);
}
}
}
return returnResult;
return returnResult;
} finally
{
LOGGER.debug("{} returned: {}", this, returnResult);
}
}
/**
......@@ -537,4 +552,10 @@ public class Rule extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Rule
}
}
@Override
public String toString()
{
return this.getClass().getSimpleName() + " id: \"" + this.ruleId + "\"";
}
}
......@@ -38,7 +38,6 @@ import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ExpressionType;
......@@ -341,20 +340,19 @@ public class TargetMatch {
}
// an AD/AS will always return a bag
BagAttribute bag = (BagAttribute) (result.getAttributeValue());
BagAttribute resultBag = (BagAttribute) (result.getAttributeValue());
if (!bag.isEmpty()) {