Started work on the ARP matching functions
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 13 Dec 2002 22:49:41 +0000 (22:49 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 13 Dec 2002 22:49:41 +0000 (22:49 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@372 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/aa/arp/ArpTests.java
src/edu/internet2/middleware/shibboleth/aa/arp/MatchFunction.java
src/edu/internet2/middleware/shibboleth/aa/arp/MatchingException.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/aa/arp/provider/ExactSharMatchFunction.java
src/edu/internet2/middleware/shibboleth/aa/arp/provider/RegexMatchFunction.java
src/edu/internet2/middleware/shibboleth/aa/arp/provider/ResourceTreeMatchFunction.java

index 29cde33..16cc4da 100755 (executable)
@@ -51,6 +51,10 @@ package edu.internet2.middleware.shibboleth.aa.arp;
 
 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;
@@ -62,7 +66,7 @@ import org.xml.sax.InputSource;
 /**
  * Validation suite for <code>Arp</code> processing.
  * 
- * @author Walter Hoehn (wassa@columbia.edu)
+ * @ author Walter Hoehn(wassa@columbia.edu)
  */
 
 public class ArpTests extends TestCase {
@@ -119,6 +123,125 @@ 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() {
 
                /*
index 4748483..ca4a9fd 100755 (executable)
@@ -55,4 +55,12 @@ package edu.internet2.middleware.shibboleth.aa.arp;
  *
  * @author Walter Hoehn (wassa&#064;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;
+}
diff --git a/src/edu/internet2/middleware/shibboleth/aa/arp/MatchingException.java b/src/edu/internet2/middleware/shibboleth/aa/arp/MatchingException.java
new file mode 100755 (executable)
index 0000000..66392e0
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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&#064;columbia.edu)
+ */
+public class MatchingException extends ArpException {
+       public MatchingException(String message) {
+               super(message);
+       }
+}
index 5057e78..cfffb4a 100755 (executable)
 
 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.
@@ -57,10 +60,18 @@ import edu.internet2.middleware.shibboleth.aa.arp.MatchFunction;
  * @author Walter Hoehn (wassa&#064;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);
        }
 }
index ed6447e..2c1f19d 100755 (executable)
@@ -50,6 +50,7 @@
 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
@@ -59,9 +60,12 @@ import edu.internet2.middleware.shibboleth.aa.arp.MatchFunction;
  */
 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;
        }
 }
index 930786c..f3f48be 100755 (executable)
 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.
@@ -57,10 +63,104 @@ import edu.internet2.middleware.shibboleth.aa.arp.MatchFunction;
  * @author Walter Hoehn (wassa&#064;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());
        }
 }