package org.fcrepo.server.security.impl; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; import org.fcrepo.common.Constants; import org.fcrepo.server.errors.GeneralException; import org.fcrepo.server.errors.authorization.AuthzOperationalException; import org.fcrepo.server.security.Attribute; import org.fcrepo.server.security.PolicyEnforcementPoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.jboss.security.xacml.sunxacml.PDP; import org.jboss.security.xacml.sunxacml.PDPConfig; import org.jboss.security.xacml.sunxacml.attr.AnyURIAttribute; import org.jboss.security.xacml.sunxacml.attr.StringAttribute; import org.jboss.security.xacml.sunxacml.ctx.Result; import org.jboss.security.xacml.sunxacml.ctx.Subject; public abstract class AbstractPolicyEnforcementPoint implements PolicyEnforcementPoint { private static final Logger logger = LoggerFactory.getLogger(AbstractPolicyEnforcementPoint.class); static final URI SUBJECT_ID_URI = Constants.SUBJECT.LOGIN_ID.attributeId; static final URI ACTION_ID_URI = Constants.ACTION.ID.attributeId; static final URI ACTION_API_URI = Constants.ACTION.API.attributeId; static final URI ACTION_CONTEXT_URI = Constants.ACTION.CONTEXT_ID.attributeId; static final URI RESOURCE_PID_URI = Constants.OBJECT.PID.attributeId; static final URI RESOURCE_NAMESPACE_URI = Constants.OBJECT.NAMESPACE.attributeId; static final StringAttribute EMPTY_ATTRIBUTE = new StringAttribute(""); static final Attribute ACTION_ATTRIBUTE = new SingletonAttribute(Constants.XACML1_ACTION.ID.attributeId, null, null, EMPTY_ATTRIBUTE); static final Attribute RESOURCE_ATTRIBUTE = new SingletonAttribute(Constants.XACML1_RESOURCE.ID.attributeId, null, null, EMPTY_ATTRIBUTE); static final Attribute SUBJECT_ATTRIBUTE = new SingletonAttribute(Constants.XACML1_SUBJECT.ID.attributeId, null, null, EMPTY_ATTRIBUTE); protected final PDPConfig m_pdpConfig; protected PDP m_pdp; public AbstractPolicyEnforcementPoint(PDPConfig pdpConfig) { m_pdpConfig = pdpConfig; } public void init() throws GeneralException { newPdp(); } @Override public final void newPdp() { PDP pdp = new PDP(m_pdpConfig); synchronized (this) { this.m_pdp = pdp; //so enforce() will wait, if this pdp update is in progress } } /* (non-Javadoc) * @see org.fcrepo.server.security.PolicyEnforcementPoint#inactivate() */ @Override public void inactivate() { destroy(); } /* (non-Javadoc) * @see org.fcrepo.server.security.PolicyEnforcementPoint#destroy() */ @Override public void destroy() { m_pdp = null; } protected List<Subject> wrapSubjects(String subjectLoginId) { logger.debug("wrapSubjectIdAsSubjects(): {}", subjectLoginId); StringAttribute stringAttribute = EMPTY_ATTRIBUTE; Attribute subjectAttribute = SUBJECT_ATTRIBUTE; logger.debug("wrapSubjectIdAsSubjects(): subjectAttribute, id={}, type={}, value={}", subjectAttribute.getId(), subjectAttribute.getType(), subjectAttribute.getValue()); List<Attribute> subjectAttributes; if (subjectLoginId != null && !subjectLoginId.isEmpty()) { subjectAttributes = new ArrayList<Attribute>(2); subjectAttributes.add(subjectAttribute); stringAttribute = new StringAttribute(subjectLoginId); subjectAttribute = new SingletonAttribute(SUBJECT_ID_URI, null, null, stringAttribute); logger.debug("wrapSubjectIdAsSubjects(): subjectAttribute, id={}, type={}, value={}", subjectAttribute.getId(), subjectAttribute.getType(), subjectAttribute.getValue()); subjectAttributes.add(subjectAttribute); } else { subjectAttributes = new ArrayList<Attribute>(1); subjectAttributes.add(subjectAttribute); } Subject singleSubject = new Subject(subjectAttributes); return Collections.singletonList(singleSubject); } protected List<Attribute> wrapActions(String actionId, String actionApi, String contextIndex) { List<Attribute> actions = new ArrayList<Attribute>(4); actions.add(ACTION_ATTRIBUTE); Attribute action = new SingletonAttribute(ACTION_ID_URI, null, null, new StringAttribute(actionId)); actions.add(action); action = new SingletonAttribute(ACTION_API_URI, null, null, new StringAttribute(actionApi)); actions.add(action); if (contextIndex != null) { action = new SingletonAttribute(ACTION_CONTEXT_URI, null, null, new StringAttribute(contextIndex)); actions.add(action); } return actions; } protected List<Attribute> wrapResources(String pid, String namespace) throws AuthzOperationalException { List<Attribute> resources = new ArrayList<Attribute>(3); Attribute attribute; try { attribute = new SingletonAttribute(Constants.XACML1_RESOURCE.ID.attributeId, null, null, AnyURIAttribute.getInstance(pid)); } catch (Exception e) { logger.warn("pid {} is not a valid uri; write policies against the StringAttribute {} instead.", pid, Constants.OBJECT.PID.uri); attribute = new SingletonAttribute(Constants.XACML1_RESOURCE.ID.attributeId, null, null, StringAttribute.getInstance(pid)); } resources.add(attribute); attribute = new SingletonAttribute(RESOURCE_PID_URI, null, null, new StringAttribute(pid)); resources.add(attribute); attribute = new SingletonAttribute(RESOURCE_NAMESPACE_URI, null, null, new StringAttribute(namespace)); resources.add(attribute); return resources; } protected static final boolean denyBiasedAuthz(Set<Result> set) { int nPermits = 0; //explicit permit returned int nDenies = 0; //explicit deny returned int nNotApplicables = 0; //no targets matched int nIndeterminates = 0; //for targets matched, no rules matched int nWrongs = 0; //none of the above, i.e., unreported failure, should not happen Iterator<Result> it = set.iterator(); while (it.hasNext()) { Result result = it.next(); int decision = result.getDecision(); switch (decision) { case Result.DECISION_PERMIT: nPermits++; break; case Result.DECISION_DENY: nDenies++; break; case Result.DECISION_INDETERMINATE: nIndeterminates++; break; case Result.DECISION_NOT_APPLICABLE: nNotApplicables++; break; default: nWrongs++; break; } } if (logger.isDebugEnabled()) { logger.debug("AUTHZ: permits=" + nPermits + " denies=" + nDenies + " indeterminates=" + nIndeterminates + " notApplicables=" + nNotApplicables + " unexpecteds=" + nWrongs); } return nPermits >= 1 && nDenies == 0 && nIndeterminates == 0 && nWrongs == 0; // don't care about NotApplicables } }