Importing Handle Service code.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 28 May 2002 14:47:48 +0000 (14:47 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Tue, 28 May 2002 14:47:48 +0000 (14:47 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@2 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

37 files changed:
.classpath [new file with mode: 0644]
.project [new file with mode: 0644]
build.xml [new file with mode: 0755]
lib/jce-bc-src.jar [new file with mode: 0755]
lib/jug-src.jar [new file with mode: 0755]
lib/junit-src.jar [new file with mode: 0755]
lib/junit.jar [new file with mode: 0755]
lib/servlet-src.jar [new file with mode: 0755]
lib/servlet.jar [new file with mode: 0755]
lib/xerces.jar [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/common/AQHTest.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/common/AttributeQueryHandle.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/common/Base64.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/common/HandleException.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/hs/HandleService.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/hs/HandleServiceConfig.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/hs/HandleServiceException.java [new file with mode: 0755]
src/edu/internet2/middleware/shibboleth/hs/HsConfigDigester.java [new file with mode: 0755]
webApplication/WEB-INF/conf/log4j.properties [new file with mode: 0755]
webApplication/WEB-INF/conf/shibboleth.xml [new file with mode: 0755]
webApplication/WEB-INF/lib/commons-beanutils.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/commons-collections.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/commons-digester.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/jce-bc.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/jug-src.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/jug.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/log4j-1.2.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/shibboleth.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/struts.jar [new file with mode: 0644]
webApplication/WEB-INF/lib/xercesImpl.jar [new file with mode: 0644]
webApplication/WEB-INF/tlds/struts-bean.tld [new file with mode: 0755]
webApplication/WEB-INF/tlds/struts-logic.tld [new file with mode: 0755]
webApplication/WEB-INF/web.xml [new file with mode: 0755]
webApplication/hs.jsp [new file with mode: 0755]
webApplication/hserror.jsp [new file with mode: 0755]
webApplication/images/internet2.gif [new file with mode: 0755]
webApplication/main.css [new file with mode: 0755]

diff --git a/.classpath b/.classpath
new file mode 100644 (file)
index 0000000..b453034
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+    <classpathentry kind="var" path="JRE_LIB" rootpath="JRE_SRCROOT" sourcepath="JRE_SRC"/>
+    <classpathentry kind="src" path="source"/>
+    <classpathentry kind="lib" path="webApplication/WEB-INF/lib/shibboleth.jar"/>
+    <classpathentry kind="lib" path="buildlibs/servlet.jar" sourcepath="/ShibTest/buildlibs/servlet-src.jar"/>
+    <classpathentry kind="lib" path="buildlibs/xerces.jar"/>
+    <classpathentry kind="lib" path="webApplication/WEB-INF/lib/log4j-1.2.jar"/>
+    <classpathentry kind="lib" path="webApplication/WEB-INF/lib/commons-beanutils.jar"/>
+    <classpathentry kind="lib" path="webApplication/WEB-INF/lib/commons-collections.jar"/>
+    <classpathentry kind="lib" path="webApplication/WEB-INF/lib/commons-digester.jar"/>
+    <classpathentry kind="lib"
+        path="webApplication/WEB-INF/lib/jce-bc.jar" sourcepath="/ShibTest/buildlibs/jce-bc-src.jar"/>
+    <classpathentry kind="lib" path="buildlibs/junit.jar" sourcepath="/ShibTest/buildlibs/junit-src.jar"/>
+    <classpathentry kind="lib" path="webApplication/WEB-INF/lib/jug.jar"
+        rootpath="" sourcepath="/ShibTest/buildlibs/jug-src.jar"/>
+    <classpathentry kind="output" path="webApplication\WEB-INF\classes"/>
+</classpath>
diff --git a/.project b/.project
new file mode 100644 (file)
index 0000000..8ba8f1a
--- /dev/null
+++ b/.project
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>shibboleth</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.eclipse.team.cvs.core.cvsnature</nature>
+       </natures>
+</projectDescription>
diff --git a/build.xml b/build.xml
new file mode 100755 (executable)
index 0000000..49784fb
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,28 @@
+<project name="AA" default="dist" basedir=".">
+
+  <!-- set global properties for this build -->
+  <property name="src" value="."/>
+  <property name="build" value="build"/>
+  <property name="dist"  value="/var/tomcat3/webapps/"/>
+  <target name="init">
+    <!-- Create the time stamp -->
+    <tstamp/>
+    <!-- Create the build directory structure used by compile -->
+    <mkdir dir="${build}" />
+  </target>
+
+  <target name="compile" depends="init">
+    <!-- Compile the java code from ${src} into ${build} -->
+    <javac srcdir="${src}" destdir="${build}" classpath=".:/usr/java/jdk1.3.1_02/lib/jre:/usr/local/shib/lib/shibboleth.jar:/usr/local/shib/lib/xmlParserAPIs.jar:/usr/local/shib/lib/xercesImpl.jar:/var/tomcat3/lib/common/servlet.jar:/var/tomcat3/lib/common/mm.mysql-2.0.8-bin.jar"/>
+  </target>
+  <target name="dist" depends="compile">
+    <war warfile="shibb.war" webxml="web.xml">
+      <classes dir="build"/>
+    </war>
+    <copy file="shibb.war" tofile="${dist}/shibb.war">
+    </copy>
+  </target>
+
+</project>
+
diff --git a/lib/jce-bc-src.jar b/lib/jce-bc-src.jar
new file mode 100755 (executable)
index 0000000..007ecf9
Binary files /dev/null and b/lib/jce-bc-src.jar differ
diff --git a/lib/jug-src.jar b/lib/jug-src.jar
new file mode 100755 (executable)
index 0000000..8a6e0ef
Binary files /dev/null and b/lib/jug-src.jar differ
diff --git a/lib/junit-src.jar b/lib/junit-src.jar
new file mode 100755 (executable)
index 0000000..2a8c7ce
Binary files /dev/null and b/lib/junit-src.jar differ
diff --git a/lib/junit.jar b/lib/junit.jar
new file mode 100755 (executable)
index 0000000..914a5cf
Binary files /dev/null and b/lib/junit.jar differ
diff --git a/lib/servlet-src.jar b/lib/servlet-src.jar
new file mode 100755 (executable)
index 0000000..ee73cef
Binary files /dev/null and b/lib/servlet-src.jar differ
diff --git a/lib/servlet.jar b/lib/servlet.jar
new file mode 100755 (executable)
index 0000000..3f7648f
Binary files /dev/null and b/lib/servlet.jar differ
diff --git a/lib/xerces.jar b/lib/xerces.jar
new file mode 100755 (executable)
index 0000000..b5a5fde
Binary files /dev/null and b/lib/xerces.jar differ
diff --git a/src/edu/internet2/middleware/shibboleth/common/AQHTest.java b/src/edu/internet2/middleware/shibboleth/common/AQHTest.java
new file mode 100755 (executable)
index 0000000..69b3401
--- /dev/null
@@ -0,0 +1,110 @@
+package edu.internet2.middleware.shibboleth.common;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.Security;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import junit.framework.TestCase;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+/**
+ * Exercises the <code>AttributeQueryHandle</code>
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ *
+ */
+
+public class AQHTest extends TestCase {
+       protected SecretKey goodKey;
+       public AQHTest(String name) {
+               super(name);
+       }
+       public static void main(String args[]) {
+               junit.textui.TestRunner.run(AQHTest.class);
+       }
+       protected void setUp() {
+               try {
+                       Security.addProvider(new BouncyCastleProvider());
+                       KeyGenerator gen = KeyGenerator.getInstance("DESede");
+                       gen.init(new SecureRandom());
+                       goodKey = gen.generateKey();
+               } catch (NoSuchAlgorithmException e) {
+                       fail("Could not generate fixture (secret key)");
+               }
+       }
+       /**
+        * Tests the basic, creation, serialization, and unmarshalling of the <code>AttributeQueryHandle</code>
+        */
+       public void testAQH() {
+               try {
+
+                       //Create an AQH
+                       AttributeQueryHandle originalAQH =
+                               new AttributeQueryHandle("Walter", goodKey, 300000l);
+
+                       //Ensure that a unique id was generated 
+                       assertNotNull(
+                               "No unique id generated for handle",
+                               originalAQH.getHandleID());
+                       String cacheHandleID = originalAQH.getHandleID();
+
+                       //Ensure that the principal was set correctly
+                       assertEquals(
+                               "Principal incorrect",
+                               "Walter",
+                               originalAQH.getPrincipal());
+
+                       //Test to see that the handle has not expired   
+                       //Hopefull this doesn't take more than 5 mintues to run :-)
+                       assertTrue(
+                               "AttributeQueryHandle unexpectedly expired.",
+                               (!originalAQH.isExpired()));
+
+                       //Create a new AQH from the serialized first AQH
+                       AttributeQueryHandle secondAQH =
+                               new AttributeQueryHandle(originalAQH.serialize(), goodKey);
+
+                       //Ensure that the principal was set correctly
+                       assertEquals(
+                               "Principal incorrect",
+                               "Walter",
+                               secondAQH.getPrincipal());
+
+                       //Test to see that the handle has not expired   
+                       //Hopefull this doesn't take more than 5 mintues to run :-)
+                       assertTrue(
+                               "AttributeQueryHandle unexpectedly expired.",
+                               (!secondAQH.isExpired()));
+
+                       //Make sure that the handle id matches that of the first object
+                       assertEquals(
+                               "Improper unmarshalling of unique handle id",
+                               cacheHandleID,
+                               secondAQH.getHandleID());
+
+               } catch (HandleException e) {
+                       fail("Failed to create AttributeQueryHandle" + e);
+               }
+       }
+
+       /**
+        * Ensure that <code>AttributeQueryHandle</code> objects expire correctly
+        */
+
+       public void testExpiration() {
+
+               try {
+                       AttributeQueryHandle aqh =
+                               new AttributeQueryHandle("Walter", goodKey, 1l);
+                       Thread.sleep(2);
+                       assertTrue(
+                               "AttributeQueryHandle failed to expire appropriately",
+                               aqh.isExpired());
+               } catch (InterruptedException e) {
+               } catch (HandleException e) {
+                       fail("Failed to create AttributeQueryHandle" + e);
+               }
+
+       }
+}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/common/AttributeQueryHandle.java b/src/edu/internet2/middleware/shibboleth/common/AttributeQueryHandle.java
new file mode 100755 (executable)
index 0000000..ae53c55
--- /dev/null
@@ -0,0 +1,127 @@
+package edu.internet2.middleware.shibboleth.common;
+
+import java.util.StringTokenizer;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import org.doomdark.uuid.UUIDGenerator;
+
+/**
+ * A Shibboleth Attribute Query Handle.
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ *
+ */
+
+public class AttributeQueryHandle {
+
+       private String principal;
+       private long creationTime;
+       private long expirationTime;
+       private byte[] cipherTextHandle;
+       private String handleID;
+
+       /**
+        * Unmarshalls an <code>AttributeQueryHandle</code> based on the results of the serialize() method
+        * of an existing <code>AttributeQueryHandle</code>.  Requires a key identical to the one used
+        * in the creation of the original <code>AttributeQueryHandle</code>.
+        * 
+        */
+
+       public AttributeQueryHandle(String handle, SecretKey key)
+               throws HandleException {
+
+               try {
+                       Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
+                       cipher.init(Cipher.DECRYPT_MODE, key);
+                       StringTokenizer tokenizer =
+                               new StringTokenizer(
+                                       new String(cipher.doFinal(Base64.decode(handle))),
+                                       "||",
+                                       false);
+                       principal = tokenizer.nextToken();
+                       expirationTime = new Long(tokenizer.nextToken()).longValue();
+                       handleID = tokenizer.nextToken();
+               } catch (Exception e) {
+                       throw new HandleException("Error unmarshalling handle: " + e);
+               }
+
+       }
+
+       /**
+        * Creates a new <code>AttributeQueryHandle</code>
+        * @param principal <code>String</code> representation of user that the handle should reference
+        * @param ticketLength Time in milliseconds for which the handle should be valid
+        * 
+        */
+
+       public AttributeQueryHandle(
+               String principal,
+               SecretKey key,
+               long ticketLength)
+               throws HandleException {
+                       
+               UUIDGenerator uuidGen = UUIDGenerator.getInstance();
+//Need to create an actual UUID here
+               handleID = "12345";
+               this.principal = principal;
+               this.creationTime = System.currentTimeMillis();
+               this.expirationTime = creationTime + ticketLength;
+
+               try {
+                       Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
+                       cipher.init(Cipher.ENCRYPT_MODE, key);
+                       cipherTextHandle =
+                               cipher.doFinal(
+                                       (principal + "||" + expirationTime + "||" + handleID)
+                                               .getBytes());
+
+               } catch (Exception e) {
+                       throw new HandleException("Error creating handle: " + e);
+
+               }
+
+       }
+
+       /**
+        * Returns a <code>String</code> representation of the user that the handle references.
+        * @return Returns a String
+        */
+
+       public String getPrincipal() {
+               return principal;
+       }
+
+       /**
+        * Returns a <code>String</code> of ciphertext representing the <code>AttributeQueryHandle</code> instance.
+        * @return Returns a String
+        */
+
+       public String serialize() {
+
+               return new String(Base64.encode(cipherTextHandle));
+       }
+
+       /**
+        * Boolean result indicates whether the validity of this <code>AttributeQueryHandle</code> 
+        * has lapsed.
+        */
+
+       public boolean isExpired() {
+
+               if (System.currentTimeMillis() > expirationTime) {
+                       return true;
+               } else {
+                       return false;
+               }
+
+       }
+
+       /**
+        * Returns a <code>String</code> representation of the unique identifier for this handle.
+        */
+       public String getHandleID() {
+               return handleID;
+       }
+
+}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/common/Base64.java b/src/edu/internet2/middleware/shibboleth/common/Base64.java
new file mode 100755 (executable)
index 0000000..356457e
--- /dev/null
@@ -0,0 +1,277 @@
+package edu.internet2.middleware.shibboleth.common;
+
+/**
+ * The Bouncy Castle License
+ *
+ * Copyright (c) 2000 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+ * <p>
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
+ * and associated documentation files (the "Software"), to deal in the Software without restriction, 
+ * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+ * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ * <p>
+ * The above copyright notice and this permission notice shall be included in all copies or substantial
+ * portions of the Software.
+ * <p>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+
+public class Base64
+{
+       private static final byte[] encodingTable =
+               {
+                   (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+            (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+            (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+            (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+                   (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+            (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+            (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+            (byte)'v',
+                   (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+                   (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+            (byte)'7', (byte)'8', (byte)'9',
+                   (byte)'+', (byte)'/'
+               };
+
+       /**
+        * encode the input data producong a base 64 encoded byte array.
+        *
+        * @return a byte array containing the base 64 encoded data.
+        */
+       public static byte[] encode(
+               byte[]  data)
+       {
+               byte[]  bytes;
+               
+               int modulus = data.length % 3;
+               if (modulus == 0)
+               {
+                       bytes = new byte[4 * data.length / 3];
+               }
+               else
+               {
+                       bytes = new byte[4 * ((data.length / 3) + 1)];
+               }
+
+        int dataLength = (data.length - modulus);
+               int a1, a2, a3;
+               for (int i = 0, j = 0; i < dataLength; i += 3, j += 4)
+               {
+                       a1 = data[i] & 0xff;
+                       a2 = data[i + 1] & 0xff;
+                       a3 = data[i + 2] & 0xff;
+
+                       bytes[j] = encodingTable[(a1 >>> 2) & 0x3f];
+                       bytes[j + 1] = encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f];
+                       bytes[j + 2] = encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f];
+                       bytes[j + 3] = encodingTable[a3 & 0x3f];
+               }
+
+               /*
+                * process the tail end.
+                */
+               int     b1, b2, b3;
+               int     d1, d2;
+
+               switch (modulus)
+               {
+               case 0:         /* nothing left to do */
+                       break;
+               case 1:
+                       d1 = data[data.length - 1] & 0xff;
+                       b1 = (d1 >>> 2) & 0x3f;
+                       b2 = (d1 << 4) & 0x3f;
+
+                       bytes[bytes.length - 4] = encodingTable[b1];
+                       bytes[bytes.length - 3] = encodingTable[b2];
+                       bytes[bytes.length - 2] = (byte)'=';
+                       bytes[bytes.length - 1] = (byte)'=';
+                       break;
+               case 2:
+                       d1 = data[data.length - 2] & 0xff;
+                       d2 = data[data.length - 1] & 0xff;
+
+                       b1 = (d1 >>> 2) & 0x3f;
+                       b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f;
+                       b3 = (d2 << 2) & 0x3f;
+
+                       bytes[bytes.length - 4] = encodingTable[b1];
+                       bytes[bytes.length - 3] = encodingTable[b2];
+                       bytes[bytes.length - 2] = encodingTable[b3];
+                       bytes[bytes.length - 1] = (byte)'=';
+                       break;
+               }
+
+               return bytes;
+       }
+
+       /*
+        * set up the decoding table.
+        */
+       private static final byte[] decodingTable;
+
+       static
+       {
+               decodingTable = new byte[128];
+
+               for (int i = 'A'; i <= 'Z'; i++)
+               {
+                       decodingTable[i] = (byte)(i - 'A');
+               }
+
+               for (int i = 'a'; i <= 'z'; i++)
+               {
+                       decodingTable[i] = (byte)(i - 'a' + 26);
+               }
+
+               for (int i = '0'; i <= '9'; i++)
+               {
+                       decodingTable[i] = (byte)(i - '0' + 52);
+               }
+
+               decodingTable['+'] = 62;
+               decodingTable['/'] = 63;
+       }
+
+       /**
+        * decode the base 64 encoded input data.
+        *
+        * @return a byte array representing the decoded data.
+        */
+       public static byte[] decode(
+               byte[]  data)
+       {
+               byte[]  bytes;
+               byte    b1, b2, b3, b4;
+
+               if (data[data.length - 2] == '=')
+               {
+                       bytes = new byte[(((data.length / 4) - 1) * 3) + 1];
+               }
+               else if (data[data.length - 1] == '=')
+               {
+                       bytes = new byte[(((data.length / 4) - 1) * 3) + 2];
+               }
+               else
+               {
+                       bytes = new byte[((data.length / 4) * 3)];
+               }
+
+               for (int i = 0, j = 0; i < data.length - 4; i += 4, j += 3)
+               {
+                       b1 = decodingTable[data[i]];
+                       b2 = decodingTable[data[i + 1]];
+                       b3 = decodingTable[data[i + 2]];
+                       b4 = decodingTable[data[i + 3]];
+
+                       bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
+                       bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
+                       bytes[j + 2] = (byte)((b3 << 6) | b4);
+               }
+
+               if (data[data.length - 2] == '=')
+               {
+                       b1 = decodingTable[data[data.length - 4]];
+                       b2 = decodingTable[data[data.length - 3]];
+
+                       bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
+               }
+               else if (data[data.length - 1] == '=')
+               {
+                       b1 = decodingTable[data[data.length - 4]];
+                       b2 = decodingTable[data[data.length - 3]];
+                       b3 = decodingTable[data[data.length - 2]];
+
+                       bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
+                       bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
+               }
+               else
+               {
+                       b1 = decodingTable[data[data.length - 4]];
+                       b2 = decodingTable[data[data.length - 3]];
+                       b3 = decodingTable[data[data.length - 2]];
+                       b4 = decodingTable[data[data.length - 1]];
+
+                       bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
+                       bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
+                       bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
+               }
+
+               return bytes;
+       }
+
+       /**
+        * decode the base 64 encoded String data.
+        *
+        * @return a byte array representing the decoded data.
+        */
+       public static byte[] decode(
+               String  data)
+       {
+               byte[]  bytes;
+               byte    b1, b2, b3, b4;
+
+               if (data.charAt(data.length() - 2) == '=')
+               {
+                       bytes = new byte[(((data.length() / 4) - 1) * 3) + 1];
+               }
+               else if (data.charAt(data.length() - 1) == '=')
+               {
+                       bytes = new byte[(((data.length() / 4) - 1) * 3) + 2];
+               }
+               else
+               {
+                       bytes = new byte[((data.length() / 4) * 3)];
+               }
+
+               for (int i = 0, j = 0; i < data.length() - 4; i += 4, j += 3)
+               {
+                       b1 = decodingTable[data.charAt(i)];
+                       b2 = decodingTable[data.charAt(i + 1)];
+                       b3 = decodingTable[data.charAt(i + 2)];
+                       b4 = decodingTable[data.charAt(i + 3)];
+
+                       bytes[j] = (byte)((b1 << 2) | (b2 >> 4));
+                       bytes[j + 1] = (byte)((b2 << 4) | (b3 >> 2));
+                       bytes[j + 2] = (byte)((b3 << 6) | b4);
+               }
+
+               if (data.charAt(data.length() - 2) == '=')
+               {
+                       b1 = decodingTable[data.charAt(data.length() - 4)];
+                       b2 = decodingTable[data.charAt(data.length() - 3)];
+
+                       bytes[bytes.length - 1] = (byte)((b1 << 2) | (b2 >> 4));
+               }
+               else if (data.charAt(data.length() - 1) == '=')
+               {
+                       b1 = decodingTable[data.charAt(data.length() - 4)];
+                       b2 = decodingTable[data.charAt(data.length() - 3)];
+                       b3 = decodingTable[data.charAt(data.length() - 2)];
+
+                       bytes[bytes.length - 2] = (byte)((b1 << 2) | (b2 >> 4));
+                       bytes[bytes.length - 1] = (byte)((b2 << 4) | (b3 >> 2));
+               }
+               else
+               {
+                       b1 = decodingTable[data.charAt(data.length() - 4)];
+                       b2 = decodingTable[data.charAt(data.length() - 3)];
+                       b3 = decodingTable[data.charAt(data.length() - 2)];
+                       b4 = decodingTable[data.charAt(data.length() - 1)];
+
+                       bytes[bytes.length - 3] = (byte)((b1 << 2) | (b2 >> 4));
+                       bytes[bytes.length - 2] = (byte)((b2 << 4) | (b3 >> 2));
+                       bytes[bytes.length - 1] = (byte)((b3 << 6) | b4);
+               }
+
+               return bytes;
+       }
+}
diff --git a/src/edu/internet2/middleware/shibboleth/common/HandleException.java b/src/edu/internet2/middleware/shibboleth/common/HandleException.java
new file mode 100755 (executable)
index 0000000..cd59ae6
--- /dev/null
@@ -0,0 +1,29 @@
+package edu.internet2.middleware.shibboleth.common;
+
+
+/**
+ * 
+ * Signals that an error has occurred while creating
+ * a shibboleth AQH (Attribute Query Handle)
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ *
+ */
+
+public class HandleException extends Exception {
+
+       /**
+        * Constructs a <code>HandleException</code> with the specified detail
+        * message. The error message string <code>s</code> can later be
+        * retrieved by the <code>{@link java.lang.Throwable#getMessage}</code>
+        * method of class <code>java.lang.Throwable</code>.
+        *
+        * @param   s   the detail message.
+        */
+
+       public HandleException(String message) {
+
+               super(message);
+       }
+
+}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/hs/HandleService.java b/src/edu/internet2/middleware/shibboleth/hs/HandleService.java
new file mode 100755 (executable)
index 0000000..2ef5c62
--- /dev/null
@@ -0,0 +1,307 @@
+package edu.internet2.middleware.shibboleth.hs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.Security;
+import java.util.Date;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESedeKeySpec;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.xml.sax.SAXException;
+
+import edu.internet2.middleware.shibboleth.AABindingInfo;
+import edu.internet2.middleware.shibboleth.Policies;
+import edu.internet2.middleware.shibboleth.SAMLAuthenticationAssertionFactory;
+import edu.internet2.middleware.shibboleth.SAMLException;
+import edu.internet2.middleware.shibboleth.common.AttributeQueryHandle;
+import edu.internet2.middleware.shibboleth.common.Base64;
+import edu.internet2.middleware.shibboleth.common.HandleException;
+
+/**
+ * 
+ * A servlet implementation of the Shibboleth Handle Service.  Accepts 
+ * Shibboleth Attribute Query Handle Requests via HTTP GET and generates 
+ * SAML authN assertions containing an opaque user handle.  These assertions are 
+ * embedded in an HTML that auto-POSTs to the referring SHIRE.
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ *
+ */
+
+public class HandleService extends HttpServlet {
+
+       private static Logger log = Logger.getLogger(HandleService.class.getName());
+       private SAMLAuthenticationAssertionFactory factory;
+       private String hsConfigFileLocation;
+       private String log4jConfigFileLocation;
+       private SecretKey key;
+
+       /**
+        * @see GenericServlet#init()
+        */
+
+       public void init() throws ServletException {
+
+               super.init();
+               loadInitParams();
+               initLogger();
+               initConfig();
+               initViewConfig();
+               initSecretKey();
+               initAuthNFactory();
+       }
+       
+       /**
+        * Initializes symmetric key for use in AQH creation
+        */
+
+       private void initSecretKey() throws ServletException {
+
+               try {
+                       
+//Change this to work with any JCE
+                       Security.addProvider(new BouncyCastleProvider());
+                       SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
+                       DESedeKeySpec keySpec =
+                               new DESedeKeySpec(Base64.decode(HandleServiceConfig.getSecretKey()));
+                       key = keyFactory.generateSecret(keySpec);
+               } catch (Exception t) {
+                       log.fatal("Error reading Secret Key from configuration.", t);
+                       throw new ServletException("Error reading Key from configuration.");
+               }
+
+       }
+
+       /**
+        * Retrieves location of HS configuration files from the servlet configuration.
+        */
+
+       private void loadInitParams() {
+
+               hsConfigFileLocation = getServletConfig().getInitParameter("HSConfigFileLocation");
+               if (hsConfigFileLocation == null) {
+                       hsConfigFileLocation = "/WEB-INF/conf/shibboleth.xml";
+               }
+               log4jConfigFileLocation = getServletConfig().getInitParameter("log4jConfigFileLocation");
+               if (log4jConfigFileLocation == null) {
+                       log4jConfigFileLocation = "/WEB-INF/conf/log4j.properties";
+               }
+
+       }
+
+       /**
+        * Loads HS configuration.
+        */
+
+       private void initConfig() throws ServletException {
+
+               InputStream is = getServletContext().getResourceAsStream(hsConfigFileLocation);
+               HsConfigDigester digester = new HsConfigDigester();
+               try {
+                       digester.parse(is);
+               } catch (SAXException se) {
+                       log.fatal("Error parsing HS configuration file.", se);
+                       throw new ServletException("Error parsing HS configuration file.", se);
+               } catch (IOException ioe) {
+                       log.fatal("Error reading HS configuration file.", ioe);
+                       throw new ServletException("Error reading HS configuration file.", ioe);
+               }
+       }
+
+       /**
+        * Starts up Log4J.
+        */
+
+       private void initLogger() {
+
+               PropertyConfigurator.configure(
+                       getServletContext().getRealPath("/") + log4jConfigFileLocation);
+
+       }
+
+       /**
+        * Places configuration parameters in the <code>ServletContext</code> so that they may 
+        * be retreived by view components.
+        */
+
+       private void initViewConfig() {
+               getServletContext().setAttribute(
+                       "hs_supportContact",
+                       HandleServiceConfig.getSupportContact());
+               getServletContext().setAttribute("hs_logoLocation", HandleServiceConfig.getLogoLocation());
+               getServletContext().setAttribute("hs_helpText", HandleServiceConfig.getHelpText());
+               getServletContext().setAttribute(
+                       "hs_detailedHelpURL",
+                       HandleServiceConfig.getDetailedHelpURL());
+               String hsLocation = HandleServiceConfig.getLocation();
+               if (hsLocation == null) {
+                       hsLocation = "HS";
+               }
+               getServletContext().setAttribute("hs_location", hsLocation);
+       }
+
+       /**
+        * Initializes SAML AuthN Factory
+        */
+
+       private void initAuthNFactory() throws ServletException {
+               try {
+                       AABindingInfo[] binfo = new AABindingInfo[1];
+                       binfo[0] =
+                               new AABindingInfo(AABindingInfo.SAML_SOAP_HTTPS, HandleServiceConfig.getAaURL());
+                       String[] policies = { Policies.POLICY_URI_CLUBSHIB };
+                       factory =
+                               SAMLAuthenticationAssertionFactory.getInstance(
+                                       policies,
+                                       HandleServiceConfig.getIssuer(),
+                                       HandleServiceConfig.getDomain(),
+                                       binfo,
+                                       null,
+                                       null);
+
+               } catch (SAMLException se) {
+                       log.fatal("Error initializing SAML library: ", se);
+                       throw new ServletException("Error initializing SAML library: ", se);
+               }
+       }
+
+       /**
+        * @see HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
+        */
+
+       public void doGet(HttpServletRequest req, HttpServletResponse resp)
+               throws ServletException, IOException {
+
+               try {
+                       validateRequestParameters(req);
+                       req.setAttribute("shire", req.getParameter("shire"));
+                       req.setAttribute("target", req.getParameter("target"));
+                       log.info("Generating assertion...");
+                       byte[] assertion =
+                               generateAssertion(
+                                       req.getParameter("shire"),
+                                       req.getRemoteAddr(),
+                                       req.getRemoteUser(),
+                                       req.getAuthType());
+                       log.info("Assertion Generated!");
+                       log.debug("Assertion: " + new String(Base64.decode(assertion)));
+                       handleForm(req, resp, assertion);
+               } catch (HandleServiceException e) {
+                       handleError(req, resp, e);
+               }
+
+       }
+
+       /**
+        * Deals with HS runtime exceptions.  Logs errors locally and then 
+        * formats them for output to user.
+        * 
+        * @param e The Exception to be handled
+        */
+
+       private void handleError(HttpServletRequest req, HttpServletResponse res, Exception e) {
+
+               log.info("Handle Service Failure: " + e);
+
+               req.setAttribute("errorText", e.toString());
+               RequestDispatcher rd = req.getRequestDispatcher("/hserror.jsp");
+
+               try {
+                       rd.forward(req, res);
+               } catch (IOException ioe) {
+                       log.error("Problem trying to display Handle Service error page: " + ioe);
+               } catch (ServletException se) {
+                       log.error("Problem trying to display Handle Service error page: " + se);
+               }
+       }
+
+       /**
+        * Method for auto-POSTing a Base64 encoded SAML assertion.
+        * 
+        * @param assertion Base64 encoded SAML authN assertion
+        */
+
+       private void handleForm(HttpServletRequest req, HttpServletResponse res, byte[] assertion)
+               throws HandleServiceException {
+
+               try {
+                       //Hardcoded to ASCII to ensure Base64 encoding compatibility
+                       req.setAttribute("assertion", new String(assertion, "ASCII"));
+                       RequestDispatcher rd = req.getRequestDispatcher("/hs.jsp");
+                       log.info("POSTing assertion to SHIRE.");
+                       rd.forward(req, res);
+               } catch (IOException ioe) {
+                       throw new HandleServiceException("Problem displaying Handle Service UI." + ioe);
+               } catch (ServletException se) {
+                       throw new HandleServiceException("Problem displaying Handle Service UI." + se);
+               }
+       }
+
+       /**
+        * Generates a new <code>AttributeQueryHandle</code> and includes it in a 
+        * <code>SAMLAuthenticationAssertion</code>.
+        */
+
+       private byte[] generateAssertion(
+               String shireURL,
+               String clientAddress,
+               String remoteUser,
+               String authType)
+               throws HandleServiceException {
+               try {
+
+                       AttributeQueryHandle aqh =
+                               new AttributeQueryHandle(
+                                       remoteUser,
+                                       key,
+                                       Long.parseLong(HandleServiceConfig.getValidityPeriod()));
+
+                       log.info("Acquired Handle: " + aqh.getHandleID());
+
+                       return factory
+                               .getAssertion(aqh.serialize(), shireURL, clientAddress, authType, new Date(), null)
+                               .toBase64();
+
+               } catch (SAMLException se) {
+                       throw new HandleServiceException("Error creating SAML assertion: " + se);
+               } catch (IOException ioe) {
+                       throw new HandleServiceException("Error creating SAML assertion: " + ioe);
+               } catch (HandleException he) {
+                       throw new HandleServiceException("Error creating User Handle: " + he);
+               }
+       }
+
+       /**
+        * Ensures that <code>HttpServletRequest</code> contains all of the parameters necessary
+        * for generation of an <code>AttributeQueryHandle</code>.
+        */
+
+       private void validateRequestParameters(HttpServletRequest req) throws HandleServiceException {
+
+               if ((req.getParameter("shire") == null) || (req.getParameter("shire").equals(""))) {
+                       throw new HandleServiceException("Invalid data from SHIRE: No acceptance URL received.");
+               }
+               if ((req.getParameter("target") == null) || (req.getParameter("target").equals(""))) {
+                       throw new HandleServiceException("Invalid data from SHIRE: No target URL received.");
+               }
+               if ((req.getRemoteUser() == null) || (req.getRemoteUser().equals(""))) {
+                       throw new HandleServiceException("No authentication received from webserver.");
+               }
+               if ((req.getAuthType() == null) || (req.getAuthType().equals(""))) {
+                       throw new HandleServiceException("Unable to ascertain authentication type.");
+               }
+               if ((req.getRemoteAddr() == null) || (req.getRemoteAddr().equals(""))) {
+                       throw new HandleServiceException("Unable to ascertain client address.");
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/hs/HandleServiceConfig.java b/src/edu/internet2/middleware/shibboleth/hs/HandleServiceConfig.java
new file mode 100755 (executable)
index 0000000..ddff8ed
--- /dev/null
@@ -0,0 +1,218 @@
+package edu.internet2.middleware.shibboleth.hs;
+
+
+
+/**
+ * Class used by the  WAYF service to determine runtime options.  
+ * Most of the fields of this class should have reasonable defaults.
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ */
+
+public class HandleServiceConfig {
+
+       private static String logoLocation = "images/internet2.gif";
+       private static String supportContact = "mailto:shib-support@internet2.org";
+       private static String location;
+       private static String helpText =
+               "In order to fulfill the request for the web"
+                       + " resource you have just chosen, information must be sent from your home institution to the "
+                       + "provider of the resource.  The web resource should load automatically.  If it does not load within "
+                       + "five seconds, click on the Transmit button.";
+       private static String detailedHelpURL = "http://blah";
+       private static String handleRepositoryImplementation =
+               "edu.internet2.middleware.shibboleth.common.provider.MemoryHandleRepository";
+       private static String validityPeriod = "1400000";
+       private static String domain = "internet2.edu";
+       private static String issuer = "shib2.internet2.edu";
+       private static String aaURL = "https://shib2.internet2.edu/shibb/servlet/AAServlet";
+       private static String secretKey;
+
+       /**
+        * Constructor for HandleServiceConfig.
+        */
+       public HandleServiceConfig() {
+               super();
+       }
+
+       /**
+        * Gets the logoLocation.
+        * @return Returns a String
+        */
+       public static String getLogoLocation() {
+               return logoLocation;
+       }
+
+       /**
+        * Sets the logoLocation.
+        * @param logoLocation The logoLocation to set
+        */
+       public static void setLogoLocation(String logoLocation) {
+               HandleServiceConfig.logoLocation = logoLocation;
+       }
+
+       /**
+        * Gets the supportContact.
+        * @return Returns a String
+        */
+       public static String getSupportContact() {
+               return supportContact;
+       }
+
+       /**
+        * Sets the supportContact.
+        * @param supportContact The supportContact to set
+        */
+       public static void setSupportContact(String supportContact) {
+               HandleServiceConfig.supportContact = supportContact;
+       }
+
+       /**
+        * Gets the helpText.
+        * @return Returns a String
+        */
+       public static String getHelpText() {
+               return helpText;
+       }
+
+       /**
+        * Sets the helpText.
+        * @param helpText The helpText to set
+        */
+       public static void setHelpText(String hs_helpText) {
+               HandleServiceConfig.helpText = hs_helpText;
+       }
+
+       
+       
+       /**
+        * Gets the handleRepositoryImplementation.
+        * @return Returns a String
+        */
+       public static String getHandleRepositoryImplementation() {
+               return handleRepositoryImplementation;
+       }
+
+       /**
+        * Sets the handleRepositoryImplementation.
+        * @param handleRepositoryImplementation The handleRepositoryImplementation to set
+        */
+       public static void setHandleRepositoryImplementation(String handleRepositoryImplementation) {
+               HandleServiceConfig.handleRepositoryImplementation = handleRepositoryImplementation;
+       }
+
+       /**
+        * Gets the detailedHelpURL.
+        * @return Returns a String
+        */
+       public static String getDetailedHelpURL() {
+               return detailedHelpURL;
+       }
+
+       /**
+        * Sets the detailedHelpURL.
+        * @param detailedHelpURL The detailedHelpURL to set
+        */
+       public static void setDetailedHelpURL(String hs_detailedHelpURL) {
+               HandleServiceConfig.detailedHelpURL = hs_detailedHelpURL;
+       }
+
+       /**
+        * Gets the location.
+        * @return Returns a String
+        */
+       public static String getLocation() {
+               return location;
+       }
+
+       /**
+        * Sets the location.
+        * @param location The location to set
+        */
+       public static void setLocation(String hs_location) {
+               HandleServiceConfig.location = hs_location;
+       }
+
+       /**
+        * Gets the ticket.
+        * @return Returns a String
+        */
+       public static String getValidityPeriod() {
+               return validityPeriod;
+       }
+
+       /**
+        * Sets the ticket.
+        * @param ticket The ticket to set
+        */
+       public static void setValidityPeriod(String validityPeriod) {
+               HandleServiceConfig.validityPeriod = validityPeriod;
+       }
+
+       /**
+        * Gets the domain.
+        * @return Returns a String
+        */
+       public static String getDomain() {
+               return domain;
+       }
+
+       /**
+        * Sets the domain.
+        * @param domain The domain to set
+        */
+       public static void setDomain(String domain) {
+               HandleServiceConfig.domain = domain;
+       }
+
+       /**
+        * Gets the issuer.
+        * @return Returns a String
+        */
+       public static String getIssuer() {
+               return issuer;
+       }
+
+       /**
+        * Sets the issuer.
+        * @param issuer The issuer to set
+        */
+       public static void setIssuer(String issuer) {
+               HandleServiceConfig.issuer = issuer;
+       }
+
+       /**
+        * Gets the aaURL.
+        * @return Returns a String
+        */
+       public static String getAaURL() {
+               return aaURL;
+       }
+
+       /**
+        * Sets the aaURL.
+        * @param aaURL The aaURL to set
+        */
+       public static void setAaURL(String aaURL) {
+               HandleServiceConfig.aaURL = aaURL;
+       }
+
+       /**
+        * Gets the secretKey.  Can only be retrieved one time.
+        * @return Returns a String
+        */
+       public static String getSecretKey() {
+               String cacheKey = secretKey;
+               secretKey = null;
+               return cacheKey;
+       }
+
+       /**
+        * Sets the secretKey.
+        * @param secretKey The secretKey to set
+        */
+       public static void setSecretKey(String secretKey) {
+               HandleServiceConfig.secretKey = secretKey;
+       }
+
+}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/hs/HandleServiceException.java b/src/edu/internet2/middleware/shibboleth/hs/HandleServiceException.java
new file mode 100755 (executable)
index 0000000..bb619d8
--- /dev/null
@@ -0,0 +1,28 @@
+package edu.internet2.middleware.shibboleth.hs;
+
+/**
+ * 
+ * Signals that an error has occurred while processing a 
+ * Shibboleth AQHR (Attribute Query Handle Request)
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ *
+ */
+
+public class HandleServiceException extends Exception {
+
+       /**
+        * Constructs a <code>HandleServiceException</code> with the specified detail
+        * message. The error message string <code>s</code> can later be
+        * retrieved by the <code>{@link java.lang.Throwable#getMessage}</code>
+        * method of class <code>java.lang.Throwable</code>.
+        *
+        * @param   s   the detail message.
+        */
+
+       public HandleServiceException(String message) {
+
+               super(message);
+       }
+
+}
\ No newline at end of file
diff --git a/src/edu/internet2/middleware/shibboleth/hs/HsConfigDigester.java b/src/edu/internet2/middleware/shibboleth/hs/HsConfigDigester.java
new file mode 100755 (executable)
index 0000000..fc77a9c
--- /dev/null
@@ -0,0 +1,81 @@
+package edu.internet2.middleware.shibboleth.hs;
+
+import javax.xml.parsers.SAXParser;
+import org.apache.commons.digester.Digester;
+import org.xml.sax.XMLReader;
+
+/**
+ * This class is a jakarta Digester style parser for the HS configuration file.  
+ * It should populate the HandleServiceConfig object during HS initilization. NOTE: It is
+ * assumed that the mutators of this class will only be called by a single thread during
+ * servlet initilization only (NOT thread safe)
+ * 
+ * @author Walter Hoehn wassa&#064;columbia.edu
+ */
+
+public class HsConfigDigester extends Digester {
+
+    protected String hsConfigClass = "edu.internet2.middleware.shibboleth.hs.HandleServiceConfig";
+    private boolean configured = false;
+
+    /**
+     * Constructor for ShibbolethConfigDigester.
+     */
+    public HsConfigDigester() {
+        super();
+        configure();
+    }
+
+    /**
+     * Constructor for ShibbolethConfigDigester.
+     * @param parser
+     */
+    public HsConfigDigester(SAXParser parser) {
+        super(parser);
+        configure();
+    }
+
+    /**
+     * Constructor for ShibbolethConfigDigester.
+     * @param reader
+     */
+    public HsConfigDigester(XMLReader reader) {
+        super(reader);
+        configure();
+    }
+
+    
+    
+    protected void configure() {
+
+        if (configured == true) {
+            return;
+        }
+        addObjectCreate("ShibbolethConfig", hsConfigClass);
+        addSetProperties("ShibbolethConfig/HsConfig");
+        addCallMethod("ShibbolethConfig/HsConfig/HelpText", "setHelpText", 0);
+        addCallMethod("ShibbolethConfig/HsConfig/SecretKey", "setSecretKey", 0);
+
+        configured = true;
+
+    }
+
+    
+    
+    /**
+     * Gets the wayfDataClass.
+     * @return Returns a String
+     */
+    public String getHsConfigClass() {
+        return hsConfigClass;
+    }
+
+    /**
+     * Sets the wayfDataClass.
+     * @param wayfDataClass The wayfDataClass to set
+     */
+    public void setHsConfigClass(String wayfDataClass) {
+        this.hsConfigClass = wayfDataClass;
+    }
+
+}
diff --git a/webApplication/WEB-INF/conf/log4j.properties b/webApplication/WEB-INF/conf/log4j.properties
new file mode 100755 (executable)
index 0000000..6b2b6b0
--- /dev/null
@@ -0,0 +1,3 @@
+log4j.rootCategory=DEBUG, dest1
+log4j.appender.dest1=org.apache.log4j.ConsoleAppender
+log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
\ No newline at end of file
diff --git a/webApplication/WEB-INF/conf/shibboleth.xml b/webApplication/WEB-INF/conf/shibboleth.xml
new file mode 100755 (executable)
index 0000000..036254e
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<ShibbolethConfig>
+
+       <CommonConfig>
+       <OriginSet name="Higher Education">
+               <Origin name="Carnegie Mellon" handleService="https://nada.andrew.cmu.edu/shibb/servlet/HandleServlet">
+                       <Alias name="cmu" />
+                       <Alias name="Tartans" />
+               </Origin>
+               <Origin name="The Ohio State University" handleService="https://usfs2.us.ohio-state.edu/webdev/Shibboleth/secure/servlet/HandleServlet">
+                       <Alias name="osu" />
+                       <Alias name="Buckeyes" />
+               </Origin>
+               <Origin name="University of Washington" handleService="https://abajo.cac.washington.edu/shibb/servlet/HandleServlet">
+                       <Alias name="uwash" />
+                       <Alias name="Huskies" />
+               </Origin>
+               <Origin name="Brown University" handleService="http://dilbert2.cis.brown.edu:1080/shibb/servlet/HandleServlet">
+                       <Alias name="Bears" />
+               </Origin>
+       </OriginSet>
+       <OriginSet name="Other">
+               <Origin name="Walter's Test" handleService="http://wassa.org:8080/shibb/servlet/HandleServlet">
+                       <Alias name="wassa" />
+                       <Alias name="columbia" />
+               </Origin>
+               <Origin name="Internet2" handleService="https://shib2.internet2.edu/shibb/servlet/HandleServlet">
+                       <Alias name="I2" />
+               </Origin>
+       </OriginSet>
+       </CommonConfig>
+       
+       <WayfConfig cache="COOKIES" 
+               supportContact="mailto:shib-test@internet2.org"
+               logoLocation="images/internet2.gif">
+               <SearchIgnore>
+                       <String>Institution</String>
+                       <String>University</String>
+                       <String>State </String>
+                       <String>School</String>
+               </SearchIgnore>
+       </WayfConfig>
+       
+       <HsConfig 
+               supportContact="mailto:shib-test@internet2.org"
+               logoLocation="images/internet2.gif"
+               location = "http://blah.com/HS"
+               validityPeriod = "1400000"
+               domain = "internet2.edu"
+               issuer = "shib2.internet2.edu"
+               aaURL = "https://shib2.internet2.edu/shibb/servlet/AAServlet"
+               detailedHelpURL = "http://foo.bar"
+               handleRepositoryImplementation = "edu.internet2.middleware.shibboleth.common.provider.MemoryHandleRepository">
+                       <HelpText>In order to fulfill the request for the web resource you have just chosen, information must be sent from your home institution to the provider of the resource.  The web resource should load automatically.  If it does not load within five seconds, click on the Transmit button.</HelpText>
+                       <SecretKey>npsHVB/3OALcE+ydFtxAKp6bB1Qf9zgC</SecretKey>
+       </HsConfig>
+
+</ShibbolethConfig>
diff --git a/webApplication/WEB-INF/lib/commons-beanutils.jar b/webApplication/WEB-INF/lib/commons-beanutils.jar
new file mode 100644 (file)
index 0000000..5398fe1
Binary files /dev/null and b/webApplication/WEB-INF/lib/commons-beanutils.jar differ
diff --git a/webApplication/WEB-INF/lib/commons-collections.jar b/webApplication/WEB-INF/lib/commons-collections.jar
new file mode 100644 (file)
index 0000000..0b490e0
Binary files /dev/null and b/webApplication/WEB-INF/lib/commons-collections.jar differ
diff --git a/webApplication/WEB-INF/lib/commons-digester.jar b/webApplication/WEB-INF/lib/commons-digester.jar
new file mode 100644 (file)
index 0000000..97c877b
Binary files /dev/null and b/webApplication/WEB-INF/lib/commons-digester.jar differ
diff --git a/webApplication/WEB-INF/lib/jce-bc.jar b/webApplication/WEB-INF/lib/jce-bc.jar
new file mode 100644 (file)
index 0000000..46a103d
Binary files /dev/null and b/webApplication/WEB-INF/lib/jce-bc.jar differ
diff --git a/webApplication/WEB-INF/lib/jug-src.jar b/webApplication/WEB-INF/lib/jug-src.jar
new file mode 100644 (file)
index 0000000..8a6e0ef
Binary files /dev/null and b/webApplication/WEB-INF/lib/jug-src.jar differ
diff --git a/webApplication/WEB-INF/lib/jug.jar b/webApplication/WEB-INF/lib/jug.jar
new file mode 100644 (file)
index 0000000..1430119
Binary files /dev/null and b/webApplication/WEB-INF/lib/jug.jar differ
diff --git a/webApplication/WEB-INF/lib/log4j-1.2.jar b/webApplication/WEB-INF/lib/log4j-1.2.jar
new file mode 100644 (file)
index 0000000..78f2a7c
Binary files /dev/null and b/webApplication/WEB-INF/lib/log4j-1.2.jar differ
diff --git a/webApplication/WEB-INF/lib/shibboleth.jar b/webApplication/WEB-INF/lib/shibboleth.jar
new file mode 100644 (file)
index 0000000..66f5b05
Binary files /dev/null and b/webApplication/WEB-INF/lib/shibboleth.jar differ
diff --git a/webApplication/WEB-INF/lib/struts.jar b/webApplication/WEB-INF/lib/struts.jar
new file mode 100644 (file)
index 0000000..d8fefc4
Binary files /dev/null and b/webApplication/WEB-INF/lib/struts.jar differ
diff --git a/webApplication/WEB-INF/lib/xercesImpl.jar b/webApplication/WEB-INF/lib/xercesImpl.jar
new file mode 100644 (file)
index 0000000..205138a
Binary files /dev/null and b/webApplication/WEB-INF/lib/xercesImpl.jar differ
diff --git a/webApplication/WEB-INF/tlds/struts-bean.tld b/webApplication/WEB-INF/tlds/struts-bean.tld
new file mode 100755 (executable)
index 0000000..d8e4425
--- /dev/null
@@ -0,0 +1,347 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">\r
+<taglib>\r
+<tlibversion>1.0</tlibversion>\r
+<jspversion>1.1</jspversion>\r
+<shortname>bean</shortname>\r
+<uri>http://jakarta.apache.org/struts/tags-bean-1.0.2</uri>\r
+<tag>\r
+<name>cookie</name>\r
+<tagclass>org.apache.struts.taglib.bean.CookieTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.CookieTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>multiple</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>define</name>\r
+<tagclass>org.apache.struts.taglib.bean.DefineTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.DefineTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>toScope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>type</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>header</name>\r
+<tagclass>org.apache.struts.taglib.bean.HeaderTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.HeaderTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>multiple</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>include</name>\r
+<tagclass>org.apache.struts.taglib.bean.IncludeTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.IncludeTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>anchor</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>forward</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>href</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>page</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>transaction</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>message</name>\r
+<tagclass>org.apache.struts.taglib.bean.MessageTag</tagclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>arg0</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>arg1</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>arg2</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>arg3</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>arg4</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>bundle</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>key</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>locale</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>page</name>\r
+<tagclass>org.apache.struts.taglib.bean.PageTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.PageTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>parameter</name>\r
+<tagclass>org.apache.struts.taglib.bean.ParameterTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.ParameterTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>multiple</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>resource</name>\r
+<tagclass>org.apache.struts.taglib.bean.ResourceTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.ResourceTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>input</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>size</name>\r
+<tagclass>org.apache.struts.taglib.bean.SizeTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.SizeTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>collection</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>struts</name>\r
+<tagclass>org.apache.struts.taglib.bean.StrutsTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.bean.StrutsTei</teiclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>formBean</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>forward</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>mapping</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>write</name>\r
+<tagclass>org.apache.struts.taglib.bean.WriteTag</tagclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>filter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>ignore</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+</taglib>\r
+\r
+\r
+\r
diff --git a/webApplication/WEB-INF/tlds/struts-logic.tld b/webApplication/WEB-INF/tlds/struts-logic.tld
new file mode 100755 (executable)
index 0000000..bf03f24
--- /dev/null
@@ -0,0 +1,562 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+\r
+\r
+\r
+\r
+\r
+\r
+<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">\r
+<taglib>\r
+<tlibversion>1.0</tlibversion>\r
+<jspversion>1.1</jspversion>\r
+<shortname>logic</shortname>\r
+<uri>http://jakarta.apache.org/struts/tags-logic-1.0</uri>\r
+<tag>\r
+<name>equal</name>\r
+<tagclass>org.apache.struts.taglib.logic.EqualTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>forward</name>\r
+<tagclass>org.apache.struts.taglib.logic.ForwardTag</tagclass>\r
+<bodycontent>empty</bodycontent>\r
+<attribute>\r
+<name>name</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>greaterEqual</name>\r
+<tagclass>org.apache.struts.taglib.logic.GreaterEqualTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>greaterThan</name>\r
+<tagclass>org.apache.struts.taglib.logic.GreaterThanTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>iterate</name>\r
+<tagclass>org.apache.struts.taglib.logic.IterateTag</tagclass>\r
+<teiclass>org.apache.struts.taglib.logic.IterateTei</teiclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>collection</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>id</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>indexId</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>length</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>offset</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>type</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>lessEqual</name>\r
+<tagclass>org.apache.struts.taglib.logic.LessEqualTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>lessThan</name>\r
+<tagclass>org.apache.struts.taglib.logic.LessThanTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>match</name>\r
+<tagclass>org.apache.struts.taglib.logic.MatchTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>location</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>notEqual</name>\r
+<tagclass>org.apache.struts.taglib.logic.NotEqualTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>notMatch</name>\r
+<tagclass>org.apache.struts.taglib.logic.NotMatchTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>location</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>value</name>\r
+<required>true</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>notPresent</name>\r
+<tagclass>org.apache.struts.taglib.logic.NotPresentTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>role</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>user</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>present</name>\r
+<tagclass>org.apache.struts.taglib.logic.PresentTag</tagclass>\r
+<bodycontent>JSP</bodycontent>\r
+<attribute>\r
+<name>cookie</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>header</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>parameter</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>role</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>user</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+<tag>\r
+<name>redirect</name>\r
+<tagclass>org.apache.struts.taglib.logic.RedirectTag</tagclass>\r
+<attribute>\r
+<name>anchor</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>forward</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>href</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>name</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>page</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>paramId</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>paramName</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>paramProperty</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>paramScope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>property</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>scope</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+<attribute>\r
+<name>transaction</name>\r
+<required>false</required>\r
+<rtexprvalue>true</rtexprvalue>\r
+</attribute>\r
+</tag>\r
+</taglib>\r
+\r
+\r
+\r
diff --git a/webApplication/WEB-INF/web.xml b/webApplication/WEB-INF/web.xml
new file mode 100755 (executable)
index 0000000..e50926c
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app
+    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
+    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
+
+<web-app>
+    <servlet>
+      <servlet-name>
+          HS
+      </servlet-name>
+      <servlet-class>
+          edu.internet2.middleware.shibboleth.hs.HandleService
+      </servlet-class>
+      </servlet>
+      
+     <servlet-mapping>
+               <servlet-name>HS</servlet-name>
+               <url-pattern>/HS</url-pattern>
+       </servlet-mapping>
+       <mime-mapping>
+               <extension>css</extension>
+               <mime-type>text/css</mime-type>
+       </mime-mapping>
+
+ <security-constraint>
+<web-resource-collection>
+<web-resource-name>HS Login Test</web-resource-name>
+<url-pattern>/HS</url-pattern>
+</web-resource-collection>
+<auth-constraint>
+<role-name>tomcat</role-name>
+</auth-constraint>
+</security-constraint>
+
+ <login-config>
+<auth-method>BASIC</auth-method>
+<realm-name>HS Login Test</realm-name>
+</login-config>
+
+
+</web-app>
diff --git a/webApplication/hs.jsp b/webApplication/hs.jsp
new file mode 100755 (executable)
index 0000000..fea733c
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+       PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "DTD/xhtml1-strict.dtd">
+       <%@ taglib uri="/WEB-INF/tlds/struts-logic.tld" prefix="logic" %>
+       <%@ taglib uri="/WEB-INF/tlds/struts-bean.tld" prefix="bean" %>
+       
+       <jsp:useBean id="shire" scope="request" class="java.lang.String" />
+       <jsp:useBean id="target" scope="request" class="java.lang.String" />
+       <jsp:useBean id="assertion" scope="request" class="java.lang.String" />
+       <jsp:useBean id="hs_helpText" scope="application" class="java.lang.String"/>
+       <jsp:useBean id="hs_detailedHelpURL" scope="application" class="java.lang.String"/>
+       
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" type="text/css" href="main.css" />
+       <title>Access Request</title>
+</head>
+
+<body onLoad="document.forms[0].submit()">
+
+<h1>Inter-institutional Access Request</h1>
+
+<p><bean:write name="hs_helpText" /></p>
+<p>
+<form name="shib"  action="<bean:write name="shire" />" method="POST">
+<input type="hidden" name="TARGET" value="<bean:write name="target" />">
+<input type="hidden" name="SAMLAssertion"value="<bean:write name="assertion" />">
+<input type="submit" value="Transmit">
+</form>
+</p>
+<p><a href="<bean:write name="hs_detailedHelpURL" />">Detailed information</a> explaining this process.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/webApplication/hserror.jsp b/webApplication/hserror.jsp
new file mode 100755 (executable)
index 0000000..f3e6277
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+       PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "DTD/xhtml1-strict.dtd">
+       <%@ taglib uri="/WEB-INF/tlds/struts-logic.tld" prefix="logic" %>
+       <%@ taglib uri="/WEB-INF/tlds/struts-bean.tld" prefix="bean" %>
+       
+       <jsp:useBean id="hs_location" scope="application" class="java.lang.String"/>
+       <jsp:useBean id="errorText" scope="request" class="java.lang.String"/>
+       <jsp:useBean id="hs_supportContact" scope="application" class="java.lang.String"/>
+       <jsp:useBean id="hs_logoLocation" scope="application" class="java.lang.String"/>
+       
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <link rel="stylesheet" type="text/css" href="main.css" />
+       <title>Access System Failure</title>
+</head>
+
+<body>
+<div class="head">
+<img src="<bean:write name="hs_logoLocation" />" alt="Logo" />
+<h1>Inter-institutional Access System Failure</h1>
+</div>
+
+<p>The inter-institutional access system experienced a technical failure.</p>
+
+<p>Please email <a href="mailto:<bean:write name="hs_supportContact" />"><bean:write name="hs_supportContact" /></a> and include the following error message:</p>
+
+<p class="error">Handle Service failure at (<bean:write name="hs_location" />)</p>
+
+<p><bean:write name="errorText" /></p>
+
+
+</body>
+</html>
\ No newline at end of file
diff --git a/webApplication/images/internet2.gif b/webApplication/images/internet2.gif
new file mode 100755 (executable)
index 0000000..74ecbcb
Binary files /dev/null and b/webApplication/images/internet2.gif differ
diff --git a/webApplication/main.css b/webApplication/main.css
new file mode 100755 (executable)
index 0000000..2fbb0b8
--- /dev/null
@@ -0,0 +1,39 @@
+body {
+               background-color: #FFFFFF;
+               font-family : Geneva, Arial, Helvetica, sans-serif;
+               text-align: center;
+               letter-spacing: 0px;
+               color: black;
+               text-align: left;
+}
+
+p {
+       font-size: 10pt;
+       margin-top: 20px;
+       margin-bottom: 20px;
+}
+
+
+li {
+
+       font-size: 10pt;
+}
+
+h1 {
+       font-size: 14pt;
+       font-weight: bold;
+}
+
+h2 { 
+       font-size: 12pt;
+       font-weight: bold;
+}
+
+.error {
+       font-size: 10pt;
+       font-weight: bold;
+}
+
+img {
+       margin-bottom: 15px;
+}
\ No newline at end of file