IdPSessionFilter throws ArrayIndexOutOfBoundsException on validation of unexpected...
authorlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 26 Nov 2008 07:10:43 +0000 (07:10 +0000)
committerlajoie <lajoie@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Wed, 26 Nov 2008 07:10:43 +0000 (07:10 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/branches/REL_2@2806 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

.classpath
doc/RELEASE-NOTES.txt
pom.xml
src/installer/resources/conf-tmpl/tc-config.xml
src/main/java/edu/internet2/middleware/shibboleth/idp/session/IdPSessionFilter.java

index 8b0ba27..89dad3c 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+    <classpathentry including="**/*.java" kind="src" path="src/main/java"/>
        <classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
-       <classpathentry including="**/*.java" kind="src" path="src/main/java"/>
        <classpathentry kind="con" path="org.devzuz.q.maven.jdt.core.mavenClasspathContainer"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="output" path="target/classes"/>
index f1569fe..e00cae6 100644 (file)
@@ -1,3 +1,7 @@
+Changes in Release 2.1.1
+=============================================
+[SIDP-252] - IdPSessionFilter throws ArrayIndexOutOfBoundsException on validation of unexpected cookie
+
 Changes in Release 2.1.0
 =============================================
 [SIDP-20] - Cannot deploy on Windows. Spring and DOS device names?
diff --git a/pom.xml b/pom.xml
index 4983614..eb521db 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>edu.internet2.middleware</groupId>
     <artifactId>shibboleth-identityprovider</artifactId>
-    <version>2.1.0</version>
+    <version>2.1.1</version>
     <!-- We bundle as a jar here, the installer creates the WAR -->
     <packaging>jar</packaging>
 
index c79f5a0..b37edc6 100644 (file)
@@ -45,6 +45,9 @@
     <clients>
         <logs>$IDP_HOME$/cluster/client/logs-%i</logs>
         <statistics>$IDP_HOME$/cluster/client/stats-%i</statistics>
+        <modules>
+            <module name="tim-vector" version="2.4.0-SNAPSHOT" group-id="org.terracotta.modules"/>
+        </modules>
     </clients>
 
     <application>
                     <honor-transient>true</honor-transient>
                 </include>
                 <include>
+                    <class-expression>edu.internet2.middleware.shibboleth.idp.authn.UsernamePrincipal</class-expression>
+                    <honor-transient>true</honor-transient>
+                </include> 
+                <include>
                     <class-expression>edu.vt.middleware.ldap.jaas.LdapCredential</class-expression>
                     <honor-transient>true</honor-transient>
                 </include>
@@ -79,7 +86,7 @@
                     <honor-transient>true</honor-transient>
                 </include>
                 <include>
-                    <class-expression>edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.attributeDefinition.IdEntry</class-expression>
+                    <class-expression>edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.attributeDefinition.TransientIdEntry</class-expression>
                     <honor-transient>true</honor-transient>
                 </include>
                 <include>
index 484dd0a..347553c 100644 (file)
@@ -66,7 +66,7 @@ public class IdPSessionFilter implements Filter {
         HttpServletRequest httpRequest = (HttpServletRequest) request;
 
         Cookie sessionCookie = getIdPSessionCookie(httpRequest);
-        Session idpSession = validateCookie(sessionCookie, httpRequest);
+        Session idpSession = getUserSession(sessionCookie, httpRequest);
         if (idpSession != null) {
             log.trace("Updating IdP session activity time and adding session object to the request");
             idpSession.setLastActivityInstant(new DateTime());
@@ -118,55 +118,82 @@ public class IdPSessionFilter implements Filter {
     }
 
     /**
-     * Validates the given session cookie against the associated session.
+     * Gets the user session associated with a session cookie.
      * 
      * @param sessionCookie the session cookie
      * @param httpRequest the current HTTP request
      * 
-     * @return the session against which the cookie was validated
+     * @return the session associated with the cookie or null if there is no currently assoicated session
      */
-    protected Session validateCookie(Cookie sessionCookie, HttpServletRequest httpRequest) {
-        if (sessionCookie == null) {
+    protected Session getUserSession(Cookie sessionCookie, HttpServletRequest httpRequest) {
+        if (sessionCookie == null || DatatypeHelper.isEmpty(sessionCookie.getValue())) {
             return null;
         }
 
         // index 0: remote address
         // index 1: session ID
         // index 2: Base64(HMAC(index 0 + index 1))
-        String[] valueComponents = HTTPTransportUtils.urlDecode(sessionCookie.getValue()).split("\\|");
+        String cookieValue = HTTPTransportUtils.urlDecode(sessionCookie.getValue());
+        String[] valueComponents = cookieValue.split("\\|");
+        if (valueComponents.length != 3) {
+            log.warn("IdP session cookie has an improperly formated value: {}", cookieValue);
+            return null;
+        }
+
         byte[] remoteAddressBytes = Base64.decode(valueComponents[0]);
         byte[] sessionIdBytes = Base64.decode(valueComponents[1]);
         byte[] signatureBytes = Base64.decode(valueComponents[2]);
 
+        String sessionId = new String(sessionIdBytes);
+        Session userSession = sessionManager.getSession(sessionId);
+
+        if (userSession != null) {
+            if (isCookieValid(httpRequest, remoteAddressBytes, sessionIdBytes, signatureBytes, userSession
+                    .getSessionSecret())) {
+                return userSession;
+            }
+        } else {
+            log.debug("No session associated with session ID {} - session must have timed out", valueComponents[1]);
+        }
+        return null;
+    }
+
+    /**
+     * Validates the session cookie. This validates that the cookie came from the same IP address to which it was given,
+     * if consistent address checking is enabled, and that cookie data hasn't been changed.
+     * 
+     * @param httpRequest incoming HTTP request
+     * @param remoteAddressBytes remote address from the cookie value
+     * @param sessionIdBytes session ID from the cookie value
+     * @param signatureBytes signature from the cookie value
+     * @param sessionSecret secrete associated with the user's session
+     * 
+     * @return true if the information in the cookie is valid, false if not
+     */
+    protected boolean isCookieValid(HttpServletRequest httpRequest, byte[] remoteAddressBytes, byte[] sessionIdBytes,
+            byte[] signatureBytes, byte[] sessionSecret) {
         if (consistentAddress) {
             String remoteAddress = new String(remoteAddressBytes);
             if (!httpRequest.getRemoteAddr().equals(remoteAddress)) {
                 log.error("Client sent a cookie from addres {} but the cookie was issued to address {}", httpRequest
                         .getRemoteAddr(), remoteAddress);
-                return null;
+                return false;
             }
         }
 
-        String sessionId = new String(sessionIdBytes);
-        Session userSession = sessionManager.getSession(sessionId);
-
-        if (userSession != null) {
-            try {
-                MessageDigest digester = MessageDigest.getInstance("SHA");
-                digester.update(userSession.getSessionSecret());
-                digester.update(remoteAddressBytes);
-                digester.update(sessionIdBytes);
-                if (!Arrays.equals(digester.digest(), signatureBytes)) {
-                    log.error("Session cookie signature did not match, the session cookie has been tampered with");
-                    return null;
-                }
-            } catch (GeneralSecurityException e) {
-                log.error("Unable to computer over session cookie material", e);
+        try {
+            MessageDigest digester = MessageDigest.getInstance("SHA");
+            digester.update(sessionSecret);
+            digester.update(remoteAddressBytes);
+            digester.update(sessionIdBytes);
+            if (!Arrays.equals(digester.digest(), signatureBytes)) {
+                log.error("Session cookie has been tampered with, its signature no longer matches expected value");
+                return false;
             }
-        } else {
-            log.debug("No session associated with session ID {} - session must have timed out",
-                            valueComponents[1]);
+        } catch (GeneralSecurityException e) {
+            log.error("Unable to compute signature over session cookie material", e);
         }
-        return userSession;
+
+        return true;
     }
 }
\ No newline at end of file