/*
* Copyright 2008-2010 HERAS-AF (www.herasaf.org)
* Holistic Enterprise-Ready Application Security Architecture Framework
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.herasaf.xacml.core.targetMatcher.impl;
import java.util.List;
import org.herasaf.xacml.core.ProcessingException;
import org.herasaf.xacml.core.SyntaxException;
import org.herasaf.xacml.core.context.EvaluationContext;
import org.herasaf.xacml.core.context.impl.RequestType;
import org.herasaf.xacml.core.function.Function;
import org.herasaf.xacml.core.policy.MissingAttributeException;
import org.herasaf.xacml.core.policy.impl.ActionType;
import org.herasaf.xacml.core.policy.impl.ActionsType;
import org.herasaf.xacml.core.policy.impl.AttributeDesignatorType;
import org.herasaf.xacml.core.policy.impl.AttributeValueType;
import org.herasaf.xacml.core.policy.impl.EnvironmentType;
import org.herasaf.xacml.core.policy.impl.EnvironmentsType;
import org.herasaf.xacml.core.policy.impl.Match;
import org.herasaf.xacml.core.policy.impl.ResourceType;
import org.herasaf.xacml.core.policy.impl.ResourcesType;
import org.herasaf.xacml.core.policy.impl.SubjectType;
import org.herasaf.xacml.core.policy.impl.SubjectsType;
import org.herasaf.xacml.core.policy.impl.TargetType;
import org.herasaf.xacml.core.targetMatcher.TargetMatcher;
import org.herasaf.xacml.core.targetMatcher.TargetMatchingResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Matches a policy's, a policy set's or a rule's target against a given
* request.
*
* @author Florian Huonder
* @author René Eggenschwiler
*/
public class TargetMatcherImpl implements TargetMatcher {
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(TargetMatcherImpl.class);
/**
* {@inheritDoc}
*/
public TargetMatchingResult match(RequestType request, TargetType target, EvaluationContext evaluationContext) throws SyntaxException,
ProcessingException, MissingAttributeException {
if (target != null) {
logger.debug("Starting subjects match.");
boolean subjectsMatches = subjectsMatch(target.getSubjects(), request, evaluationContext);
logger.debug("Subjects match resulted in: {}", subjectsMatches);
if (!subjectsMatches) {
return TargetMatchingResult.NO_MATCH;
}
logger.debug("Starting recources match.");
boolean resourcesMatches = resourcesMatch(target.getResources(), request, evaluationContext);
logger.debug("Resources match resulted in: {}", resourcesMatches);
if (!resourcesMatches) {
return TargetMatchingResult.NO_MATCH;
}
logger.debug("Starting actions match.");
boolean actionsMatches = actionMatch(target.getActions(), request, evaluationContext);
logger.debug("Actions match resulted in: {}", actionsMatches);
if (!actionsMatches) {
return TargetMatchingResult.NO_MATCH;
}
logger.debug("Starting environments match.");
boolean environmentsMatches = environmentMatch(target.getEnvironments(), request, evaluationContext);
logger.debug("Environments match resulted in: {}", environmentsMatches);
if (!environmentsMatches) {
return TargetMatchingResult.NO_MATCH;
}
}
// If there was no target, or all the subjects, resources, actions, and
// environments matched
// then the overall target is considered a match.
//
// This part references OASIS eXtensible Access Control Markup Language
// (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 45 (5.5).
return TargetMatchingResult.MATCH;
}
/**
* Checks if the <Subjects> element matches the given request.
*
* @param subjects The <Subjects> element to be matched.
* @param request The requests containing the attributes to be matched against the <Subjects>.
* @param evaluationContext The {@link EvaluationContext} containing additional information.
* @return
* @throws ProcessingException If an exception occurred while processing the matching functions.
* @throws SyntaxException If the request or the policy contained a syntax error.
* @throws MissingAttributeException If a must-be-present attribute is missing.
*/
private boolean subjectsMatch(SubjectsType subjects, RequestType request, EvaluationContext evaluationContext)
throws ProcessingException, SyntaxException, MissingAttributeException {
if (subjects == null) {
logger.debug("No subjects present.");
return true;
}
for (int i = 0; i < subjects.getSubjects().size(); i++) {
SubjectType targetSubject = subjects.getSubjects().get(i);
logger.debug("Starting subject match. (id:{})", targetSubject.toString());
boolean matches = match(targetSubject.getSubjectMatches(), request, evaluationContext);
if (matches) {
// If one subject matches the subjects matches and returns true.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 46 (5.6).
logger.debug("Subject match resulted in: {}", matches);
return true;
}
}
return false;
}
/**
* Checks if the <Resources> element matches the given request.
*
* @param resources The <Resources> element to be matched.
* @param request The requests containing the attributes to be matched against the <Resources>.
* @param evaluationContext The {@link EvaluationContext} containing additional information.
* @return
* @throws ProcessingException If an exception occurred while processing the matching functions.
* @throws SyntaxException If the request or the policy contained a syntax error.
* @throws MissingAttributeException If a must-be-present attribute is missing.
*/
private boolean resourcesMatch(ResourcesType resources, RequestType request, EvaluationContext evaluationContext)
throws ProcessingException, SyntaxException, MissingAttributeException {
if (resources == null) {
logger.debug("No resources present.");
return true;
}
for (int i = 0; i < resources.getResources().size(); i++) {
ResourceType targetResource = resources.getResources().get(i);
logger.debug("Starting resource match. (id:{})", targetResource.toString());
boolean matches = match(targetResource.getResourceMatches(), request, evaluationContext);
if (matches) {
// If one resource matches the resources matches and returns
// true.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 47 (5.9).
logger.debug("Resource match resulted in: {}", matches);
return true;
}
}
return false;
}
/**
* Checks if the <Actions> element matches the given request.
*
* @param actions The <Actions> element to be matched.
* @param request The requests containing the attributes to be matched against the <Actions>.
* @param evaluationContext The {@link EvaluationContext} containing additional information.
* @return
* @throws ProcessingException If an exception occurred while processing the matching functions.
* @throws SyntaxException If the request or the policy contained a syntax error.
* @throws MissingAttributeException If a must-be-present attribute is missing.
*/
private boolean actionMatch(ActionsType actions, RequestType request, EvaluationContext evaluationContext)
throws ProcessingException, SyntaxException, MissingAttributeException {
if (actions == null) {
logger.debug("No actions present.");
return true;
}
for (int i = 0; i < actions.getActions().size(); i++) {
ActionType targetAction = actions.getActions().get(i);
logger.debug("Starting action match. (id:{})", targetAction.toString());
boolean matches = match(targetAction.getActionMatches(), request, evaluationContext);
if (matches) {
// If one action matches the actions matches and returns true.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 48 (5.12).
logger.debug("Action match resulted in: {}", matches);
return true;
}
}
return false;
}
/**
* Checks if the <Environments> element matches the given request.
*
* @param environments The <Environments> element to be matched.
* @param request The requests containing the attributes to be matched against the <Environments>.
* @param evaluationContext The {@link EvaluationContext} containing additional information.
* @return
* @throws ProcessingException If an exception occurred while processing the matching functions.
* @throws SyntaxException If the request or the policy contained a syntax error.
* @throws MissingAttributeException If a must-be-present attribute is missing.
*/
private boolean environmentMatch(EnvironmentsType environments, RequestType request, EvaluationContext evaluationContext)
throws ProcessingException, SyntaxException, MissingAttributeException {
if (environments == null) {
logger.debug("No environments present.");
return true;
}
for (int i = 0; i < environments.getEnvironments().size(); i++) {
EnvironmentType targetEnvironment = environments.getEnvironments().get(i);
logger.debug("Starting environment match. (id:{})", targetEnvironment.toString());
boolean matches = match(targetEnvironment.getEnvironmentMatches(), request, evaluationContext);
if (matches) {
// If one environment matches the environments matches and
// returns true.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 50 (5.15).
logger.debug("Environment match resulted in: {}", matches);
return true;
}
}
return false;
}
/**
* @param matches The matching element (either <SubjectMatch>, <ResourceMatch>, <ActionMatch> or <EnvironmentMatch>) to be matched against the request.
* @param request The requests containing the attributes to be matched against the <Environments>.
* @param evaluationContext The {@link EvaluationContext} containing additional information.
* @return
* @throws ProcessingException If an exception occurred while processing the matching functions.
* @throws SyntaxException If the request or the policy contained a syntax error.
* @throws MissingAttributeException If a must-be-present attribute is missing.
*/
private boolean match(List extends Match> matches, RequestType request, EvaluationContext evaluationContext)
throws ProcessingException, SyntaxException, MissingAttributeException {
for (int i = 0; i < matches.size(); i++) {
Match match = matches.get(i);
Function matchFunction = match.getMatchFunction();
logger.debug("Matching with function: {}", matchFunction.toString());
AttributeDesignatorType designator = match.getAttributeDesignator();
List> requestAttributeValues = (List>) designator.handle(request, evaluationContext); // Fetches
// all
// AttributeValue-contents
// from the element (element = subject,
// resource, action or environment)
// AttributeDesignator.
// If the list returned by the designator is empty, than no more
// processing is needed for this element (element = subject,
// resource, action or environment) and the next subject will be
// checked.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 79 (Match evaluation, line 3394).
if (requestAttributeValues.size() == 0) {
logger.debug("Request did not contain the required attributes.");
return false;
}
// Tells if a single match is true for a specific element (element =
// subject, resource, action or environment).
boolean matchMatches = false;
for (int k = 0; k < requestAttributeValues.size(); k++) {
Object requestAttributeValue = requestAttributeValues.get(k);
// The attribute value specified in the matching element must be
// supplied as the first argument.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 79 (Match evaluation, line 3371).
AttributeValueType policyAttributeValue = match.getAttributeValue();
matchMatches = (Boolean) matchFunction.handle(policyAttributeValue.getDataType().convertTo(
(String) policyAttributeValue.getContent().get(0)), requestAttributeValue);
logger
.debug(
"Match function resulted in {} with policy attribute datatype:{} value:{} and request attribute value:{}",
new Object[] { matchMatches, policyAttributeValue.getDataType(),
policyAttributeValue.getContent().get(0), requestAttributeValue });
// If the call of the match function (above) returns true for at
// least one attribute value in the request
// than the match is true and no more processing is needed
// (therefore the break)
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 79 (Match evaluation, line 3398).
if (matchMatches) {
break;
}
}
// All matches in element (element = subject, resource, action or
// environment) must return true that the element
// (element = subject, resource, action or environment) matches.
// If the first match returned false than the whole element (element
// = subject, resource, action or environment)
// does not match the request.
//
// This part references OASIS eXtensible Access Control Markup
// Langugage (XACML) 2.0, Errata 29 June 2006
// (http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=xacml#XACML20)
// on page 46 (5.7).
if (!matchMatches) {
return false;
}
}
return true;
}
}