--- /dev/null
+/*
+ * The Shibboleth License, Version 1.
+ * Copyright (c) 2002
+ * University Corporation for Advanced Internet Development, Inc.
+ * All rights reserved
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution, if any, must include
+ * the following acknowledgment: "This product includes software developed by
+ * the University Corporation for Advanced Internet Development
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
+ * may appear in the software itself, if and wherever such third-party
+ * acknowledgments normally appear.
+ *
+ * Neither the name of Shibboleth nor the names of its contributors, nor
+ * Internet2, nor the University Corporation for Advanced Internet Development,
+ * Inc., nor UCAID may be used to endorse or promote products derived from this
+ * software without specific prior written permission. For written permission,
+ * please contact shibboleth@shibboleth.org
+ *
+ * Products derived from this software may not be called Shibboleth, Internet2,
+ * UCAID, or the University Corporation for Advanced Internet Development, nor
+ * may Shibboleth appear in their name, without prior written permission of the
+ * University Corporation for Advanced Internet Development.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.aa.arp;
+
+/**
+ * Defines an attribute to which Shibboleth Attribute Release Policies may be applied.
+ *
+ * @author Walter Hoehn (wassa@columbia.edu)
+ */
+public interface ArpAttribute {
+ /**
+ * Returns the name of the Attribute
+ */
+ public String getName();
+
+ /**
+ * Sets the values of the attribute to those represented in an array
+ */
+ public void setValues(Object[] values);
+
+ /**
+ * Returns an array representing the attributes values
+ */
+ public Object[] getValues();
+}
return (URI[]) possibleReleaseSet.toArray(new URI[0]);
}
+ public ArpAttribute[] filterAttributes(
+ ArpAttribute[] attributes,
+ Principal principal,
+ String requester,
+ URL resource)
+ throws ArpProcessingException {
+
+ Set releaseSet = new HashSet();
+
+ //Gather all applicable ARP attribute specifiers
+ Set attributeNames = new HashSet();
+ for (int i = 0; attributes.length > i; i++) {
+ attributeNames.add(attributes[i].getName());
+ }
+ Rule[] rules = createEffectiveArp(principal, requester, resource).getAllRules();
+ Set applicableRuleAttributes = new HashSet();
+ for (int i = 0; rules.length > i; i++) {
+ Rule.Attribute[] ruleAttributes = rules[i].getAttributes();
+ for (int j = 0; ruleAttributes.length > j; j++) {
+ if (attributeNames.contains(ruleAttributes[j].getName().toString())) {
+ applicableRuleAttributes.add(ruleAttributes[j]);
+ }
+ }
+ }
+
+ //Canonicalize specifiers
+ Map arpAttributeSpecs =
+ createCanonicalAttributeSpec(
+ (Rule.Attribute[]) applicableRuleAttributes.toArray(new Rule.Attribute[0]));
+
+ //Filter
+ for (int i = 0; attributes.length > i; i++) {
+ Rule.Attribute attribute = (Rule.Attribute) arpAttributeSpecs.get(attributes[i].getName());
+
+ //Handle no specifier
+ if (attribute == null) {
+ continue;
+ }
+
+ //Handle Deny All
+ if (attribute.denyAnyValue()) {
+ continue;
+ }
+
+ //Handle Permit All
+ if (attribute.releaseAnyValue() && attribute.getValues().length == 0) {
+ releaseSet.add(attributes[i]);
+ continue;
+ }
+
+ //Handle Permit All-Except and Permit Specific
+ Object[] resolvedValues = attributes[i].getValues();
+ Set releaseValues = new HashSet();
+ for (int j = 0; resolvedValues.length > j; j++) {
+ System.err.println(attribute.isValuePermitted(resolvedValues[j]));
+ if (attribute.isValuePermitted(resolvedValues[j])) {
+ releaseValues.add(resolvedValues[j]);
+ }
+ }
+ attributes[i].setValues((ArpAttribute[]) releaseValues.toArray(new ArpAttribute[0]));
+ releaseSet.add(attributes[i]);
+ }
+ return (ArpAttribute[]) releaseSet.toArray(new ArpAttribute[0]);
+ }
+
+ private Map createCanonicalAttributeSpec(Rule.Attribute[] attributes) {
+ Map canonicalSpec = new HashMap();
+ for (int i = 0; attributes.length > i; i++) {
+ if (!canonicalSpec.containsKey(attributes[i].getName().toString())) {
+ canonicalSpec.put(attributes[i].getName().toString(), attributes[i]);
+ } else {
+ if (((Rule.Attribute) canonicalSpec.get(attributes[i].getName().toString())).denyAnyValue()) {
+ continue;
+ }
+ if (attributes[i].denyAnyValue()) {
+ ((Rule.Attribute) canonicalSpec.get(attributes[i].getName())).setAnyValueDeny(true);
+ continue;
+ }
+ if (attributes[i].releaseAnyValue()) {
+ ((Rule.Attribute) canonicalSpec.get(attributes[i].getName().toString())).setAnyValuePermit(true);
+ }
+ Rule.AttributeValue[] values = attributes[i].getValues();
+ for (int j = 0; values.length > j; j++) {
+ ((Rule.Attribute) canonicalSpec.get(attributes[i].getName().toString())).addValue(values[j]);
+ }
+ }
+ }
+ return canonicalSpec;
+ }
+
}
}
}
+
+ public void testArpApplication() {
+ Properties props = new Properties();
+ props.setProperty(
+ "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
+ "edu.internet2.middleware.shibboleth.aa.arp.provider.MemoryArpRepository");
+ ArpRepository repository = null;
+ try {
+ repository = ArpRepositoryFactory.getInstance(props);
+ } catch (ArpRepositoryException e) {
+ fail("Failed to create memory-based Arp Repository" + e);
+ }
+ try {
+ Principal principal1 = new AAPrincipal("TestPrincipal");
+ URL url1 = new URL("http://www.example.edu/");
+
+ //Test with just a site ARP
+ InputStream inStream = new FileInputStream("test/arp1.xml");
+ DOMParser parser = new DOMParser();
+ parser.parse(new InputSource(inStream));
+ Arp arp1 = new Arp();
+ arp1.marshall(parser.getDocument().getDocumentElement());
+ repository.update(arp1);
+ ArpEngine engine = new ArpEngine(repository, props);
+
+ TestAttribute testAttribute1 =
+ new TestAttribute(
+ "urn:mace:eduPerson:1.0:eduPersonAffiliation",
+ new Object[] { "member@example.edu", "faculty@example.edu" });
+ TestAttribute testAttribute2 =
+ new TestAttribute(
+ "urn:mace:eduPerson:1.0:eduPersonPrincipalName",
+ new Object[] { "mehoehn@example.edu" });
+ ArpAttribute[] releaseAttributes =
+ engine.filterAttributes(
+ new ArpAttribute[] { testAttribute1, testAttribute2 },
+ principal1,
+ "shar.example.edu",
+ url1);
+ for (int i = 0; releaseAttributes.length > i; i++) {
+ Object[] values = releaseAttributes[i].getValues();
+ for (int j = 0; values.length > j; j++) {
+ System.err.println(values[j]);
+ }
+ }
+ System.err.println("---");
+ //Test with site and user ARPs
+ inStream = new FileInputStream("test/arp7.xml");
+ parser.parse(new InputSource(inStream));
+ Arp arp7 = new Arp();
+ arp7.setPrincipal(principal1);
+ arp7.marshall(parser.getDocument().getDocumentElement());
+ repository.update(arp7);
+ releaseAttributes =
+ engine.filterAttributes(
+ new ArpAttribute[] { testAttribute1, testAttribute2 },
+ principal1,
+ "shar.example.edu",
+ url1);
+ for (int i = 0; releaseAttributes.length > i; i++) {
+ Object[] values = releaseAttributes[i].getValues();
+ for (int j = 0; values.length > j; j++) {
+ System.err.println(values[j]);
+ }
+ }
+ System.err.println("---");
+ releaseAttributes =
+ engine.filterAttributes(
+ new ArpAttribute[] { testAttribute1, testAttribute2 },
+ principal1,
+ "shar1.example.edu",
+ url1);
+ for (int i = 0; releaseAttributes.length > i; i++) {
+ Object[] values = releaseAttributes[i].getValues();
+ for (int j = 0; values.length > j; j++) {
+ System.err.println(values[j]);
+ }
+ }
+ System.err.println("---");
+ inStream = new FileInputStream("test/arp6.xml");
+ parser.parse(new InputSource(inStream));
+ Arp arp6 = new Arp();
+ arp6.setPrincipal(principal1);
+ arp6.marshall(parser.getDocument().getDocumentElement());
+ repository.update(arp6);
+ releaseAttributes =
+ engine.filterAttributes(
+ new ArpAttribute[] { testAttribute1, testAttribute2 },
+ principal1,
+ "shar.example.edu",
+ url1);
+ for (int i = 0; releaseAttributes.length > i; i++) {
+ Object[] values = releaseAttributes[i].getValues();
+ for (int j = 0; values.length > j; j++) {
+ System.err.println(values[j]);
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to apply ARPs: " + e);
+ }
+ }
+
+ public class TestAttribute implements ArpAttribute {
+ private String name;
+ private Object[] values;
+
+ public TestAttribute(String name, Object[] values) {
+ this.name = name;
+ this.values = values;
+ }
+
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute#getValues()
+ */
+ public Object[] getValues() {
+ return values;
+ }
+
+ /**
+ * @see edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute#setValues(Object[])
+ */
+ public void setValues(Object[] values) {
+ this.values = values;
+ }
+
+ public boolean equals(Object object) {
+ if (!(object instanceof TestAttribute)) {
+ return false;
+ }
+ //finish this
+ return super.equals(object);
+ }
+
+ }
}
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Set;
import org.apache.log4j.Logger;
return false;
}
+ void setAnyValueDeny(boolean b) {
+ if (b) {
+ anyValue = true;
+ anyValueRelease = "deny";
+ values.clear();
+ } else {
+ if (anyValueRelease.equals("deny") && anyValue) {
+ anyValue = false;
+ }
+ }
+ }
+
+ boolean isValuePermitted(Object value) {
+ //Handle Deny All
+ if (denyAnyValue()) {
+ return false;
+ }
+
+ //Handle Permit All with no specific values
+ if (releaseAnyValue() && getValues().length == 0) {
+ return true;
+ }
+
+ //Handle Deny Specific
+ Iterator iterator = values.iterator();
+ while (iterator.hasNext()) {
+ AttributeValue valueSpec = (AttributeValue) iterator.next();
+ if (valueSpec.getValue().equals(value) && valueSpec.getRelease().equals("deny")) {
+ return false;
+ }
+ }
+ //Handle Permit All with no relevant specific denies
+ if (releaseAnyValue()) {
+ return true;
+ }
+
+ //Handle Permit Specific
+ iterator = values.iterator();
+ while (iterator.hasNext()) {
+ AttributeValue valueSpec = (AttributeValue) iterator.next();
+ if (valueSpec.getValue().equals(value) && valueSpec.getRelease().equals("permit")) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void setAnyValuePermit(boolean b) {
+ if (b) {
+ anyValue = true;
+ anyValueRelease = "permit";
+ Iterator iterator = values.iterator();
+ while (iterator.hasNext()) {
+ AttributeValue value = (AttributeValue) iterator.next();
+ if (value.getRelease().equals("permit")) {
+ values.remove(value);
+ }
+ }
+ } else {
+ if (anyValueRelease.equals("permit") && anyValue) {
+ anyValue = false;
+ }
+ }
+ }
+
URI getName() {
return name;
}
AttributeValue[] getValues() {
return (AttributeValue[]) values.toArray(new AttributeValue[0]);
}
+
+ void addValue(AttributeValue value) {
+ if (denyAnyValue()) {
+ return;
+ }
+ if (releaseAnyValue() && value.getRelease().equals("permit")) {
+ return;
+ }
+ values.add(value);
+ }
void marshall(Element element) throws ArpMarshallingException {
//Make sure we are dealing with an Attribute
}
//Handle Value definitions
+ if (!denyAnyValue()) {
NodeList valueNodeList = element.getElementsByTagName("Value");
for (int i = 0; valueNodeList.getLength() > i; i++) {
String release = null;
&& ((Element) valueNodeList.item(i)).getFirstChild().getNodeType() == Node.TEXT_NODE) {
value = ((CharacterData) ((Element) valueNodeList.item(i)).getFirstChild()).getData();
}
+ if (releaseAnyValue() && release.equals("permit")) {
+ continue;
+ }
AttributeValue aValue = new AttributeValue(release, value);
values.add(aValue);
}
+ }
}
}