package org.exist.security.xacml;
import java.net.URI;
import java.util.Iterator;
import org.apache.log4j.Logger;
import org.exist.EXistException;
import org.exist.dom.DocumentImpl;
import org.exist.dom.DocumentSet;
import org.exist.security.XMLSecurityManager;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import com.sun.xacml.AbstractPolicy;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.MatchResult;
import com.sun.xacml.ParsingException;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.PolicyFinderModule;
import com.sun.xacml.finder.PolicyFinderResult;
/*
*Added new constructor to AnyURIValue to accept a URI
*/
/**
* This class finds Policy and PolicySet documents located in
* the /db/system/policies collection. It implements both of the
* <code>findPolicy</code> methods of <code>PolicyFinderModule</code>.
* Finding policies by reference uses a range index on PolicySetId
* and PolicyId, so that must be set up for references to work.
* Finding policies for a given request is not yet optimized, but
* just loads all policies in the policies collection, parses them,
* and determines if they match the request.
*
* @see XACMLConstants
*/
public class ExistPolicyModule extends PolicyFinderModule
{
private static final Logger LOG = Logger.getLogger(ExistPolicyModule.class);
private ExistPDP pdp;
private ExistPolicyModule() {}
/**
* Creates a new <code>ExistPolicyModule</code>. Retains a reference
* to the specified <code>BrokerPool</code>.
*
* @param pdp The <code>ExistPDP</code> for this database instance.
*/
public ExistPolicyModule(ExistPDP pdp)
{
if(pdp == null)
throw new NullPointerException("BrokerPool cannot be null");
this.pdp = pdp;
}
public boolean isRequestSupported()
{
return true;
}
public boolean isIdReferenceSupported()
{
return true;
}
public void init(PolicyFinder finder) {}
public PolicyFinderResult findPolicy(EvaluationCtx context)
{
BrokerPool pool = pdp.getBrokerPool();
DBBroker broker = null;
try
{
broker = pool.get(XMLSecurityManager.SYSTEM_USER);
return findPolicy(broker, context);
}
catch(EXistException ee)
{
return XACMLUtil.errorResult("Error while finding policy: " + ee.getMessage(), ee);
}
finally
{
pool.release(broker);
}
}
private PolicyFinderResult findPolicy(DBBroker broker, EvaluationCtx context)
{
DocumentSet mainPolicyDocs = XACMLUtil.getPolicyDocuments(broker, false);
if(mainPolicyDocs == null)
return new PolicyFinderResult();
AbstractPolicy matchedPolicy = null;
AbstractPolicy policy;
MatchResult match;
int result;
try
{
XACMLUtil util = pdp.getUtil();
for(Iterator it = mainPolicyDocs.getDocumentIterator(); it.hasNext();)
{
policy = util.getPolicyDocument((DocumentImpl)it.next());
match = policy.match(context);
result = match.getResult();
if(result == MatchResult.INDETERMINATE)
return new PolicyFinderResult(match.getStatus());
else if(result == MatchResult.MATCH)
{
if(matchedPolicy == null)
matchedPolicy = policy;
else
return XACMLUtil.errorResult("Matched multiple policies for reqest", null);
}
}
}
catch(ParsingException pe)
{
return XACMLUtil.errorResult("Error retrieving policies: " + pe.getMessage(), pe);
}
if(matchedPolicy == null)
return new PolicyFinderResult();
else
return new PolicyFinderResult(matchedPolicy);
}
public PolicyFinderResult findPolicy(URI idReference, int type)
{
BrokerPool pool = pdp.getBrokerPool();
DBBroker broker = null;
try
{
broker = pool.get(XMLSecurityManager.SYSTEM_USER);
AbstractPolicy policy = pdp.getUtil().findPolicy(broker, idReference, type);
return (policy == null) ? new PolicyFinderResult() : new PolicyFinderResult(policy);
}
catch(Exception e)
{
return XACMLUtil.errorResult("Error resolving id '" + idReference.toString() + "': " + e.getMessage(), e);
}
finally
{
pool.release(broker);
}
}
}