import java.io.FileInputStream;
import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
import java.util.Properties;
import junit.framework.TestCase;
/**
* Validation suite for <code>Arp</code> processing.
*
- * @author Walter Hoehn (wassa@columbia.edu)
+ * @ author Walter Hoehn(wassa@columbia.edu)
*/
public class ArpTests extends TestCase {
}
+ public void testMatchingFunctions() {
+
+ try {
+
+ /*
+ * Test Arp Engine function retrieval
+ */
+
+ //Lookup a function that doesn't exist
+ MatchFunction noFunction =
+ ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:dummy"));
+ assertNull("ArpEngine did not return null on dummy function.", noFunction);
+
+ //Lookup some real functions
+ MatchFunction exactSharFunction =
+ ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:exactShar"));
+ assertNotNull("ArpEngine did not properly load the Exact SHAR function.", exactSharFunction);
+ MatchFunction resourceTreeFunction =
+ ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:resourceTree"));
+ assertNotNull(
+ "ArpEngine did not properly load the Resource Tree SHAR function.",
+ resourceTreeFunction);
+
+ /*
+ * Test the Exact SHAR function
+ */
+
+ assertTrue(
+ "Exact SHAR function: false negative",
+ exactSharFunction.match("shar.example.edu", "shar.example.edu"));
+ assertTrue(
+ "Exact SHAR function: false negative",
+ !exactSharFunction.match("shar.example.edu", "www.example.edu"));
+ assertTrue(
+ "Exact SHAR function: false negative",
+ !exactSharFunction.match("example.edu", "shar.example.edu"));
+
+ //Make sure we properly handle bad input
+ try {
+ exactSharFunction.match(null, null);
+ fail("Exact SHAR function seems to take improper input without throwing an exception.");
+ } catch (ArpException ie) {
+ //This is supposed to fail
+ }
+
+ /*
+ * Test the Resource Tree function
+ */
+
+ URL requestURL1 = new URL("http://www.example.edu/test/");
+ URL requestURL2 = new URL("http://www.example.edu/test/index.html");
+ URL requestURL3 = new URL("http://www.example.edu/test2/index.html");
+ URL requestURL4 = new URL("http://www.example.edu/test2/index.html?test1=test1");
+
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu/", requestURL1));
+ assertTrue(
+ "Resource Tree function: false positive",
+ !resourceTreeFunction.match("https://www.example.edu/", requestURL1));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu:80/", requestURL1));
+ assertTrue(
+ "Resource Tree function: false positive",
+ !resourceTreeFunction.match("http://www.example.edu:81/", requestURL1));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu/test/", requestURL1));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu/test/", requestURL2));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu/", requestURL3));
+ assertTrue(
+ "Resource Tree function: false positive",
+ !resourceTreeFunction.match("http://www.example.edu/test/", requestURL3));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu/test2/index.html", requestURL3));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match("http://www.example.edu/test2/index.html", requestURL4));
+ assertTrue(
+ "Resource Tree function: false negative",
+ resourceTreeFunction.match(
+ "http://www.example.edu/test2/index.html?test1=test1",
+ requestURL4));
+ assertTrue(
+ "Resource Tree function: false positive",
+ !resourceTreeFunction.match(
+ "http://www.example.edu/test2/index.html?test1=test1",
+ requestURL3));
+
+ //Make sure we properly handle bad input
+ try {
+ resourceTreeFunction.match(null, null);
+ fail("Resource Tree function seems to take improper input without throwing an exception.");
+ } catch (ArpException ie) {
+ //This is supposed to fail
+ }
+ try {
+ resourceTreeFunction.match("Test", "Test");
+ fail("Resource Tree function seems to take improper input without throwing an exception.");
+ } catch (ArpException ie) {
+ //This is supposed to fail
+ }
+
+ } catch (ArpException e) {
+ fail("Encountered a problem loading match function: " + e);
+ } catch (URISyntaxException e) {
+ fail("Unable to create URI from test string.");
+ } catch (MalformedURLException e) {
+ fail("Couldn't create test URLs: " + e);
+ }
+
+ }
+
public void testRepositories() {
/*
*
* @author Walter Hoehn (wassa@columbia.edu)
*/
-public interface MatchFunction {}
+public interface MatchFunction {
+ /**
+ * Boolean indication of whether the specified ARP component matches the
+ * specified Request component. Used to determine if an ARP is applicable
+ * to a particular request.
+ */
+ public boolean match(Object arpComponent, Object requestComponent)
+ throws MatchingException;
+}
--- /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;
+
+/**
+ * Signals that an error occurred while processing an ARP match function.
+ *
+ * @author Walter Hoehn (wassa@columbia.edu)
+ */
+public class MatchingException extends ArpException {
+ public MatchingException(String message) {
+ super(message);
+ }
+}
package edu.internet2.middleware.shibboleth.aa.arp.provider;
+import org.apache.log4j.Logger;
+
import edu.internet2.middleware.shibboleth.aa.arp.MatchFunction;
+import edu.internet2.middleware.shibboleth.aa.arp.MatchingException;
/**
* Match function that does exact matching on requesters.
* @author Walter Hoehn (wassa@columbia.edu)
*/
public class ExactSharMatchFunction implements MatchFunction {
+ private static Logger log = Logger.getLogger(ExactSharMatchFunction.class.getName());
/**
- * Constructor for ExactSharMatchFunction.
+ * @see edu.internet2.middleware.shibboleth.aa.arp.MatchFunction#match(Object,
+ * Object)
*/
- public ExactSharMatchFunction() {
- super();
+ public boolean match(Object arpComponent, Object requestComponent)
+ throws MatchingException
+ {
+ if (!(arpComponent instanceof String) && !(requestComponent instanceof String)) {
+ log.error("Invalid use of ARP matching function (ExacthSharMatchFunction).");
+ throw new MatchingException("Invalid use of ARP matching function (ExacthSharMatchFunction).");
+ }
+ return arpComponent.equals(requestComponent);
}
}
package edu.internet2.middleware.shibboleth.aa.arp.provider;
import edu.internet2.middleware.shibboleth.aa.arp.MatchFunction;
+import edu.internet2.middleware.shibboleth.aa.arp.MatchingException;
/**
* Match function implementaiton that does regular expression matching on both
*/
public class RegexMatchFunction implements MatchFunction {
/**
- * Constructor for RegexMatchFunction.
+ * @see edu.internet2.middleware.shibboleth.aa.arp.MatchFunction#match(Object,
+ * Object)
*/
- public RegexMatchFunction() {
- super();
+ public boolean match(Object arpComponent, Object requestComponent)
+ throws MatchingException
+ {
+ return false;
}
}
package edu.internet2.middleware.shibboleth.aa.arp.provider;
import edu.internet2.middleware.shibboleth.aa.arp.MatchFunction;
+import edu.internet2.middleware.shibboleth.aa.arp.MatchingException;
+
+import org.apache.log4j.Logger;
+
+import java.net.MalformedURLException;
+import java.net.URL;
/**
* MatchFuction implementation that does "tail" matching on resources.
* @author Walter Hoehn (wassa@columbia.edu)
*/
public class ResourceTreeMatchFunction implements MatchFunction {
+ private static Logger log = Logger.getLogger(ResourceTreeMatchFunction.class.getName());
+
/**
- * Constructor for ResourceTreeMatchFunction.
+ * @see edu.internet2.middleware.shibboleth.aa.arp.MatchFunction#match(Object,
+ * Object)
*/
- public ResourceTreeMatchFunction() {
- super();
+ public boolean match(Object arpComponent, Object requestComponent)
+ throws MatchingException
+ {
+ if (!(arpComponent instanceof String) && !(requestComponent instanceof URL)) {
+ log.error("Invalid use of ARP matching function (ExacthSharMatchFunction).");
+ throw new MatchingException(
+ "Invalid use of ARP matching function (ExacthSharMatchFunction).");
+ }
+
+ URL arpURL = null;
+
+ try {
+ arpURL = new URL((String) arpComponent);
+ } catch (MalformedURLException e) {
+ log.error(
+ "Invalid use of ARP matching function (ExacthSharMatchFunction): ARP Component is not a URL.");
+ throw new MatchingException(
+ "Invalid use of ARP matching function (ExacthSharMatchFunction).");
+ }
+
+ if (!matchProtocol(arpURL, (URL) requestComponent)) {
+ return false;
+ }
+
+ if (!matchHost(arpURL, (URL) requestComponent)) {
+ return false;
+ }
+
+ if (!matchPort(arpURL, (URL) requestComponent)) {
+ return false;
+ }
+
+ if (!matchPath(arpURL, (URL) requestComponent)) {
+ return false;
+ }
+
+ if (!matchQuery(arpURL, (URL) requestComponent)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ protected boolean matchHost(URL arpURL, URL requestURL) {
+ return arpURL.getHost().equals(requestURL.getHost());
+ }
+
+ protected boolean matchPath(URL arpURL, URL requestURL) {
+ String arpPath = arpURL.getPath();
+
+ if (arpPath.equals("")) {
+ arpPath = "/";
+ }
+
+ String requestPath = requestURL.getPath();
+
+ if (requestPath.equals("")) {
+ requestPath = "/";
+ }
+
+ return requestPath.startsWith(arpPath);
+ }
+
+ protected boolean matchPort(URL arpURL, URL requestURL) {
+ int arpPort = arpURL.getPort();
+
+ if (arpPort < 1) {
+ arpPort = arpURL.getDefaultPort();
+ }
+
+ int requestPort = requestURL.getPort();
+
+ if (requestPort < 1) {
+ requestPort = requestURL.getDefaultPort();
+ }
+
+ if (arpPort == requestPort) {
+ return true;
+ }
+
+ return false;
+ }
+
+ protected boolean matchProtocol(URL arpURL, URL requestURL) {
+ return arpURL.getProtocol().equals(requestURL.getProtocol());
+ }
+
+ protected boolean matchQuery(URL arpURL, URL requestURL) {
+ if (arpURL.getQuery() == null) {
+ return true;
+ }
+
+ return arpURL.getQuery().equals(requestURL.getQuery());
}
}