Started to convert HS to new handle repository interface.
authorwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 31 Jan 2003 23:23:14 +0000 (23:23 +0000)
committerwassa <wassa@ab3bd59b-922f-494d-bb5f-6f0a3c29deca>
Fri, 31 Jan 2003 23:23:14 +0000 (23:23 +0000)
git-svn-id: https://subversion.switch.ch/svn/shibboleth/java-idp/trunk@441 ab3bd59b-922f-494d-bb5f-6f0a3c29deca

src/edu/internet2/middleware/shibboleth/aa/AAServlet.java
src/edu/internet2/middleware/shibboleth/hs/HandleRepository.java
src/edu/internet2/middleware/shibboleth/hs/HandleRepositoryException.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/hs/HandleRepositoryFactory.java
src/edu/internet2/middleware/shibboleth/hs/HandleServlet.java
src/edu/internet2/middleware/shibboleth/hs/provider/BaseHandleRepository.java [new file with mode: 0644]
src/edu/internet2/middleware/shibboleth/hs/provider/CryptoHandleRepository.java
src/edu/internet2/middleware/shibboleth/hs/provider/MemoryHandleRepository.java [new file with mode: 0644]
webAppConfig/all.xml
webApplication/WEB-INF/conf/origin.properties

index cd63ed1..5626da6 100755 (executable)
@@ -54,6 +54,7 @@ import java.io.IOException;
 import java.io.PrintStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.security.Principal;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Properties;
@@ -61,8 +62,6 @@ import java.util.Properties;
 import javax.naming.NamingException;
 import javax.naming.directory.DirContext;
 import javax.naming.directory.InitialDirContext;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.UnavailableException;
 import javax.servlet.http.HttpServlet;
@@ -79,9 +78,9 @@ import edu.internet2.middleware.eduPerson.Init;
 import edu.internet2.middleware.shibboleth.aa.arp.AAPrincipal;
 import edu.internet2.middleware.shibboleth.aa.arp.ArpEngine;
 import edu.internet2.middleware.shibboleth.aa.arp.ArpException;
-import edu.internet2.middleware.shibboleth.common.Constants;
-import edu.internet2.middleware.shibboleth.hs.HandleEntry;
 import edu.internet2.middleware.shibboleth.hs.HandleException;
+import edu.internet2.middleware.shibboleth.hs.HandleRepository;
+import edu.internet2.middleware.shibboleth.hs.HandleRepositoryException;
 import edu.internet2.middleware.shibboleth.hs.HandleRepositoryFactory;
 
 /**
@@ -95,7 +94,7 @@ import edu.internet2.middleware.shibboleth.hs.HandleRepositoryFactory;
 public class AAServlet extends HttpServlet {
 
     protected AAResponder responder;
-    protected HandleRepositoryFactory hrf;
+    protected HandleRepository handleRepository;
     protected Properties configuration;
     private static Logger log = Logger.getLogger(AAServlet.class.getName());    
     
@@ -111,7 +110,7 @@ public class AAServlet extends HttpServlet {
 
                        ArpEngine arpEngine = new ArpEngine(configuration);
                        
-                       hrf = getHandleRepository();
+                       handleRepository = HandleRepositoryFactory.getInstance(configuration);
 
                        log.info(
                                "Using JNDI context ("
@@ -141,7 +140,7 @@ public class AAServlet extends HttpServlet {
                } catch (AAException ae) {
                        log.fatal("The AA could not be initialized: " + ae);
                        throw new UnavailableException("Attribute Authority failed to initialize.");
-               } catch (HandleException he) {
+               } catch (HandleRepositoryException he) {
                        log.fatal(
                                "The AA could not be initialized due to a problem with the Handle Repository configuration: "
                                        + he);
@@ -204,7 +203,7 @@ public class AAServlet extends HttpServlet {
                List attrs = null;
                SAMLException ourSE = null;
                AASaml saml = null;
-               String userName = null;
+               Principal principal = null;
 
                try {
                        saml =
@@ -228,32 +227,28 @@ public class AAServlet extends HttpServlet {
                        log.info("AA: handle:" + handle);
                        if (handle.equalsIgnoreCase("foo")) {
                                // for testing only
-                               userName = "dummy";
+                               new AAPrincipal("dummy");
                        } else {
-                               if (hrf == null) {
-                                       throw new HandleException("No HandleRepository found! Has HS initialized?");
-                               } else {
-                                       HandleEntry he = hrf.getHandleEntry(handle);
-                                       userName = he.getUsername();
-                                       if (userName == null)
-                                               throw new HandleException("HandleServer returns null for user name!");
+                               principal = handleRepository.getPrincipal(handle);
+                               if (principal == null) {
+                                       throw new HandleException("Received a request for an invalid/unknown handle.");
                                }
                        }
 
                        attrs =
                                Arrays.asList(
                                        responder.getReleaseAttributes(
-                                               new AAPrincipal(userName),
+                                               principal,
                                                configuration.getProperty(
                                                        "edu.internet2.middleware.shibboleth.aa.AAServlet.ldapUserDnPhrase"),
                                                shar,
                                                resource));
-                       log.info("Got " + attrs.size() + " attributes for " + userName);
+                       log.info("Got " + attrs.size() + " attributes for " + principal.getName());
                        saml.respond(resp, attrs, null);
-                       log.info("Successfully responded about " + userName);
+                       log.info("Successfully responded about " + principal.getName());
 
                } catch (org.opensaml.SAMLException se) {
-                       log.error("AA failed for " + userName + " because of: " + se);
+                       log.error("AA failed for " + principal.getName() + " because of: " + se);
                        try {
                                saml.fail(resp, se);
                        } catch (Exception ee) {
@@ -264,12 +259,17 @@ public class AAServlet extends HttpServlet {
                                                + se);
                        }
                } catch (HandleException he) {
-                       log.error("AA failed for " + userName + " because of: " + he);
+                       log.error("AA failed for " + principal.getName() + " because of: " + he);
                        try {
                                QName[] codes = new QName[2];
                                codes[0] = SAMLException.REQUESTER;
-                               codes[1] = new QName(edu.internet2.middleware.shibboleth.common.XML.SHIB_NS, "InvalidHandle");
-                               saml.fail(resp, new SAMLException(Arrays.asList(codes), "AA got a HandleException: " + he));
+                               codes[1] =
+                                       new QName(
+                                               edu.internet2.middleware.shibboleth.common.XML.SHIB_NS,
+                                               "InvalidHandle");
+                               saml.fail(
+                                       resp,
+                                       new SAMLException(Arrays.asList(codes), "AA got a HandleException: " + he));
                        } catch (Exception ee) {
                                throw new ServletException(
                                        "AA failed to even make a SAML Failure message because "
@@ -281,7 +281,7 @@ public class AAServlet extends HttpServlet {
                        e.printStackTrace();
                        log.error(
                                "Attribute Authority Error for principal ("
-                                       + userName
+                                       + principal.getName()
                                        + ") : "
                                        + e.getClass().getName()
                                        + " : "
@@ -304,30 +304,4 @@ public class AAServlet extends HttpServlet {
        }
 
 
-    private synchronized HandleRepositoryFactory getHandleRepository()
-       throws HandleException, AAException{
-
-       ServletConfig sc = getServletConfig();
-       ServletContext sctx = sc.getServletContext(); 
-       HandleRepositoryFactory hrf = (HandleRepositoryFactory)sctx.getAttribute("HandleRepository");
-
-       log.debug("Context attribute for HandleRepository: "+hrf);
-           
-           
-       if(hrf == null){
-           // make one
-           String repositoryType = this.getServletContext().getInitParameter("repository");
-           if(repositoryType == null)
-               throw new AAException("repository parameter not set. Unknown Handle repository type");
-           hrf = HandleRepositoryFactory.getInstance(                                                Constants.POLICY_CLUBSHIB, 
-                                                                                                     repositoryType,
-                                                                                                     this );
-           sctx.setAttribute("HandleRepository", hrf);
-           log.info("A new HandleRepository created by AA: "+hrf);
-           
-       }
-       return hrf;
-    }
-
-
 }
index 1b7c19b..9cee2de 100644 (file)
@@ -53,7 +53,7 @@ import java.security.Principal;
 
 /**
  * Defines a mechanism for communicating identities between the Shibboleth Handle
- * Service and Attribute Authority.
+ * Service and Attribute Authority.  Implementations must be thread-safe.
  * 
  * @author Walter Hoehn (wassa@columbia.edu)
  */
diff --git a/src/edu/internet2/middleware/shibboleth/hs/HandleRepositoryException.java b/src/edu/internet2/middleware/shibboleth/hs/HandleRepositoryException.java
new file mode 100644 (file)
index 0000000..dbf0cf7
--- /dev/null
@@ -0,0 +1,62 @@
+/* 
+ * The Shibboleth License, Version 1. 
+ * Copyright (c) 2002 
+ * University Corporation for Advanced Internet Development, Inc. 
+ * All rights reserved
+ * 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this 
+ * list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation 
+ * and/or other materials provided with the distribution, if any, must include 
+ * the following acknowledgment: "This product includes software developed by 
+ * the University Corporation for Advanced Internet Development 
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
+ * may appear in the software itself, if and wherever such third-party 
+ * acknowledgments normally appear.
+ * 
+ * Neither the name of Shibboleth nor the names of its contributors, nor 
+ * Internet2, nor the University Corporation for Advanced Internet Development, 
+ * Inc., nor UCAID may be used to endorse or promote products derived from this 
+ * software without specific prior written permission. For written permission, 
+ * please contact shibboleth@shibboleth.org
+ * 
+ * Products derived from this software may not be called Shibboleth, Internet2, 
+ * UCAID, or the University Corporation for Advanced Internet Development, nor 
+ * may Shibboleth appear in their name, without prior written permission of the 
+ * University Corporation for Advanced Internet Development.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.hs;
+
+/**
+ * Indicates an error occurred while manipulating an instance of <code>HandleRepository</code>
+ * 
+ * @author Walter Hoehn (wassa@columbia.edu)
+ */
+public class HandleRepositoryException extends Exception {
+
+       public HandleRepositoryException(String message) {
+               super(message);
+       }
+}
index 2eca354..c2bf502 100644 (file)
 
 package edu.internet2.middleware.shibboleth.hs;
 
-import javax.servlet.http.*;
-import edu.internet2.middleware.shibboleth.*;
-import edu.internet2.middleware.shibboleth.common.*;
+import java.lang.reflect.Constructor;
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
 
 /**
- *  Used by Shibboleth Handle Service and Attribute Authority to build a repository object
+ * Factory for generating instances of <code>HandleRepository</code>.  Configuration
+ * is delegated to the Handle Repository.  Runtime options are passed to concrete constructors
+ * via a <code>Properties</code> object.
+ *
+ * @author Walter Hoehn (wassa@columbia.edu)
  */
-public abstract class HandleRepositoryFactory
-{
-    /**  Array of policy URI(s) (HS and SHIRE) */
-    protected String[] policies;
-    protected String SQL = "SQL";
-    protected String MEMORY = "MEMORY";
 
-    public HandleRepositoryFactory()
-    {
-    }
+public class HandleRepositoryFactory {
 
-    public static HandleRepositoryFactory getInstance(String policy, 
-                                                     String repository,
-                                                     HttpServlet HS)
-        throws HandleException {
+       private static Logger log = Logger.getLogger(HandleRepositoryFactory.class.getName());
 
-       if (policy.equalsIgnoreCase( Constants.POLICY_CLUBSHIB )) {
-           if (repository.equalsIgnoreCase( "SQL" )) {
-               return new ClubShibSQLHandleRepository(HS);
-           } else if (repository.equalsIgnoreCase( "MEMORY" )) {
-               return new ClubShibInMemoryHandleRepository(HS);
-           } else {
-               throw new HandleException("Unspecified repository type.");
-           }
-       }else{
-           throw new HandleException("Unsupported policy found.");
-       }
-    }
+       public static HandleRepository getInstance(Properties props) throws HandleRepositoryException {
 
-    public abstract HandleEntry getHandleEntry(String handle)
-       throws HandleException;
+               if (props.getProperty("edu.internet2.middleware.shibboleth.hs.HandleRepository.implementation") == null) {
+                       throw new HandleRepositoryException("No Handle Repository implementaiton specified.");
+               }
+               try {
+                       Class implementorClass =
+                               Class.forName(
+                                       props.getProperty("edu.internet2.middleware.shibboleth.hs.HandleRepository.implementation"));
+                       Class[] params = new Class[1];
+                       params[0] = Class.forName("java.util.Properties");
+                       Constructor implementorConstructor = implementorClass.getConstructor(params);
+                       Object[] args = new Object[1];
+                       args[0] = props;
+                       log.debug("Initializing Handle Repository of type (" + implementorClass.getName() + ").");
+                       return (HandleRepository) implementorConstructor.newInstance(args);
 
-    public abstract  void insertHandleEntry(HandleEntry he)
-       throws HandleException;
-    
-    /* for debugging purposes only */
-    public abstract String toHTMLString()
-        throws HandleException;
+               } catch (NoSuchMethodException nsme) {
+                       log.error(
+                               "Failed to instantiate an Handle Repository: HandleRepository "
+                                       + "implementation must contain a constructor that accepts a Properties bundle for "
+                                       + "configuration data.");
+                       throw new HandleRepositoryException("Failed to instantiate an Handle Repository.");
+               } catch (Exception e) {
+                       log.error("Failed to instantiate an Handle Repository: " + e);
+                       throw new HandleRepositoryException("Failed to instantiate an Handle Repository: " + e.getMessage());
 
+               }
+       }
 }
-
index 58258f6..bbb4171 100644 (file)
@@ -54,6 +54,8 @@ import java.text.*;
 import java.util.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
+
+import edu.internet2.middleware.shibboleth.aa.arp.AAPrincipal;
 import edu.internet2.middleware.shibboleth.common.*;
 import org.opensaml.*;
 import sun.misc.BASE64Decoder;
@@ -63,254 +65,225 @@ import org.doomdark.uuid.UUIDGenerator;
 
 public class HandleServlet extends HttpServlet {
 
-    private HandleRepositoryFactory hrf;
-    private long ticketExp; 
-    private String username=null;
-    private HandleServiceSAML hsSAML;
-    private String rep;
-    private static Logger log = Logger.getLogger(HandleServlet.class.getName());; 
-
-    public void init()
-       throws ServletException
-    {
-    
-    MDC.put("serviceId", "[HS Core]");
-       
-       ServletConfig sc = getServletConfig();
-       ServletContext sctx = sc.getServletContext();
-
-       getInitParams();
-       log.info("HS: Loading init params");
-
-       try {
-           edu.internet2.middleware.eduPerson.Init.init();
-           InputStream is = sctx.getResourceAsStream(getInitParameter("KSpath"));
-           hsSAML = new HandleServiceSAML( getInitParameter("domain"), 
-                                           getInitParameter("AAurl"),
-                                           getInitParameter("HSname"),
-                                           getInitParameter("KSpass"),
-                                           getInitParameter("KSkeyalias"),
-                                           getInitParameter("KSkeypass"),
-                                           getInitParameter("certalias"),
-                                           is );
-           
-           log.info("HS: Initializing Handle Repository with "+rep+" repository type.");
-           hrf = getHandleRepository();
-       }
-       catch (SAMLException ex) {
-           log.fatal("Error initializing SAML libraries: "+ ex);
-           throw new ServletException( "Error initializing SAML libraries: " + ex );
-       }
-       catch (java.security.KeyStoreException ex) {
-           log.fatal("Error initializing private KeyStore: "+ex);
-           throw new ServletException( "Error initializing private KeyStore: " + ex );
-       }
-       catch (RuntimeException ex) {
-           log.fatal("Error initializing eduPerson.Init: "+ ex); 
-           throw new ServletException( "Error initializing eduPerson.Init: "+ ex); 
-       }
-       catch (HandleException ex) {
-           log.fatal("Error initializing Handle Service: " +ex );
-           throw new ServletException( "Error initializing Handle Service: " +ex );
-       }
-       catch (Exception ex) {
-           log.fatal("Error in initialization: " +ex );
-           throw new ServletException( "Error in initialization: " +ex );
+       protected Properties configuration;
+       protected HandleRepository handleRepository;
+       private HandleServiceSAML hsSAML;
+       private String username;
+       private String rep;
+       private static Logger log = Logger.getLogger(HandleServlet.class.getName());
+       ;
+
+       protected Properties loadConfiguration() throws HandleException {
+
+               //Set defaults
+               Properties defaultProps = new Properties();
+               defaultProps.setProperty(
+                       "edu.internet2.middleware.shibboleth.hs.HandleRepository.implementation",
+                       "edu.internet2.middleware.shibboleth.hs.provider.MemoryHandleRepository");
+               defaultProps.setProperty("edu.internet2.middleware.shibboleth.hs.BaseHandleRepository.handleTTL", "1800000");
+               defaultProps.setProperty("edu.internet2.middleware.shibboleth.hs.HandleServlet.issuer", "shib2.internet2.edu");
+
+               //Load from file
+               Properties properties = new Properties(defaultProps);
+               String propertiesFileLocation = getInitParameter("OriginPropertiesFile");
+               if (propertiesFileLocation == null) {
+                       propertiesFileLocation = "/WEB-INF/conf/origin.properties";
+               }
+               try {
+                       log.debug("Loading Configuration from (" + propertiesFileLocation + ").");
+                       properties.load(getServletContext().getResourceAsStream(propertiesFileLocation));
+               } catch (IOException e) {
+                       log.error("Could not load HS servlet configuration: " + e);
+                       throw new HandleException("Could not load HS servlet configuration.");
+               }
+
+               if (log.isDebugEnabled()) {
+                       ByteArrayOutputStream debugStream = new ByteArrayOutputStream();
+                       PrintStream debugPrinter = new PrintStream(debugStream);
+                       properties.list(debugPrinter);
+                       log.debug(
+                               "Runtime configuration parameters: " + System.getProperty("line.separator") + debugStream.toString());
+               }
+
+               return properties;
        }
 
-       if (hsSAML == null) {
-           log.fatal("Error initializing SAML libraries: No Profile created." );
-           throw new ServletException( "Error initializing SAML libraries: No Profile created." );
-       }  
+       public void init() throws ServletException {
+
+               MDC.put("serviceId", "[HS Core]");
+               try {
+                       configuration = loadConfiguration();
+
+                       ServletConfig sc = getServletConfig();
+                       ServletContext sctx = sc.getServletContext();
+
+                       getInitParams();
+                       log.info("HS: Loading init params");
+
+                       edu.internet2.middleware.eduPerson.Init.init();
+                       InputStream is = sctx.getResourceAsStream(getInitParameter("KSpath"));
+                       hsSAML =
+                               new HandleServiceSAML(
+                                       getInitParameter("domain"),
+                                       getInitParameter("AAurl"),
+                                       configuration.getProperty("edu.internet2.middleware.shibboleth.hs.HandleServlet.issuer"),
+                                       getInitParameter("KSpass"),
+                                       getInitParameter("KSkeyalias"),
+                                       getInitParameter("KSkeypass"),
+                                       getInitParameter("certalias"),
+                                       is);
+
+                       log.info("HS: Initializing Handle Repository with " + rep + " repository type.");
+                       handleRepository = HandleRepositoryFactory.getInstance(configuration);
+                       
+               } catch (SAMLException ex) {
+                       log.fatal("Error initializing SAML libraries: " + ex);
+                       throw new ServletException("Error initializing SAML libraries: " + ex);
+               } catch (java.security.KeyStoreException ex) {
+                       log.fatal("Error initializing private KeyStore: " + ex);
+                       throw new ServletException("Error initializing private KeyStore: " + ex);
+               } catch (RuntimeException ex) {
+                       log.fatal("Error initializing eduPerson.Init: " + ex);
+                       throw new ServletException("Error initializing eduPerson.Init: " + ex);
+               } catch (HandleException ex) {
+                       log.fatal("Error initializing Handle Service: " + ex);
+                       throw new ServletException("Error initializing Handle Service: " + ex);
+               } catch (Exception ex) {
+                       log.fatal("Error in initialization: " + ex);
+                       throw new ServletException("Error in initialization: " + ex);
+               }
+
+               if (hsSAML == null) {
+                       log.fatal("Error initializing SAML libraries: No Profile created.");
+                       throw new ServletException("Error initializing SAML libraries: No Profile created.");
+               }
 
-    }
-
-
-    private void getInitParams() throws ServletException {
-
-       String ticket = getInitParameter("ticket");
-       if (ticket == null) {
-           ticket = "1400000";
        }
-       ticketExp = Long.parseLong(ticket);
-
-       username=getInitParameter("username");
 
-       if ( getInitParameter("domain") == null || 
-            getInitParameter("domain").equals("")) {
-           throw new ServletException("Cannot find host domain in init parameters");
-       }
-       if ( getInitParameter("AAurl") == null || 
-            getInitParameter("AAurl").equals("")) {
-           throw new ServletException("Cannot find host Attribute Authority location in init parameters");
-       }
-       if ( getInitParameter("HSname") == null || 
-            getInitParameter("HSname").equals("")) {
-           throw new ServletException("Cannot find Handle Service name in init parameters");
-       }
-       if ( getInitParameter("KSpath") == null || 
-            getInitParameter("KSpath").equals("")) {
-           throw new ServletException("Cannot find path to KeyStore file in init parameters");
-       }
-       if ( getInitParameter("KSpass") == null || 
-            getInitParameter("KSpass").equals("")) {
-           throw new ServletException("Cannot find password to KeyStore in init parameters");
+       private void getInitParams() throws ServletException {
+
+               username = getInitParameter("username");
+
+               if (getInitParameter("domain") == null || getInitParameter("domain").equals("")) {
+                       throw new ServletException("Cannot find host domain in init parameters");
+               }
+               if (getInitParameter("AAurl") == null || getInitParameter("AAurl").equals("")) {
+                       throw new ServletException("Cannot find host Attribute Authority location in init parameters");
+               }
+               if (getInitParameter("KSpath") == null || getInitParameter("KSpath").equals("")) {
+                       throw new ServletException("Cannot find path to KeyStore file in init parameters");
+               }
+               if (getInitParameter("KSpass") == null || getInitParameter("KSpass").equals("")) {
+                       throw new ServletException("Cannot find password to KeyStore in init parameters");
+               }
+               if (getInitParameter("KSkeyalias") == null || getInitParameter("KSkeyalias").equals("")) {
+                       throw new ServletException("Cannot find private key alias to KeyStore in init parameters");
+               }
+               if (getInitParameter("KSkeypass") == null || getInitParameter("KSkeypass").equals("")) {
+                       throw new ServletException("Cannot find private key password to Keystore in init parameters");
+               }
+               if (getInitParameter("certalias") == null || getInitParameter("certalias").equals("")) {
+                       throw new ServletException("Cannot find certificate alias in init parameters");
+               }
+               rep = getInitParameter("repository");
+               if (rep == null || rep.equals("")) {
+                       rep = "MEMORY";
+               }
        }
-       if ( getInitParameter("KSkeyalias") == null || 
-            getInitParameter("KSkeyalias").equals("")) {
-           throw new ServletException("Cannot find private key alias to KeyStore in init parameters");
-       }
-       if ( getInitParameter("KSkeypass") == null || 
-            getInitParameter("KSkeypass").equals("")) {
-           throw new ServletException("Cannot find private key password to Keystore in init parameters");
-       }
-       if ( getInitParameter("certalias") == null || 
-            getInitParameter("certalias").equals("")) {
-           throw new ServletException("Cannot find certificate alias in init parameters");
-       }
-       rep = getInitParameter("repository");
-       if ( rep == null || rep.equals("")) {
-           rep = "MEMORY"; 
-       }
-    }
 
+       public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
 
-    public void doGet(HttpServletRequest req, 
-                     HttpServletResponse res)
-       throws ServletException, IOException
-    {
+               log.debug("Recieved a request.");
+               MDC.put("serviceId", UUIDGenerator.getInstance().generateRandomBasedUUID());
+               MDC.put("remoteAddr", req.getRemoteAddr());
+               log.info("Handling request.");
 
-       log.debug("Recieved a request.");
-       MDC.put("serviceId", UUIDGenerator.getInstance().generateRandomBasedUUID());
-       MDC.put("remoteAddr", req.getRemoteAddr());
-       log.info("Handling request.");
+               try {
+                       checkRequestParams(req);
 
-       HandleEntry he = null;
+                       req.setAttribute("shire", req.getParameter("shire"));
+                       req.setAttribute("target", req.getParameter("target"));
 
-       try {
-           checkRequestParams(req);
+                       String localUsername =
+                               (username == null || username.equalsIgnoreCase("REMOTE_USER"))
+                                       ? req.getRemoteUser()
+                                       : req.getHeader(username);
+                       String handle = handleRepository.getHandle(new AAPrincipal(localUsername));
+                       log.info("Issued Handle (" + handle + ") to (" + localUsername + ")");
 
-           req.setAttribute("shire", req.getParameter("shire"));
-           req.setAttribute("target", req.getParameter("target"));
+                       byte[] buf =
+                               hsSAML.prepare(
+                                       handle,
+                                       req.getParameter("shire"),
+                                       req.getRemoteAddr(),
+                                       req.getAuthType(),
+                                       new Date(System.currentTimeMillis()));
 
-           he = new HandleEntry(
-               (username==null || username.equalsIgnoreCase("REMOTE_USER")) ? req.getRemoteUser() : req.getHeader(username),
-               req.getAuthType(),
-               ticketExp );
-           log.info("Issued Handle (" + he.getHandle() + ") to (" + he.getUsername() + ")");
-           hrf.insertHandleEntry( he );
-           
-           byte[] buf = hsSAML.prepare
-               ( he.getHandle(), req.getParameter("shire"), 
-                 req.getRemoteAddr(), he.getAuthType(), 
-                 new Date(he.getAuthInstant()));
+                       createForm(req, res, buf);
+               } catch (HandleException ex) {
+                       log.error(ex);
+                       handleError(req, res, ex);
+               }
 
-           createForm( req, res, buf );
-       }
-       catch (HandleException ex) {
-           log.error(ex);
-           handleError( req, res, ex );
        }
 
-    }
-    
-    private void createForm( HttpServletRequest req, 
-                            HttpServletResponse res,
-                            byte[] buf )  
-       throws HandleException
-    {
-       try {
-           /**
-            * forwarding to hs.jsp for submission
-             */
-           //Hardcoded to ASCII to ensure Base64 encoding compatibility
-           req.setAttribute("assertion", new String(buf, "ASCII"));
-           
-           if (log.isDebugEnabled()) {
+       private void createForm(HttpServletRequest req, HttpServletResponse res, byte[] buf) throws HandleException {
+               try {
+                       /**
+                        * forwarding to hs.jsp for submission
+                            */
+                       //Hardcoded to ASCII to ensure Base64 encoding compatibility
+                       req.setAttribute("assertion", new String(buf, "ASCII"));
+
+                       if (log.isDebugEnabled()) {
                                try {
                                        log.debug(
                                                "Dumping generated SAML Response:"
                                                        + System.getProperty("line.separator")
-                                                       + new String(
-                                                               new BASE64Decoder().decodeBuffer(new String(buf, "ASCII")),
-                                                               "UTF8"));
+                                                       + new String(new BASE64Decoder().decodeBuffer(new String(buf, "ASCII")), "UTF8"));
                                } catch (IOException e) {
                                        log.error("Encountered an error while decoding SAMLReponse for logging purposes.");
                                }
                        }
-           
-           
-           RequestDispatcher rd = req.getRequestDispatcher("/hs.jsp");
-           rd.forward(req, res);
-           
-       } catch (IOException ex) {
-           throw new HandleException
-               ("IO interruption while displaying Handle Service UI." + ex);
-       } 
-       
-         catch (ServletException ex) {
-           throw new HandleException
-               ("Problem displaying Handle Service UI." + ex);
-       }
 
-    }
+                       RequestDispatcher rd = req.getRequestDispatcher("/hs.jsp");
+                       rd.forward(req, res);
 
-    private void handleError( HttpServletRequest req, 
-                            HttpServletResponse res,
-                            Exception e )  
-       throws ServletException, IOException {
+               } catch (IOException ex) {
+                       throw new HandleException("IO interruption while displaying Handle Service UI." + ex);
+               } catch (ServletException ex) {
+                       throw new HandleException("Problem displaying Handle Service UI." + ex);
+               }
 
-       req.setAttribute("errorText", e.toString());
-       req.setAttribute("requestURL", req.getRequestURI().toString());
-       RequestDispatcher rd = req.getRequestDispatcher("/hserror.jsp");
-       
-       rd.forward(req, res);
-       
-    }
+       }
 
-                    
-    private void checkRequestParams( HttpServletRequest req )
-       throws HandleException {
+       private void handleError(HttpServletRequest req, HttpServletResponse res, Exception e)
+               throws ServletException, IOException {
+
+               req.setAttribute("errorText", e.toString());
+               req.setAttribute("requestURL", req.getRequestURI().toString());
+               RequestDispatcher rd = req.getRequestDispatcher("/hserror.jsp");
+
+               rd.forward(req, res);
 
-       if ( req.getParameter("target") == null 
-            || req.getParameter("target").equals("")) {
-           throw new HandleException("Invalid data from SHIRE: no target URL received.");
-       }
-       if ((req.getParameter("shire") == null)
-           || (req.getParameter("shire").equals(""))) {
-           throw new HandleException("Invalid data from SHIRE: No acceptance URL received.");
-       }
-       if ((req.getRemoteUser() == null)
-           || (req.getRemoteUser().equals(""))) {
-           throw new HandleException("Unable to authenticate remote user");
        }
-       if ((req.getRemoteAddr() == null)
-           || (req.getRemoteAddr().equals(""))) {
-           throw new HandleException("Unable to obtain client address.");
-       }    
-    }
-
-
-    private synchronized HandleRepositoryFactory getHandleRepository()
-       throws HandleException{
-
-       ServletConfig sc = getServletConfig();
-       ServletContext sctx = sc.getServletContext(); 
-       HandleRepositoryFactory hrf = (HandleRepositoryFactory)sctx.getAttribute("HandleRepository");
-
-       log.debug("Context attribute for HandleRepository: "+hrf);
-           
-       if(hrf == null){
-           // make one
-           String repositoryType = this.getServletContext().getInitParameter("repository");
-           hrf = HandleRepositoryFactory.getInstance(Constants.POLICY_CLUBSHIB,
-                                                     repositoryType,
-                                                     this );
-           sctx.setAttribute("HandleRepository", hrf);
-           log.info("A new HandleRepository created by HS: "+hrf);
+
+       private void checkRequestParams(HttpServletRequest req) throws HandleException {
+
+               if (req.getParameter("target") == null || req.getParameter("target").equals("")) {
+                       throw new HandleException("Invalid data from SHIRE: no target URL received.");
+               }
+               if ((req.getParameter("shire") == null) || (req.getParameter("shire").equals(""))) {
+                       throw new HandleException("Invalid data from SHIRE: No acceptance URL received.");
+               }
+               if ((req.getRemoteUser() == null) || (req.getRemoteUser().equals(""))) {
+                       throw new HandleException("Unable to authenticate remote user");
+               }
+               if ((req.getRemoteAddr() == null) || (req.getRemoteAddr().equals(""))) {
+                       throw new HandleException("Unable to obtain client address.");
+               }
        }
-       return hrf;
-    }
+
 }
 
     
diff --git a/src/edu/internet2/middleware/shibboleth/hs/provider/BaseHandleRepository.java b/src/edu/internet2/middleware/shibboleth/hs/provider/BaseHandleRepository.java
new file mode 100644 (file)
index 0000000..6b60dae
--- /dev/null
@@ -0,0 +1,107 @@
+/* 
+ * The Shibboleth License, Version 1. 
+ * Copyright (c) 2002 
+ * University Corporation for Advanced Internet Development, Inc. 
+ * All rights reserved
+ * 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this 
+ * list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation 
+ * and/or other materials provided with the distribution, if any, must include 
+ * the following acknowledgment: "This product includes software developed by 
+ * the University Corporation for Advanced Internet Development 
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
+ * may appear in the software itself, if and wherever such third-party 
+ * acknowledgments normally appear.
+ * 
+ * Neither the name of Shibboleth nor the names of its contributors, nor 
+ * Internet2, nor the University Corporation for Advanced Internet Development, 
+ * Inc., nor UCAID may be used to endorse or promote products derived from this 
+ * software without specific prior written permission. For written permission, 
+ * please contact shibboleth@shibboleth.org
+ * 
+ * Products derived from this software may not be called Shibboleth, Internet2, 
+ * UCAID, or the University Corporation for Advanced Internet Development, nor 
+ * may Shibboleth appear in their name, without prior written permission of the 
+ * University Corporation for Advanced Internet Development.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.hs.provider;
+
+import java.security.Principal;
+import java.util.Properties;
+
+import org.apache.log4j.Logger;
+
+import edu.internet2.middleware.shibboleth.hs.HandleRepository;
+import edu.internet2.middleware.shibboleth.hs.HandleRepositoryException;
+
+/**
+ * <code>HandleRepository</code> shared implementation code.
+ * 
+ * @author Walter Hoehn (wassa@columbia.edu)
+ */
+public abstract class BaseHandleRepository implements HandleRepository {
+
+       protected long handleTTL = 1800000;
+       private static Logger log = Logger.getLogger(BaseHandleRepository.class.getName());
+
+       protected BaseHandleRepository(Properties properties) throws HandleRepositoryException {
+               try {
+                       if (properties.getProperty("edu.internet2.middleware.shibboleth.hs.HandleRepository.handleTTL", null)
+                               != null) {
+
+                               handleTTL =
+                                       Long.parseLong(
+                                               properties.getProperty(
+                                                       "edu.internet2.middleware.shibboleth.hs.HandleRepository.handleTTL",
+                                                       null));
+                               if (handleTTL < 30000) {
+                                       log.warn(
+                                               "You have set the Attribute Query Handle \"Time To Live\' to a very low "
+                                                       + "value.  It is recommended that you increase it.");
+                               }
+                       }
+               } catch (NumberFormatException nfe) {
+                       log.error(
+                               "Value for (edu.internet2.middleware.shibboleth.hs.HandleRepository.handleTTL) must be a long integer.");
+                       throw new HandleRepositoryException("Value for (edu.internet2.middleware.shibboleth.hs.HandleRepository.handleTTL) must be a long integer.");
+               }
+
+       }
+
+       protected class HandleEntry {
+               protected Principal principal;
+               protected long creationTime;
+               
+               protected HandleEntry(Principal principal) {
+                       this.principal = principal;
+                       creationTime = System.currentTimeMillis();      
+               }
+
+               protected boolean isExpired() {
+                       return ((System.currentTimeMillis() - creationTime) > handleTTL);
+               }
+       }
+}
index 41f840d..6f67532 100644 (file)
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+
 package edu.internet2.middleware.shibboleth.hs.provider;
 
 import java.security.Principal;
+import java.util.Properties;
 
 import edu.internet2.middleware.shibboleth.hs.HandleRepository;
+import edu.internet2.middleware.shibboleth.hs.HandleRepositoryException;
 
 /**
  * <code>HandleRepository</code> implementation that employs the use of a shard secret
@@ -59,7 +61,11 @@ import edu.internet2.middleware.shibboleth.hs.HandleRepository;
  * 
  * @author Walter Hoehn (wassa@columbia.edu)
  */
-public class CryptoHandleRepository implements HandleRepository {
+public class CryptoHandleRepository extends BaseHandleRepository implements HandleRepository {
+
+       protected CryptoHandleRepository(Properties properties) throws HandleRepositoryException {
+               super(properties);
+       }
 
        /**
         * @see edu.internet2.middleware.shibboleth.hs.HandleRepository#getHandle(Principal)
diff --git a/src/edu/internet2/middleware/shibboleth/hs/provider/MemoryHandleRepository.java b/src/edu/internet2/middleware/shibboleth/hs/provider/MemoryHandleRepository.java
new file mode 100644 (file)
index 0000000..9e0f2c8
--- /dev/null
@@ -0,0 +1,110 @@
+/* 
+ * The Shibboleth License, Version 1. 
+ * Copyright (c) 2002 
+ * University Corporation for Advanced Internet Development, Inc. 
+ * All rights reserved
+ * 
+ * 
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * Redistributions of source code must retain the above copyright notice, this 
+ * list of conditions and the following disclaimer.
+ * 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation 
+ * and/or other materials provided with the distribution, if any, must include 
+ * the following acknowledgment: "This product includes software developed by 
+ * the University Corporation for Advanced Internet Development 
+ * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
+ * may appear in the software itself, if and wherever such third-party 
+ * acknowledgments normally appear.
+ * 
+ * Neither the name of Shibboleth nor the names of its contributors, nor 
+ * Internet2, nor the University Corporation for Advanced Internet Development, 
+ * Inc., nor UCAID may be used to endorse or promote products derived from this 
+ * software without specific prior written permission. For written permission, 
+ * please contact shibboleth@shibboleth.org
+ * 
+ * Products derived from this software may not be called Shibboleth, Internet2, 
+ * UCAID, or the University Corporation for Advanced Internet Development, nor 
+ * may Shibboleth appear in their name, without prior written permission of the 
+ * University Corporation for Advanced Internet Development.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+ * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
+ * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
+ * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
+ * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package edu.internet2.middleware.shibboleth.hs.provider;
+
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.doomdark.uuid.UUIDGenerator;
+
+import edu.internet2.middleware.shibboleth.hs.HandleRepository;
+import edu.internet2.middleware.shibboleth.hs.HandleRepositoryException;
+
+/**
+ * <code>HandleRepository</code> implementation that uses a static cache.  This requires
+ * that the HS and AA run in the same JVM.
+ * 
+ * @author Walter Hoehn (wassa@columbia.edu)
+ */
+public class MemoryHandleRepository extends BaseHandleRepository implements HandleRepository {
+
+       protected static Map handleEntries = new HashMap();
+
+       public MemoryHandleRepository(Properties properties) throws HandleRepositoryException {
+               super(properties);
+       }
+
+       /**
+        * @see edu.internet2.middleware.shibboleth.hs.HandleRepository#getHandle(Principal)
+        */
+       public String getHandle(Principal principal) {
+               String handle = UUIDGenerator.getInstance().generateRandomBasedUUID().toString();
+               synchronized (handleEntries) {
+                       handleEntries.put(handle, new HandleEntry(principal));
+               }
+               return handle;
+       }
+
+       /**
+        * @see edu.internet2.middleware.shibboleth.hs.HandleRepository#getPrincipal(String)
+        */
+       public Principal getPrincipal(String handle) {
+               synchronized (handleEntries) {
+                       if (!handleEntries.containsKey(handle)) {
+                               return null;
+                       }
+               }
+               HandleEntry handleEntry;
+               synchronized (handleEntries) {
+                       handleEntry = (HandleEntry) handleEntries.get(handle);
+               }
+               if (handleEntry.isExpired()) {
+                       synchronized (handleEntries) {
+                               handleEntries.remove(handle);
+                       }
+                       return null;
+               } else {
+                       return handleEntry.principal;
+               }
+       }
+
+}
index 252016d..bb49dc0 100755 (executable)
                        <param-value>shibdev.edu</param-value>
                </init-param>
                <init-param>
-                       <param-name>HSname</param-name>
-                       <param-value>shib2.internet2.edu</param-value>
-               </init-param>
-               <init-param>
-                       <param-name>ticket</param-name>
-                       <param-value>1400000</param-value>
-               </init-param>
-               <init-param>
                          <param-name>AAurl</param-name>
                          <param-value>https://shib2.internet2.edu/shibboleth-origin/servlet/AA</param-value>
                </init-param>
index 2f2b8d0..de73899 100755 (executable)
@@ -1,15 +1,24 @@
 #Full Path to ARP repository
 #edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository.Path = \
-       /opt/local/tomcat/webapps/shibboleth/WEB-INF/conf/arps/
+#      /opt/local/tomcat/webapps/shibboleth/WEB-INF/conf/arps/
 edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation = \
        edu.internet2.middleware.shibboleth.aa.arp.provider.FileSystemArpRepository
 
 edu.internet2.middleware.shibboleth.aa.AAServlet.authorityName = shib2.internet2.edu
 edu.internet2.middleware.shibboleth.aa.AAServlet.ldapUserDnPhrase = uid=
-
+#edu.internet2.middleware.shibboleth.aa.arp.BaseArpRepository.ArpTTL = 300000
 java.naming.factory.initial=edu.internet2.middleware.shibboleth.aaLocal.EchoCtxFactory
 
+#java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
 #java.naming.provider.url = ldap://shib2.internet2.edu/ou=People,dc=internet2,dc=edu
 #java.naming.security.principal =
 #java.naming.security.credentials =
 
+#edu.internet2.middleware.shibboleth.hs.HandleRepository.implementation = \
+#      edu.internet2.middleware.shibboleth.hs.provider.CryptoHandleRepository
+       
+edu.internet2.middleware.shibboleth.hs.HandleRepository.implementation = \
+       edu.internet2.middleware.shibboleth.hs.provider.MemoryHandleRepository
+       
+edu.internet2.middleware.shibboleth.hs.BaseHandleRepository.handleTTL = 1800000
+edu.internet2.middleware.shibboleth.hs.HandleServlet.issuer = shib2.internet2.edu
\ No newline at end of file