package org.fcrepo.server.security.xacml.pdp.finder.attribute; import java.net.URI; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.naming.NamingEnumeration; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import org.fcrepo.server.security.xacml.pdp.finder.AttributeFinderException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.fcrepo.common.Constants; import org.fcrepo.common.policy.xacml1.XACML1SubjectCategoryNamespace; import org.jboss.security.xacml.sunxacml.EvaluationCtx; import org.jboss.security.xacml.sunxacml.attr.AttributeFactory; import org.jboss.security.xacml.sunxacml.attr.AttributeValue; import org.jboss.security.xacml.sunxacml.attr.BagAttribute; import org.jboss.security.xacml.sunxacml.attr.StandardAttributeFactory; import org.jboss.security.xacml.sunxacml.cond.EvaluationResult; public class LDAPAttributeFinder extends DesignatorAttributeFinderModule { private static final Logger logger = LoggerFactory.getLogger(LDAPAttributeFinder.class); private static final URI STRING_DATATYPE = URI.create("http://www.w3.org/2001/XMLSchema#string"); private final AttributeFactory attributeFactory = StandardAttributeFactory.getFactory(); private Hashtable<String, String> dirEnv = null; private Map<String, String> m_options = null; private InitialDirContext ctx = null; public LDAPAttributeFinder(Map<String, String> options) { try { m_options = options; dirEnv = new Hashtable<String, String>(options); ctx = new InitialDirContext(dirEnv); } catch (Exception e) { logger.error("Attribute finder not initialised:" + this.getClass().getName(), e); } } public void init() throws AttributeFinderException { if (emptyAttributeMap()) { logger.warn(this.getClass().getName() + " configured with no registered attributes"); return; } if (logger.isDebugEnabled()) { logger.debug("registering the following attributes: "); for (int desNum : m_attributes.keySet()) { for (String attrName : m_attributes.get(desNum).keySet()) { logger.debug(desNum + ": " + attrName); } } } logger.info("Initialised AttributeFinder:" + this.getClass().getName()); } /** * Returns true always because this module supports designators. * * @return true always */ @Override public boolean isDesignatorSupported() { return true; } /** * Used to get an attribute. If one of those values isn't being asked for, * or if the types are wrong, then an empty bag is returned. * * @param attributeType * the datatype of the attributes to find, which must be time, date, * or dateTime for this module to resolve a value * @param attributeId * the identifier of the attributes to find, which must be one of the * three ENVIRONMENT_* fields for this module to resolve a value * @param issuer * the issuer of the attributes, or null if unspecified * @param subjectCategory * the category of the attribute or null, which ignored since this * only handles non-subjects * @param context * the representation of the request data * @param designatorType * the type of designator, which must be ENVIRONMENT_TARGET for this * module to resolve a value * @return the result of attribute retrieval, which will be a bag with a * single attribute, an empty bag, or an error */ @Override public EvaluationResult findAttribute(URI attributeType, URI attributeId, URI issuer, URI subjectCategory, EvaluationCtx context, int designatorType) { String user = null; URI userId = Constants.SUBJECT.LOGIN_ID.getURI(); URI category = XACML1SubjectCategoryNamespace.getInstance().ACCESS_SUBJECT.getURI(); EvaluationResult userER = context.getSubjectAttribute(STRING_DATATYPE, userId, category); if (userER == null) { return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } AttributeValue userAV = userER.getAttributeValue(); if (userAV == null) { return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } user = userAV.encode(); if (logger.isDebugEnabled()) { logger.debug("LDAPAttributeFinder: Getting info for " + user); } // figure out which attribute we're looking for String attrName = attributeId.toString(); // we only know about registered attributes from config file if (m_attributes.get(designatorType) == null) { if (logger.isDebugEnabled()) { logger.debug("Does not know about designatorType: " + designatorType); } return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } Set<String> allowedAttributes = m_attributes.get(designatorType).keySet(); if (!allowedAttributes.contains(attrName)) { if (logger.isDebugEnabled()) { logger.debug("Does not know about attribute: " + attrName); } return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } EvaluationResult result = null; try { result = getEvaluationResult(user, attrName, attributeType); } catch (Exception e) { logger.error("Error finding attribute: " + e.getMessage(), e); return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } return result; } private EvaluationResult getEvaluationResult(String user, String attribute, URI type) { String[] attrsReturned = new String[] {attribute}; String base = m_options.get("searchbase"); String filter = "(" + m_options.get("id-attribute") + "=" + user + ")"; SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); searchControls.setDerefLinkFlag(true); searchControls.setReturningObjFlag(true); searchControls.setReturningAttributes(attrsReturned); Set<AttributeValue> bagValues = new HashSet<AttributeValue>(); try { NamingEnumeration<SearchResult> ne = ctx.search(base, filter, searchControls); while (ne.hasMore()) { SearchResult result = (SearchResult) ne.next(); Attributes attrs = result.getAttributes(); NamingEnumeration<? extends Attribute> neas = attrs.getAll(); while (neas.hasMoreElements()) { Attribute attr = (Attribute) neas.nextElement(); if (!attr.getID().equals(attribute)) { continue; } NamingEnumeration<?> nea = attr.getAll(); while (nea.hasMoreElements()) { String value = (String) nea.nextElement(); if (logger.isDebugEnabled()) { logger.debug(attr.getID() + ": " + value); } AttributeValue attributeValue = null; try { attributeValue = attributeFactory.createValue(type, value); } catch (Exception e) { logger.error("Error creating attribute: " + e.getMessage(), e); continue; } bagValues.add(attributeValue); if (logger.isDebugEnabled()) { logger.debug("AttributeValue found: [" + type.toASCIIString() + "] " + value); } } } } } catch (Exception e) { logger.error("Error getting evaluation result", e); return new EvaluationResult(BagAttribute.createEmptyBag(type)); } BagAttribute bag = new BagAttribute(type, bagValues); return new EvaluationResult(bag); } public static void main(String[] args) throws Exception { HashMap<String,String> test = new HashMap<String, String>(); LDAPAttributeFinder finder = new LDAPAttributeFinder(test); URI type = new URI("http://www.w3.org/2001/XMLSchema#string"); EvaluationResult result = finder.getEvaluationResult("nishen", "eduPersonEntitlement", type); BagAttribute bag = (BagAttribute) result.getAttributeValue(); Iterator<?> i = bag.iterator(); while (i.hasNext()) { AttributeValue a = (AttributeValue) i.next(); logger.info("value: " + a.encode()); } } }