From e28000f11a5c2afab19c23d9596e87941a541f79 Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Wed, 23 Nov 2016 18:22:32 -0800 Subject: [PATCH 01/11] * Dependency-related fixes --- agents/josso-php-agent/pom.xml | 1 + agents/josso-phpBB-agent/pom.xml | 1 + applications/josso-console/josso-console-web/pom.xml | 1 + distributions/josso-gateway-web/pom.xml | 1 + examples/josso-partner-applet/josso-partner-applet-web/pom.xml | 1 + examples/josso-partner-asp/pom.xml | 1 + examples/josso-partner-jboss/josso-partner-jboss-web/pom.xml | 1 + examples/josso-partner-jboss5/josso-partner-jboss5-web/pom.xml | 1 + examples/josso-partner-jboss7/josso-partner-jboss7-web/pom.xml | 1 + examples/josso-partner-jetty/josso-partner-jetty-web/pom.xml | 1 + examples/josso-partner-php/pom.xml | 1 + examples/josso-partner-tomcat/josso-partner-tomcat-web/pom.xml | 1 + examples/josso-partner-wasce/josso-partner-wasce-web/pom.xml | 1 + examples/spring-security-contacts/pom.xml | 1 + examples/spring-security-v3-contacts/pom.xml | 2 +- pom.xml | 2 +- .../src/main/resources/archetype-resources/pom.xml | 2 +- 17 files changed, 17 insertions(+), 3 deletions(-) diff --git a/agents/josso-php-agent/pom.xml b/agents/josso-php-agent/pom.xml index 3ac70cb0..d0cd4627 100644 --- a/agents/josso-php-agent/pom.xml +++ b/agents/josso-php-agent/pom.xml @@ -42,6 +42,7 @@ org.codehaus.mojo build-helper-maven-plugin + 1.6 add-source diff --git a/agents/josso-phpBB-agent/pom.xml b/agents/josso-phpBB-agent/pom.xml index b269eb51..dc96a1b8 100644 --- a/agents/josso-phpBB-agent/pom.xml +++ b/agents/josso-phpBB-agent/pom.xml @@ -42,6 +42,7 @@ org.codehaus.mojo build-helper-maven-plugin + 1.6 add-source diff --git a/applications/josso-console/josso-console-web/pom.xml b/applications/josso-console/josso-console-web/pom.xml index b97927a7..d2731268 100644 --- a/applications/josso-console/josso-console-web/pom.xml +++ b/applications/josso-console/josso-console-web/pom.xml @@ -283,6 +283,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/consoleapp diff --git a/distributions/josso-gateway-web/pom.xml b/distributions/josso-gateway-web/pom.xml index f4c14dd7..19f89b4d 100644 --- a/distributions/josso-gateway-web/pom.xml +++ b/distributions/josso-gateway-web/pom.xml @@ -311,6 +311,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-applet/josso-partner-applet-web/pom.xml b/examples/josso-partner-applet/josso-partner-applet-web/pom.xml index b02ce4d1..0800b56b 100644 --- a/examples/josso-partner-applet/josso-partner-applet-web/pom.xml +++ b/examples/josso-partner-applet/josso-partner-applet-web/pom.xml @@ -50,6 +50,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-asp/pom.xml b/examples/josso-partner-asp/pom.xml index afd1260b..a8b0d8da 100644 --- a/examples/josso-partner-asp/pom.xml +++ b/examples/josso-partner-asp/pom.xml @@ -63,6 +63,7 @@ org.codehaus.mojo build-helper-maven-plugin + 1.6 add-source diff --git a/examples/josso-partner-jboss/josso-partner-jboss-web/pom.xml b/examples/josso-partner-jboss/josso-partner-jboss-web/pom.xml index 3498e62b..bb5efb49 100644 --- a/examples/josso-partner-jboss/josso-partner-jboss-web/pom.xml +++ b/examples/josso-partner-jboss/josso-partner-jboss-web/pom.xml @@ -82,6 +82,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-jboss5/josso-partner-jboss5-web/pom.xml b/examples/josso-partner-jboss5/josso-partner-jboss5-web/pom.xml index 91c6e4c3..18166248 100644 --- a/examples/josso-partner-jboss5/josso-partner-jboss5-web/pom.xml +++ b/examples/josso-partner-jboss5/josso-partner-jboss5-web/pom.xml @@ -82,6 +82,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-jboss7/josso-partner-jboss7-web/pom.xml b/examples/josso-partner-jboss7/josso-partner-jboss7-web/pom.xml index eaf349c1..7008e525 100644 --- a/examples/josso-partner-jboss7/josso-partner-jboss7-web/pom.xml +++ b/examples/josso-partner-jboss7/josso-partner-jboss7-web/pom.xml @@ -82,6 +82,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-jetty/josso-partner-jetty-web/pom.xml b/examples/josso-partner-jetty/josso-partner-jetty-web/pom.xml index 98d0ec79..e07846a6 100644 --- a/examples/josso-partner-jetty/josso-partner-jetty-web/pom.xml +++ b/examples/josso-partner-jetty/josso-partner-jetty-web/pom.xml @@ -97,6 +97,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-php/pom.xml b/examples/josso-partner-php/pom.xml index 88fa6b65..3c29f925 100644 --- a/examples/josso-partner-php/pom.xml +++ b/examples/josso-partner-php/pom.xml @@ -63,6 +63,7 @@ org.codehaus.mojo build-helper-maven-plugin + 1.6 add-source diff --git a/examples/josso-partner-tomcat/josso-partner-tomcat-web/pom.xml b/examples/josso-partner-tomcat/josso-partner-tomcat-web/pom.xml index a6c5dce1..7bb8cf3a 100644 --- a/examples/josso-partner-tomcat/josso-partner-tomcat-web/pom.xml +++ b/examples/josso-partner-tomcat/josso-partner-tomcat-web/pom.xml @@ -82,6 +82,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/josso-partner-wasce/josso-partner-wasce-web/pom.xml b/examples/josso-partner-wasce/josso-partner-wasce-web/pom.xml index 9a50d176..b239f478 100644 --- a/examples/josso-partner-wasce/josso-partner-wasce-web/pom.xml +++ b/examples/josso-partner-wasce/josso-partner-wasce-web/pom.xml @@ -82,6 +82,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/spring-security-contacts/pom.xml b/examples/spring-security-contacts/pom.xml index dd5adf77..6a86bfda 100644 --- a/examples/spring-security-contacts/pom.xml +++ b/examples/spring-security-contacts/pom.xml @@ -169,6 +169,7 @@ org.apache.maven.plugins maven-war-plugin + 2.1.1 src/main/webapp/ diff --git a/examples/spring-security-v3-contacts/pom.xml b/examples/spring-security-v3-contacts/pom.xml index 481f428c..1b134b3c 100644 --- a/examples/spring-security-v3-contacts/pom.xml +++ b/examples/spring-security-v3-contacts/pom.xml @@ -210,7 +210,7 @@ org.apache.maven.plugins maven-war-plugin - 2.0.2 + 2.1.1 ${basedir}/src/main/webapp/WEB-INF/web.xml ${basedir}/src/main/webapp diff --git a/pom.xml b/pom.xml index 76968b9b..9fd58fc5 100644 --- a/pom.xml +++ b/pom.xml @@ -1620,7 +1620,7 @@ org.apache.maven.plugins maven-war-plugin - 2.1-beta-1 + 2.1.1 src/webapp/ diff --git a/tooling/archetypes/josso-archetype-gateway/src/main/resources/archetype-resources/pom.xml b/tooling/archetypes/josso-archetype-gateway/src/main/resources/archetype-resources/pom.xml index a09cd081..aeb77860 100644 --- a/tooling/archetypes/josso-archetype-gateway/src/main/resources/archetype-resources/pom.xml +++ b/tooling/archetypes/josso-archetype-gateway/src/main/resources/archetype-resources/pom.xml @@ -372,7 +372,7 @@ org.apache.maven.plugins maven-war-plugin - 2.1-beta-1 + 2.1.1 src/main/webapp/ From fae8073d528eae543ea0c5493afa00a871ea6f13 Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Fri, 9 Dec 2016 18:53:00 -0800 Subject: [PATCH 02/11] * Implemented Apache Tomcat 8.5 agent --- agents/josso-tomcat85-agent/pom.xml | 159 +++ .../src/main/assembly/bin-spring.xml | 57 + .../src/main/assembly/bin.xml | 70 ++ .../tc85/agent/CatalinaLocalSession.java | 44 + .../josso/tc85/agent/CatalinaNativeRealm.java | 128 +++ .../josso/tc85/agent/CatalinaSSOAgent.java | 131 +++ .../tc85/agent/CatalinaSSOAgentRequest.java | 59 ++ .../josso/tc85/agent/LocalSessionImpl.java | 107 ++ .../org/josso/tc85/agent/SSOAgentValve.java | 970 ++++++++++++++++++ .../tc85/agent/jaas/CatalinaJAASRealm.java | 62 ++ .../tc85/agent/jaas/CatalinaSSOUser.java | 196 ++++ .../agent/jaas/SSOGatewayLoginModule.java | 324 ++++++ agents/pom.xml | 2 + 13 files changed, 2309 insertions(+) create mode 100644 agents/josso-tomcat85-agent/pom.xml create mode 100644 agents/josso-tomcat85-agent/src/main/assembly/bin-spring.xml create mode 100644 agents/josso-tomcat85-agent/src/main/assembly/bin.xml create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaNativeRealm.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgentRequest.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaJAASRealm.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaSSOUser.java create mode 100644 agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/SSOGatewayLoginModule.java diff --git a/agents/josso-tomcat85-agent/pom.xml b/agents/josso-tomcat85-agent/pom.xml new file mode 100644 index 00000000..6ac2d6ab --- /dev/null +++ b/agents/josso-tomcat85-agent/pom.xml @@ -0,0 +1,159 @@ + + + + + + 4.0.0 + + + org.josso + agents + 1.8.11-SNAPSHOT + + + josso-tomcat85-agent + jar + JOSSO :: Tomcat 8.5 Agent + Tomcat 8.5 Agent + + + 8.5.9 + + + + + + + + + + org.josso + josso-agent + + + + org.josso + josso-protocol-client + + + + org.josso + josso-ws + + + + + + + org.apache.tomcat + tomcat-catalina + ${tomcat-version} + provided + + + + org.apache.tomcat + tomcat-util-scan + ${tomcat-version} + provided + + + + commons-httpclient + commons-httpclient + 3.1 + provided + + + + + + + + commons-beanutils + commons-beanutils + 1.6.1 + runtime + + + + commons-collections + commons-collections + 3.0 + runtime + + + + commons-digester + commons-digester + 1.5 + runtime + + + + commons-discovery + commons-discovery + 0.2 + runtime + + + + commons-lang + commons-lang + 2.0 + runtime + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + + + org.apache.xbean + maven-xbean-plugin + ${xbean-version} + + + + urn:org:josso:agent:tomcat85 + + + mapping + + + + + + + + + diff --git a/agents/josso-tomcat85-agent/src/main/assembly/bin-spring.xml b/agents/josso-tomcat85-agent/src/main/assembly/bin-spring.xml new file mode 100644 index 00000000..a5fd4f96 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/assembly/bin-spring.xml @@ -0,0 +1,57 @@ + + + + + + bin + false + + tar.gz + zip + + + + lib + + org.josso:josso-tomcat85-agent + org.josso:josso-agent-shared + org.apache.axis:axis + commons-beanutils:commons-beanutils + commons-collections:commons-collections + commons-configuration:commons-configuration + commons-digester:commons-digester + commons-discovery:commons-discovery + commons-httpclient:commons-httpclient + commons-lang:commons-lang + org.apache.axis:axis-jaxrpc + org.apache.axis:axis-saaj + org.apache.axis:axis-wsdl4j + org.springframework:spring-aop + org.springframework:spring-beans + org.springframework:spring-context + org.springframework:spring-core + org.springframework:spring-jmx + + + + diff --git a/agents/josso-tomcat85-agent/src/main/assembly/bin.xml b/agents/josso-tomcat85-agent/src/main/assembly/bin.xml new file mode 100644 index 00000000..23d817ed --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/assembly/bin.xml @@ -0,0 +1,70 @@ + + + + + + bin + false + + tar.gz + zip + + + + lib + + + org.josso:josso-tomcat85-agent + org.josso:josso-agent-shared + org.josso:josso-core + org.josso:josso-protocol-client + org.josso:josso-ws + + commons-beanutils:commons-beanutils + commons-collections:commons-collections + commons-digester:commons-digester + commons-discovery:commons-discovery + commons-httpclient:commons-httpclient + commons-lang:commons-lang + + commons-logging:commons-logging + + + + org.springframework:spring-beans + org.springframework:spring-context + org.springframework:spring-core + org.apache.xbean:xbean-spring + + org.apache.axis:axis + org.apache.axis:axis-jaxrpc + org.apache.axis:axis-saaj + axis:axis-wsdl4j + + + + + diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java new file mode 100644 index 00000000..db8849b0 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java @@ -0,0 +1,44 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent; + +import org.apache.catalina.Session; + +/** + * Acts as a Catalina Session wrapper. + * + * @author Gianluca Brigandi + * @version CVS $Id: CatalinaLocalSession.java 974 2009-01-14 00:39:45Z sgonzalez $ + */ +public class CatalinaLocalSession extends LocalSessionImpl { + + public CatalinaLocalSession( Session catalinaSession) { + super(); + + setWrapped(catalinaSession); + setMaxInactiveInterval(catalinaSession.getMaxInactiveInterval()); + + + } + +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaNativeRealm.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaNativeRealm.java new file mode 100644 index 00000000..1010b4c1 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaNativeRealm.java @@ -0,0 +1,128 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent; + +import org.apache.catalina.realm.RealmBase; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.josso.agent.AbstractSSOAgent; +import org.josso.agent.Lookup; +import org.josso.agent.SSOAgent; +import org.josso.agent.SSOAgentRequest; +import org.josso.gateway.identity.SSORole; +import org.josso.gateway.identity.SSOUser; +import org.josso.gateway.identity.exceptions.SSOIdentityException; +import org.josso.gateway.identity.service.SSOIdentityManagerService; +import org.josso.tc85.agent.jaas.CatalinaSSOUser; + +import javax.security.auth.Subject; +import java.security.Principal; + +/** + * Catalina Realm replacement that will authenticate users + * directly against the gateway. + */ +public class CatalinaNativeRealm extends RealmBase { + private static Log log = LogFactory.getLog(CatalinaNativeRealm.class); + + /** + * Descriptive information about this Realm implementation. + */ + protected static final String name = "CatalinaNativeRealm"; + + @Override + public Principal authenticate(String username, String credentials) { + try { + SSOAgentRequest request = AbstractSSOAgent._currentRequest.get(); + SSOAgent agent = Lookup.getInstance().lookupSSOAgent(); + + SSOIdentityManagerService im = request.getConfig(agent).getIdentityManagerService(); + if (im == null) + im = agent.getSSOIdentityManager(); + + String requester = ""; + // Check for nulls ? + + if (request != null) + requester = request.getRequester(); + else + log.warn("No SSO Agent request found in thread local variable, can't identify requester"); + + SSOUser ssoUser = im.findUserInSession(requester, username); + + Principal principal = null; + + if (ssoUser != null) { + Subject subject = new Subject(); + subject.getPrincipals().add(ssoUser); + SSORole[] ssoRolePrincipals = im.findRolesBySSOSessionId(requester, username); + for (int i=0; i < ssoRolePrincipals.length; i++) { + subject.getPrincipals().add(ssoRolePrincipals[i]); + } + // Return the appropriate Principal for this authenticated Subject + principal = createPrincipal(username, subject); + } + + return principal; + } catch (SSOIdentityException e) { + // Ignore this ... (user does not exist for this session) + if (log.isDebugEnabled()) { + log.debug(e.getMessage()); + } + return null; + } catch (Exception e) { + log.error("Session authentication failed : " + username, e); + throw new RuntimeException("Fatal error authenticating session : " + e); + } + } + + /** + * Construct and return a java.security.Principal instance + * representing the authenticated user for the specified Subject. If no + * such Principal can be constructed, return null. + * + * The Principal constructed is CatalinaSSOUser which is a SSOUser. + * The Partner Application can access SSOUser-specific properties that are not available + * in GenericPrincipal. + * + * @param subject The Subject representing the logged in user + */ + protected Principal createPrincipal(String username, Subject subject) { + return CatalinaSSOUser.newInstance(this, subject); + } + + @Override + protected String getName() { + return name; + } + + @Override + protected String getPassword(String username) { + return null; + } + + @Override + protected Principal getPrincipal(String username) { + return authenticate(username, username); + } +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java new file mode 100644 index 00000000..0e1f5eb0 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java @@ -0,0 +1,131 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent; + +import org.apache.catalina.Container; +import org.apache.catalina.Context; +import org.apache.catalina.Realm; +import org.josso.agent.SSOAgentRequest; +import org.josso.agent.http.HttpSSOAgent; + +import java.security.Principal; + +/** + * @org.apache.xbean.XBean element="agent" + * + * Catalina SSO Agent Implementation that authenticates using the configured Catalina Realm's + * Gateway SSO Login module. + * + * @author Gianluca Brigandi + * @version CVS $Id: CatalinaSSOAgent.java 974 2009-01-14 00:39:45Z sgonzalez $ + */ +public class CatalinaSSOAgent extends HttpSSOAgent { + + private Container _container; + + public CatalinaSSOAgent() { + super(); + } + + + public CatalinaSSOAgent(Container container) { + super(); + _container = container; + + } + + public void start() { + super.start(); + // Add context config as partner app ... + if (_container instanceof Context) { + Context context = (Context) _container; + _cfg.addSSOPartnerApp(context.getPublicId(), null, context.getPath(), null, null); + } + } + + /** + * Sets the Catalina Context to be used by the authenticator. + * + * @param container + */ + public void setCatalinaContainer(Container container) { + _container = container; + + } + + /** + * Authenticates the Single Sign-on Session by calling the + * configured Realm for the Catalina Context. The configured Realm + * should be the JAAS one so that the GatewayLoginModule can act + * and validate de given SSO Session Identifier in the Gateway. + * + * @param request + * @return the authenticated principal. + */ + protected Principal authenticate(SSOAgentRequest request) { + CatalinaSSOAgentRequest r = (CatalinaSSOAgentRequest) request; + Context c = r.getContext(); + + // Invoke authentication + Realm realm = c.getRealm(); + + if (debug > 0) + log("Using realm : " + realm.getClass().getName() + " SSOSID : " + r.getSessionId()); + + Principal p = realm.authenticate(r.getSessionId(), r.getSessionId()); + + if (debug > 0) + log("Received principal : " + p + "[" + ( p != null ? p.getClass().getName() : "" ) +"]"); + + return p; + } + + protected void log(String message) { + if (_container != null) { + if (_container.getLogger().isDebugEnabled()) + _container.getLogger().debug(this.toString() + ": " + message); + } else + System.out.println(this.toString() + ": " + message); + } + + protected void log(String message, Throwable throwable) { + if (_container != null) { + if (_container.getLogger().isDebugEnabled()) + _container.getLogger().debug(this.toString() + ": " + message, throwable); + } else + System.out.println(this.toString() + ": " + message); + } + + /** + * Return a String rendering of this object. + */ + public String toString() { + + StringBuffer sb = new StringBuffer("CatalinaSSOAgent["); + sb.append(_container != null ? _container.getName() : ""); + sb.append("]"); + return (sb.toString()); + + } + +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgentRequest.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgentRequest.java new file mode 100644 index 00000000..fb9c0a49 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgentRequest.java @@ -0,0 +1,59 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent; + + +import org.apache.catalina.Context; +import org.josso.agent.LocalSession; +import org.josso.agent.http.HttpSSOAgentRequest; + +/** + * @author Sebastian Gonzalez Oyuela + * @version $Id: CatalinaSSOAgentRequest.java 1607 2010-05-11 13:39:08Z sgonzalez $ + */ + +public class CatalinaSSOAgentRequest extends HttpSSOAgentRequest { + + private Context _context; + + + public CatalinaSSOAgentRequest(String requester, int action, String sessionId, LocalSession session, String assertionId) { + super(requester, action, sessionId, session, assertionId, null); + } + + public CatalinaSSOAgentRequest(String requester, int action, String sessionId, LocalSession session) { + this(requester, action, sessionId, session, null); + } + + void setContext(Context c) { + _context = c; + } + + /** + * The context associated with this request. + */ + public Context getContext() { + return _context; + } + +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java new file mode 100644 index 00000000..177c0bfb --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java @@ -0,0 +1,107 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent; + +import org.apache.catalina.Session; +import org.josso.agent.LocalSession; +import org.josso.agent.LocalSessionEvent; +import org.josso.agent.LocalSessionListener; + +import java.util.ArrayList; +import java.util.Iterator; + +/** + * Local Session default implementation. + * + * @author Gianluca Brigandi + * @version CVS $Id: LocalSessionImpl.java 974 2009-01-14 00:39:45Z sgonzalez $ + */ + +public class LocalSessionImpl implements LocalSession { + + /** + * The session event listeners for this Session. + */ + private transient ArrayList _listeners = new ArrayList(); + private long _creationTime; + + + private String _id; + private long _lastAccessedTime; + private int _maxInactiveInterval; + private Object _wrapped; + + public LocalSessionImpl() { + } + + public long getCreationTime() { + return _creationTime; + } + + public String getId() { + return _id; + } + + public long getLastAccessedTime() { + return _lastAccessedTime; + } + + public void setMaxInactiveInterval(int i) { + _maxInactiveInterval = i; + } + + public int getMaxInactiveInterval() { + return _maxInactiveInterval; + } + + public void expire() { + + Iterator i = _listeners.iterator(); + while (i.hasNext()) { + LocalSessionListener listener = (LocalSessionListener) i.next(); + + listener.localSessionEvent(new LocalSessionEvent(this, LocalSession.LOCAL_SESSION_DESTROYED_EVENT, null)); + } + } + + public void addSessionListener(LocalSessionListener sessionListener) { + _listeners.add(sessionListener); + } + + public void removeSessionListener(LocalSessionListener sessionListener) { + _listeners.remove(sessionListener); + } + + public void invalidate() { + ((Session)_wrapped).expire(); + } + + public void setWrapped(Object wrapped) { + _wrapped = wrapped; + } + + public Object getWrapped() { + return _wrapped; + } +} + diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java new file mode 100644 index 00000000..679c9afe --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java @@ -0,0 +1,970 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent; + +import org.apache.catalina.*; +import org.apache.catalina.authenticator.SavedRequest; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.apache.tomcat.util.descriptor.web.SecurityConstraint; +import org.josso.agent.*; +import org.josso.agent.http.WebAccessControlUtil; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.util.*; + + +/** + * Single Sign-On Agent implementation for Tomcat Catalina. + * + * @author Gianluca Brigandi + * @version $Id: SSOAgentValve.java 1657 2010-10-13 20:48:21Z sgonzalez $ + */ +public class SSOAgentValve extends ValveBase + implements Lifecycle, SessionListener { + + /** + * The debugging detail level for this component. + */ + protected int debug = 0; + + + /** + * Descriptive information about this Valve implementation. + */ + protected static String info = + "org.apache.catalina.authenticator.SingleSignOn"; + + + /** + * Component started flag. + */ + protected boolean started = false; + private CatalinaSSOAgent _agent; + + /** + * Catalina Session to Local Session Map. + */ + Map _sessionMap = Collections.synchronizedMap(new HashMap()); + + // ------------------------------------------------------------- Properties + + /** + * Return the debugging detail level. + */ + public int getDebug() { + + return (this.debug); + + } + + + /** + * Set the debugging detail level. + * + * @param debug The new debugging detail level + */ + public void setDebug(int debug) { + + this.debug = debug; + + } + + // ------------------------------------------------------ SessionListener Methods + + public void sessionEvent(SessionEvent event) { + + + // obtain the local session for the catalina session, and notify the listeners for it. + LocalSession localSession = (LocalSession) _sessionMap.get(event.getSession().getId()); + + if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { + localSession.expire(); + _sessionMap.remove(event.getSession().getId()); + } + + } + + // ------------------------------------------------------ Lifecycle Methods + + + /** + * Set the Container to which this Valve is attached. + * + * @param container The container to which we are attached + public void setContainer(Container container) { + + if (!(container instanceof Context)) + throw new IllegalArgumentException + ("The SSOAgentValve must be associated to a Catalina Context or Host"); + + super.setContainer(container); + _container = container; + } + */ + + /** + * Prepare for the beginning of active use of the public methods of this + * component. This method should be called after configure(), + * and before any of the public methods of the component are utilized. + * + * @throws org.apache.catalina.LifecycleException if this component detects a fatal error + * that prevents this component from being used + */ + protected synchronized void startInternal() throws LifecycleException { + + // Validate and update our current component state + if (started) + throw new LifecycleException + ("Agent already started"); + fireLifecycleEvent(START_EVENT, null); + started = true; + + try { + Lookup lookup = Lookup.getInstance(); + lookup.init("josso-agent-config.xml"); + _agent = (CatalinaSSOAgent) lookup.lookupSSOAgent(); + _agent.setDebug(debug); + _agent.setCatalinaContainer(container); + } catch (Exception e) { + System.err.println(e.getMessage()); + e.printStackTrace(System.err); + throw new LifecycleException("Error starting SSO Agent : " + e.getMessage()); + } + _agent.start(); + + if (debug >= 1) + log("Started"); + + setState(LifecycleState.STARTING); + } + + /** + * Gracefully terminate the active use of the public methods of this + * component. This method should be the last one called on a given + * instance of this component. + * + * @throws org.apache.catalina.LifecycleException if this component detects a fatal error + * that needs to be reported + */ + protected synchronized void stopInternal() throws LifecycleException { + + setState(LifecycleState.STOPPING); + + // Validate and update our current component state + if (!started) + throw new LifecycleException + ("Agent not started"); + fireLifecycleEvent(STOP_EVENT, null); + started = false; + + _agent.stop(); + + if (debug >= 1) + log("Stopped"); + + } + + + + // ---------------------------------------------------------- Valve Methods + + + /** + * Return descriptive information about this Valve implementation. + */ + public String getInfo() { + return (info); + } + + /** + * Perform single-sign-on support processing for this request. + * + * @param request The servlet request we are processing + * @param response The servlet response we are creating + * in the current processing pipeline + * @throws IOException if an input/output error occurs + * @throws javax.servlet.ServletException if a servlet error occurs + */ + + public void invoke(Request request, Response response) + throws IOException, ServletException { + + HttpServletRequest hreq = + (HttpServletRequest) request.getRequest(); + HttpServletResponse hres = + (HttpServletResponse) response.getResponse(); + + + if (debug >= 1) + log("Processing : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + + try { + // ------------------------------------------------------------------ + // Check with the agent if this context should be processed. + // ------------------------------------------------------------------ + String contextPath = hreq.getContextPath(); + String vhost = hreq.getServerName(); + + // In catalina, the empty context is considered the root context + if ("".equals(contextPath)) + contextPath = "/"; + + if (!_agent.isPartnerApp(vhost, contextPath)) { + getNext().invoke(request, response); + if (debug >= 1) + log("Context is not a josso partner app : " + hreq.getContextPath()); + + return; + } + + // URI Encoding + if (_agent.getUriEncoding() != null) { + if (debug >= 1) + log("Setting request/response encoding to " + _agent.getUriEncoding()); + hreq.setCharacterEncoding(_agent.getUriEncoding()); + hres.setCharacterEncoding(_agent.getUriEncoding()); + } + + String nodeId = hreq.getParameter("josso_node"); + if (nodeId != null) { + if (debug >= 1) + log("Storing JOSSO Node id : " + nodeId); + _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); + } else { + nodeId = _agent.getAttribute(hreq, "JOSSO_NODE"); + if (debug >= 1) + log("Found JOSSO Node id : " + nodeId); + } + + + // ------------------------------------------------------------------ + // Check some basic HTTP handling + // ------------------------------------------------------------------ + SSOPartnerAppConfig cfg = _agent.getPartnerAppConfig(vhost, contextPath); + + + // P3P Header for IE 6+ compatibility when embedding JOSSO in a IFRAME + if (cfg.isSendP3PHeader() && !hres.isCommitted()) { + hres.setHeader("P3P", cfg.getP3PHeaderValue()); + } + + // Get our session ... + Session session = getSession(request, true); + + // ------------------------------------------------------------------ + // Check if the partner application required the login form + // ------------------------------------------------------------------ + if (debug >= 1) + log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); + + if (hreq.getRequestURI().endsWith(_agent.getJossoLoginUri()) || + hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { + + if (debug >= 1) + log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); + + //save referer url in case the user clicked on Login from some public resource (page) + //so agent can redirect the user back to that page after successful login + if (hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { + saveLoginBackToURL(hreq, hres, session, true); + } else { + saveLoginBackToURL(hreq, hres, session, false); + } + + String loginUrl = _agent.buildLoginUrl(hreq); + + if (debug >= 1) + log("Redirecting to login url '" + loginUrl + "'"); + + //set non cache headers + _agent.prepareNonCacheResponse(hres); + hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); + + return; + + } + + // ------------------------------------------------------------------ + // Check if the partner application required a logout + // ------------------------------------------------------------------ + if (debug >= 1) + log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); + + if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) { + + if (debug >= 1) + log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); + + String logoutUrl = _agent.buildLogoutUrl(hreq, cfg); + + if (debug >= 1) + log("Redirecting to logout url '" + logoutUrl + "'"); + + // Clear previous COOKIE ... + Cookie ssoCookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); + hres.addCookie(ssoCookie); + + //set non cache headers + _agent.prepareNonCacheResponse(hres); + hres.sendRedirect(hres.encodeRedirectURL(logoutUrl)); + + return; + + } + + // ------------------------------------------------------------------ + // Check for the single sign on cookie + // ------------------------------------------------------------------ + if (debug >= 1) + log("Checking for SSO cookie"); + Cookie cookie = null; + Cookie cookies[] = hreq.getCookies(); + if (cookies == null) + cookies = new Cookie[0]; + for (int i = 0; i < cookies.length; i++) { + if (org.josso.gateway.Constants.JOSSO_SINGLE_SIGN_ON_COOKIE.equals(cookies[i].getName())) { + cookie = cookies[i]; + break; + } + } + + String jossoSessionId = (cookie == null) ? null : cookie.getValue(); + if (debug >= 1) + log("Session is: " + session); + LocalSession localSession = (LocalSession) _sessionMap.get(session.getId()); + if (localSession == null) { + localSession = new CatalinaLocalSession(session); + // the local session is new so, make the valve listen for its events so that it can + // map them to local session events. + session.addSessionListener(this); + _sessionMap.put(session.getId(), localSession); + } + // ------------------------------------------------------------------ + // Check if the partner application submitted custom login form + // ------------------------------------------------------------------ + + if (debug >= 1){ + log("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'"); + } + if (hreq.getRequestURI().endsWith(_agent.getJossoAuthenticationUri())) { + + if (debug >= 1) + log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); + + CatalinaSSOAgentRequest customAuthRequest = new CatalinaSSOAgentRequest(cfg.getId(), + SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); + + customAuthRequest.setRequest(hreq); + customAuthRequest.setResponse(hres); + customAuthRequest.setContext(request.getContext()); + + _agent.processRequest(customAuthRequest); + + return; + } + + if (cookie == null || cookie.getValue().equals("-")) { + + // ------------------------------------------------------------------ + // Trigger LOGIN OPTIONAL if required + // ------------------------------------------------------------------ + + if (debug >= 1) + log("SSO cookie is not present, verifying optional login process "); + + // We have no cookie, remember me is enabled and a security check without assertion was received ... + // This means that the user could not be identified ... go back to the original resource + if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && + hreq.getParameter("josso_assertion_id") == null) { + + if (debug >= 1) + log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); + + String requestURI = this.getSavedRequestURL(hreq, session); + _agent.prepareNonCacheResponse(hres); + hres.sendRedirect(hres.encodeRedirectURL(requestURI)); + return; + + } + + // This is a standard anonymous request! + if (!hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri())) { + + // If saved request is NOT null, we're in the middle of another process ... + if (!isResourceIgnored(cfg, request) && + _agent.isAutomaticLoginRequired(hreq, hres)) { + + if (debug >= 1) + log("SSO cookie is not present, attempting automatic login"); + + // Save current request, so we can co back to it later ... + saveRequest(request, session); + String loginUrl = _agent.buildLoginOptionalUrl(hreq); + + if (debug >= 1) + log("Redirecting to login url '" + loginUrl + "'"); + + //set non cache headers + _agent.prepareNonCacheResponse(hres); + hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); + return; + } else { + if (debug >= 1) + log("SSO cookie is not present, but login optional process is not required"); + } + // save requested resource + if (!isResourceIgnored(cfg, request)) { + StringBuffer sb = new StringBuffer(hreq.getRequestURI()); + if (hreq.getQueryString() != null) { + sb.append('?'); + sb.append(hreq.getQueryString()); + } + _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + } + } + + if (debug >= 1) + log("SSO cookie is not present, checking for outbound relaying"); + + if (!(hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && + hreq.getParameter("josso_assertion_id") != null)) { + log("SSO cookie not present and relaying was not requested, skipping"); + getNext().invoke(request, response); + return; + } + + } + + // ------------------------------------------------------------------ + // Check if this URI is subject to SSO protection + // ------------------------------------------------------------------ + if (isResourceIgnored(cfg, request)) { + getNext().invoke(request, response); + return; + } + + // This URI should be protected by SSO, go on ... + if (debug >= 1) + log("Session is: " + session); + + // ------------------------------------------------------------------ + // Invoke the SSO Agent + // ------------------------------------------------------------------ + if (debug >= 1) + log("Executing agent..."); + + _agent.setCatalinaContainer(request.getContext()); + + // ------------------------------------------------------------------ + // Check if a user has been authenticated and should be checked by the agent. + // ------------------------------------------------------------------ + if (debug >= 1) + log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); + + if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && + hreq.getParameter("josso_assertion_id") != null) { + + if (debug >= 1) + log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + + hreq.getParameter("josso_assertion_id") + ); + + String assertionId = hreq.getParameter(Constants.JOSSO_ASSERTION_ID_PARAMETER); + + CatalinaSSOAgentRequest relayRequest; + + if (debug >= 1) + log("Outbound relaying requested for assertion id [" + assertionId + "]"); + + relayRequest = new CatalinaSSOAgentRequest(cfg.getId(), + SSOAgentRequest.ACTION_RELAY, null, localSession, assertionId + ); + relayRequest.setRequest(hreq); + relayRequest.setResponse(hres); + relayRequest.setContext(request.getContext()); + + SingleSignOnEntry entry = _agent.processRequest(relayRequest); + if (entry == null) { + // This is wrong! We should have an entry here! + if (debug >= 1) + log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); + // Throw an exception, we will handle it below ! + throw new RuntimeException("Outbound relaying failed. No Principal found. Verify your SSO Agent Configuration!"); + } + + if (debug >= 1) + log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); + + if (debug >= 1) + log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); + + // The cookie is valid to for the partner application only ... in the future each partner app may + // store a different auth. token (SSO SESSION) value + cookie = _agent.newJossoCookie(request.getContextPath(), entry.ssoId, hreq.isSecure()); + hres.addCookie(cookie); + + //Redirect user to the saved splash resource (in case of auth request) or to request URI otherwise + String requestURI = getSavedSplashResource(hreq); + if(requestURI == null) { + requestURI = getSavedRequestURL(hreq, session); + if (requestURI == null) { + + if (cfg.getDefaultResource() != null) { + requestURI = cfg.getDefaultResource(); + } else { + // If no saved request is found, redirect to the partner app root : + requestURI = hreq.getRequestURI().substring( + 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); + } + + // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! + String singlePointOfAccess = _agent.getSinglePointOfAccess(); + if (singlePointOfAccess != null) { + requestURI = singlePointOfAccess + requestURI; + } else { + String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); + if (reverseProxyHost != null) { + requestURI = reverseProxyHost + requestURI; + } + } + + if (debug >= 1) + log("No saved request found, using : '" + requestURI + "'"); + } + } + + clearSavedRequestURLs(hreq, hres, session); + _agent.clearAutomaticLoginReferer(hreq, hres); + _agent.prepareNonCacheResponse(hres); + + // Check if we have a post login resource : + String postAuthURI = cfg.getPostAuthenticationResource(); + if (postAuthURI != null) { + String postAuthURL = _agent.buildPostAuthUrl(hres, requestURI, postAuthURI); + if (debug >= 1) + log("Redirecting to post-auth-resource '" + postAuthURL + "'"); + hres.sendRedirect(postAuthURL); + } else { + if (debug >= 1) + log("Redirecting to original '" + requestURI + "'"); + hres.sendRedirect(hres.encodeRedirectURL(requestURI)); + } + + return; + } + + CatalinaSSOAgentRequest r; + + log("Creating Security Context for Session [" + session + "]"); + r = new CatalinaSSOAgentRequest(cfg.getId(), + SSOAgentRequest.ACTION_ESTABLISH_SECURITY_CONTEXT, jossoSessionId, localSession + ); + r.setRequest(hreq); + r.setResponse(hres); + r.setContext(request.getContext()); + + SingleSignOnEntry entry = _agent.processRequest(r); + + if (debug >= 1) + log("Executed agent."); + + // ------------------------------------------------------------------ + // Has a valid user already been authenticated? + // ------------------------------------------------------------------ + if (debug >= 1) + log("Process request for '" + hreq.getRequestURI() + "'"); + + if (entry != null) { + if (debug >= 1) + log("Principal '" + entry.principal + + "' has already been authenticated"); + + (request).setAuthType(entry.authType); + (request).setUserPrincipal(entry.principal); + + } else { + log("No Valid SSO Session, attempt an optional login?"); + // This is a standard anonymous request! + + if (cookie != null) { + // cookie is not valid + cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); + hres.addCookie(cookie); + } + + if (cookie != null || (getSavedRequestURL(hreq, session) == null && _agent.isAutomaticLoginRequired(hreq, hres))) { + + if (debug >= 1) + log("SSO Session is not valid, attempting automatic login"); + + // Save current request, so we can co back to it later ... + saveRequest(request, session); + String loginUrl = _agent.buildLoginOptionalUrl(hreq); + + if (debug >= 1) + log("Redirecting to login url '" + loginUrl + "'"); + + //set non cache headers + _agent.prepareNonCacheResponse(hres); + hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); + return; + } else { + if (debug >= 1) + log("SSO cookie is not present, but login optional process is not required"); + } + + } + + // propagate the login and logout URLs to + // partner applications. + hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl() ); + hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl() ); + hreq.setAttribute("org.josso.agent.ssoSessionid", jossoSessionId); + + // ------------------------------------------------------------------ + // Invoke the next Valve in our pipeline + // ------------------------------------------------------------------ + getNext().invoke(request, response); + } catch (Throwable t) { + // This is a 'hack' : Because this valve exectues before the ErrorReportingValve, we need to preapare + // some stuff and invoke the next valve in the chain always ... + + // Store this error, it will be checked by the ErrorReportingValve + request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t); + + System.err.println(t); + t.printStackTrace(); + + // Mark this response as error! + response.setError(); + + // Let the next valves work on this + getNext().invoke(request, response); + return; + + } finally { + if (debug >= 1) + log("Processed : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + } + } + + // --------------------------------------------------------- Public Methods + + + /** + * Return a String rendering of this object. + */ + public String toString() { + + StringBuffer sb = new StringBuffer("SingleSignOn["); + // Sometimes the container is not present when this method is invoked ... + sb.append(container != null ? container.getName() : ""); + sb.append("]"); + return (sb.toString()); + + } + + + // -------------------------------------------------------- Package Methods + + + + + // ------------------------------------------------------ Protected Methods + + /** + * Return the internal Session that is associated with this HttpRequest, + * or null if there is no such Session. + * + * @param request The HttpRequest we are processing + */ + protected Session getSession(Request request) { + + return (getSession(request, false)); + + } + + /** + * Return the internal Session that is associated with this HttpRequest, + * possibly creating a new one if necessary, or null if + * there is no such session and we did not create one. + * + * @param request The HttpRequest we are processing + * @param create Should we create a session if needed? + */ + protected Session getSession(Request request, boolean create) { + + HttpServletRequest hreq = + (HttpServletRequest) request.getRequest(); + HttpSession hses = hreq.getSession(create); + if (debug >= 1) + log("getSession() : hses " + hses); + + if (hses == null) + return (null); + // Get catalina Context from request ... + Manager manager = request.getContext().getManager(); + + if (debug >= 1) + log("getSession() : manager is " + manager); + if (manager == null) + return (null); + else { + try { + return (manager.findSession(hses.getId())); + } catch (IOException e) { + return (null); + } + } + + } + + /** + * Log a message on the Logger associated with our Container (if any). + * + * @param message Message to be logged + */ + protected void log(String message) { + if (_agent != null) + _agent.log(message); + } + + + /** + * Log a message on the Logger associated with our Container (if any). + * + * @param message Message to be logged + * @param throwable Associated exception + */ + protected void log(String message, Throwable throwable) { + if (_agent != null) + _agent.log(message, throwable); + } + + + /** + * Return the request URI (with the corresponding query string, if any) + * from the saved request so that we can redirect to it. + * + * @param hreq http request + * @param session Our current session + */ + private String getSavedRequestURL(HttpServletRequest hreq, Session session) { + String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + if (savedURL == null || savedURL.equals("")) { + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (saved == null) + return (null); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); + if (saved.getQueryString() != null) { + sb.append('?'); + sb.append(saved.getQueryString()); + } + savedURL = sb.toString(); + } + return savedURL; + } + + /** + * Return the splash resource from session so that we can redirect the user to it + * if (s)he was logged in using custom form + * @param hreq http request + */ + private String getSavedSplashResource(HttpServletRequest hreq) { + return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + } + + /** + * Save the original request information into our session. + * + * @param request The request to be saved + * @param session The session to contain the saved information + * @throws IOException + */ + protected void saveRequest(Request request, Session session) + throws IOException { + + // Create and populate a SavedRequest object for this request + SavedRequest saved = new SavedRequest(); + Cookie cookies[] = request.getCookies(); + if (cookies != null) { + for (int i = 0; i < cookies.length; i++) + saved.addCookie(cookies[i]); + } + Enumeration names = request.getHeaderNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + Enumeration values = request.getHeaders(name); + while (values.hasMoreElements()) { + String value = (String) values.nextElement(); + saved.addHeader(name, value); + } + } + Enumeration locales = request.getLocales(); + while (locales.hasMoreElements()) { + Locale locale = (Locale) locales.nextElement(); + saved.addLocale(locale); + } + + /** Need more catalina classes + if ("POST".equalsIgnoreCase(request.getMethod())) { + ByteChunk body = new ByteChunk(); + body.setLimit(request.getConnector().getMaxSavePostSize()); + + byte[] buffer = new byte[4096]; + int bytesRead; + InputStream is = request.getInputStream(); + + while ( (bytesRead = is.read(buffer) ) >= 0) { + body.append(buffer, 0, bytesRead); + } + saved.setContentType(request.getContentType()); + saved.setBody(body); + } */ + + saved.setMethod(request.getMethod()); + saved.setQueryString(request.getQueryString()); + saved.setRequestURI(request.getRequestURI()); + + // Stash the SavedRequest in our session for later use + session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); + + StringBuffer sb = new StringBuffer(request.getRequestURI()); + if (request.getQueryString() != null) { + String q = request.getQueryString(); + if (!q.startsWith("?")) + sb.append('?'); + sb.append(q); + } + _agent.setAttribute(request.getRequest(), request.getResponse().getResponse(), WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + } + + /** + * Save referer URI into our session for later use. + * + * This method is used so agent can know from which + * public resource (page) user requested login. + * + * @param request http request + * @param response http response + * @param session current session + * @param overrideSavedResource true if saved resource should be overridden, false otherwise + */ + protected void saveLoginBackToURL(HttpServletRequest request, HttpServletResponse response, Session session, boolean overrideSavedResource) { + String referer = request.getHeader("referer"); + //saved request will exist only if user requested some protected resource + String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { + + saved = new SavedRequest(); + + int p = referer.indexOf("?"); + + String uri = p >= 0 ? referer.substring(0, p) : referer; + String queryStr = p >= 0 ? referer.substring(p) : null; + saved.setRequestURI(uri); + saved.setQueryString(queryStr); + + session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); + + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, referer); + } else if (saved != null) { + StringBuffer sb = new StringBuffer(saved.getRequestURI()); + if (saved.getQueryString() != null) { + String q = saved.getQueryString(); + if (!q.startsWith("?")) + sb.append('?'); + sb.append(q); + } + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + } + } + + /** + * Remove saved request URLs from session + * to avoid mixing up resources from previous operations + * (logins, logouts) with the current one. + * + * @param hreq http request + * @param hres http response + * @param session Our current session + */ + protected void clearSavedRequestURLs(HttpServletRequest hreq, HttpServletResponse hres, Session session) { + session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + } + + protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { + // There are some web-resources to ignore. + String[] ignoredWebResources = cfg.getIgnoredWebRources(); + + if (debug >= 1) + log("Found [" + (ignoredWebResources!= null ? ignoredWebResources.length+"" : "no") + "] ignored web resources "); + + if (ignoredWebResources != null && ignoredWebResources.length > 0) { + + Realm realm = request.getContext().getRealm(); + SecurityConstraint[] constraints + = realm.findSecurityConstraints(request, request.getContext()); + + if ((constraints != null)) { + + for (int i = 0; i < ignoredWebResources.length; i++) { + + // For each ignored web resource, find a correspondig web resource collection. + String ignoredWebResource = ignoredWebResources[i]; + for (int j = 0; j < constraints.length; j++) { + + // Find a matching web resource collection for each ignored web resources + SecurityConstraint constraint = constraints[j]; + if (constraint.findCollection(ignoredWebResource) != null) { + + // We should ignore this URI, it's not subject to SSO protection. + if (debug >= 1) + log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); + + return true; + } + } + } + } + } + + return false; + + } + + +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaJAASRealm.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaJAASRealm.java new file mode 100644 index 00000000..b6c77f18 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaJAASRealm.java @@ -0,0 +1,62 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent.jaas; + +import org.apache.catalina.realm.JAASRealm; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import java.security.Principal; + +/** + * Catalina JAASRealm replacement that instantiates CatalinaSSOUser Principal instead of + * GenericPrincipal. + * + * @author Gianluca Brigandi + * @version CVS $Id: CatalinaJAASRealm.java 974 2009-01-14 00:39:45Z sgonzalez $ + */ + +public class CatalinaJAASRealm extends JAASRealm { + private static Log log = LogFactory.getLog(CatalinaJAASRealm.class); + + /** + * Construct and return a java.security.Principal instance + * representing the authenticated user for the specified Subject. If no + * such Principal can be constructed, return null. + * + * The Principal constructed is *not* GenericPrincipal as in Catalina JAASRealm class, + * but CatalinaSSOUser which is a SSOUser. + * The Partner Application can access SSOUser-specific properties that are not available + * in GenericPrincipal. + * The JAASRealm superclass invokes this factory method to build the Catalina-specific + * Principal from the Subject filled by the configured JAASLoginModule. + * + * @param subject The Subject representing the logged in user + */ + protected Principal createPrincipal(String username, Subject subject, LoginContext loginContext) { + return CatalinaSSOUser.newInstance(this, subject); + } + +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaSSOUser.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaSSOUser.java new file mode 100644 index 00000000..d84248f2 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/CatalinaSSOUser.java @@ -0,0 +1,196 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent.jaas; + +import org.apache.catalina.Realm; +import org.apache.catalina.realm.GenericPrincipal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.josso.gateway.SSONameValuePair; +import org.josso.gateway.identity.SSOUser; + +import javax.security.auth.Subject; +import java.security.Principal; +import java.security.acl.Group; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; + +/** + * On authentication, Catalina JAAS Realm doesn't return the Principal instances as + * built by the Login Modules. It returns a Catalina-specific Principal called GenericPrincipal. + * As a consequence all the additional properties that the SSOUser instance carries are lost. + * With this class, we'll make Catalina beleive that our SSOUser its actually a GenericPrincipal, so that it + * doesn't create a new one. + * + * @author Gianluca Brigandi + * @version CVS $Id: CatalinaSSOUser.java 974 2009-01-14 00:39:45Z sgonzalez $ + */ + +public class CatalinaSSOUser extends GenericPrincipal implements SSOUser { + private static Log logger = LogFactory.getLog(CatalinaSSOUser.class); + + private static List _userClasses = new ArrayList(); + private static List _roleClasses = new ArrayList(); + + static { + _userClasses.add("org.josso.gateway.identity.service.BaseUserImpl"); + _roleClasses.add("org.josso.gateway.identity.service.BaseRoleImpl"); + } + + private SSOUser _ssoUser; + + + /** + * Construct and return a java.security.Principal instance + * representing the authenticated user for the specified Subject. If no + * such Principal can be constructed, return null. + * + * The Principal constructed is *not* GenericPrincipal as in Catalina JAASRealm class, + * but CatalinaSSOUser which is a SSOUser. + * The Partner Application can access SSOUser-specific properties that are not available + * in GenericPrincipal. + * The JAASRealm superclass invokes this factory method to build the Catalina-specific + * Principal from the Subject filled by the configured JAASLoginModule. + * + * @param subject The Subject representing the logged in user + */ + public static CatalinaSSOUser newInstance(Realm realm, Subject subject) { + // Prepare to scan the Principals for this Subject + String password = null; // Will not be carried forward + ArrayList roles = new ArrayList(); + SSOUser ssoUser = null; + String username = null; + + // Scan the Principals for this Subject + Iterator principals = subject.getPrincipals().iterator(); + while (principals.hasNext()) { + Principal principal = (Principal) principals.next(); + // No need to look further - that's our own stuff + if (principal instanceof CatalinaSSOUser) { + if (logger.isDebugEnabled()) + logger.debug("Found old CatalinaSSOUser Principal " + principal); + return (CatalinaSSOUser) principal; + } + String principalClass = principal.getClass().getName(); + + if (logger.isDebugEnabled()) + logger.debug("Principal: " + principalClass + " " + principal); + + if (_userClasses.contains(principalClass)) { + // Override the default - which is the original user, accepted by + // the friendly LoginManager + username = principal.getName(); + } + if (_roleClasses.contains(principalClass)) { + roles.add(principal.getName()); + } + // Same as Jboss - that's a pretty clean solution + if ((principal instanceof Group) && + "Roles".equals(principal.getName())) { + Group grp = (Group) principal; + Enumeration en = grp.members(); + while (en.hasMoreElements()) { + Principal roleP = (Principal) en.nextElement(); + roles.add(roleP.getName()); + } + + } + + // Save the SSOUser principal so that it can be included in the + // CatalinaSSOUser Principal + if (principal instanceof SSOUser) { + ssoUser = (SSOUser) principal; + } + } + + if (ssoUser == null) { + logger.error("Fatal: Subject does not contain an SSOUser Principal"); + return null; + } + + // Create the resulting Principal for our authenticated user + if (username != null) { + return (new CatalinaSSOUser(ssoUser, realm, username, password, roles)); + } else { + return (null); + } + } + + /** + * Construct a new Principal, associated with the specified Realm, for the + * specified username and password. + * + * @param realm The Realm that owns this Principal + * @param name The username of the user represented by this Principal + * @param password Credentials used to authenticate this user + */ + private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name, String password) { + + this(ssoUser, realm, name, password, null); + } + + + /** + * Construct a new Principal, associated with the specified Realm, for the + * specified username and password, with the specified role names + * (as Strings). + * + * @param realm The Realm that owns this principal + * @param name The username of the user represented by this Principal + * @param password Credentials used to authenticate this user + * @param roles List of roles (must be Strings) possessed by this user + */ + private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name, String password, + List roles) { + + super(name, password, roles); + _ssoUser = ssoUser; + + } + + /** + * @deprecated this method always return null + * @return always null + */ + public String getSessionId() { + return null; + } + + public SSONameValuePair[] getProperties() { + return _ssoUser.getProperties(); + } + + /** + * Return a String representation of this object, which exposes only + * information that should be public. + */ + public String toString() { + StringBuffer sb = new StringBuffer("CatalinaSSOUser["); + sb.append(this.name); + sb.append("]"); + return (sb.toString()); + } + +} diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/SSOGatewayLoginModule.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/SSOGatewayLoginModule.java new file mode 100644 index 00000000..6451d471 --- /dev/null +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/jaas/SSOGatewayLoginModule.java @@ -0,0 +1,324 @@ +/* + * JOSSO: Java Open Single Sign-On + * + * Copyright 2004-2009, Atricore, Inc. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ + +package org.josso.tc85.agent.jaas; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.josso.agent.AbstractSSOAgent; +import org.josso.agent.Lookup; +import org.josso.agent.SSOAgent; +import org.josso.agent.SSOAgentRequest; +import org.josso.gateway.identity.SSORole; +import org.josso.gateway.identity.SSOUser; +import org.josso.gateway.identity.exceptions.SSOIdentityException; +import org.josso.gateway.identity.service.SSOIdentityManagerService; + +import javax.security.auth.Subject; +import javax.security.auth.callback.*; +import javax.security.auth.login.FailedLoginException; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; +import java.util.Map; + +/** + * SSO Gateway JAAS Login Module. + * + * This Login Module authenticates an SSO Session against the Single Sign-on Gateway + * by getting the associated user and roles and filling it to the provided Subject. + * This way clients can obtain the authenticated identity associated with the session and use it + * to protect resources (ie: web, etc.). + * + * @author Gianluca Brigandi + * @version CVS $Id: SSOGatewayLoginModule.java 1607 2010-05-11 13:39:08Z sgonzalez $ + */ +public class SSOGatewayLoginModule implements LoginModule { + + private static final Log logger = LogFactory.getLog(SSOGatewayLoginModule.class); + + + // initial state + private Subject _subject; + private CallbackHandler _callbackHandler; + + // the authentication status + protected boolean _succeeded; + protected boolean commitSucceeded; + + // the logged user and his roles. + protected String _currentSSOSessionId; + protected String _requester; + protected SSOUser _ssoUserPrincipal; + protected SSORole[] _ssoRolePrincipals; + + /** + * Initialize this LoginModule + * + * @param subject the Subject to be authenticated. + * + * @param callbackHandler a CallbackHandler for communicating + * with the end user (prompting for user names and + * passwords, for example). + * + * @param sharedState shared LoginModule state. + * + * @param options options specified in the login Configuration + * for this particular LoginModule. + */ + public void initialize(Subject subject, CallbackHandler callbackHandler, + Map sharedState, Map options) { + + this._subject = subject; + this._callbackHandler = callbackHandler; + } + + /** + * Authenticate the user by prompting for the SSO Session Identifier assigned by the SSO Gateway on logon. + * + * This method obtains from the gateway, using the provided session identifier, the user associated with + * such session identifier. + * Only the NameCallBack is used, since its not a user/password pair but only one value containing the session + * identifier. Any other callback type is ignored. + * + * @return true in all cases since this LoginModule + * should not be ignored. + * + * @exception FailedLoginException if the authentication fails. + * + * @exception LoginException if this LoginModule + * is unable to perform the authentication. + */ + public boolean login() throws LoginException { + + if (_callbackHandler == null) + throw new LoginException("Error: no CallbackHandler available " + + "to garner authentication information from the user"); + + Callback[] callbacks = new Callback[2]; + + // Just ask for the session identifier + callbacks[0] = new NameCallback("ssoSessionId"); + callbacks[1] = new PasswordCallback("password", false); + + String ssoSessionId; + String ssoSessionId2 = null; + + try { + _callbackHandler.handle(callbacks); + ssoSessionId = ((NameCallback) callbacks[0]).getName(); + if (((PasswordCallback) callbacks[1]).getPassword() != null) + ssoSessionId2 = String.valueOf(((PasswordCallback) callbacks[1]).getPassword()); + + _requester = ""; + // Check for nulls ? + SSOAgentRequest request = AbstractSSOAgent._currentRequest.get(); + if (request != null) + _requester = request.getRequester(); + else + logger.warn("No SSO Agent request found in thread local variable, can't identify requester"); + + } catch (java.io.IOException ioe) { + throw new LoginException(ioe.toString()); + } catch (UnsupportedCallbackException uce) { + throw new LoginException("Error: " + uce.getCallback().toString() + + " not available to garner authentication information " + + "from the user"); + } + + logger.debug("Requested authentication to gateway by " + _requester + " using sso session " + ssoSessionId + "/" + ssoSessionId2 ); + + try { + + if (ssoSessionId2 != null && !ssoSessionId2.equals(ssoSessionId)) + ssoSessionId = ssoSessionId2; + + // If no session is found, ignore this module. + if (ssoSessionId == null) { + logger.debug("Session authentication failed : " + ssoSessionId); + _succeeded = false; + return false; + } + + _currentSSOSessionId = ssoSessionId; + + SSOAgentRequest request = AbstractSSOAgent._currentRequest.get(); + SSOAgent agent = Lookup.getInstance().lookupSSOAgent(); + + SSOIdentityManagerService im = request.getConfig(agent).getIdentityManagerService(); + if (im == null) + im = agent.getSSOIdentityManager(); + SSOUser ssoUser = im.findUserInSession(_requester, ssoSessionId); + + logger.debug("Session authentication succeeded : " + ssoSessionId); + _ssoUserPrincipal = ssoUser; + _succeeded = true; + + } catch (SSOIdentityException e) { + // Ignore this ... (user does not exist for this session) + if (logger.isDebugEnabled()) + logger.debug(e.getMessage(), e); + _succeeded = false; + return false; + + } catch (Exception e) { + logger.error("Session authentication failed : " + ssoSessionId, e); + _succeeded = false; + clearCredentials(); + throw new FailedLoginException("Fatal error authenticating session : " + e); + } + + return true; + } + + /** + * This method is called if the LoginContext's overall authentication succeeded. + * + * Using the SSO user name, saved by the previosuly executed login() operation, obtains from the gateway + * the roles associated with the user and fills the Subject with the user and role principals. + * If this LoginModule's own authentication attempted failed, then this method removes any state that was + * originally saved. + * + * @exception LoginException if the commit fails. + * + * @return true if this LoginModule's own login and commit + * attempts succeeded, or false otherwise. + */ + public boolean commit() throws LoginException { + if (_succeeded == false) { + return false; + } else { + + try { + + // Add the SSOUser as a Principal + if (!_subject.getPrincipals().contains(_ssoUserPrincipal)) { + _subject.getPrincipals().add(_ssoUserPrincipal); + } + + logger.debug("Added SSOUser Principal to the Subject : " + _ssoUserPrincipal); + + + _ssoRolePrincipals = getRoleSets(_requester); + + // Add to the Subject the SSORoles associated with the SSOUser . + for (int i=0; i < _ssoRolePrincipals .length; i++) { + if (_subject.getPrincipals().contains(_ssoRolePrincipals [i])) + continue; + + _subject.getPrincipals().add(_ssoRolePrincipals [i]); + logger.debug("Added SSORole Principal to the Subject : " + _ssoRolePrincipals [i]); + } + + commitSucceeded = true; + return true; + } catch (Exception e) { + logger.error("Session login failed for Principal : " + _ssoUserPrincipal, e); + throw new LoginException("Session login failed for Principal : " + _ssoUserPrincipal); + } finally { + // in any case, clean out state + clearCredentials(); + } + + } + } + + /** + * This method is called if the LoginContext's + * overall authentication failed. + * + * @exception LoginException if the abort fails. + * + * @return false if this LoginModule's own login and/or commit attempts + * failed, and true otherwise. + */ + public boolean abort() throws LoginException { + if (_succeeded == false) { + return false; + } else if (_succeeded == true && commitSucceeded == false) { + // login _succeeded but overall authentication failed + _succeeded = false; + clearCredentials(); + } else { + // overall authentication _succeeded and commit _succeeded, + // but someone else's commit failed + logout(); + } + return true; + } + + /** + * Logout the user. + * + * This method removes the SSO User and Role Principals from the Subject that were added by the commit() + * method. + * + * @exception LoginException if the logout fails. + * + * @return true in all cases since this LoginModule + * should not be ignored. + */ + public boolean logout() throws LoginException { + _subject.getPrincipals().remove(_ssoUserPrincipal); + logger.debug("Removed SSOUser Principal from Subject : " + _ssoUserPrincipal); + + // Remove all the SSORole Principals from the Subject. + for (int i=0; i < _ssoRolePrincipals.length; i++) { + _subject.getPrincipals().remove(_ssoRolePrincipals[i]); + logger.debug("Removed SSORole Principal from Subject : " + _ssoRolePrincipals[i]); + } + + _succeeded = commitSucceeded; + clearCredentials(); + return true; + } + + /** + * Reset the login module state. + */ + private void clearCredentials() { + _ssoUserPrincipal = null; + _ssoRolePrincipals = null; + _currentSSOSessionId = null; + } + + /** + * Retreives the list of roles associated to current principal + */ + protected SSORole[] getRoleSets(String requester) throws LoginException { + try { + // obtain user roles principals and add it to the subject + SSOAgentRequest request = AbstractSSOAgent._currentRequest.get(); + SSOAgent agent = Lookup.getInstance().lookupSSOAgent(); + + SSOIdentityManagerService im = request.getConfig(agent).getIdentityManagerService(); + if (im == null) + im = agent.getSSOIdentityManager(); + + return im.findRolesBySSOSessionId(requester, _currentSSOSessionId); + } catch(Exception e) { + logger.error("Session login failed for Principal : " + _ssoUserPrincipal, e); + throw new LoginException("Session login failed for Principal : " + _ssoUserPrincipal); + } + + } + +} diff --git a/agents/pom.xml b/agents/pom.xml index cf6778a7..b0a65f54 100644 --- a/agents/pom.xml +++ b/agents/pom.xml @@ -52,6 +52,7 @@ josso-tomcat60-agent josso-tomcat70-agent josso-tomcat80-agent + josso-tomcat85-agent josso-jboss32-agent josso-jboss40-agent josso-jboss42-agent @@ -91,6 +92,7 @@ josso-tomcat60-agent josso-tomcat70-agent josso-tomcat80-agent + josso-tomcat85-agent josso-jboss32-agent josso-jboss40-agent josso-jboss42-agent From 67c779efc0b92b78a46bcdbec122ef83003a1f3b Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Wed, 1 Feb 2017 11:31:30 -0800 Subject: [PATCH 03/11] Merge branch 'robertdale-tomcat7-session-fixation-workaround' into 1.8.7 --- agents/josso-tomcat70-agent/pom.xml | 2 +- .../tc70/agent/CatalinaLocalSession.java | 7 +- .../josso/tc70/agent/CatalinaSSOAgent.java | 16 +- .../josso/tc70/agent/LocalSessionImpl.java | 8 +- .../org/josso/tc70/agent/SSOAgentValve.java | 144 +++++++++++++++--- 5 files changed, 141 insertions(+), 36 deletions(-) diff --git a/agents/josso-tomcat70-agent/pom.xml b/agents/josso-tomcat70-agent/pom.xml index 36355381..c8761050 100644 --- a/agents/josso-tomcat70-agent/pom.xml +++ b/agents/josso-tomcat70-agent/pom.xml @@ -38,7 +38,7 @@ Tomcat 7 Agent - 7.0.59 + 7.0.53 diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaLocalSession.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaLocalSession.java index 1a1d6183..2b4d3ab4 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaLocalSession.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaLocalSession.java @@ -37,8 +37,11 @@ public CatalinaLocalSession( Session catalinaSession) { setWrapped(catalinaSession); setMaxInactiveInterval(catalinaSession.getMaxInactiveInterval()); - - + } + + @Override + public String toString() { + return "CatalinaLocalSession [toString()=" + super.toString() + "]"; } } diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java index 8194e17a..b449667f 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java @@ -25,6 +25,8 @@ import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.Realm; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.josso.agent.SSOAgentRequest; import org.josso.agent.http.HttpSSOAgent; @@ -41,6 +43,8 @@ */ public class CatalinaSSOAgent extends HttpSSOAgent { + private static final Log LOG = LogFactory.getLog(CatalinaSSOAgent.class); + private Container _container; public CatalinaSSOAgent() { @@ -101,19 +105,11 @@ protected Principal authenticate(SSOAgentRequest request) { } protected void log(String message) { - if (_container != null) { - if (_container.getLogger().isDebugEnabled()) - _container.getLogger().debug(this.toString() + ": " + message); - } else - System.out.println(this.toString() + ": " + message); + LOG.debug(message); } protected void log(String message, Throwable throwable) { - if (_container != null) { - if (_container.getLogger().isDebugEnabled()) - _container.getLogger().debug(this.toString() + ": " + message, throwable); - } else - System.out.println(this.toString() + ": " + message); + LOG.debug(message, throwable); } /** diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/LocalSessionImpl.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/LocalSessionImpl.java index a6b82f22..6b48f0ed 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/LocalSessionImpl.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/LocalSessionImpl.java @@ -103,5 +103,11 @@ public void setWrapped(Object wrapped) { public Object getWrapped() { return _wrapped; } -} + @Override + public String toString() { + return "LocalSessionImpl [_creationTime=" + _creationTime + ", _id=" + _id + ", _lastAccessedTime=" + + _lastAccessedTime + ", _maxInactiveInterval=" + _maxInactiveInterval + ", _wrapped=" + _wrapped + "]"; + } + +} diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java index 9863e42d..9df776bf 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java @@ -22,15 +22,14 @@ package org.josso.tc70.agent; -import org.apache.catalina.*; -import org.apache.catalina.authenticator.SavedRequest; -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.deploy.SecurityConstraint; -import org.apache.catalina.util.LifecycleSupport; -import org.apache.catalina.valves.ValveBase; -import org.josso.agent.*; -import org.josso.agent.http.WebAccessControlUtil; +import java.io.IOException; +import java.security.Principal; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; @@ -38,9 +37,31 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.io.IOException; -import java.util.*; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.Manager; +import org.apache.catalina.Realm; +import org.apache.catalina.Session; +import org.apache.catalina.SessionEvent; +import org.apache.catalina.SessionListener; +import org.apache.catalina.authenticator.SavedRequest; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.deploy.SecurityConstraint; +import org.apache.catalina.util.LifecycleSupport; +import org.apache.catalina.valves.ValveBase; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.josso.agent.Constants; +import org.josso.agent.LocalSession; +import org.josso.agent.Lookup; +import org.josso.agent.SSOAgentRequest; +import org.josso.agent.SSOPartnerAppConfig; +import org.josso.agent.SingleSignOnEntry; +import org.josso.agent.http.WebAccessControlUtil; /** * Single Sign-On Agent implementation for Tomcat Catalina. @@ -51,6 +72,8 @@ public class SSOAgentValve extends ValveBase implements Lifecycle, SessionListener { + private static final Log LOG = LogFactory.getLog(SSOAgentValve.class); + /** * The debugging detail level for this component. */ @@ -78,7 +101,7 @@ public class SSOAgentValve extends ValveBase /** * Catalina Session to Local Session Map. */ - Map _sessionMap = Collections.synchronizedMap(new HashMap()); + private Map _sessionMap = Collections.synchronizedMap(new HashMap()); // ------------------------------------------------------------- Properties @@ -107,15 +130,95 @@ public void setDebug(int debug) { public void sessionEvent(SessionEvent event) { + if (LOG.isInfoEnabled()) { + LOG.info("JOSSO: SSOAgentValve.sessionEvent: " + event); + } + + // extra protective guard + try { + // obtain the local session for the catalina session, and notify the + // listeners for it. + LocalSession localSession = _sessionMap.get(event.getSession().getId()); + + if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { + // This was the main bug + if (localSession != null) { + localSession.expire(); + LOG.info("JOSSO: SSOAgentValve.sessionEvent: session not null. can expire."); + } else { + LOG.info("JOSSO: SSOAgentValve.sessionEvent: session is null. using brute force."); + + String foundId = null; + + Session eventSession = event.getSession(); + String authType = eventSession.getAuthType(); + long creationTime = eventSession.getCreationTime(); + String id = eventSession.getId(); + Principal p = eventSession.getPrincipal(); - // obtain the local session for the catalina session, and notify the listeners for it. - LocalSession localSession = (LocalSession) _sessionMap.get(event.getSession().getId()); + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: eventSession: authType=" + authType + + ", creationTime=" + creationTime + ", id=" + id + ", Principal=" + p); - if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { - localSession.expire(); - _sessionMap.remove(event.getSession().getId()); + // free any sessions that can't be looked up + synchronized (_sessionMap) { + for (Entry ks : _sessionMap.entrySet()) { + String key = ks.getKey(); + LocalSession mapSession = ks.getValue(); + + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: _sessionMap: key: " + key + ", value: " + + mapSession); + + Object mapWrapped = mapSession.getWrapped(); + if (mapWrapped instanceof Session) { + Session mapS = (Session) mapWrapped; + String mapAuthType = mapS.getAuthType(); + long mapCreationTime = mapS.getCreationTime(); + String mapId = mapS.getId(); + Principal mapP = mapS.getPrincipal(); + + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: mapWrapped Session: authType=" + + mapAuthType + ", creationTime=" + mapCreationTime + ", id=" + mapId + + ", Principal=" + mapP); + + if (creationTime == mapCreationTime && id != null && id.equals(mapId)) { + + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: Found ID match: " + key); + + foundId = key; + break; + } + } + + } + + if (foundId != null) { + _sessionMap.remove(foundId); + if (LOG.isInfoEnabled()) + LOG.info("JOSSO: SSOAgentValve.sessionEvent: removed by brute force: " + foundId); + } + + } + + } + + _sessionMap.remove(event.getSession().getId()); + + if (LOG.isInfoEnabled()) + LOG.info("JOSSO: SSOAgentValve.sessionEvent: sessionMap.size remaining: " + _sessionMap.size()); + } + + } catch ( + + Exception ex) { + LOG.error("JOSSO: SESSION FIX EXCEPTION: ", ex); } - + + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: complete"); + } // ------------------------------------------------------ Lifecycle Methods @@ -399,7 +502,7 @@ public void invoke(Request request, Response response) String jossoSessionId = (cookie == null) ? null : cookie.getValue(); if (debug >= 1) log("Session is: " + session); - LocalSession localSession = (LocalSession) _sessionMap.get(session.getId()); + LocalSession localSession = _sessionMap.get(session.getId()); if (localSession == null) { localSession = new CatalinaLocalSession(session); // the local session is new so, make the valve listen for its events so that it can @@ -700,9 +803,6 @@ public void invoke(Request request, Response response) // Store this error, it will be checked by the ErrorReportingValve request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t); - System.err.println(t); - t.printStackTrace(); - // Mark this response as error! //response.setError(); response.setStatus(500); From e5634e124754506470f7bf62f9c80b85ef513d86 Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Wed, 1 Feb 2017 12:00:31 -0800 Subject: [PATCH 04/11] * Performance-wise, replaced bruce force approach for removing dangling sessions with acting upon session identifier changes triggered due to session fixation protection. * Session-related logging level from INFO to DEBUG. * Build against latest Tomcat 7's libraries available. * Other minor improvements. --- agents/josso-tomcat70-agent/pom.xml | 2 +- .../josso/tc70/agent/CatalinaSSOAgent.java | 6 +- .../org/josso/tc70/agent/SSOAgentValve.java | 583 ++++++++---------- 3 files changed, 256 insertions(+), 335 deletions(-) diff --git a/agents/josso-tomcat70-agent/pom.xml b/agents/josso-tomcat70-agent/pom.xml index c8761050..bb6254fb 100644 --- a/agents/josso-tomcat70-agent/pom.xml +++ b/agents/josso-tomcat70-agent/pom.xml @@ -38,7 +38,7 @@ Tomcat 7 Agent - 7.0.53 + 7.0.75 diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java index b449667f..99461d8f 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/CatalinaSSOAgent.java @@ -105,11 +105,13 @@ protected Principal authenticate(SSOAgentRequest request) { } protected void log(String message) { - LOG.debug(message); + if (LOG.isDebugEnabled()) + LOG.debug(message); } protected void log(String message, Throwable throwable) { - LOG.debug(message, throwable); + if (LOG.isDebugEnabled()) + LOG.debug(message, throwable); } /** diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java index 9df776bf..cf7fe5b2 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java @@ -22,31 +22,7 @@ package org.josso.tc70.agent; -import java.io.IOException; -import java.security.Principal; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.apache.catalina.Lifecycle; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.LifecycleListener; -import org.apache.catalina.LifecycleState; -import org.apache.catalina.Manager; -import org.apache.catalina.Realm; -import org.apache.catalina.Session; -import org.apache.catalina.SessionEvent; -import org.apache.catalina.SessionListener; +import org.apache.catalina.*; import org.apache.catalina.authenticator.SavedRequest; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; @@ -55,14 +31,18 @@ import org.apache.catalina.valves.ValveBase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.josso.agent.Constants; -import org.josso.agent.LocalSession; -import org.josso.agent.Lookup; -import org.josso.agent.SSOAgentRequest; -import org.josso.agent.SSOPartnerAppConfig; -import org.josso.agent.SingleSignOnEntry; +import org.josso.agent.*; import org.josso.agent.http.WebAccessControlUtil; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.util.*; + /** * Single Sign-On Agent implementation for Tomcat Catalina. * @@ -70,16 +50,10 @@ * @version $Id: SSOAgentValve.java 1657 2010-10-13 20:48:21Z sgonzalez $ */ public class SSOAgentValve extends ValveBase - implements Lifecycle, SessionListener { + implements Lifecycle, SessionListener, ContainerListener { private static final Log LOG = LogFactory.getLog(SSOAgentValve.class); - /** - * The debugging detail level for this component. - */ - protected int debug = 0; - - /** * Descriptive information about this Valve implementation. */ @@ -103,35 +77,12 @@ public class SSOAgentValve extends ValveBase */ private Map _sessionMap = Collections.synchronizedMap(new HashMap()); - // ------------------------------------------------------------- Properties - - /** - * Return the debugging detail level. - */ - public int getDebug() { - - return (this.debug); - - } - - - /** - * Set the debugging detail level. - * - * @param debug The new debugging detail level - */ - public void setDebug(int debug) { - - this.debug = debug; - - } - // ------------------------------------------------------ SessionListener Methods public void sessionEvent(SessionEvent event) { - if (LOG.isInfoEnabled()) { - LOG.info("JOSSO: SSOAgentValve.sessionEvent: " + event); + if (LOG.isDebugEnabled()) { + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: " + event); } // extra protective guard @@ -141,84 +92,54 @@ public void sessionEvent(SessionEvent event) { LocalSession localSession = _sessionMap.get(event.getSession().getId()); if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { - // This was the main bug if (localSession != null) { localSession.expire(); - LOG.info("JOSSO: SSOAgentValve.sessionEvent: session not null. can expire."); - } else { - LOG.info("JOSSO: SSOAgentValve.sessionEvent: session is null. using brute force."); - - String foundId = null; - - Session eventSession = event.getSession(); - String authType = eventSession.getAuthType(); - long creationTime = eventSession.getCreationTime(); - String id = eventSession.getId(); - Principal p = eventSession.getPrincipal(); - + _sessionMap.remove(event.getSession().getId()); if (LOG.isDebugEnabled()) - LOG.debug("JOSSO: SSOAgentValve.sessionEvent: eventSession: authType=" + authType - + ", creationTime=" + creationTime + ", id=" + id + ", Principal=" + p); - - // free any sessions that can't be looked up - synchronized (_sessionMap) { - for (Entry ks : _sessionMap.entrySet()) { - String key = ks.getKey(); - LocalSession mapSession = ks.getValue(); - - if (LOG.isDebugEnabled()) - LOG.debug("JOSSO: SSOAgentValve.sessionEvent: _sessionMap: key: " + key + ", value: " - + mapSession); - - Object mapWrapped = mapSession.getWrapped(); - if (mapWrapped instanceof Session) { - Session mapS = (Session) mapWrapped; - String mapAuthType = mapS.getAuthType(); - long mapCreationTime = mapS.getCreationTime(); - String mapId = mapS.getId(); - Principal mapP = mapS.getPrincipal(); - - if (LOG.isDebugEnabled()) - LOG.debug("JOSSO: SSOAgentValve.sessionEvent: mapWrapped Session: authType=" - + mapAuthType + ", creationTime=" + mapCreationTime + ", id=" + mapId - + ", Principal=" + mapP); - - if (creationTime == mapCreationTime && id != null && id.equals(mapId)) { - - if (LOG.isDebugEnabled()) - LOG.debug("JOSSO: SSOAgentValve.sessionEvent: Found ID match: " + key); - - foundId = key; - break; - } - } + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: session not null. can expire."); + } + } - } + } catch (Exception ex) { + LOG.error("JOSSO: SESSION PURGE EXCEPTION: ", ex); + } - if (foundId != null) { - _sessionMap.remove(foundId); - if (LOG.isInfoEnabled()) - LOG.info("JOSSO: SSOAgentValve.sessionEvent: removed by brute force: " + foundId); - } + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: sessionMap.size remaining: " + _sessionMap.size()); - } + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: complete"); - } + } - _sessionMap.remove(event.getSession().getId()); + // ------------------------------------------------------ ContainerListener Methods - if (LOG.isInfoEnabled()) - LOG.info("JOSSO: SSOAgentValve.sessionEvent: sessionMap.size remaining: " + _sessionMap.size()); - } + public void containerEvent(ContainerEvent event) { + if (LOG.isDebugEnabled()) { + LOG.debug("JOSSO: SSOAgentValve.containerEvent: " + event); + } - } catch ( + if (event.getType().equals(Context.CHANGE_SESSION_ID_EVENT)) { + String[] sessionIds = (String[]) event.getData(); + String oldId = sessionIds[0]; + String newId = sessionIds[1]; + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: Due to session fixation protection session id " + oldId + " has changed to " + newId); + + LocalSession localSession = _sessionMap.get(oldId); + if (localSession != null) { + localSession.expire(); + _sessionMap.remove(oldId); + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: Expired local session " + oldId + " as it's no longer in use"); + } - Exception ex) { - LOG.error("JOSSO: SESSION FIX EXCEPTION: ", ex); } + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.containerEvent: sessionMap.size remaining: " + _sessionMap.size()); - LOG.debug("JOSSO: SSOAgentValve.sessionEvent: complete"); - + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.containerEvent: complete"); } // ------------------------------------------------------ Lifecycle Methods @@ -262,15 +183,15 @@ public void removeLifecycleListener(LifecycleListener listener) { * Set the Container to which this Valve is attached. * * @param container The container to which we are attached - public void setContainer(Container container) { + public void setContainer(Container container) { - if (!(container instanceof Context)) - throw new IllegalArgumentException - ("The SSOAgentValve must be associated to a Catalina Context or Host"); + if (!(container instanceof Context)) + throw new IllegalArgumentException + ("The SSOAgentValve must be associated to a Catalina Context or Host"); - super.setContainer(container); - _container = container; - } + super.setContainer(container); + _container = container; + } */ /** @@ -279,7 +200,7 @@ public void setContainer(Container container) { * and before any of the public methods of the component are utilized. * * @throws org.apache.catalina.LifecycleException if this component detects a fatal error - * that prevents this component from being used + * that prevents this component from being used */ protected synchronized void startInternal() throws LifecycleException { @@ -294,7 +215,7 @@ protected synchronized void startInternal() throws LifecycleException { Lookup lookup = Lookup.getInstance(); lookup.init("josso-agent-config.xml"); _agent = (CatalinaSSOAgent) lookup.lookupSSOAgent(); - _agent.setDebug(debug); + _agent.setDebug(LOG.isDebugEnabled() ? 1 : 0); _agent.setCatalinaContainer(container); } catch (Exception e) { System.err.println(e.getMessage()); @@ -303,8 +224,8 @@ protected synchronized void startInternal() throws LifecycleException { } _agent.start(); - if (debug >= 1) - log("Started"); + + log("Started"); setState(LifecycleState.STARTING); } @@ -315,12 +236,12 @@ protected synchronized void startInternal() throws LifecycleException { * instance of this component. * * @throws org.apache.catalina.LifecycleException if this component detects a fatal error - * that needs to be reported + * that needs to be reported */ protected synchronized void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); - + // Validate and update our current component state if (!started) throw new LifecycleException @@ -330,11 +251,10 @@ protected synchronized void stopInternal() throws LifecycleException { _agent.stop(); - if (debug >= 1) - log("Stopped"); - } + log("Stopped"); + } // ---------------------------------------------------------- Valve Methods @@ -353,21 +273,18 @@ public String getInfo() { * @param request The servlet request we are processing * @param response The servlet response we are creating * in the current processing pipeline - * @throws java.io.IOException if an input/output error occurs + * @throws java.io.IOException if an input/output error occurs * @throws javax.servlet.ServletException if a servlet error occurs */ public void invoke(Request request, Response response) throws IOException, ServletException { - HttpServletRequest hreq = - (HttpServletRequest) request.getRequest(); - HttpServletResponse hres = - (HttpServletResponse) response.getResponse(); + HttpServletRequest hreq = request.getRequest(); + HttpServletResponse hres = response.getResponse(); - if (debug >= 1) - log("Processing : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + log("Processing : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]"); try { // ------------------------------------------------------------------ @@ -382,8 +299,8 @@ public void invoke(Request request, Response response) if (!_agent.isPartnerApp(vhost, contextPath)) { getNext().invoke(request, response); - if (debug >= 1) - log("Context is not a josso partner app : " + hreq.getContextPath()); + + log("Context is not a josso partner app : " + hreq.getContextPath()); return; } @@ -398,13 +315,13 @@ public void invoke(Request request, Response response) String nodeId = hreq.getParameter("josso_node"); if (nodeId != null) { - if (debug >= 1) - log("Storing JOSSO Node id : " + nodeId); - _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); + + log("Storing JOSSO Node id : " + nodeId); + _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); } else { nodeId = _agent.getAttribute(hreq, "JOSSO_NODE"); - if (debug >= 1) - log("Found JOSSO Node id : " + nodeId); + + log("Found JOSSO Node id : " + nodeId); } @@ -425,27 +342,27 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Check if the partner application required the login form // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); + + log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoLoginUri()) || - hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { + hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { - if (debug >= 1) - log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); + + log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); //save referer url in case the user clicked on Login from some public resource (page) //so agent can redirect the user back to that page after successful login if (hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { - saveLoginBackToURL(hreq, hres, session, true); + saveLoginBackToURL(hreq, hres, session, true); } else { - saveLoginBackToURL(hreq, hres, session, false); + saveLoginBackToURL(hreq, hres, session, false); } String loginUrl = _agent.buildLoginUrl(hreq); - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); @@ -458,18 +375,18 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Check if the partner application required a logout // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); + + log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) { - if (debug >= 1) - log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); + + log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); String logoutUrl = _agent.buildLogoutUrl(hreq, cfg); - if (debug >= 1) - log("Redirecting to logout url '" + logoutUrl + "'"); + + log("Redirecting to logout url '" + logoutUrl + "'"); // Clear previous COOKIE ... Cookie ssoCookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); @@ -486,8 +403,8 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Check for the single sign on cookie // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking for SSO cookie"); + + log("Checking for SSO cookie"); Cookie cookie = null; Cookie cookies[] = hreq.getCookies(); if (cookies == null) @@ -500,30 +417,33 @@ public void invoke(Request request, Response response) } String jossoSessionId = (cookie == null) ? null : cookie.getValue(); - if (debug >= 1) - log("Session is: " + session); + + log("Session is: " + session); LocalSession localSession = _sessionMap.get(session.getId()); if (localSession == null) { localSession = new CatalinaLocalSession(session); // the local session is new so, make the valve listen for its events so that it can // map them to local session events. session.addSessionListener(this); + session.getManager().getContainer().addContainerListener(this); _sessionMap.put(session.getId(), localSession); + + log("Monitoring session " + session.getId()); } // ------------------------------------------------------------------ // Check if the partner application submitted custom login form // ------------------------------------------------------------------ - if (debug >= 1){ + { log("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'"); } if (hreq.getRequestURI().endsWith(_agent.getJossoAuthenticationUri())) { - if (debug >= 1) - log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); + + log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); CatalinaSSOAgentRequest customAuthRequest = new CatalinaSSOAgentRequest(cfg.getId(), - SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); + SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); customAuthRequest.setRequest(hreq); customAuthRequest.setResponse(hres); @@ -540,16 +460,16 @@ public void invoke(Request request, Response response) // Trigger LOGIN OPTIONAL if required // ------------------------------------------------------------------ - if (debug >= 1) - log("SSO cookie is not present, verifying optional login process "); + + log("SSO cookie is not present, verifying optional login process "); // We have no cookie, remember me is enabled and a security check without assertion was received ... // This means that the user could not be identified ... go back to the original resource if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") == null) { + hreq.getParameter("josso_assertion_id") == null) { + - if (debug >= 1) - log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); + log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); String requestURI = this.getSavedRequestURL(hreq, session); _agent.prepareNonCacheResponse(hres); @@ -565,40 +485,40 @@ public void invoke(Request request, Response response) if (!isResourceIgnored(cfg, request) && _agent.isAutomaticLoginRequired(hreq, hres)) { - if (debug >= 1) - log("SSO cookie is not present, attempting automatic login"); + + log("SSO cookie is not present, attempting automatic login"); // Save current request, so we can co back to it later ... saveRequest(request, session); String loginUrl = _agent.buildLoginOptionalUrl(hreq); - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); return; } else { - if (debug >= 1) - log("SSO cookie is not present, but login optional process is not required"); + + log("SSO cookie is not present, but login optional process is not required"); } // save requested resource - if (!isResourceIgnored(cfg, request)) { - StringBuffer sb = new StringBuffer(hreq.getRequestURI()); - if (hreq.getQueryString() != null) { - sb.append('?'); - sb.append(hreq.getQueryString()); - } - _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); - } + if (!isResourceIgnored(cfg, request)) { + StringBuffer sb = new StringBuffer(hreq.getRequestURI()); + if (hreq.getQueryString() != null) { + sb.append('?'); + sb.append(hreq.getQueryString()); + } + _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + } } - if (debug >= 1) - log("SSO cookie is not present, checking for outbound relaying"); + + log("SSO cookie is not present, checking for outbound relaying"); if (!(hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") != null)) { + hreq.getParameter("josso_assertion_id") != null)) { log("SSO cookie not present and relaying was not requested, skipping"); getNext().invoke(request, response); return; @@ -615,41 +535,41 @@ public void invoke(Request request, Response response) } // This URI should be protected by SSO, go on ... - if (debug >= 1) - log("Session is: " + session); + + log("Session is: " + session); // ------------------------------------------------------------------ // Invoke the SSO Agent // ------------------------------------------------------------------ - if (debug >= 1) - log("Executing agent..."); + + log("Executing agent..."); _agent.setCatalinaContainer(request.getContext()); // ------------------------------------------------------------------ // Check if a user has been authenticated and should be checked by the agent. // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); + + log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") != null) { + hreq.getParameter("josso_assertion_id") != null) { - if (debug >= 1) - log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + - hreq.getParameter("josso_assertion_id") - ); + + log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + + hreq.getParameter("josso_assertion_id") + ); String assertionId = hreq.getParameter(Constants.JOSSO_ASSERTION_ID_PARAMETER); CatalinaSSOAgentRequest relayRequest; - if (debug >= 1) - log("Outbound relaying requested for assertion id [" + assertionId + "]"); + + log("Outbound relaying requested for assertion id [" + assertionId + "]"); relayRequest = new CatalinaSSOAgentRequest(cfg.getId(), SSOAgentRequest.ACTION_RELAY, null, localSession, assertionId - ); + ); relayRequest.setRequest(hreq); relayRequest.setResponse(hres); relayRequest.setContext(request.getContext()); @@ -657,17 +577,17 @@ public void invoke(Request request, Response response) SingleSignOnEntry entry = _agent.processRequest(relayRequest); if (entry == null) { // This is wrong! We should have an entry here! - if (debug >= 1) - log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); + + log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); // Throw an exception, we will handle it below ! throw new RuntimeException("Outbound relaying failed. No Principal found. Verify your SSO Agent Configuration!"); } - if (debug >= 1) - log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); - if (debug >= 1) - log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); + log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); + + + log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); // The cookie is valid to for the partner application only ... in the future each partner app may // store a different auth. token (SSO SESSION) value @@ -676,48 +596,48 @@ public void invoke(Request request, Response response) //Redirect user to the saved splash resource (in case of auth request) or to request URI otherwise String requestURI = getSavedSplashResource(hreq); - if(requestURI == null) { - requestURI = getSavedRequestURL(hreq, session); + if (requestURI == null) { + requestURI = getSavedRequestURL(hreq, session); if (requestURI == null) { if (cfg.getDefaultResource() != null) { requestURI = cfg.getDefaultResource(); } else { - // If no saved request is found, redirect to the partner app root : - requestURI = hreq.getRequestURI().substring( - 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); + // If no saved request is found, redirect to the partner app root : + requestURI = hreq.getRequestURI().substring( + 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); } - // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! - String singlePointOfAccess = _agent.getSinglePointOfAccess(); - if (singlePointOfAccess != null) { - requestURI = singlePointOfAccess + requestURI; - } else { - String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); - if (reverseProxyHost != null) { - requestURI = reverseProxyHost + requestURI; - } - } - - if (debug >= 1) - log("No saved request found, using : '" + requestURI + "'"); - } + // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! + String singlePointOfAccess = _agent.getSinglePointOfAccess(); + if (singlePointOfAccess != null) { + requestURI = singlePointOfAccess + requestURI; + } else { + String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); + if (reverseProxyHost != null) { + requestURI = reverseProxyHost + requestURI; + } + } + + + log("No saved request found, using : '" + requestURI + "'"); + } } clearSavedRequestURLs(hreq, hres, session); - _agent.clearAutomaticLoginReferer(hreq, hres); + _agent.clearAutomaticLoginReferer(hreq, hres); _agent.prepareNonCacheResponse(hres); // Check if we have a post login resource : String postAuthURI = cfg.getPostAuthenticationResource(); if (postAuthURI != null) { String postAuthURL = _agent.buildPostAuthUrl(hres, requestURI, postAuthURI); - if (debug >= 1) - log("Redirecting to post-auth-resource '" + postAuthURL + "'"); + + log("Redirecting to post-auth-resource '" + postAuthURL + "'"); hres.sendRedirect(postAuthURL); } else { - if (debug >= 1) - log("Redirecting to original '" + requestURI + "'"); + + log("Redirecting to original '" + requestURI + "'"); hres.sendRedirect(hres.encodeRedirectURL(requestURI)); } @@ -736,18 +656,18 @@ public void invoke(Request request, Response response) SingleSignOnEntry entry = _agent.processRequest(r); - if (debug >= 1) - log("Executed agent."); + + log("Executed agent."); // ------------------------------------------------------------------ // Has a valid user already been authenticated? // ------------------------------------------------------------------ - if (debug >= 1) - log("Process request for '" + hreq.getRequestURI() + "'"); + + log("Process request for '" + hreq.getRequestURI() + "'"); if (entry != null) { - if (debug >= 1) - log("Principal '" + entry.principal + + + log("Principal '" + entry.principal + "' has already been authenticated"); (request).setAuthType(entry.authType); @@ -758,38 +678,38 @@ public void invoke(Request request, Response response) // This is a standard anonymous request! if (cookie != null) { - // cookie is not valid - cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); - hres.addCookie(cookie); + // cookie is not valid + cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); + hres.addCookie(cookie); } if (cookie != null || (getSavedRequestURL(hreq, session) == null && _agent.isAutomaticLoginRequired(hreq, hres))) { - if (debug >= 1) - log("SSO Session is not valid, attempting automatic login"); + + log("SSO Session is not valid, attempting automatic login"); // Save current request, so we can co back to it later ... saveRequest(request, session); String loginUrl = _agent.buildLoginOptionalUrl(hreq); - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); return; } else { - if (debug >= 1) - log("SSO cookie is not present, but login optional process is not required"); + + log("SSO cookie is not present, but login optional process is not required"); } } // propagate the login and logout URLs to // partner applications. - hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl() ); - hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl() ); + hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl()); + hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl()); hreq.setAttribute("org.josso.agent.ssoSessionid", jossoSessionId); // ------------------------------------------------------------------ @@ -812,8 +732,8 @@ public void invoke(Request request, Response response) return; } finally { - if (debug >= 1) - log("Processed : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + + log("Processed : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]"); } } @@ -837,8 +757,6 @@ public String toString() { // -------------------------------------------------------- Package Methods - - // ------------------------------------------------------ Protected Methods /** @@ -866,16 +784,16 @@ protected Session getSession(Request request, boolean create) { HttpServletRequest hreq = (HttpServletRequest) request.getRequest(); HttpSession hses = hreq.getSession(create); - if (debug >= 1) - log("getSession() : hses " + hses); + + log("getSession() : hses " + hses); if (hses == null) return (null); // Get catalina Context from request ... Manager manager = request.getContext().getManager(); - if (debug >= 1) - log("getSession() : manager is " + manager); + + log("getSession() : manager is " + manager); if (manager == null) return (null); else { @@ -915,33 +833,34 @@ protected void log(String message, Throwable throwable) { * Return the request URI (with the corresponding query string, if any) * from the saved request so that we can redirect to it. * - * @param hreq http request + * @param hreq http request * @param session Our current session */ private String getSavedRequestURL(HttpServletRequest hreq, Session session) { - String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - if (savedURL == null || savedURL.equals("")) { - SavedRequest saved = - (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - if (saved == null) - return (null); - StringBuffer sb = new StringBuffer(saved.getRequestURI()); - if (saved.getQueryString() != null) { - sb.append('?'); - sb.append(saved.getQueryString()); - } - savedURL = sb.toString(); - } + String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + if (savedURL == null || savedURL.equals("")) { + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (saved == null) + return (null); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); + if (saved.getQueryString() != null) { + sb.append('?'); + sb.append(saved.getQueryString()); + } + savedURL = sb.toString(); + } return savedURL; } /** * Return the splash resource from session so that we can redirect the user to it * if (s)he was logged in using custom form + * * @param hreq http request */ private String getSavedSplashResource(HttpServletRequest hreq) { - return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); } /** @@ -952,7 +871,7 @@ private String getSavedSplashResource(HttpServletRequest hreq) { * @throws java.io.IOException */ protected void saveRequest(Request request, Session session) - throws IOException { + throws IOException { // Create and populate a SavedRequest object for this request SavedRequest saved = new SavedRequest(); @@ -977,28 +896,28 @@ protected void saveRequest(Request request, Session session) } /** Need more catalina classes - if ("POST".equalsIgnoreCase(request.getMethod())) { - ByteChunk body = new ByteChunk(); - body.setLimit(request.getConnector().getMaxSavePostSize()); + if ("POST".equalsIgnoreCase(request.getMethod())) { + ByteChunk body = new ByteChunk(); + body.setLimit(request.getConnector().getMaxSavePostSize()); - byte[] buffer = new byte[4096]; - int bytesRead; - InputStream is = request.getInputStream(); + byte[] buffer = new byte[4096]; + int bytesRead; + InputStream is = request.getInputStream(); - while ( (bytesRead = is.read(buffer) ) >= 0) { - body.append(buffer, 0, bytesRead); - } - saved.setContentType(request.getContentType()); - saved.setBody(body); - } */ + while ( (bytesRead = is.read(buffer) ) >= 0) { + body.append(buffer, 0, bytesRead); + } + saved.setContentType(request.getContentType()); + saved.setBody(body); + } */ saved.setMethod(request.getMethod()); saved.setQueryString(request.getQueryString()); saved.setRequestURI(request.getRequestURI()); - + // Stash the SavedRequest in our session for later use session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); - + StringBuffer sb = new StringBuffer(request.getRequestURI()); if (request.getQueryString() != null) { String q = request.getQueryString(); @@ -1008,25 +927,25 @@ protected void saveRequest(Request request, Session session) } _agent.setAttribute(request.getRequest(), request.getResponse().getResponse(), WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); } - + /** * Save referer URI into our session for later use. - * + *

* This method is used so agent can know from which * public resource (page) user requested login. - * - * @param request http request - * @param response http response - * @param session current session + * + * @param request http request + * @param response http response + * @param session current session * @param overrideSavedResource true if saved resource should be overridden, false otherwise */ protected void saveLoginBackToURL(HttpServletRequest request, HttpServletResponse response, Session session, boolean overrideSavedResource) { - String referer = request.getHeader("referer"); + String referer = request.getHeader("referer"); //saved request will exist only if user requested some protected resource - String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - SavedRequest saved = - (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { + String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { saved = new SavedRequest(); @@ -1034,51 +953,51 @@ protected void saveLoginBackToURL(HttpServletRequest request, HttpServletRespons String uri = p >= 0 ? referer.substring(0, p) : referer; String queryStr = p >= 0 ? referer.substring(p) : null; - saved.setRequestURI(uri); + saved.setRequestURI(uri); saved.setQueryString(queryStr); session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); - + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, referer); } else if (saved != null) { - StringBuffer sb = new StringBuffer(saved.getRequestURI()); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); if (saved.getQueryString() != null) { String q = saved.getQueryString(); if (!q.startsWith("?")) sb.append('?'); sb.append(q); } - _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); } } - + /** - * Remove saved request URLs from session - * to avoid mixing up resources from previous operations + * Remove saved request URLs from session + * to avoid mixing up resources from previous operations * (logins, logouts) with the current one. - * - * @param hreq http request - * @param hres http response + * + * @param hreq http request + * @param hres http response * @param session Our current session */ protected void clearSavedRequestURLs(HttpServletRequest hreq, HttpServletResponse hres, Session session) { - session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); } protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { // There are some web-resources to ignore. String[] ignoredWebResources = cfg.getIgnoredWebRources(); - if (debug >= 1) - log("Found [" + (ignoredWebResources!= null ? ignoredWebResources.length+"" : "no") + "] ignored web resources "); + + log("Found [" + (ignoredWebResources != null ? ignoredWebResources.length + "" : "no") + "] ignored web resources "); if (ignoredWebResources != null && ignoredWebResources.length > 0) { Realm realm = request.getContext().getRealm(); - SecurityConstraint [] constraints - = realm.findSecurityConstraints(request, request.getContext()); + SecurityConstraint[] constraints + = realm.findSecurityConstraints(request, request.getContext()); if ((constraints != null)) { @@ -1093,8 +1012,8 @@ protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { if (constraint.findCollection(ignoredWebResource) != null) { // We should ignore this URI, it's not subject to SSO protection. - if (debug >= 1) - log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); + + log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); return true; } From bc69b832f825f801b9a6a93e9ab7be9d6ccfd2c9 Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Wed, 1 Feb 2017 12:41:55 -0800 Subject: [PATCH 05/11] Downgraded maven plugin for the project to be built using Maven 2.2 --- pom.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pom.xml b/pom.xml index 9fd58fc5..36ba8a6e 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,11 @@ axistools-maven-plugin 1.1 + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + @@ -363,6 +368,11 @@ axistools-maven-plugin 1.1 + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + @@ -388,6 +398,11 @@ axistools-maven-plugin 1.1 + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + @@ -419,6 +434,11 @@ axistools-maven-plugin 1.1 + + org.codehaus.mojo + build-helper-maven-plugin + 1.10 + From 16da8dc3dcd94bc8729b836b00e2bcc3b161a455 Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Wed, 1 Feb 2017 14:35:48 -0800 Subject: [PATCH 06/11] * Fixed merge issue --- .../src/main/java/org/josso/tc70/agent/SSOAgentValve.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java index cf7fe5b2..553e11b7 100644 --- a/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java +++ b/agents/josso-tomcat70-agent/src/main/java/org/josso/tc70/agent/SSOAgentValve.java @@ -307,8 +307,7 @@ public void invoke(Request request, Response response) // URI Encoding if (_agent.getUriEncoding() != null) { - if (debug >= 1) - log("Setting request/response encoding to " + _agent.getUriEncoding()); + log("Setting request/response encoding to " + _agent.getUriEncoding()); hreq.setCharacterEncoding(_agent.getUriEncoding()); hres.setCharacterEncoding(_agent.getUriEncoding()); } From 9bf12fc4664c3f64254695d3a429450021eb5a2e Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Wed, 1 Feb 2017 16:44:30 -0800 Subject: [PATCH 07/11] Applied memory leak fix due to session fixation protection on Tomcatn --- .../tc80/agent/CatalinaLocalSession.java | 13 +- .../josso/tc80/agent/CatalinaNativeRealm.java | 82 +-- .../josso/tc80/agent/CatalinaSSOAgent.java | 29 +- .../josso/tc80/agent/LocalSessionImpl.java | 8 +- .../org/josso/tc80/agent/SSOAgentValve.java | 520 ++++++++---------- .../tc80/agent/jaas/CatalinaJAASRealm.java | 2 +- .../tc80/agent/jaas/CatalinaSSOUser.java | 16 +- .../agent/jaas/SSOGatewayLoginModule.java | 64 +-- .../tc85/agent/CatalinaLocalSession.java | 5 +- .../josso/tc85/agent/CatalinaSSOAgent.java | 19 +- .../josso/tc85/agent/LocalSessionImpl.java | 6 + .../org/josso/tc85/agent/SSOAgentValve.java | 509 ++++++++--------- 12 files changed, 586 insertions(+), 687 deletions(-) diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaLocalSession.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaLocalSession.java index d4b3361a..48ada5b3 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaLocalSession.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaLocalSession.java @@ -27,18 +27,21 @@ /** * Acts as a Catalina Session wrapper. * - * @author Gianluca Brigandi + * @author Gianluca Brigandi * @version CVS $Id: CatalinaLocalSession.java 974 2009-01-14 00:39:45Z sgonzalez $ */ public class CatalinaLocalSession extends LocalSessionImpl { - public CatalinaLocalSession( Session catalinaSession) { + public CatalinaLocalSession(Session catalinaSession) { super(); - setWrapped(catalinaSession); - setMaxInactiveInterval(catalinaSession.getMaxInactiveInterval()); - + setWrapped(catalinaSession); + setMaxInactiveInterval(catalinaSession.getMaxInactiveInterval()); + } + @Override + public String toString() { + return "CatalinaLocalSession [toString()=" + super.toString() + "]"; } } diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaNativeRealm.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaNativeRealm.java index cf4908bf..42a1ad20 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaNativeRealm.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaNativeRealm.java @@ -39,7 +39,7 @@ import java.security.Principal; /** - * Catalina Realm replacement that will authenticate users + * Catalina Realm replacement that will authenticate users * directly against the gateway. */ public class CatalinaNativeRealm extends RealmBase { @@ -49,58 +49,58 @@ public class CatalinaNativeRealm extends RealmBase { * Descriptive information about this Realm implementation. */ protected static final String name = "CatalinaNativeRealm"; - - @Override - public Principal authenticate(String username, String credentials) { - try { + + @Override + public Principal authenticate(String username, String credentials) { + try { SSOAgentRequest request = AbstractSSOAgent._currentRequest.get(); SSOAgent agent = Lookup.getInstance().lookupSSOAgent(); SSOIdentityManagerService im = request.getConfig(agent).getIdentityManagerService(); if (im == null) im = agent.getSSOIdentityManager(); - - String requester = ""; - // Check for nulls ? + + String requester = ""; + // Check for nulls ? if (request != null) - requester = request.getRequester(); + requester = request.getRequester(); else log.warn("No SSO Agent request found in thread local variable, can't identify requester"); SSOUser ssoUser = im.findUserInSession(requester, username); - - Principal principal = null; - - if (ssoUser != null) { - Subject subject = new Subject(); - subject.getPrincipals().add(ssoUser); + + Principal principal = null; + + if (ssoUser != null) { + Subject subject = new Subject(); + subject.getPrincipals().add(ssoUser); SSORole[] ssoRolePrincipals = im.findRolesBySSOSessionId(requester, username); - for (int i=0; i < ssoRolePrincipals.length; i++) { - subject.getPrincipals().add(ssoRolePrincipals[i]); - } - // Return the appropriate Principal for this authenticated Subject - principal = createPrincipal(username, subject); - } - - return principal; - } catch (SSOIdentityException e) { + for (int i = 0; i < ssoRolePrincipals.length; i++) { + subject.getPrincipals().add(ssoRolePrincipals[i]); + } + // Return the appropriate Principal for this authenticated Subject + principal = createPrincipal(username, subject); + } + + return principal; + } catch (SSOIdentityException e) { // Ignore this ... (user does not exist for this session) if (log.isDebugEnabled()) { - log.debug(e.getMessage()); + log.debug(e.getMessage()); } return null; } catch (Exception e) { - log.error("Session authentication failed : " + username, e); + log.error("Session authentication failed : " + username, e); throw new RuntimeException("Fatal error authenticating session : " + e); } - } + } - /** + /** * Construct and return a java.security.Principal instance * representing the authenticated user for the specified Subject. If no * such Principal can be constructed, return null. - * + *

* The Principal constructed is CatalinaSSOUser which is a SSOUser. * The Partner Application can access SSOUser-specific properties that are not available * in GenericPrincipal. @@ -111,18 +111,18 @@ protected Principal createPrincipal(String username, Subject subject) { return CatalinaSSOUser.newInstance(this, subject); } - @Override - protected String getName() { - return name; - } + @Override + protected String getName() { + return name; + } - @Override - protected String getPassword(String username) { - return null; - } + @Override + protected String getPassword(String username) { + return null; + } - @Override - protected Principal getPrincipal(String username) { - return authenticate(username, username); - } + @Override + protected Principal getPrincipal(String username) { + return authenticate(username, username); + } } diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaSSOAgent.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaSSOAgent.java index a5f79932..d852006d 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaSSOAgent.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/CatalinaSSOAgent.java @@ -25,22 +25,25 @@ import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.Realm; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.josso.agent.SSOAgentRequest; import org.josso.agent.http.HttpSSOAgent; import java.security.Principal; /** + * @author Gianluca Brigandi + * @version CVS $Id: CatalinaSSOAgent.java 974 2009-01-14 00:39:45Z sgonzalez $ * @org.apache.xbean.XBean element="agent" - * + *

* Catalina SSO Agent Implementation that authenticates using the configured Catalina Realm's * Gateway SSO Login module. - * - * @author Gianluca Brigandi - * @version CVS $Id: CatalinaSSOAgent.java 974 2009-01-14 00:39:45Z sgonzalez $ */ public class CatalinaSSOAgent extends HttpSSOAgent { + private static final Log LOG = LogFactory.getLog(CatalinaSSOAgent.class); + private Container _container; public CatalinaSSOAgent() { @@ -50,7 +53,7 @@ public CatalinaSSOAgent() { public CatalinaSSOAgent(Container container) { super(); - _container = container; + _container = container; } @@ -95,25 +98,19 @@ protected Principal authenticate(SSOAgentRequest request) { Principal p = realm.authenticate(r.getSessionId(), r.getSessionId()); if (debug > 0) - log("Received principal : " + p + "[" + ( p != null ? p.getClass().getName() : "" ) +"]"); + log("Received principal : " + p + "[" + (p != null ? p.getClass().getName() : "") + "]"); return p; } protected void log(String message) { - if (_container != null) { - if (_container.getLogger().isDebugEnabled()) - _container.getLogger().debug(this.toString() + ": " + message); - } else - System.out.println(this.toString() + ": " + message); + if (LOG.isDebugEnabled()) + LOG.debug(message); } protected void log(String message, Throwable throwable) { - if (_container != null) { - if (_container.getLogger().isDebugEnabled()) - _container.getLogger().debug(this.toString() + ": " + message, throwable); - } else - System.out.println(this.toString() + ": " + message); + if (LOG.isDebugEnabled()) + LOG.debug(message, throwable); } /** diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/LocalSessionImpl.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/LocalSessionImpl.java index b7a7408f..872c9b2d 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/LocalSessionImpl.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/LocalSessionImpl.java @@ -93,7 +93,7 @@ public void removeSessionListener(LocalSessionListener sessionListener) { } public void invalidate() { - ((Session)_wrapped).expire(); + ((Session) _wrapped).expire(); } public void setWrapped(Object wrapped) { @@ -103,5 +103,11 @@ public void setWrapped(Object wrapped) { public Object getWrapped() { return _wrapped; } + + @Override + public String toString() { + return "LocalSessionImpl [_creationTime=" + _creationTime + ", _id=" + _id + ", _lastAccessedTime=" + + _lastAccessedTime + ", _maxInactiveInterval=" + _maxInactiveInterval + ", _wrapped=" + _wrapped + "]"; + } } diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/SSOAgentValve.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/SSOAgentValve.java index d149c439..0e591ead 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/SSOAgentValve.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/SSOAgentValve.java @@ -28,6 +28,8 @@ import org.apache.catalina.connector.Response; import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.valves.ValveBase; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.josso.agent.*; import org.josso.agent.http.WebAccessControlUtil; @@ -49,13 +51,9 @@ * @version $Id: SSOAgentValve.java 1657 2010-10-13 20:48:21Z sgonzalez $ */ public class SSOAgentValve extends ValveBase - implements Lifecycle, SessionListener { - - /** - * The debugging detail level for this component. - */ - protected int debug = 0; + implements Lifecycle, SessionListener, ContainerListener { + private static final Log LOG = LogFactory.getLog(SSOAgentValve.class); /** * Descriptive information about this Valve implementation. @@ -63,7 +61,6 @@ public class SSOAgentValve extends ValveBase protected static String info = "org.apache.catalina.authenticator.SingleSignOn"; - /** * The lifecycle event support for this component. */ @@ -78,44 +75,71 @@ public class SSOAgentValve extends ValveBase /** * Catalina Session to Local Session Map. */ - Map _sessionMap = Collections.synchronizedMap(new HashMap()); + private Map _sessionMap = Collections.synchronizedMap(new HashMap()); - // ------------------------------------------------------------- Properties + // ------------------------------------------------------ SessionListener Methods - /** - * Return the debugging detail level. - */ - public int getDebug() { + public void sessionEvent(SessionEvent event) { - return (this.debug); + if (LOG.isDebugEnabled()) { + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: " + event); + } - } + // extra protective guard + try { + // obtain the local session for the catalina session, and notify the + // listeners for it. + LocalSession localSession = _sessionMap.get(event.getSession().getId()); + + if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { + if (localSession != null) { + localSession.expire(); + _sessionMap.remove(event.getSession().getId()); + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: session not null. can expire."); + } + } + } catch (Exception ex) { + LOG.error("JOSSO: SESSION PURGE EXCEPTION: ", ex); + } - /** - * Set the debugging detail level. - * - * @param debug The new debugging detail level - */ - public void setDebug(int debug) { + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: sessionMap.size remaining: " + _sessionMap.size()); - this.debug = debug; + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: complete"); } - // ------------------------------------------------------ SessionListener Methods - - public void sessionEvent(SessionEvent event) { + // ------------------------------------------------------ ContainerListener Methods + public void containerEvent(ContainerEvent event) { + if (LOG.isDebugEnabled()) { + LOG.debug("JOSSO: SSOAgentValve.containerEvent: " + event); + } - // obtain the local session for the catalina session, and notify the listeners for it. - LocalSession localSession = (LocalSession) _sessionMap.get(event.getSession().getId()); + if (event.getType().equals(Context.CHANGE_SESSION_ID_EVENT)) { + String[] sessionIds = (String[]) event.getData(); + String oldId = sessionIds[0]; + String newId = sessionIds[1]; + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: Due to session fixation protection session id " + oldId + " has changed to " + newId); + + LocalSession localSession = _sessionMap.get(oldId); + if (localSession != null) { + localSession.expire(); + _sessionMap.remove(oldId); + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: Expired local session " + oldId + " as it's no longer in use"); + } - if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { - localSession.expire(); - _sessionMap.remove(event.getSession().getId()); } - + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.containerEvent: sessionMap.size remaining: " + _sessionMap.size()); + + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.containerEvent: complete"); } // ------------------------------------------------------ Lifecycle Methods @@ -159,15 +183,15 @@ public void removeLifecycleListener(LifecycleListener listener) { * Set the Container to which this Valve is attached. * * @param container The container to which we are attached - public void setContainer(Container container) { + public void setContainer(Container container) { - if (!(container instanceof Context)) - throw new IllegalArgumentException - ("The SSOAgentValve must be associated to a Catalina Context or Host"); + if (!(container instanceof Context)) + throw new IllegalArgumentException + ("The SSOAgentValve must be associated to a Catalina Context or Host"); - super.setContainer(container); - _container = container; - } + super.setContainer(container); + _container = container; + } */ /** @@ -176,7 +200,7 @@ public void setContainer(Container container) { * and before any of the public methods of the component are utilized. * * @throws org.apache.catalina.LifecycleException if this component detects a fatal error - * that prevents this component from being used + * that prevents this component from being used */ protected synchronized void startInternal() throws LifecycleException { @@ -191,7 +215,7 @@ protected synchronized void startInternal() throws LifecycleException { Lookup lookup = Lookup.getInstance(); lookup.init("josso-agent-config.xml"); _agent = (CatalinaSSOAgent) lookup.lookupSSOAgent(); - _agent.setDebug(debug); + _agent.setDebug(LOG.isDebugEnabled() ? 1 : 0); _agent.setCatalinaContainer(container); } catch (Exception e) { System.err.println(e.getMessage()); @@ -199,10 +223,7 @@ protected synchronized void startInternal() throws LifecycleException { throw new LifecycleException("Error starting SSO Agent : " + e.getMessage()); } _agent.start(); - - if (debug >= 1) - log("Started"); - + log("Started"); setState(LifecycleState.STARTING); } @@ -212,28 +233,24 @@ protected synchronized void startInternal() throws LifecycleException { * instance of this component. * * @throws org.apache.catalina.LifecycleException if this component detects a fatal error - * that needs to be reported + * that needs to be reported */ protected synchronized void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); - + // Validate and update our current component state if (!started) throw new LifecycleException ("Agent not started"); lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; - _agent.stop(); - - if (debug >= 1) - log("Stopped"); + log("Stopped"); } - // ---------------------------------------------------------- Valve Methods @@ -250,22 +267,16 @@ public String getInfo() { * @param request The servlet request we are processing * @param response The servlet response we are creating * in the current processing pipeline - * @throws IOException if an input/output error occurs + * @throws java.io.IOException if an input/output error occurs * @throws javax.servlet.ServletException if a servlet error occurs */ public void invoke(Request request, Response response) throws IOException, ServletException { - HttpServletRequest hreq = - (HttpServletRequest) request.getRequest(); - HttpServletResponse hres = - (HttpServletResponse) response.getResponse(); - - - if (debug >= 1) - log("Processing : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); - + HttpServletRequest hreq = request.getRequest(); + HttpServletResponse hres = response.getResponse(); + log("Processing : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]"); try { // ------------------------------------------------------------------ // Check with the agent if this context should be processed. @@ -279,29 +290,24 @@ public void invoke(Request request, Response response) if (!_agent.isPartnerApp(vhost, contextPath)) { getNext().invoke(request, response); - if (debug >= 1) - log("Context is not a josso partner app : " + hreq.getContextPath()); - + log("Context is not a josso partner app : " + hreq.getContextPath()); return; } // URI Encoding if (_agent.getUriEncoding() != null) { - if (debug >= 1) - log("Setting request/response encoding to " + _agent.getUriEncoding()); + log("Setting request/response encoding to " + _agent.getUriEncoding()); hreq.setCharacterEncoding(_agent.getUriEncoding()); hres.setCharacterEncoding(_agent.getUriEncoding()); } String nodeId = hreq.getParameter("josso_node"); if (nodeId != null) { - if (debug >= 1) - log("Storing JOSSO Node id : " + nodeId); - _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); + log("Storing JOSSO Node id : " + nodeId); + _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); } else { nodeId = _agent.getAttribute(hreq, "JOSSO_NODE"); - if (debug >= 1) - log("Found JOSSO Node id : " + nodeId); + log("Found JOSSO Node id : " + nodeId); } @@ -322,51 +328,36 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Check if the partner application required the login form // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); - + log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoLoginUri()) || - hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { - - if (debug >= 1) - log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); - + hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { + log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); //save referer url in case the user clicked on Login from some public resource (page) //so agent can redirect the user back to that page after successful login if (hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { - saveLoginBackToURL(hreq, hres, session, true); + saveLoginBackToURL(hreq, hres, session, true); } else { - saveLoginBackToURL(hreq, hres, session, false); + saveLoginBackToURL(hreq, hres, session, false); } String loginUrl = _agent.buildLoginUrl(hreq); - - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); - + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); - return; - } // ------------------------------------------------------------------ // Check if the partner application required a logout // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); - if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) { - - if (debug >= 1) - log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); + log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); + if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) { + log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); String logoutUrl = _agent.buildLogoutUrl(hreq, cfg); - - if (debug >= 1) - log("Redirecting to logout url '" + logoutUrl + "'"); + log("Redirecting to logout url '" + logoutUrl + "'"); // Clear previous COOKIE ... Cookie ssoCookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); @@ -375,16 +366,14 @@ public void invoke(Request request, Response response) //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(logoutUrl)); - return; - } // ------------------------------------------------------------------ // Check for the single sign on cookie // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking for SSO cookie"); + + log("Checking for SSO cookie"); Cookie cookie = null; Cookie cookies[] = hreq.getCookies(); if (cookies == null) @@ -397,37 +386,31 @@ public void invoke(Request request, Response response) } String jossoSessionId = (cookie == null) ? null : cookie.getValue(); - if (debug >= 1) - log("Session is: " + session); - LocalSession localSession = (LocalSession) _sessionMap.get(session.getId()); + log("Session is: " + session); + LocalSession localSession = _sessionMap.get(session.getId()); if (localSession == null) { localSession = new CatalinaLocalSession(session); // the local session is new so, make the valve listen for its events so that it can // map them to local session events. session.addSessionListener(this); + session.getManager().getContainer().addContainerListener(this); _sessionMap.put(session.getId(), localSession); + + log("Monitoring session " + session.getId()); } // ------------------------------------------------------------------ // Check if the partner application submitted custom login form // ------------------------------------------------------------------ - if (debug >= 1){ - log("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'"); - } + log("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoAuthenticationUri())) { - - if (debug >= 1) - log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); - + log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); CatalinaSSOAgentRequest customAuthRequest = new CatalinaSSOAgentRequest(cfg.getId(), - SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); - + SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); customAuthRequest.setRequest(hreq); customAuthRequest.setResponse(hres); customAuthRequest.setContext(request.getContext()); - _agent.processRequest(customAuthRequest); - return; } @@ -436,23 +419,17 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Trigger LOGIN OPTIONAL if required // ------------------------------------------------------------------ - - if (debug >= 1) - log("SSO cookie is not present, verifying optional login process "); + log("SSO cookie is not present, verifying optional login process "); // We have no cookie, remember me is enabled and a security check without assertion was received ... // This means that the user could not be identified ... go back to the original resource if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") == null) { - - if (debug >= 1) - log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); - + hreq.getParameter("josso_assertion_id") == null) { + log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); String requestURI = this.getSavedRequestURL(hreq, session); _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(requestURI)); return; - } // This is a standard anonymous request! @@ -461,41 +438,33 @@ public void invoke(Request request, Response response) // If saved request is NOT null, we're in the middle of another process ... if (!isResourceIgnored(cfg, request) && _agent.isAutomaticLoginRequired(hreq, hres)) { - - if (debug >= 1) - log("SSO cookie is not present, attempting automatic login"); + log("SSO cookie is not present, attempting automatic login"); // Save current request, so we can co back to it later ... saveRequest(request, session); String loginUrl = _agent.buildLoginOptionalUrl(hreq); - - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); return; } else { - if (debug >= 1) - log("SSO cookie is not present, but login optional process is not required"); + log("SSO cookie is not present, but login optional process is not required"); } // save requested resource - if (!isResourceIgnored(cfg, request)) { - StringBuffer sb = new StringBuffer(hreq.getRequestURI()); - if (hreq.getQueryString() != null) { - sb.append('?'); - sb.append(hreq.getQueryString()); - } - _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); - } + if (!isResourceIgnored(cfg, request)) { + StringBuffer sb = new StringBuffer(hreq.getRequestURI()); + if (hreq.getQueryString() != null) { + sb.append('?'); + sb.append(hreq.getQueryString()); + } + _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + } } - - if (debug >= 1) - log("SSO cookie is not present, checking for outbound relaying"); - + log("SSO cookie is not present, checking for outbound relaying"); if (!(hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") != null)) { + hreq.getParameter("josso_assertion_id") != null)) { log("SSO cookie not present and relaying was not requested, skipping"); getNext().invoke(request, response); return; @@ -512,41 +481,30 @@ public void invoke(Request request, Response response) } // This URI should be protected by SSO, go on ... - if (debug >= 1) - log("Session is: " + session); + log("Session is: " + session); // ------------------------------------------------------------------ // Invoke the SSO Agent // ------------------------------------------------------------------ - if (debug >= 1) - log("Executing agent..."); - + log("Executing agent..."); _agent.setCatalinaContainer(request.getContext()); // ------------------------------------------------------------------ // Check if a user has been authenticated and should be checked by the agent. // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); + log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") != null) { - - if (debug >= 1) - log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + - hreq.getParameter("josso_assertion_id") - ); - + hreq.getParameter("josso_assertion_id") != null) { + log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + + hreq.getParameter("josso_assertion_id") + ); String assertionId = hreq.getParameter(Constants.JOSSO_ASSERTION_ID_PARAMETER); - CatalinaSSOAgentRequest relayRequest; - - if (debug >= 1) - log("Outbound relaying requested for assertion id [" + assertionId + "]"); - + log("Outbound relaying requested for assertion id [" + assertionId + "]"); relayRequest = new CatalinaSSOAgentRequest(cfg.getId(), SSOAgentRequest.ACTION_RELAY, null, localSession, assertionId - ); + ); relayRequest.setRequest(hreq); relayRequest.setResponse(hres); relayRequest.setContext(request.getContext()); @@ -554,17 +512,13 @@ public void invoke(Request request, Response response) SingleSignOnEntry entry = _agent.processRequest(relayRequest); if (entry == null) { // This is wrong! We should have an entry here! - if (debug >= 1) - log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); + + log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); // Throw an exception, we will handle it below ! throw new RuntimeException("Outbound relaying failed. No Principal found. Verify your SSO Agent Configuration!"); } - - if (debug >= 1) - log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); - - if (debug >= 1) - log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); + log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); + log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); // The cookie is valid to for the partner application only ... in the future each partner app may // store a different auth. token (SSO SESSION) value @@ -573,48 +527,46 @@ public void invoke(Request request, Response response) //Redirect user to the saved splash resource (in case of auth request) or to request URI otherwise String requestURI = getSavedSplashResource(hreq); - if(requestURI == null) { - requestURI = getSavedRequestURL(hreq, session); + if (requestURI == null) { + requestURI = getSavedRequestURL(hreq, session); if (requestURI == null) { if (cfg.getDefaultResource() != null) { requestURI = cfg.getDefaultResource(); } else { - // If no saved request is found, redirect to the partner app root : - requestURI = hreq.getRequestURI().substring( - 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); + // If no saved request is found, redirect to the partner app root : + requestURI = hreq.getRequestURI().substring( + 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); } - // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! - String singlePointOfAccess = _agent.getSinglePointOfAccess(); - if (singlePointOfAccess != null) { - requestURI = singlePointOfAccess + requestURI; - } else { - String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); - if (reverseProxyHost != null) { - requestURI = reverseProxyHost + requestURI; - } - } - - if (debug >= 1) - log("No saved request found, using : '" + requestURI + "'"); - } + // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! + String singlePointOfAccess = _agent.getSinglePointOfAccess(); + if (singlePointOfAccess != null) { + requestURI = singlePointOfAccess + requestURI; + } else { + String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); + if (reverseProxyHost != null) { + requestURI = reverseProxyHost + requestURI; + } + } + log("No saved request found, using : '" + requestURI + "'"); + } } clearSavedRequestURLs(hreq, hres, session); - _agent.clearAutomaticLoginReferer(hreq, hres); + _agent.clearAutomaticLoginReferer(hreq, hres); _agent.prepareNonCacheResponse(hres); // Check if we have a post login resource : String postAuthURI = cfg.getPostAuthenticationResource(); if (postAuthURI != null) { String postAuthURL = _agent.buildPostAuthUrl(hres, requestURI, postAuthURI); - if (debug >= 1) - log("Redirecting to post-auth-resource '" + postAuthURL + "'"); + + log("Redirecting to post-auth-resource '" + postAuthURL + "'"); hres.sendRedirect(postAuthURL); } else { - if (debug >= 1) - log("Redirecting to original '" + requestURI + "'"); + + log("Redirecting to original '" + requestURI + "'"); hres.sendRedirect(hres.encodeRedirectURL(requestURI)); } @@ -633,18 +585,18 @@ public void invoke(Request request, Response response) SingleSignOnEntry entry = _agent.processRequest(r); - if (debug >= 1) - log("Executed agent."); + + log("Executed agent."); // ------------------------------------------------------------------ // Has a valid user already been authenticated? // ------------------------------------------------------------------ - if (debug >= 1) - log("Process request for '" + hreq.getRequestURI() + "'"); + + log("Process request for '" + hreq.getRequestURI() + "'"); if (entry != null) { - if (debug >= 1) - log("Principal '" + entry.principal + + + log("Principal '" + entry.principal + "' has already been authenticated"); (request).setAuthType(entry.authType); @@ -655,38 +607,38 @@ public void invoke(Request request, Response response) // This is a standard anonymous request! if (cookie != null) { - // cookie is not valid - cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); - hres.addCookie(cookie); + // cookie is not valid + cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); + hres.addCookie(cookie); } if (cookie != null || (getSavedRequestURL(hreq, session) == null && _agent.isAutomaticLoginRequired(hreq, hres))) { - if (debug >= 1) - log("SSO Session is not valid, attempting automatic login"); + + log("SSO Session is not valid, attempting automatic login"); // Save current request, so we can co back to it later ... saveRequest(request, session); String loginUrl = _agent.buildLoginOptionalUrl(hreq); - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); return; } else { - if (debug >= 1) - log("SSO cookie is not present, but login optional process is not required"); + + log("SSO cookie is not present, but login optional process is not required"); } } // propagate the login and logout URLs to // partner applications. - hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl() ); - hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl() ); + hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl()); + hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl()); hreq.setAttribute("org.josso.agent.ssoSessionid", jossoSessionId); // ------------------------------------------------------------------ @@ -711,8 +663,8 @@ public void invoke(Request request, Response response) return; } finally { - if (debug >= 1) - log("Processed : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + + log("Processed : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]"); } } @@ -732,12 +684,9 @@ public String toString() { } - // -------------------------------------------------------- Package Methods - - // ------------------------------------------------------ Protected Methods /** @@ -747,9 +696,7 @@ public String toString() { * @param request The HttpRequest we are processing */ protected Session getSession(Request request) { - return (getSession(request, false)); - } /** @@ -761,20 +708,15 @@ protected Session getSession(Request request) { * @param create Should we create a session if needed? */ protected Session getSession(Request request, boolean create) { - - HttpServletRequest hreq = - (HttpServletRequest) request.getRequest(); + HttpServletRequest hreq = request.getRequest(); HttpSession hses = hreq.getSession(create); - if (debug >= 1) - log("getSession() : hses " + hses); + log("getSession() : hses " + hses); if (hses == null) return (null); // Get catalina Context from request ... Manager manager = request.getContext().getManager(); - - if (debug >= 1) - log("getSession() : manager is " + manager); + log("getSession() : manager is " + manager); if (manager == null) return (null); else { @@ -797,7 +739,6 @@ protected void log(String message) { _agent.log(message); } - /** * Log a message on the Logger associated with our Container (if any). * @@ -814,33 +755,34 @@ protected void log(String message, Throwable throwable) { * Return the request URI (with the corresponding query string, if any) * from the saved request so that we can redirect to it. * - * @param hreq http request + * @param hreq http request * @param session Our current session */ private String getSavedRequestURL(HttpServletRequest hreq, Session session) { - String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - if (savedURL == null || savedURL.equals("")) { - SavedRequest saved = - (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - if (saved == null) - return (null); - StringBuffer sb = new StringBuffer(saved.getRequestURI()); - if (saved.getQueryString() != null) { - sb.append('?'); - sb.append(saved.getQueryString()); - } - savedURL = sb.toString(); - } + String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + if (savedURL == null || savedURL.equals("")) { + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (saved == null) + return (null); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); + if (saved.getQueryString() != null) { + sb.append('?'); + sb.append(saved.getQueryString()); + } + savedURL = sb.toString(); + } return savedURL; } /** * Return the splash resource from session so that we can redirect the user to it * if (s)he was logged in using custom form + * * @param hreq http request */ private String getSavedSplashResource(HttpServletRequest hreq) { - return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); } /** @@ -848,10 +790,10 @@ private String getSavedSplashResource(HttpServletRequest hreq) { * * @param request The request to be saved * @param session The session to contain the saved information - * @throws IOException + * @throws java.io.IOException */ protected void saveRequest(Request request, Session session) - throws IOException { + throws IOException { // Create and populate a SavedRequest object for this request SavedRequest saved = new SavedRequest(); @@ -876,28 +818,28 @@ protected void saveRequest(Request request, Session session) } /** Need more catalina classes - if ("POST".equalsIgnoreCase(request.getMethod())) { - ByteChunk body = new ByteChunk(); - body.setLimit(request.getConnector().getMaxSavePostSize()); + if ("POST".equalsIgnoreCase(request.getMethod())) { + ByteChunk body = new ByteChunk(); + body.setLimit(request.getConnector().getMaxSavePostSize()); - byte[] buffer = new byte[4096]; - int bytesRead; - InputStream is = request.getInputStream(); + byte[] buffer = new byte[4096]; + int bytesRead; + InputStream is = request.getInputStream(); - while ( (bytesRead = is.read(buffer) ) >= 0) { - body.append(buffer, 0, bytesRead); - } - saved.setContentType(request.getContentType()); - saved.setBody(body); - } */ + while ( (bytesRead = is.read(buffer) ) >= 0) { + body.append(buffer, 0, bytesRead); + } + saved.setContentType(request.getContentType()); + saved.setBody(body); + } */ saved.setMethod(request.getMethod()); saved.setQueryString(request.getQueryString()); saved.setRequestURI(request.getRequestURI()); - + // Stash the SavedRequest in our session for later use session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); - + StringBuffer sb = new StringBuffer(request.getRequestURI()); if (request.getQueryString() != null) { String q = request.getQueryString(); @@ -907,25 +849,25 @@ protected void saveRequest(Request request, Session session) } _agent.setAttribute(request.getRequest(), request.getResponse().getResponse(), WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); } - + /** * Save referer URI into our session for later use. - * + *

* This method is used so agent can know from which * public resource (page) user requested login. - * - * @param request http request - * @param response http response - * @param session current session + * + * @param request http request + * @param response http response + * @param session current session * @param overrideSavedResource true if saved resource should be overridden, false otherwise */ protected void saveLoginBackToURL(HttpServletRequest request, HttpServletResponse response, Session session, boolean overrideSavedResource) { - String referer = request.getHeader("referer"); + String referer = request.getHeader("referer"); //saved request will exist only if user requested some protected resource - String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - SavedRequest saved = - (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { + String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { saved = new SavedRequest(); @@ -933,51 +875,51 @@ protected void saveLoginBackToURL(HttpServletRequest request, HttpServletRespons String uri = p >= 0 ? referer.substring(0, p) : referer; String queryStr = p >= 0 ? referer.substring(p) : null; - saved.setRequestURI(uri); + saved.setRequestURI(uri); saved.setQueryString(queryStr); session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); - + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, referer); } else if (saved != null) { - StringBuffer sb = new StringBuffer(saved.getRequestURI()); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); if (saved.getQueryString() != null) { String q = saved.getQueryString(); if (!q.startsWith("?")) sb.append('?'); sb.append(q); } - _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); } } - + /** - * Remove saved request URLs from session - * to avoid mixing up resources from previous operations + * Remove saved request URLs from session + * to avoid mixing up resources from previous operations * (logins, logouts) with the current one. - * - * @param hreq http request - * @param hres http response + * + * @param hreq http request + * @param hres http response * @param session Our current session */ protected void clearSavedRequestURLs(HttpServletRequest hreq, HttpServletResponse hres, Session session) { - session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); } protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { // There are some web-resources to ignore. String[] ignoredWebResources = cfg.getIgnoredWebRources(); - if (debug >= 1) - log("Found [" + (ignoredWebResources!= null ? ignoredWebResources.length+"" : "no") + "] ignored web resources "); + + log("Found [" + (ignoredWebResources != null ? ignoredWebResources.length + "" : "no") + "] ignored web resources "); if (ignoredWebResources != null && ignoredWebResources.length > 0) { Realm realm = request.getContext().getRealm(); SecurityConstraint[] constraints - = realm.findSecurityConstraints(request, request.getContext()); + = realm.findSecurityConstraints(request, request.getContext()); if ((constraints != null)) { @@ -992,8 +934,8 @@ protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { if (constraint.findCollection(ignoredWebResource) != null) { // We should ignore this URI, it's not subject to SSO protection. - if (debug >= 1) - log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); + + log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); return true; } diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaJAASRealm.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaJAASRealm.java index 1f11f4f3..cab1cfa1 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaJAASRealm.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaJAASRealm.java @@ -45,7 +45,7 @@ public class CatalinaJAASRealm extends JAASRealm { * Construct and return a java.security.Principal instance * representing the authenticated user for the specified Subject. If no * such Principal can be constructed, return null. - * + *

* The Principal constructed is *not* GenericPrincipal as in Catalina JAASRealm class, * but CatalinaSSOUser which is a SSOUser. * The Partner Application can access SSOUser-specific properties that are not available diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaSSOUser.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaSSOUser.java index cecd7d14..26983413 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaSSOUser.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/CatalinaSSOUser.java @@ -66,7 +66,7 @@ public class CatalinaSSOUser extends GenericPrincipal implements SSOUser { * Construct and return a java.security.Principal instance * representing the authenticated user for the specified Subject. If no * such Principal can be constructed, return null. - * + *

* The Principal constructed is *not* GenericPrincipal as in Catalina JAASRealm class, * but CatalinaSSOUser which is a SSOUser. * The Partner Application can access SSOUser-specific properties that are not available @@ -142,8 +142,8 @@ public static CatalinaSSOUser newInstance(Realm realm, Subject subject) { * Construct a new Principal, associated with the specified Realm, for the * specified username and password. * - * @param realm The Realm that owns this Principal - * @param name The username of the user represented by this Principal + * @param realm The Realm that owns this Principal + * @param name The username of the user represented by this Principal * @param password Credentials used to authenticate this user */ private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name, String password) { @@ -157,13 +157,13 @@ private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name, String passwo * specified username and password, with the specified role names * (as Strings). * - * @param realm The Realm that owns this principal - * @param name The username of the user represented by this Principal + * @param realm The Realm that owns this principal + * @param name The username of the user represented by this Principal * @param password Credentials used to authenticate this user - * @param roles List of roles (must be Strings) possessed by this user + * @param roles List of roles (must be Strings) possessed by this user */ private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name, String password, - List roles) { + List roles) { super(name, password, roles); _ssoUser = ssoUser; @@ -171,8 +171,8 @@ private CatalinaSSOUser(SSOUser ssoUser, Realm realm, String name, String passwo } /** - * @deprecated this method always return null * @return always null + * @deprecated this method always return null */ public String getSessionId() { return null; diff --git a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/SSOGatewayLoginModule.java b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/SSOGatewayLoginModule.java index 8917a03e..b03f1dc5 100644 --- a/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/SSOGatewayLoginModule.java +++ b/agents/josso-tomcat80-agent/src/main/java/org/josso/tc80/agent/jaas/SSOGatewayLoginModule.java @@ -42,7 +42,7 @@ /** * SSO Gateway JAAS Login Module. - * + *

* This Login Module authenticates an SSO Session against the Single Sign-on Gateway * by getting the associated user and roles and filling it to the provided Subject. * This way clients can obtain the authenticated identity associated with the session and use it @@ -73,16 +73,13 @@ public class SSOGatewayLoginModule implements LoginModule { /** * Initialize this LoginModule * - * @param subject the Subject to be authenticated. - * + * @param subject the Subject to be authenticated. * @param callbackHandler a CallbackHandler for communicating - * with the end user (prompting for user names and - * passwords, for example). - * - * @param sharedState shared LoginModule state. - * - * @param options options specified in the login Configuration - * for this particular LoginModule. + * with the end user (prompting for user names and + * passwords, for example). + * @param sharedState shared LoginModule state. + * @param options options specified in the login Configuration + * for this particular LoginModule. */ public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { @@ -93,19 +90,17 @@ public void initialize(Subject subject, CallbackHandler callbackHandler, /** * Authenticate the user by prompting for the SSO Session Identifier assigned by the SSO Gateway on logon. - * + *

* This method obtains from the gateway, using the provided session identifier, the user associated with * such session identifier. * Only the NameCallBack is used, since its not a user/password pair but only one value containing the session * identifier. Any other callback type is ignored. * * @return true in all cases since this LoginModule - * should not be ignored. - * - * @exception FailedLoginException if the authentication fails. - * - * @exception LoginException if this LoginModule - * is unable to perform the authentication. + * should not be ignored. + * @throws FailedLoginException if the authentication fails. + * @throws LoginException if this LoginModule + * is unable to perform the authentication. */ public boolean login() throws LoginException { @@ -144,7 +139,7 @@ public boolean login() throws LoginException { "from the user"); } - logger.debug("Requested authentication to gateway by " + _requester + " using sso session " + ssoSessionId + "/" + ssoSessionId2 ); + logger.debug("Requested authentication to gateway by " + _requester + " using sso session " + ssoSessionId + "/" + ssoSessionId2); try { @@ -191,16 +186,15 @@ public boolean login() throws LoginException { /** * This method is called if the LoginContext's overall authentication succeeded. - * + *

* Using the SSO user name, saved by the previosuly executed login() operation, obtains from the gateway * the roles associated with the user and fills the Subject with the user and role principals. * If this LoginModule's own authentication attempted failed, then this method removes any state that was * originally saved. * - * @exception LoginException if the commit fails. - * * @return true if this LoginModule's own login and commit - * attempts succeeded, or false otherwise. + * attempts succeeded, or false otherwise. + * @throws LoginException if the commit fails. */ public boolean commit() throws LoginException { if (_succeeded == false) { @@ -220,12 +214,12 @@ public boolean commit() throws LoginException { _ssoRolePrincipals = getRoleSets(_requester); // Add to the Subject the SSORoles associated with the SSOUser . - for (int i=0; i < _ssoRolePrincipals .length; i++) { - if (_subject.getPrincipals().contains(_ssoRolePrincipals [i])) + for (int i = 0; i < _ssoRolePrincipals.length; i++) { + if (_subject.getPrincipals().contains(_ssoRolePrincipals[i])) continue; - _subject.getPrincipals().add(_ssoRolePrincipals [i]); - logger.debug("Added SSORole Principal to the Subject : " + _ssoRolePrincipals [i]); + _subject.getPrincipals().add(_ssoRolePrincipals[i]); + logger.debug("Added SSORole Principal to the Subject : " + _ssoRolePrincipals[i]); } commitSucceeded = true; @@ -242,13 +236,12 @@ public boolean commit() throws LoginException { } /** - * This method is called if the LoginContext's + * This method is called if the LoginContext's * overall authentication failed. * - * @exception LoginException if the abort fails. - * * @return false if this LoginModule's own login and/or commit attempts - * failed, and true otherwise. + * failed, and true otherwise. + * @throws LoginException if the abort fails. */ public boolean abort() throws LoginException { if (_succeeded == false) { @@ -267,21 +260,20 @@ public boolean abort() throws LoginException { /** * Logout the user. - * + *

* This method removes the SSO User and Role Principals from the Subject that were added by the commit() * method. * - * @exception LoginException if the logout fails. - * * @return true in all cases since this LoginModule - * should not be ignored. + * should not be ignored. + * @throws LoginException if the logout fails. */ public boolean logout() throws LoginException { _subject.getPrincipals().remove(_ssoUserPrincipal); logger.debug("Removed SSOUser Principal from Subject : " + _ssoUserPrincipal); // Remove all the SSORole Principals from the Subject. - for (int i=0; i < _ssoRolePrincipals.length; i++) { + for (int i = 0; i < _ssoRolePrincipals.length; i++) { _subject.getPrincipals().remove(_ssoRolePrincipals[i]); logger.debug("Removed SSORole Principal from Subject : " + _ssoRolePrincipals[i]); } @@ -314,7 +306,7 @@ protected SSORole[] getRoleSets(String requester) throws LoginException { im = agent.getSSOIdentityManager(); return im.findRolesBySSOSessionId(requester, _currentSSOSessionId); - } catch(Exception e) { + } catch (Exception e) { logger.error("Session login failed for Principal : " + _ssoUserPrincipal, e); throw new LoginException("Session login failed for Principal : " + _ssoUserPrincipal); } diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java index db8849b0..839e8024 100644 --- a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaLocalSession.java @@ -37,8 +37,11 @@ public CatalinaLocalSession( Session catalinaSession) { setWrapped(catalinaSession); setMaxInactiveInterval(catalinaSession.getMaxInactiveInterval()); + } - + @Override + public String toString() { + return "CatalinaLocalSession [toString()=" + super.toString() + "]"; } } diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java index 0e1f5eb0..2dcd3788 100644 --- a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/CatalinaSSOAgent.java @@ -25,6 +25,8 @@ import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.Realm; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.josso.agent.SSOAgentRequest; import org.josso.agent.http.HttpSSOAgent; @@ -41,13 +43,14 @@ */ public class CatalinaSSOAgent extends HttpSSOAgent { + private static final Log LOG = LogFactory.getLog(CatalinaSSOAgent.class); + private Container _container; public CatalinaSSOAgent() { super(); } - public CatalinaSSOAgent(Container container) { super(); _container = container; @@ -101,19 +104,13 @@ protected Principal authenticate(SSOAgentRequest request) { } protected void log(String message) { - if (_container != null) { - if (_container.getLogger().isDebugEnabled()) - _container.getLogger().debug(this.toString() + ": " + message); - } else - System.out.println(this.toString() + ": " + message); + if (LOG.isDebugEnabled()) + LOG.debug(message); } protected void log(String message, Throwable throwable) { - if (_container != null) { - if (_container.getLogger().isDebugEnabled()) - _container.getLogger().debug(this.toString() + ": " + message, throwable); - } else - System.out.println(this.toString() + ": " + message); + if (LOG.isDebugEnabled()) + LOG.debug(message, throwable); } /** diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java index 177c0bfb..c351d2ea 100644 --- a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/LocalSessionImpl.java @@ -103,5 +103,11 @@ public void setWrapped(Object wrapped) { public Object getWrapped() { return _wrapped; } + + @Override + public String toString() { + return "LocalSessionImpl [_creationTime=" + _creationTime + ", _id=" + _id + ", _lastAccessedTime=" + + _lastAccessedTime + ", _maxInactiveInterval=" + _maxInactiveInterval + ", _wrapped=" + _wrapped + "]"; + } } diff --git a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java index 679c9afe..802652e9 100644 --- a/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java +++ b/agents/josso-tomcat85-agent/src/main/java/org/josso/tc85/agent/SSOAgentValve.java @@ -27,6 +27,8 @@ import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.tomcat.util.descriptor.web.SecurityConstraint; import org.josso.agent.*; import org.josso.agent.http.WebAccessControlUtil; @@ -48,13 +50,9 @@ * @version $Id: SSOAgentValve.java 1657 2010-10-13 20:48:21Z sgonzalez $ */ public class SSOAgentValve extends ValveBase - implements Lifecycle, SessionListener { - - /** - * The debugging detail level for this component. - */ - protected int debug = 0; + implements Lifecycle, SessionListener, ContainerListener { + private static final Log LOG = LogFactory.getLog(SSOAgentValve.class); /** * Descriptive information about this Valve implementation. @@ -62,54 +60,75 @@ public class SSOAgentValve extends ValveBase protected static String info = "org.apache.catalina.authenticator.SingleSignOn"; - /** * Component started flag. */ protected boolean started = false; + private CatalinaSSOAgent _agent; /** * Catalina Session to Local Session Map. */ - Map _sessionMap = Collections.synchronizedMap(new HashMap()); - - // ------------------------------------------------------------- Properties - - /** - * Return the debugging detail level. - */ - public int getDebug() { - - return (this.debug); - - } + private Map _sessionMap = Collections.synchronizedMap(new HashMap()); + // ------------------------------------------------------ SessionListener Methods - /** - * Set the debugging detail level. - * - * @param debug The new debugging detail level - */ - public void setDebug(int debug) { + public void sessionEvent(SessionEvent event) { + // extra protective guard + try { + // obtain the local session for the catalina session, and notify the + // listeners for it. + LocalSession localSession = _sessionMap.get(event.getSession().getId()); + + if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { + if (localSession != null) { + localSession.expire(); + _sessionMap.remove(event.getSession().getId()); + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: session not null. can expire."); + } + } - this.debug = debug; + } catch (Exception ex) { + LOG.error("JOSSO: SESSION PURGE EXCEPTION: ", ex); + } - } + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: sessionMap.size remaining: " + _sessionMap.size()); - // ------------------------------------------------------ SessionListener Methods + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.sessionEvent: complete"); + } - public void sessionEvent(SessionEvent event) { + // ------------------------------------------------------ ContainerListener Methods + public void containerEvent(ContainerEvent event) { + if (LOG.isDebugEnabled()) { + LOG.debug("JOSSO: SSOAgentValve.containerEvent: " + event); + } - // obtain the local session for the catalina session, and notify the listeners for it. - LocalSession localSession = (LocalSession) _sessionMap.get(event.getSession().getId()); + if (event.getType().equals(Context.CHANGE_SESSION_ID_EVENT)) { + String[] sessionIds = (String[]) event.getData(); + String oldId = sessionIds[0]; + String newId = sessionIds[1]; + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: Due to session fixation protection session id " + oldId + " has changed to " + newId); + + LocalSession localSession = _sessionMap.get(oldId); + if (localSession != null) { + localSession.expire(); + _sessionMap.remove(oldId); + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: Expired local session " + oldId + " as it's no longer in use"); + } - if (event.getType().equals(Session.SESSION_DESTROYED_EVENT)) { - localSession.expire(); - _sessionMap.remove(event.getSession().getId()); } - + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.containerEvent: sessionMap.size remaining: " + _sessionMap.size()); + + if (LOG.isDebugEnabled()) + LOG.debug("JOSSO: SSOAgentValve.containerEvent: complete"); } // ------------------------------------------------------ Lifecycle Methods @@ -119,15 +138,15 @@ public void sessionEvent(SessionEvent event) { * Set the Container to which this Valve is attached. * * @param container The container to which we are attached - public void setContainer(Container container) { + public void setContainer(Container container) { - if (!(container instanceof Context)) - throw new IllegalArgumentException - ("The SSOAgentValve must be associated to a Catalina Context or Host"); + if (!(container instanceof Context)) + throw new IllegalArgumentException + ("The SSOAgentValve must be associated to a Catalina Context or Host"); - super.setContainer(container); - _container = container; - } + super.setContainer(container); + _container = container; + } */ /** @@ -136,7 +155,7 @@ public void setContainer(Container container) { * and before any of the public methods of the component are utilized. * * @throws org.apache.catalina.LifecycleException if this component detects a fatal error - * that prevents this component from being used + * that prevents this component from being used */ protected synchronized void startInternal() throws LifecycleException { @@ -151,7 +170,7 @@ protected synchronized void startInternal() throws LifecycleException { Lookup lookup = Lookup.getInstance(); lookup.init("josso-agent-config.xml"); _agent = (CatalinaSSOAgent) lookup.lookupSSOAgent(); - _agent.setDebug(debug); + _agent.setDebug(LOG.isDebugEnabled() ? 1 : 0); _agent.setCatalinaContainer(container); } catch (Exception e) { System.err.println(e.getMessage()); @@ -159,9 +178,7 @@ protected synchronized void startInternal() throws LifecycleException { throw new LifecycleException("Error starting SSO Agent : " + e.getMessage()); } _agent.start(); - - if (debug >= 1) - log("Started"); + log("Started"); setState(LifecycleState.STARTING); } @@ -172,12 +189,12 @@ protected synchronized void startInternal() throws LifecycleException { * instance of this component. * * @throws org.apache.catalina.LifecycleException if this component detects a fatal error - * that needs to be reported + * that needs to be reported */ protected synchronized void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); - + // Validate and update our current component state if (!started) throw new LifecycleException @@ -186,14 +203,9 @@ protected synchronized void stopInternal() throws LifecycleException { started = false; _agent.stop(); - - if (debug >= 1) - log("Stopped"); - + log("Stopped"); } - - // ---------------------------------------------------------- Valve Methods @@ -210,21 +222,16 @@ public String getInfo() { * @param request The servlet request we are processing * @param response The servlet response we are creating * in the current processing pipeline - * @throws IOException if an input/output error occurs + * @throws java.io.IOException if an input/output error occurs * @throws javax.servlet.ServletException if a servlet error occurs */ public void invoke(Request request, Response response) throws IOException, ServletException { - HttpServletRequest hreq = - (HttpServletRequest) request.getRequest(); - HttpServletResponse hres = - (HttpServletResponse) response.getResponse(); - - - if (debug >= 1) - log("Processing : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + HttpServletRequest hreq = request.getRequest(); + HttpServletResponse hres = response.getResponse(); + log("Processing : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]"); try { // ------------------------------------------------------------------ @@ -239,29 +246,25 @@ public void invoke(Request request, Response response) if (!_agent.isPartnerApp(vhost, contextPath)) { getNext().invoke(request, response); - if (debug >= 1) - log("Context is not a josso partner app : " + hreq.getContextPath()); + log("Context is not a josso partner app : " + hreq.getContextPath()); return; } // URI Encoding if (_agent.getUriEncoding() != null) { - if (debug >= 1) - log("Setting request/response encoding to " + _agent.getUriEncoding()); + log("Setting request/response encoding to " + _agent.getUriEncoding()); hreq.setCharacterEncoding(_agent.getUriEncoding()); hres.setCharacterEncoding(_agent.getUriEncoding()); } String nodeId = hreq.getParameter("josso_node"); if (nodeId != null) { - if (debug >= 1) - log("Storing JOSSO Node id : " + nodeId); - _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); + log("Storing JOSSO Node id : " + nodeId); + _agent.setAttribute(hreq, hres, "JOSSO_NODE", nodeId); } else { nodeId = _agent.getAttribute(hreq, "JOSSO_NODE"); - if (debug >= 1) - log("Found JOSSO Node id : " + nodeId); + log("Found JOSSO Node id : " + nodeId); } @@ -282,27 +285,22 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Check if the partner application required the login form // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); + log("Checking if its a josso_login_request for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoLoginUri()) || - hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { - - if (debug >= 1) - log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); + hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { + log("josso_login_request received for uri '" + hreq.getRequestURI() + "'"); //save referer url in case the user clicked on Login from some public resource (page) //so agent can redirect the user back to that page after successful login if (hreq.getRequestURI().endsWith(_agent.getJossoUserLoginUri())) { - saveLoginBackToURL(hreq, hres, session, true); + saveLoginBackToURL(hreq, hres, session, true); } else { - saveLoginBackToURL(hreq, hres, session, false); + saveLoginBackToURL(hreq, hres, session, false); } String loginUrl = _agent.buildLoginUrl(hreq); - - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); @@ -315,18 +313,14 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Check if the partner application required a logout // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); - if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) { + log("Checking if its a josso_logout request for '" + hreq.getRequestURI() + "'"); - if (debug >= 1) - log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); + if (hreq.getRequestURI().endsWith(_agent.getJossoLogoutUri())) { + log("josso_logout request received for uri '" + hreq.getRequestURI() + "'"); String logoutUrl = _agent.buildLogoutUrl(hreq, cfg); - - if (debug >= 1) - log("Redirecting to logout url '" + logoutUrl + "'"); + log("Redirecting to logout url '" + logoutUrl + "'"); // Clear previous COOKIE ... Cookie ssoCookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); @@ -337,14 +331,13 @@ public void invoke(Request request, Response response) hres.sendRedirect(hres.encodeRedirectURL(logoutUrl)); return; - } // ------------------------------------------------------------------ // Check for the single sign on cookie // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking for SSO cookie"); + + log("Checking for SSO cookie"); Cookie cookie = null; Cookie cookies[] = hreq.getCookies(); if (cookies == null) @@ -357,30 +350,28 @@ public void invoke(Request request, Response response) } String jossoSessionId = (cookie == null) ? null : cookie.getValue(); - if (debug >= 1) - log("Session is: " + session); - LocalSession localSession = (LocalSession) _sessionMap.get(session.getId()); + log("Session is: " + session); + LocalSession localSession = _sessionMap.get(session.getId()); if (localSession == null) { localSession = new CatalinaLocalSession(session); // the local session is new so, make the valve listen for its events so that it can // map them to local session events. session.addSessionListener(this); + session.getManager().getContext().addContainerListener(this); _sessionMap.put(session.getId(), localSession); + + log("Monitoring session " + session.getId()); } // ------------------------------------------------------------------ // Check if the partner application submitted custom login form // ------------------------------------------------------------------ - if (debug >= 1){ - log("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'"); - } + log("Checking if its a josso_authentication for '" + hreq.getRequestURI() + "'"); if (hreq.getRequestURI().endsWith(_agent.getJossoAuthenticationUri())) { - - if (debug >= 1) - log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); + log("josso_authentication received for uri '" + hreq.getRequestURI() + "'"); CatalinaSSOAgentRequest customAuthRequest = new CatalinaSSOAgentRequest(cfg.getId(), - SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); + SSOAgentRequest.ACTION_CUSTOM_AUTHENTICATION, jossoSessionId, localSession); customAuthRequest.setRequest(hreq); customAuthRequest.setResponse(hres); @@ -396,17 +387,13 @@ public void invoke(Request request, Response response) // ------------------------------------------------------------------ // Trigger LOGIN OPTIONAL if required // ------------------------------------------------------------------ - - if (debug >= 1) - log("SSO cookie is not present, verifying optional login process "); + log("SSO cookie is not present, verifying optional login process "); // We have no cookie, remember me is enabled and a security check without assertion was received ... // This means that the user could not be identified ... go back to the original resource if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") == null) { - - if (debug >= 1) - log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); + hreq.getParameter("josso_assertion_id") == null) { + log(_agent.getJossoSecurityCheckUri() + " received without assertion. Login Optional Process failed"); String requestURI = this.getSavedRequestURL(hreq, session); _agent.prepareNonCacheResponse(hres); @@ -421,41 +408,34 @@ public void invoke(Request request, Response response) // If saved request is NOT null, we're in the middle of another process ... if (!isResourceIgnored(cfg, request) && _agent.isAutomaticLoginRequired(hreq, hres)) { - - if (debug >= 1) - log("SSO cookie is not present, attempting automatic login"); + log("SSO cookie is not present, attempting automatic login"); // Save current request, so we can co back to it later ... saveRequest(request, session); String loginUrl = _agent.buildLoginOptionalUrl(hreq); - - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); return; } else { - if (debug >= 1) - log("SSO cookie is not present, but login optional process is not required"); + log("SSO cookie is not present, but login optional process is not required"); } // save requested resource - if (!isResourceIgnored(cfg, request)) { - StringBuffer sb = new StringBuffer(hreq.getRequestURI()); - if (hreq.getQueryString() != null) { - sb.append('?'); - sb.append(hreq.getQueryString()); - } - _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); - } + if (!isResourceIgnored(cfg, request)) { + StringBuffer sb = new StringBuffer(hreq.getRequestURI()); + if (hreq.getQueryString() != null) { + sb.append('?'); + sb.append(hreq.getQueryString()); + } + _agent.setAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + } } - - if (debug >= 1) - log("SSO cookie is not present, checking for outbound relaying"); + log("SSO cookie is not present, checking for outbound relaying"); if (!(hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") != null)) { + hreq.getParameter("josso_assertion_id") != null)) { log("SSO cookie not present and relaying was not requested, skipping"); getNext().invoke(request, response); return; @@ -472,41 +452,35 @@ public void invoke(Request request, Response response) } // This URI should be protected by SSO, go on ... - if (debug >= 1) - log("Session is: " + session); + log("Session is: " + session); // ------------------------------------------------------------------ // Invoke the SSO Agent // ------------------------------------------------------------------ - if (debug >= 1) - log("Executing agent..."); + log("Executing agent..."); _agent.setCatalinaContainer(request.getContext()); // ------------------------------------------------------------------ // Check if a user has been authenticated and should be checked by the agent. // ------------------------------------------------------------------ - if (debug >= 1) - log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); - if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && - hreq.getParameter("josso_assertion_id") != null) { + log("Checking if its a josso_security_check for '" + hreq.getRequestURI() + "'"); - if (debug >= 1) - log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + - hreq.getParameter("josso_assertion_id") - ); + if (hreq.getRequestURI().endsWith(_agent.getJossoSecurityCheckUri()) && + hreq.getParameter("josso_assertion_id") != null) { + log("josso_security_check received for uri '" + hreq.getRequestURI() + "' assertion id '" + + hreq.getParameter("josso_assertion_id") + ); String assertionId = hreq.getParameter(Constants.JOSSO_ASSERTION_ID_PARAMETER); CatalinaSSOAgentRequest relayRequest; - - if (debug >= 1) - log("Outbound relaying requested for assertion id [" + assertionId + "]"); + log("Outbound relaying requested for assertion id [" + assertionId + "]"); relayRequest = new CatalinaSSOAgentRequest(cfg.getId(), SSOAgentRequest.ACTION_RELAY, null, localSession, assertionId - ); + ); relayRequest.setRequest(hreq); relayRequest.setResponse(hres); relayRequest.setContext(request.getContext()); @@ -514,17 +488,13 @@ public void invoke(Request request, Response response) SingleSignOnEntry entry = _agent.processRequest(relayRequest); if (entry == null) { // This is wrong! We should have an entry here! - if (debug >= 1) - log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); + + log("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); // Throw an exception, we will handle it below ! throw new RuntimeException("Outbound relaying failed. No Principal found. Verify your SSO Agent Configuration!"); } - - if (debug >= 1) - log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); - - if (debug >= 1) - log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); + log("Outbound relaying succesfull for assertion id [" + assertionId + "]"); + log("Assertion id [" + assertionId + "] mapped to SSO session id [" + entry.ssoId + "]"); // The cookie is valid to for the partner application only ... in the future each partner app may // store a different auth. token (SSO SESSION) value @@ -533,48 +503,46 @@ public void invoke(Request request, Response response) //Redirect user to the saved splash resource (in case of auth request) or to request URI otherwise String requestURI = getSavedSplashResource(hreq); - if(requestURI == null) { - requestURI = getSavedRequestURL(hreq, session); + if (requestURI == null) { + requestURI = getSavedRequestURL(hreq, session); if (requestURI == null) { if (cfg.getDefaultResource() != null) { requestURI = cfg.getDefaultResource(); } else { - // If no saved request is found, redirect to the partner app root : - requestURI = hreq.getRequestURI().substring( - 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); + // If no saved request is found, redirect to the partner app root : + requestURI = hreq.getRequestURI().substring( + 0, (hreq.getRequestURI().length() - _agent.getJossoSecurityCheckUri().length())); } - // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! - String singlePointOfAccess = _agent.getSinglePointOfAccess(); - if (singlePointOfAccess != null) { - requestURI = singlePointOfAccess + requestURI; - } else { - String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); - if (reverseProxyHost != null) { - requestURI = reverseProxyHost + requestURI; - } - } - - if (debug >= 1) - log("No saved request found, using : '" + requestURI + "'"); - } + // If we're behind a reverse proxy, we have to alter the URL ... this was not necessary on tomcat 5.0 ?! + String singlePointOfAccess = _agent.getSinglePointOfAccess(); + if (singlePointOfAccess != null) { + requestURI = singlePointOfAccess + requestURI; + } else { + String reverseProxyHost = hreq.getHeader(org.josso.gateway.Constants.JOSSO_REVERSE_PROXY_HEADER); + if (reverseProxyHost != null) { + requestURI = reverseProxyHost + requestURI; + } + } + log("No saved request found, using : '" + requestURI + "'"); + } } clearSavedRequestURLs(hreq, hres, session); - _agent.clearAutomaticLoginReferer(hreq, hres); + _agent.clearAutomaticLoginReferer(hreq, hres); _agent.prepareNonCacheResponse(hres); // Check if we have a post login resource : String postAuthURI = cfg.getPostAuthenticationResource(); if (postAuthURI != null) { String postAuthURL = _agent.buildPostAuthUrl(hres, requestURI, postAuthURI); - if (debug >= 1) - log("Redirecting to post-auth-resource '" + postAuthURL + "'"); + + log("Redirecting to post-auth-resource '" + postAuthURL + "'"); hres.sendRedirect(postAuthURL); } else { - if (debug >= 1) - log("Redirecting to original '" + requestURI + "'"); + + log("Redirecting to original '" + requestURI + "'"); hres.sendRedirect(hres.encodeRedirectURL(requestURI)); } @@ -593,18 +561,18 @@ public void invoke(Request request, Response response) SingleSignOnEntry entry = _agent.processRequest(r); - if (debug >= 1) - log("Executed agent."); + + log("Executed agent."); // ------------------------------------------------------------------ // Has a valid user already been authenticated? // ------------------------------------------------------------------ - if (debug >= 1) - log("Process request for '" + hreq.getRequestURI() + "'"); + + log("Process request for '" + hreq.getRequestURI() + "'"); if (entry != null) { - if (debug >= 1) - log("Principal '" + entry.principal + + + log("Principal '" + entry.principal + "' has already been authenticated"); (request).setAuthType(entry.authType); @@ -615,38 +583,38 @@ public void invoke(Request request, Response response) // This is a standard anonymous request! if (cookie != null) { - // cookie is not valid - cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); - hres.addCookie(cookie); + // cookie is not valid + cookie = _agent.newJossoCookie(request.getContextPath(), "-", hreq.isSecure()); + hres.addCookie(cookie); } if (cookie != null || (getSavedRequestURL(hreq, session) == null && _agent.isAutomaticLoginRequired(hreq, hres))) { - if (debug >= 1) - log("SSO Session is not valid, attempting automatic login"); + + log("SSO Session is not valid, attempting automatic login"); // Save current request, so we can co back to it later ... saveRequest(request, session); String loginUrl = _agent.buildLoginOptionalUrl(hreq); - if (debug >= 1) - log("Redirecting to login url '" + loginUrl + "'"); + + log("Redirecting to login url '" + loginUrl + "'"); //set non cache headers _agent.prepareNonCacheResponse(hres); hres.sendRedirect(hres.encodeRedirectURL(loginUrl)); return; } else { - if (debug >= 1) - log("SSO cookie is not present, but login optional process is not required"); + + log("SSO cookie is not present, but login optional process is not required"); } } // propagate the login and logout URLs to // partner applications. - hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl() ); - hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl() ); + hreq.setAttribute("org.josso.agent.gateway-login-url", _agent.getGatewayLoginUrl()); + hreq.setAttribute("org.josso.agent.gateway-logout-url", _agent.getGatewayLogoutUrl()); hreq.setAttribute("org.josso.agent.ssoSessionid", jossoSessionId); // ------------------------------------------------------------------ @@ -671,8 +639,7 @@ public void invoke(Request request, Response response) return; } finally { - if (debug >= 1) - log("Processed : " + hreq.getContextPath() + " ["+hreq.getRequestURL()+"]"); + log("Processed : " + hreq.getContextPath() + " [" + hreq.getRequestURL() + "]"); } } @@ -689,15 +656,12 @@ public String toString() { sb.append(container != null ? container.getName() : ""); sb.append("]"); return (sb.toString()); - } // -------------------------------------------------------- Package Methods - - // ------------------------------------------------------ Protected Methods /** @@ -707,9 +671,7 @@ public String toString() { * @param request The HttpRequest we are processing */ protected Session getSession(Request request) { - return (getSession(request, false)); - } /** @@ -721,20 +683,16 @@ protected Session getSession(Request request) { * @param create Should we create a session if needed? */ protected Session getSession(Request request, boolean create) { - - HttpServletRequest hreq = - (HttpServletRequest) request.getRequest(); + HttpServletRequest hreq = request.getRequest(); HttpSession hses = hreq.getSession(create); - if (debug >= 1) - log("getSession() : hses " + hses); + + log("getSession() : hses " + hses); if (hses == null) return (null); // Get catalina Context from request ... Manager manager = request.getContext().getManager(); - - if (debug >= 1) - log("getSession() : manager is " + manager); + log("getSession() : manager is " + manager); if (manager == null) return (null); else { @@ -744,7 +702,6 @@ protected Session getSession(Request request, boolean create) { return (null); } } - } /** @@ -757,7 +714,6 @@ protected void log(String message) { _agent.log(message); } - /** * Log a message on the Logger associated with our Container (if any). * @@ -769,38 +725,38 @@ protected void log(String message, Throwable throwable) { _agent.log(message, throwable); } - /** * Return the request URI (with the corresponding query string, if any) * from the saved request so that we can redirect to it. * - * @param hreq http request + * @param hreq http request * @param session Our current session */ private String getSavedRequestURL(HttpServletRequest hreq, Session session) { - String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - if (savedURL == null || savedURL.equals("")) { - SavedRequest saved = - (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - if (saved == null) - return (null); - StringBuffer sb = new StringBuffer(saved.getRequestURI()); - if (saved.getQueryString() != null) { - sb.append('?'); - sb.append(saved.getQueryString()); - } - savedURL = sb.toString(); - } + String savedURL = _agent.getAttribute(hreq, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + if (savedURL == null || savedURL.equals("")) { + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (saved == null) + return (null); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); + if (saved.getQueryString() != null) { + sb.append('?'); + sb.append(saved.getQueryString()); + } + savedURL = sb.toString(); + } return savedURL; } /** * Return the splash resource from session so that we can redirect the user to it * if (s)he was logged in using custom form + * * @param hreq http request */ private String getSavedSplashResource(HttpServletRequest hreq) { - return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + return _agent.getAttribute(hreq, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); } /** @@ -808,10 +764,10 @@ private String getSavedSplashResource(HttpServletRequest hreq) { * * @param request The request to be saved * @param session The session to contain the saved information - * @throws IOException + * @throws java.io.IOException */ protected void saveRequest(Request request, Session session) - throws IOException { + throws IOException { // Create and populate a SavedRequest object for this request SavedRequest saved = new SavedRequest(); @@ -836,28 +792,28 @@ protected void saveRequest(Request request, Session session) } /** Need more catalina classes - if ("POST".equalsIgnoreCase(request.getMethod())) { - ByteChunk body = new ByteChunk(); - body.setLimit(request.getConnector().getMaxSavePostSize()); + if ("POST".equalsIgnoreCase(request.getMethod())) { + ByteChunk body = new ByteChunk(); + body.setLimit(request.getConnector().getMaxSavePostSize()); - byte[] buffer = new byte[4096]; - int bytesRead; - InputStream is = request.getInputStream(); + byte[] buffer = new byte[4096]; + int bytesRead; + InputStream is = request.getInputStream(); - while ( (bytesRead = is.read(buffer) ) >= 0) { - body.append(buffer, 0, bytesRead); - } - saved.setContentType(request.getContentType()); - saved.setBody(body); - } */ + while ( (bytesRead = is.read(buffer) ) >= 0) { + body.append(buffer, 0, bytesRead); + } + saved.setContentType(request.getContentType()); + saved.setBody(body); + } */ saved.setMethod(request.getMethod()); saved.setQueryString(request.getQueryString()); saved.setRequestURI(request.getRequestURI()); - + // Stash the SavedRequest in our session for later use session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); - + StringBuffer sb = new StringBuffer(request.getRequestURI()); if (request.getQueryString() != null) { String q = request.getQueryString(); @@ -867,25 +823,25 @@ protected void saveRequest(Request request, Session session) } _agent.setAttribute(request.getRequest(), request.getResponse().getResponse(), WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); } - + /** * Save referer URI into our session for later use. - * + *

* This method is used so agent can know from which * public resource (page) user requested login. - * - * @param request http request - * @param response http response - * @param session current session + * + * @param request http request + * @param response http response + * @param session current session * @param overrideSavedResource true if saved resource should be overridden, false otherwise */ protected void saveLoginBackToURL(HttpServletRequest request, HttpServletResponse response, Session session, boolean overrideSavedResource) { - String referer = request.getHeader("referer"); + String referer = request.getHeader("referer"); //saved request will exist only if user requested some protected resource - String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - SavedRequest saved = - (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { + String savedURL = _agent.getAttribute(request, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + SavedRequest saved = + (SavedRequest) session.getNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + if (((savedURL == null && saved == null) || overrideSavedResource) && referer != null && !referer.equals("")) { saved = new SavedRequest(); @@ -893,51 +849,51 @@ protected void saveLoginBackToURL(HttpServletRequest request, HttpServletRespons String uri = p >= 0 ? referer.substring(0, p) : referer; String queryStr = p >= 0 ? referer.substring(p) : null; - saved.setRequestURI(uri); + saved.setRequestURI(uri); saved.setQueryString(queryStr); session.setNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE, saved); - + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, referer); } else if (saved != null) { - StringBuffer sb = new StringBuffer(saved.getRequestURI()); + StringBuffer sb = new StringBuffer(saved.getRequestURI()); if (saved.getQueryString() != null) { String q = saved.getQueryString(); if (!q.startsWith("?")) sb.append('?'); sb.append(q); } - _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); + _agent.setAttribute(request, response, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI, sb.toString()); } } - + /** - * Remove saved request URLs from session - * to avoid mixing up resources from previous operations + * Remove saved request URLs from session + * to avoid mixing up resources from previous operations * (logins, logouts) with the current one. - * - * @param hreq http request - * @param hres http response + * + * @param hreq http request + * @param hres http response * @param session Our current session */ protected void clearSavedRequestURLs(HttpServletRequest hreq, HttpServletResponse hres, Session session) { - session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); - _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); - _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); + session.removeNote(org.apache.catalina.authenticator.Constants.FORM_REQUEST_NOTE); + _agent.removeAttribute(hreq, hres, WebAccessControlUtil.KEY_JOSSO_SAVED_REQUEST_URI); + _agent.removeAttribute(hreq, hres, Constants.JOSSO_SPLASH_RESOURCE_PARAMETER); } protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { // There are some web-resources to ignore. String[] ignoredWebResources = cfg.getIgnoredWebRources(); - if (debug >= 1) - log("Found [" + (ignoredWebResources!= null ? ignoredWebResources.length+"" : "no") + "] ignored web resources "); + + log("Found [" + (ignoredWebResources != null ? ignoredWebResources.length + "" : "no") + "] ignored web resources "); if (ignoredWebResources != null && ignoredWebResources.length > 0) { Realm realm = request.getContext().getRealm(); SecurityConstraint[] constraints - = realm.findSecurityConstraints(request, request.getContext()); + = realm.findSecurityConstraints(request, request.getContext()); if ((constraints != null)) { @@ -952,8 +908,8 @@ protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { if (constraint.findCollection(ignoredWebResource) != null) { // We should ignore this URI, it's not subject to SSO protection. - if (debug >= 1) - log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); + + log("Not subject to SSO protection : web-resource-name:" + ignoredWebResource); return true; } @@ -963,8 +919,5 @@ protected boolean isResourceIgnored(SSOPartnerAppConfig cfg, Request request) { } return false; - } - - } From f9f8648208b6bb7c7bfdcece9315e9dbd6fe6d5f Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Thu, 2 Feb 2017 09:42:43 -0800 Subject: [PATCH 08/11] Included tomcat 7, 8 and 8.5 agents in the distribution --- distributions/josso/pom.xml | 15 +++++++++++++++ pom.xml | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/distributions/josso/pom.xml b/distributions/josso/pom.xml index 733f66d1..48433f3b 100644 --- a/distributions/josso/pom.xml +++ b/distributions/josso/pom.xml @@ -177,6 +177,21 @@ josso-tomcat60-agent + + org.josso + josso-tomcat70-agent + + + + org.josso + josso-tomcat80-agent + + + + org.josso + josso-tomcat85-agent + + org.josso josso-geronimo-agent diff --git a/pom.xml b/pom.xml index 36ba8a6e..bb5b5125 100644 --- a/pom.xml +++ b/pom.xml @@ -1140,6 +1140,24 @@ ${pom.version} + + org.josso + josso-tomcat70-agent + ${pom.version} + + + + org.josso + josso-tomcat80-agent + ${pom.version} + + + + org.josso + josso-tomcat85-agent + ${pom.version} + + org.josso josso-jboss32-agent From e3922de5d9845a2d7cc478b5ba20aec9764bbbdc Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Thu, 2 Feb 2017 10:42:15 -0800 Subject: [PATCH 09/11] * Included Tomcat 8.5 in the distribution --- distributions/josso/src/main/assembly/unix-bin.xml | 1 + distributions/josso/src/main/assembly/windows-bin.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/distributions/josso/src/main/assembly/unix-bin.xml b/distributions/josso/src/main/assembly/unix-bin.xml index 2f44d500..5ec23aaf 100644 --- a/distributions/josso/src/main/assembly/unix-bin.xml +++ b/distributions/josso/src/main/assembly/unix-bin.xml @@ -182,6 +182,7 @@ false ${pom.groupId}:josso-agent-shared + ${pom.groupId}:josso-tomcat85-agent ${pom.groupId}:josso-tomcat80-agent ${pom.groupId}:josso-tomcat70-agent ${pom.groupId}:josso-tomcat60-agent diff --git a/distributions/josso/src/main/assembly/windows-bin.xml b/distributions/josso/src/main/assembly/windows-bin.xml index 75bb95c4..f5a12e79 100644 --- a/distributions/josso/src/main/assembly/windows-bin.xml +++ b/distributions/josso/src/main/assembly/windows-bin.xml @@ -177,6 +177,7 @@ false ${pom.groupId}:josso-agent-shared + ${pom.groupId}:josso-tomcat85-agent ${pom.groupId}:josso-tomcat80-agent ${pom.groupId}:josso-tomcat70-agent ${pom.groupId}:josso-tomcat60-agent From 8cb765f4b40f932b48b4dadfb59c8c87c050f39b Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Thu, 2 Feb 2017 11:07:18 -0800 Subject: [PATCH 10/11] Merge branch 'master' of https://github.com/striglone/josso1 into striglone-master --- .../org/josso/servlet/agent/GenericServletSSOAgentFilter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agents/josso-servlet-agent/src/main/java/org/josso/servlet/agent/GenericServletSSOAgentFilter.java b/agents/josso-servlet-agent/src/main/java/org/josso/servlet/agent/GenericServletSSOAgentFilter.java index c5974842..28d8b32e 100644 --- a/agents/josso-servlet-agent/src/main/java/org/josso/servlet/agent/GenericServletSSOAgentFilter.java +++ b/agents/josso-servlet-agent/src/main/java/org/josso/servlet/agent/GenericServletSSOAgentFilter.java @@ -427,8 +427,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha SingleSignOnEntry entry = agent.processRequest(relayRequest); if (entry == null) { // This is wrong! We should have an entry here! - log.error("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); - // Throw an exception and let the container send the INERNAL SERVER ERROR + log.debug("Outbound relaying failed for assertion id [" + assertionId + "], no Principal found."); + // Throw an exception and let the container deal with it throw new ServletException("No Principal found. Verify your SSO Agent Configuration!"); } From 4ae6359b3f0dffa8560c30809966646cb193f4a0 Mon Sep 17 00:00:00 2001 From: Gianluca Brigandi Date: Thu, 2 Feb 2017 11:38:29 -0800 Subject: [PATCH 11/11] Merge branch 'nihaoo-master' --- .../org/josso/auth/scheme/BindUsernamePasswordAuthScheme.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/josso-bind-authscheme/src/main/java/org/josso/auth/scheme/BindUsernamePasswordAuthScheme.java b/components/josso-bind-authscheme/src/main/java/org/josso/auth/scheme/BindUsernamePasswordAuthScheme.java index 8e1be722..9c54c98a 100644 --- a/components/josso-bind-authscheme/src/main/java/org/josso/auth/scheme/BindUsernamePasswordAuthScheme.java +++ b/components/josso-bind-authscheme/src/main/java/org/josso/auth/scheme/BindUsernamePasswordAuthScheme.java @@ -79,6 +79,9 @@ public boolean authenticate() throws SSOAuthenticationException { return false; } + // hash the password if needed. + password = createPasswordHash(password); + // Authenticate the user against the configured store via a bind // The configured store could be using a LDAP server , a DB, etc. if (((BindableCredentialStore) _credentialStore).bind(username, password)) {