Support reserving SessionId before WAYF Redirect
authorgilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 3 Feb 2005 15:05:12 +0000 (15:05 +0000)
committergilbert <gilbert@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Thu, 3 Feb 2005 15:05:12 +0000 (15:05 +0000)
Create strong random SessionId

git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@1230 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/serviceprovider/AuthenticationAssertionConsumerServlet.java
src/edu/internet2/middleware/shibboleth/serviceprovider/FilterSupportImpl.java
src/edu/internet2/middleware/shibboleth/serviceprovider/Session.java
src/edu/internet2/middleware/shibboleth/serviceprovider/SessionManager.java

index 282b80e..0610bd5 100644 (file)
@@ -181,7 +181,7 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
             log.debug("Authentication received from "+ipaddr+" for "+target+
                         "(application:"+applicationId+") (Provider:"+providerId+")");
 
-            String sessionId = createSessionFromPost(ipaddr, bin64Assertion, applicationId, shireURL, providerId);
+            String sessionId = createSessionFromPost(ipaddr, bin64Assertion, applicationId, shireURL, providerId, null);
             
             Cookie cookie = new Cookie("ShibbolethSPSession",sessionId);
             response.addCookie(cookie);
@@ -214,7 +214,7 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
      * @param applicationId from RequestMap
      * @param shireURL 
      * @param providerId Our Entity name
-     * @return UUID key of Session
+     * @return random key of Session
      * @throws SAMLException
      * @throws MetadataException
      */
@@ -224,7 +224,8 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
             byte[] bin64Assertion, 
             String applicationId, 
             String shireURL, 
-            String providerId 
+            String providerId,
+            String emptySessionId
             ) 
     throws SAMLException, MetadataException {
         String sessionid=null;
@@ -261,7 +262,8 @@ public class AuthenticationAssertionConsumerServlet extends HttpServlet {
                 ipaddr, 
                 pproviderId.toString(), 
                 assertion, 
-                authstmt);
+                authstmt,
+                emptySessionId);
         
         // Very agressive attribute fetch rule 
         // Get the Attributes immediately! [good for debugging]
index 43df9b3..9c54f5e 100644 (file)
@@ -151,11 +151,12 @@ public class FilterSupportImpl implements FilterSupport {
             byte[] bin64Assertion, 
             String applicationId, 
             String shireURL, 
-            String providerId) {
+            String providerId,
+            String emptySessionId) {
         String sessionid;
         try {
             sessionid = AuthenticationAssertionConsumerServlet.createSessionFromPost(
-                    ipaddr, bin64Assertion, applicationId, shireURL, providerId);
+                    ipaddr, bin64Assertion, applicationId, shireURL, providerId,emptySessionId);
         } catch (SAMLException e) {
             return null;
         } catch (MetadataException e) {
@@ -171,4 +172,16 @@ public class FilterSupportImpl implements FilterSupport {
         Sessions appSessionValues = appinfo.getApplicationConfig().getSessions();
         return appSessionValues.getShireSSL();
     }
+
+    /**
+     * Create empty Session so SessionID can be written as a Cookie
+     * before redirecting the Browser to the IDP.
+     * 
+     * @param applicationId
+     * @return SessionId of empty session
+     */
+    public String createSession(String applicationId) {
+        return context.getSessionManager().newSession(
+                applicationId, null, null, null, null, null);
+    }
 }
index fd5160f..4eed3d0 100644 (file)
@@ -2,10 +2,9 @@
  * Session.java
  * 
  * Session object holds Principal ID [handle] and Attributes.
- * A generated UUID is used as the object key in the Cache and
+ * A random ID is used as the object key in the Cache and
  * is returned to the Browser as a Cookie value. 
  *
- * External Dependencies: jug.jar to generate UUID
  * Recovery Context: No exceptions expected or generated.
  * 
  * --------------------
@@ -20,8 +19,6 @@
 package edu.internet2.middleware.shibboleth.serviceprovider;
 
 import java.io.Serializable;
-
-import org.doomdark.uuid.UUIDGenerator;
 import org.opensaml.SAMLAssertion;
 import org.opensaml.SAMLAuthenticationStatement;
 import org.opensaml.SAMLResponse;
@@ -38,15 +35,36 @@ import org.opensaml.SAMLResponse;
  */
 public class Session implements Serializable {
        
-       Session() {
-               // Should only be created by SessionManager.newSession()
+       Session(String key) {
+               // Should only be created by SessionManager
+           this.key=key;
        }
        
        // Properties
-       private String key = generateKey();
+       
+       private String key;
+       public String getKey() {
+               return key;
+       }
+       
        private String applicationId = null;
+       public String getApplicationId() {
+               return applicationId;
+       }
+       public void setApplicationId(String applicationId) {
+               this.applicationId = applicationId;
+       }
+       
        private String ipaddr = null;
+       public String getIpaddr() {
+               return ipaddr;
+       }
+       public void setIpaddr(String ipaddr) {
+               this.ipaddr = ipaddr;
+       }
+       
        private String entityId = null; // a.k.a providerId
+       
        public String getEntityId() {
                return entityId;
        }
@@ -54,89 +72,35 @@ public class Session implements Serializable {
                this.entityId = entityId;
        }
        private long lifetime;
-       private long timeout;
-       
        public long getLifetime() {
                return lifetime;
        }
        public void setLifetime(long lifetime) {
                this.lifetime = lifetime;
        }
+       
+       private long timeout;
        public long getTimeout() {
                return timeout;
        }
        public void setTimeout(long timeout) {
                this.timeout = timeout;
        }
+       
     // private persisted variable
        private long timestamp = System.currentTimeMillis();
        
        
        // Stuff saved from the POST
        private SAMLAssertion authenticationAssertion = null;
-       private SAMLAuthenticationStatement authenticationStatement=null;
-       
-       // Stuff saved from the Attribute Query
-       private SAMLResponse attributeResponse = null;
-       /*
-        * Internal key generation logic. Designed not to fail.
-        * This is not the place to signal configuration problems.
-        * Sanity check the CLASSPATH long before you call down to here.
-        */
-       private static long terriblefallback = new java.util.Random().nextLong();
-       private static String generateKey() {
-               try {
-                       // Note: performance can be improved by creating a synchonized
-                       // static UUIDGenerator preinitialized. 
-                       return UUIDGenerator.getInstance().generateTimeBasedUUID().toString();
-               } catch (Throwable t) {
-                       // Probably the jug.jar file is missing in WEB-INF/lib
-                       // Generate a unique but easy to guess integer.
-                       return Long.toString(terriblefallback++);
-               }
-       }
-
-       /**
-        * @return Returns the ipaddr.
-        */
-       public String getIpaddr() {
-               return ipaddr;
-       }
-       /**
-        * @param ipaddr The ipaddr to set.
-        */
-       public void setIpaddr(String ipaddr) {
-               this.ipaddr = ipaddr;
-       }
-       /**
-        * @return Returns the applicationId.
-        */
-       public String getApplicationId() {
-               return applicationId;
-       }
-       /**
-        * @param applicationId The applicationId to set.
-        */
-       public void setApplicationId(String applicationId) {
-               this.applicationId = applicationId;
-       }
-       /**
-        * @return Returns the key.
-        */
-       public String getKey() {
-               return key;
-       }
-       public void renew(){
-               timestamp = System.currentTimeMillis();
-       }
-       
-
        public SAMLAssertion getAuthenticationAssertion() {
                return authenticationAssertion;
        }
        public void setAuthenticationAssertion(SAMLAssertion authentication) {
                this.authenticationAssertion = authentication;
        }
+       
+       private SAMLAuthenticationStatement authenticationStatement=null;
        public SAMLAuthenticationStatement getAuthenticationStatement() {
                return authenticationStatement;
        }
@@ -144,10 +108,20 @@ public class Session implements Serializable {
                        SAMLAuthenticationStatement authenticationStatement) {
                this.authenticationStatement = authenticationStatement;
        }
+       
+       // Stuff saved from the Attribute Query
+       private SAMLResponse attributeResponse = null;
        public SAMLResponse getAttributeResponse() {
                return attributeResponse;
        }
        public void setAttributeResponse(SAMLResponse attributeResponse) {
                this.attributeResponse = attributeResponse;
        }
+
+       
+       public void renew(){
+               timestamp = System.currentTimeMillis();
+       }
+       
+
 }
index ad80800..905059f 100644 (file)
@@ -21,6 +21,7 @@
  */
 package edu.internet2.middleware.shibboleth.serviceprovider;
 
+import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -62,6 +63,23 @@ public class SessionManager {
        
        private static ServiceProviderContext context = ServiceProviderContext.getInstance();
 
+       private static SecureRandom rand = new SecureRandom();
+       private static final String table = "0123456789" +
+               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"+
+               "abcdefgjikjlmnopqrstuvwxyz"+
+               "$@";
+       public String generateKey() {
+           byte[] trash = new byte[16];
+           char[] ctrash = new char[16];
+           do {
+               rand.nextBytes(trash);
+               for (int i=0;i<16;i++) {
+                   trash[i]|=0x3f;
+                   ctrash[i]=(char)table.charAt(trash[i]);
+               }
+           } while (null!=sessions.get(ctrash));
+           return new String(ctrash);
+       }
        
        
        
@@ -69,10 +87,22 @@ public class SessionManager {
                Session s = (Session) sessions.get(sessionId);
                if (s==null)
                        return null;
+               if (null==s.getAuthenticationAssertion())
+                   return null;
                if (!applicationId.equals(s.getApplicationId()))
                        return null;
                return s;
        }
+
+       private synchronized Session findEmptySession(String sessionId) {
+               Session s = (Session) sessions.get(sessionId);
+               if (s==null)
+                       return null;
+               if (null!=s.getAuthenticationAssertion())
+                   return null;
+               return s;
+       }
+       
        
        protected synchronized void add(Session s) {
                sessions.put(s.getKey(), s);
@@ -127,9 +157,10 @@ public class SessionManager {
         * Called from Authentication Assertion Consumer [SHIRE]
         * 
         * @param applicationId The application for this session
-        * @param shireUrl The managing SHIRE
         * @param ipaddr The client's remote IP address from HTTP
-        * @param authentication SAMLAssertion from the Post data
+        * @param entityId The Entity of the AA issuing the authentication
+        * @param assertion Assertion in case one needs more data
+        * @param authentication subset of assertion with handle
         * @return String (UUID) to go in the browser cookie
         */
        public 
@@ -139,7 +170,9 @@ public class SessionManager {
                        String ipaddr,
                        String entityId,
                        SAMLAssertion assertion,
-                       SAMLAuthenticationStatement authenticationStatement){
+                       SAMLAuthenticationStatement authenticationStatement,
+                       String emptySessionId // may be null
+                       ){
                
                ServiceProviderConfig config = context.getServiceProviderConfig();
                ApplicationInfo appinfo = config.getApplication(applicationId);
@@ -147,12 +180,22 @@ public class SessionManager {
                
                String sessionId = null;
                
-               Session session = new Session();
+               Session session;
+               if (emptySessionId==null) {
+                   session = new Session(generateKey());
+               } else {
+                   session = findEmptySession(emptySessionId);
+                   if (session==null) {
+                           session = new Session(generateKey());
+                   }
+               }
                session.setApplicationId(applicationId);
                session.setIpaddr(ipaddr);
                session.setEntityId(entityId);
+               
                session.setAuthenticationAssertion(assertion);
                session.setAuthenticationStatement(authenticationStatement);
+               
                session.setLifetime(appSessionValues.getLifetime());
                session.setTimeout(appSessionValues.getTimeout());