/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package org.fcrepo.server.security;
import java.net.URI;
import org.fcrepo.common.Constants;
import org.fcrepo.server.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.jboss.security.xacml.sunxacml.EvaluationCtx;
import org.jboss.security.xacml.sunxacml.attr.AttributeDesignator;
import org.jboss.security.xacml.sunxacml.attr.StringAttribute;
import org.jboss.security.xacml.sunxacml.cond.EvaluationResult;
/**
* @author Bill Niebel
*/
class ContextAttributeFinderModule
extends AttributeFinderModule {
private static final Logger logger =
LoggerFactory.getLogger(ContextAttributeFinderModule.class);
@Override
protected boolean canHandleAdhoc() {
return true;
}
private final ContextRegistry m_contexts;
private ContextAttributeFinderModule(ContextRegistry contexts) {
super();
m_contexts = contexts;
registerSupportedDesignatorType(AttributeDesignator.SUBJECT_TARGET);
registerSupportedDesignatorType(AttributeDesignator.ACTION_TARGET); //<<??????
registerSupportedDesignatorType(AttributeDesignator.RESOURCE_TARGET); //<<?????
registerSupportedDesignatorType(AttributeDesignator.ENVIRONMENT_TARGET);
registerAttribute(Constants.ENVIRONMENT.CURRENT_DATE_TIME);
registerAttribute(Constants.ENVIRONMENT.CURRENT_DATE);
registerAttribute(Constants.ENVIRONMENT.CURRENT_TIME);
registerAttribute(Constants.HTTP_REQUEST.PROTOCOL);
registerAttribute(Constants.HTTP_REQUEST.SCHEME);
registerAttribute(Constants.HTTP_REQUEST.SECURITY);
registerAttribute(Constants.HTTP_REQUEST.AUTHTYPE);
registerAttribute(Constants.HTTP_REQUEST.METHOD);
registerAttribute(Constants.HTTP_REQUEST.SESSION_ENCODING);
registerAttribute(Constants.HTTP_REQUEST.SESSION_STATUS);
registerAttribute(Constants.HTTP_REQUEST.CONTENT_LENGTH);
registerAttribute(Constants.HTTP_REQUEST.CONTENT_TYPE);
registerAttribute(Constants.HTTP_REQUEST.CLIENT_FQDN);
registerAttribute(Constants.HTTP_REQUEST.CLIENT_IP_ADDRESS);
registerAttribute(Constants.HTTP_REQUEST.SERVER_FQDN);
registerAttribute(Constants.HTTP_REQUEST.SERVER_IP_ADDRESS);
registerAttribute(Constants.HTTP_REQUEST.SERVER_PORT);
denyAttribute(Constants.XACML1_SUBJECT.ID.attributeId);
denyAttribute(Constants.XACML1_ACTION.ID.attributeId);
denyAttribute(Constants.XACML1_RESOURCE.ID.attributeId);
denyAttribute(Constants.ACTION.CONTEXT_ID.attributeId);
denyAttribute(Constants.SUBJECT.LOGIN_ID.attributeId);
denyAttribute(Constants.ACTION.ID.attributeId);
denyAttribute(Constants.ACTION.API.attributeId);
denyAttribute(Constants.OBJECT.PID.attributeId);
setInstantiatedOk(true);
}
private final String getContextId(EvaluationCtx context) {
final URI contextIdType = STRING_ATTRIBUTE_TYPE_URI;
final URI contextIdId = Constants.ACTION.CONTEXT_ID.attributeId;
logger.debug("ContextAttributeFinder:findAttribute about to call getAttributeFromEvaluationCtx");
EvaluationResult attribute =
context.getActionAttribute(contextIdType, contextIdId, null);
Object element = getAttributeFromEvaluationResult(attribute);
if (element == null) {
logger.debug("ContextAttributeFinder:getContextId exit on can't get contextId on request callback");
return null;
}
if (!(element instanceof StringAttribute)) {
logger.debug("ContextAttributeFinder:getContextId exit on couldn't get contextId from xacml request non-string returned");
return null;
}
String contextId = ((StringAttribute) element).getValue();
if (contextId == null) {
logger.debug("ContextAttributeFinder:getContextId exit on null contextId");
return null;
}
if (!validContextId(contextId)) {
logger.debug("ContextAttributeFinder:getContextId exit on invalid context-id");
return null;
}
return contextId;
}
private final boolean validContextId(String contextId) {
if (contextId == null || contextId.isEmpty()) {
return false;
}
if (" ".equals(contextId)) {
return false;
}
return true;
}
@Override
protected final Object getAttributeLocally(int designatorType,
URI attributeId,
URI resourceCategory,
EvaluationCtx ctx) {
logger.debug("getAttributeLocally context");
String contextId = getContextId(ctx);
logger.debug("contextId={} attributeID={}", contextId, attributeId);
if (contextId == null || contextId.isEmpty()) {
return null;
}
Context context = m_contexts.getContext(contextId);
logger.debug("got context");
String[] values = null;
logger.debug("designatorType{}", designatorType);
switch (designatorType) {
case AttributeDesignator.SUBJECT_TARGET:
String attributeName = attributeId.toString();
if (context.nSubjectValues(attributeName) < 1) {
values = null;
logger.debug("RETURNING NO VALUES FOR {}", attributeName);
} else {
if (logger.isDebugEnabled()) {
logger.debug("getting n values for {}={}", attributeId,
context.nSubjectValues(attributeName));
}
values = context.getSubjectValues(attributeName);
if (logger.isDebugEnabled()) {
if (values != null) {
StringBuffer sb = new StringBuffer();
sb.append("RETURNING " + values.length
+ " VALUES FOR " + attributeName + " ==");
for (int i = 0; i < values.length; i++) {
sb.append(" " + values[i]);
}
logger.debug(sb.toString());
}
}
}
break;
case AttributeDesignator.ACTION_TARGET:
if (context.nActionValues(attributeId) < 1) {
values = null;
} else {
values = context.getActionValues(attributeId);
}
break;
case AttributeDesignator.RESOURCE_TARGET:
if (context.nResourceValues(attributeId) < 1) {
values = null;
} else {
values = context.getResourceValues(attributeId);
}
break;
case AttributeDesignator.ENVIRONMENT_TARGET:
if (context.nEnvironmentValues(attributeId) < 1) {
values = null;
} else {
values = context.getEnvironmentValues(attributeId);
}
break;
default:
}
logger.debug("local context attribute {}", attributeId);
if (values != null) {
if (logger.isDebugEnabled()) {
logger.debug("getAttributeLocally string values=<Array>");
for (int i = 0; i < ((String[]) values).length; i++) {
logger.debug("another string value={}", ((String[]) values)[i]);
}
}
} else {
logger.debug("getAttributeLocally object value=null");
}
return values;
}
}