package melcoe.xacml.pdp.finder.attribute; import java.net.URI; import java.net.URISyntaxException; 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 melcoe.xacml.pdp.finder.AttributeFinderConfigUtil; import org.apache.log4j.Logger; import com.sun.xacml.EvaluationCtx; import com.sun.xacml.attr.AttributeFactory; import com.sun.xacml.attr.AttributeValue; import com.sun.xacml.attr.BagAttribute; import com.sun.xacml.attr.StandardAttributeFactory; import com.sun.xacml.cond.EvaluationResult; import com.sun.xacml.finder.AttributeFinderModule; public class LDAPAttributeFinder extends AttributeFinderModule { private static final Logger log = Logger.getLogger(LDAPAttributeFinder.class); private AttributeFactory attributeFactory = null; private Map<Integer, Set<String>> attributes = null; private Hashtable<String, String> dirEnv = null; private Map<String, String> options = null; private InitialDirContext ctx = null; public LDAPAttributeFinder() { try { attributes = AttributeFinderConfigUtil.getAttributeFinderConfig(this .getClass().getName()); log .info("Initialised AttributeFinder:" + this.getClass().getName()); if (log.isDebugEnabled()) { log.debug("registering the following attributes: "); for (Integer k : attributes.keySet()) { for (String l : attributes.get(k)) { log.debug(k + ": " + l); } } } options = AttributeFinderConfigUtil.getOptionMap(this.getClass() .getName()); dirEnv = new Hashtable<String, String>(options); attributeFactory = StandardAttributeFactory.getFactory(); ctx = new InitialDirContext(dirEnv); } catch (Exception e) { log.fatal("Attribute finder not initialised:" + this.getClass().getName()); } } /** * Returns true always because this module supports designators. * * @return true always */ @Override public boolean isDesignatorSupported() { return true; } /** * Returns a <code>Set</code> with a single <code>Integer</code> specifying * that environment attributes are supported by this module. * * @return a <code>Set</code> with * <code>AttributeDesignator.ENVIRONMENT_TARGET</code> included */ @Override public Set<Integer> getSupportedDesignatorTypes() { return attributes.keySet(); } /** * 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; try { URI userId = new URI("urn:fedora:names:fedora:2.1:subject:loginId"); URI userType = new URI("http://www.w3.org/2001/XMLSchema#string"); URI category = new URI("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"); EvaluationResult userER = context.getSubjectAttribute(userType, 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 (log.isDebugEnabled()) { log.debug("LDAPAttributeFinder: Getting info for " + user); } } catch (URISyntaxException use) { log.error(use.getMessage()); return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } // figure out which attribute we're looking for String attrName = attributeId.toString(); // we only know about registered attributes from config file if (!attributes.keySet().contains(new Integer(designatorType))) { if (log.isDebugEnabled()) { log.debug("Does not know about designatorType: " + designatorType); } return new EvaluationResult(BagAttribute .createEmptyBag(attributeType)); } Set<String> allowedAttributes = attributes.get(new Integer(designatorType)); if (!allowedAttributes.contains(attrName)) { if (log.isDebugEnabled()) { log.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) { log.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 = options.get("searchbase"); String filter = "(" + 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 ne = ctx.search(base, filter, searchControls); while (ne.hasMore()) { SearchResult result = (SearchResult) ne.next(); Attributes attrs = result.getAttributes(); NamingEnumeration 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 (log.isDebugEnabled()) { log.debug(attr.getID() + ": " + value); } AttributeValue attributeValue = null; try { attributeValue = attributeFactory.createValue(type, value); } catch (Exception e) { log.error("Error creating attribute: " + e.getMessage(), e); continue; } bagValues.add(attributeValue); if (log.isDebugEnabled()) { log.debug("AttributeValue found: [" + type.toASCIIString() + "] " + value); } } } } } catch (Exception e) { log.error(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 { LDAPAttributeFinder finder = new LDAPAttributeFinder(); 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(); log.info("value: " + a.encode()); } } }