From 61bd0eeb86b0747a69fec9f8f7481f52949c11cb Mon Sep 17 00:00:00 2001 From: BernhardLenz Date: Thu, 4 Feb 2016 18:45:03 -0500 Subject: [PATCH] Added cas-client-integration-tomcat-v8 --- cas-client-integration-tomcat-v8/NOTICE | 30 +++ cas-client-integration-tomcat-v8/pom.xml | 70 +++++++ .../tomcat/v8/AbstractAuthenticator.java | 198 ++++++++++++++++++ .../tomcat/v8/AbstractCasAuthenticator.java | 47 +++++ .../client/tomcat/v8/AbstractCasRealm.java | 85 ++++++++ .../client/tomcat/v8/AbstractLogoutValve.java | 55 +++++ .../client/tomcat/v8/AssertionCasRealm.java | 49 +++++ .../tomcat/v8/Cas10CasAuthenticator.java | 56 +++++ .../tomcat/v8/Cas20CasAuthenticator.java | 62 ++++++ .../tomcat/v8/Cas20ProxyCasAuthenticator.java | 77 +++++++ .../client/tomcat/v8/PropertiesCasRealm.java | 63 ++++++ .../client/tomcat/v8/ProxyCallbackValve.java | 90 ++++++++ .../client/tomcat/v8/RegexUriLogoutValve.java | 55 +++++ .../client/tomcat/v8/Saml11Authenticator.java | 84 ++++++++ .../client/tomcat/v8/SingleSignOutValve.java | 97 +++++++++ .../tomcat/v8/StaticUriLogoutValve.java | 55 +++++ pom.xml | 1 + 17 files changed, 1174 insertions(+) create mode 100644 cas-client-integration-tomcat-v8/NOTICE create mode 100644 cas-client-integration-tomcat-v8/pom.xml create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractAuthenticator.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasRealm.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractLogoutValve.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AssertionCasRealm.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas10CasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20CasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20ProxyCasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/PropertiesCasRealm.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/ProxyCallbackValve.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/RegexUriLogoutValve.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Saml11Authenticator.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/SingleSignOutValve.java create mode 100644 cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/StaticUriLogoutValve.java diff --git a/cas-client-integration-tomcat-v8/NOTICE b/cas-client-integration-tomcat-v8/NOTICE new file mode 100644 index 0000000..f5ce3c0 --- /dev/null +++ b/cas-client-integration-tomcat-v8/NOTICE @@ -0,0 +1,30 @@ +Licensed to Apereo under one or more contributor license +agreements. See the NOTICE file distributed with this work +for additional information regarding copyright ownership. +Apereo licenses this file to you under the Apache License, +Version 2.0 (the "License"); you may not use this file +except in compliance with the License. You may obtain a +copy of the License at the following location: + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. + +This project includes: + Jasig CAS Client for Java - Common Tomcat Integration Support under Apache License Version 2.0 + Jasig CAS Client for Java - Core under Apache License Version 2.0 + Jasig CAS Client for Java - SAML Protocol Support under Apache License Version 2.0 + Jasig CAS Client for Java - Tomcat 7.x Integration under Apache License Version 2.0 + Java Servlet API under CDDL + GPLv2 with classpath exception + JCL 1.1.1 implemented over SLF4J under MIT License + Joda-Time under Apache 2 + JUnit under Common Public License Version 1.0 + SLF4J API Module under MIT License + SLF4J Simple Binding under MIT License + tomcat-catalina under Apache License, Version 2.0 + diff --git a/cas-client-integration-tomcat-v8/pom.xml b/cas-client-integration-tomcat-v8/pom.xml new file mode 100644 index 0000000..531abde --- /dev/null +++ b/cas-client-integration-tomcat-v8/pom.xml @@ -0,0 +1,70 @@ + + + + cas-client + org.jasig.cas.client + 3.4.2-SNAPSHOT + + 4.0.0 + + org.jasig.cas.client + cas-client-integration-tomcat-v8 + jar + Jasig CAS Client for Java - Tomcat 8.x Integration + + + + org.jasig.cas.client + cas-client-integration-tomcat-common + ${project.version} + jar + compile + + + org.jasig.cas.client + cas-client-support-saml + ${project.version} + jar + compile + true + + + org.apache.tomcat + tomcat-catalina + 8.0.1 + jar + provided + + + org.apache.tomcat + tomcat-servlet-api + + + org.apache.tomcat + tomcat-juli + + + org.apache.tomcat + tomcat-annotations-api + + + org.apache.tomcat + tomcat-api + + + org.apache.tomcat + tomcat-util + + + + + + org.jasig.cas.client + cas-client-core + ${project.version} + jar + compile + + + + diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractAuthenticator.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractAuthenticator.java new file mode 100644 index 0000000..6ad0d4b --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractAuthenticator.java @@ -0,0 +1,198 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import java.io.IOException; +import java.security.Principal; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.catalina.*; +import org.apache.catalina.authenticator.AuthenticatorBase; +import org.apache.catalina.connector.Request; +import org.jasig.cas.client.tomcat.AuthenticatorDelegate; +import org.jasig.cas.client.tomcat.CasRealm; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.validation.TicketValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Base authenticator for all authentication protocols supported by CAS. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public abstract class AbstractAuthenticator extends AuthenticatorBase implements LifecycleListener { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + private final AuthenticatorDelegate delegate = new AuthenticatorDelegate(); + + private String casServerUrlPrefix; + + private String encoding; + + private boolean encode; + + private boolean renew; + + protected abstract String getAuthenticationMethod(); + + /** + * Provided for Tomcat 7.0.8 support. + * + * @return the authentication method. + */ + protected String getAuthMethod() { + return getAuthenticationMethod(); + } + + /** + * Abstract method that subclasses should use to provide the name of the artifact parameter (i.e. ticket) + * + * @return the artifact parameter name. CANNOT be NULL. + */ + protected abstract String getArtifactParameterName(); + + /** + * Abstract method that subclasses should use to provide the name of the service parameter (i.e. service) + * + * @return the service parameter name. CANNOT be NULL. + */ + protected abstract String getServiceParameterName(); + + /** + * Returns the single instance of the ticket validator to use to validate tickets. Sub classes should include + * the one appropriate for the + * + * @return a fully configured ticket validator. CANNOT be NULL. + */ + protected abstract TicketValidator getTicketValidator(); + + protected void startInternal() throws LifecycleException { + super.startInternal(); + logger.debug("{} starting.", getName()); + final Realm realm = this.context.getRealm(); + try { + CommonUtils.assertTrue(realm instanceof CasRealm, "Expected CasRealm but got " + realm.getClass()); + CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null."); + CommonUtils.assertNotNull(this.delegate.getCasServerLoginUrl(), "casServerLoginUrl cannot be null."); + CommonUtils.assertTrue(this.delegate.getServerName() != null || this.delegate.getServiceUrl() != null, + "either serverName or serviceUrl must be set."); + this.delegate.setRealm((CasRealm) realm); + } catch (final Exception e) { + throw new LifecycleException(e); + } + // Complete delegate initialization after the component is started. + // See #lifecycleEvent() method. + addLifecycleListener(this); + } + + protected final String getCasServerUrlPrefix() { + return this.casServerUrlPrefix; + } + + public final void setCasServerUrlPrefix(final String casServerUrlPrefix) { + this.casServerUrlPrefix = casServerUrlPrefix; + } + + public final void setCasServerLoginUrl(final String casServerLoginUrl) { + this.delegate.setCasServerLoginUrl(casServerLoginUrl); + } + + public final boolean isEncode() { + return this.encode; + } + + public final void setEncode(final boolean encode) { + this.encode = encode; + } + + protected final boolean isRenew() { + return this.renew; + } + + public void setRenew(final boolean renew) { + this.renew = renew; + } + + public final void setServerName(final String serverName) { + this.delegate.setServerName(serverName); + } + + public final void setServiceUrl(final String serviceUrl) { + this.delegate.setServiceUrl(serviceUrl); + } + + protected final String getEncoding() { + return this.encoding; + } + + public final void setEncoding(final String encoding) { + this.encoding = encoding; + } + + /** {@inheritDoc} */ + public final boolean authenticate(final Request request, final HttpServletResponse response) throws IOException { + Principal principal = request.getUserPrincipal(); + boolean result = false; + if (principal == null) { + // Authentication sets the response headers for status and redirect if needed + principal = this.delegate.authenticate(request.getRequest(), response); + if (principal != null) { + register(request, response, principal, getAuthenticationMethod(), null, null); + result = true; + } + } else { + result = true; + } + return result; + } + + /** {@inheritDoc} */ + public void lifecycleEvent(final LifecycleEvent event) { + if (AFTER_START_EVENT.equals(event.getType())) { + logger.debug("{} processing lifecycle event {}", getName(), AFTER_START_EVENT); + this.delegate.setTicketValidator(getTicketValidator()); + this.delegate.setArtifactParameterName(getArtifactParameterName()); + this.delegate.setServiceParameterName(getServiceParameterName()); + } + } + + /** {@inheritDoc} */ + public String getInfo() { + return getName() + "/1.0"; + } + + /** {@inheritDoc} + * @throws LifecycleException */ + protected synchronized void setState(LifecycleState state, Object data) throws LifecycleException { + super.setState(state, data); + if (LifecycleState.STARTED.equals(state)) { + logger.info("{} started.", getName()); + } + } + + /** + * @return Authenticator descriptive name. + */ + protected abstract String getName(); +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasAuthenticator.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasAuthenticator.java new file mode 100644 index 0000000..3be3db8 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasAuthenticator.java @@ -0,0 +1,47 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +/** + * Base class for all CAS protocol authenticators. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public abstract class AbstractCasAuthenticator extends AbstractAuthenticator { + + private String proxyCallbackUrl; + + protected final String getProxyCallbackUrl() { + return this.proxyCallbackUrl; + } + + public final void setProxyCallbackUrl(final String proxyCallbackUrl) { + this.proxyCallbackUrl = proxyCallbackUrl; + } + + protected final String getArtifactParameterName() { + return "ticket"; + } + + protected final String getServiceParameterName() { + return "service"; + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasRealm.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasRealm.java new file mode 100644 index 0000000..c3b2144 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractCasRealm.java @@ -0,0 +1,85 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import java.security.Principal; +import org.apache.catalina.Wrapper; +import org.apache.catalina.realm.RealmBase; +import org.jasig.cas.client.tomcat.CasRealm; + +/** + * Base Realm implementation for all CAS realms. + * + * @author Marvin S. Addison + * @version $Revision$ + * + */ +public abstract class AbstractCasRealm extends RealmBase implements CasRealm { + + /** {@inheritDoc} */ + public Principal authenticate(final Principal p) { + return getDelegate().authenticate(p); + } + + /** {@inheritDoc} */ + public String[] getRoles(final Principal p) { + return getDelegate().getRoles(p); + } + + public boolean hasRole(final Principal principal, final String role) { + return getDelegate().hasRole(principal, role); + } + + /** + * Tomcat 7.0.8 changed their APIs so {@link #hasRole(java.security.Principal, String)} is only valid for 7.0.7 and below. + */ + public boolean hasRole(final Wrapper wrapper, final Principal principal, final String role) { + return hasRole(principal, role); + } + + /** {@inheritDoc} */ + public String toString() { + return getName(); + } + + /** {@inheritDoc} */ + public String getInfo() { + return getClass().getName() + "/1.0"; + } + + /** {@inheritDoc} */ + protected String getName() { + return getClass().getSimpleName(); + } + + /** {@inheritDoc} */ + protected String getPassword(final String userName) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + protected Principal getPrincipal(final String userName) { + throw new UnsupportedOperationException(); + } + + /** + * @return Delegate that all {@link CasRealm} operations are delegated to. + */ + protected abstract CasRealm getDelegate(); +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractLogoutValve.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractLogoutValve.java new file mode 100644 index 0000000..4264c0d --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AbstractLogoutValve.java @@ -0,0 +1,55 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import java.io.IOException; +import javax.servlet.ServletException; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.jasig.cas.client.tomcat.LogoutHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract base class for Container-managed log out. Removes the attributes + * from the session. + * + * @author Scott Battaglia + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public abstract class AbstractLogoutValve extends ValveBase { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + public final void invoke(final Request request, final Response response) throws IOException, ServletException { + if (getLogoutHandler().isLogoutRequest(request)) { + getLogoutHandler().logout(request, response); + // Do not proceed up valve chain + return; + } + + logger.debug("URI is not a logout request: {}", request.getRequestURI()); + getNext().invoke(request, response); + } + + protected abstract LogoutHandler getLogoutHandler(); +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AssertionCasRealm.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AssertionCasRealm.java new file mode 100644 index 0000000..422f48a --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/AssertionCasRealm.java @@ -0,0 +1,49 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.jasig.cas.client.tomcat.AssertionCasRealmDelegate; +import org.jasig.cas.client.tomcat.CasRealm; + +/** + * Tomcat Realm that implements {@link CasRealm} for principal and + * role data backed by the CAS {@link org.jasig.cas.client.validation.Assertion}. + *

+ * Authentication always succeeds and simply returns the given principal. + * + * @author Marvin S. Addison + * @version $Revision$ + * + */ +public class AssertionCasRealm extends AbstractCasRealm { + + private final AssertionCasRealmDelegate delegate = new AssertionCasRealmDelegate(); + + /** + * @param name Name of the attribute in the principal that contains role data. + */ + public void setRoleAttributeName(final String name) { + delegate.setRoleAttributeName(name); + } + + /** {@inheritDoc} */ + protected CasRealm getDelegate() { + return delegate; + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas10CasAuthenticator.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas10CasAuthenticator.java new file mode 100644 index 0000000..a518343 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas10CasAuthenticator.java @@ -0,0 +1,56 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.validation.Cas10TicketValidator; +import org.jasig.cas.client.validation.TicketValidator; + +/** + * Authenticator that handles CAS 1.0 protocol. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class Cas10CasAuthenticator extends AbstractCasAuthenticator { + + public static final String AUTH_METHOD = "CAS10"; + + private static final String NAME = Cas10CasAuthenticator.class.getName(); + + private Cas10TicketValidator ticketValidator; + + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + protected String getName() { + return NAME; + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Cas10TicketValidator(getCasServerUrlPrefix()); + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20CasAuthenticator.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20CasAuthenticator.java new file mode 100644 index 0000000..86d40b4 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20CasAuthenticator.java @@ -0,0 +1,62 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.validation.Cas20ServiceTicketValidator; +import org.jasig.cas.client.validation.TicketValidator; + +/** + * Authenticator that handles the CAS 2.0 protocol. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class Cas20CasAuthenticator extends AbstractCasAuthenticator { + + public static final String AUTH_METHOD = "CAS20"; + + private static final String NAME = Cas20CasAuthenticator.class.getName(); + + private Cas20ServiceTicketValidator ticketValidator; + + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + protected String getName() { + return NAME; + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Cas20ServiceTicketValidator(getCasServerUrlPrefix()); + if (getEncoding() != null) { + this.ticketValidator.setEncoding(getEncoding()); + } + this.ticketValidator.setProxyCallbackUrl(getProxyCallbackUrl()); + this.ticketValidator.setProxyGrantingTicketStorage(ProxyCallbackValve.getProxyGrantingTicketStorage()); + this.ticketValidator.setRenew(isRenew()); + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20ProxyCasAuthenticator.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20ProxyCasAuthenticator.java new file mode 100644 index 0000000..b5fa702 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Cas20ProxyCasAuthenticator.java @@ -0,0 +1,77 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.validation.Cas20ProxyTicketValidator; +import org.jasig.cas.client.validation.TicketValidator; + +/** + * Authenticator that handles the CAS 2.0 protocol with proxying support. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class Cas20ProxyCasAuthenticator extends AbstractCasAuthenticator { + + public static final String AUTH_METHOD = "CAS20-PROXY"; + + private static final String NAME = Cas20ProxyCasAuthenticator.class.getName(); + + private Cas20ProxyTicketValidator ticketValidator; + + private boolean acceptAnyProxy; + + private String allowedProxyChains; + + public void setAcceptAnyProxy(final boolean acceptAnyProxy) { + this.acceptAnyProxy = acceptAnyProxy; + } + + public void setAllowedProxyChains(final String allowedProxyChains) { + this.allowedProxyChains = allowedProxyChains; + } + + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + protected String getName() { + return NAME; + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Cas20ProxyTicketValidator(getCasServerUrlPrefix()); + this.ticketValidator.setRenew(isRenew()); + this.ticketValidator.setProxyCallbackUrl(getProxyCallbackUrl()); + this.ticketValidator.setProxyGrantingTicketStorage(ProxyCallbackValve.getProxyGrantingTicketStorage()); + this.ticketValidator.setAcceptAnyProxy(this.acceptAnyProxy); + this.ticketValidator.setAllowedProxyChains(CommonUtils.createProxyList(this.allowedProxyChains)); + if (getEncoding() != null) { + this.ticketValidator.setEncoding(getEncoding()); + } + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/PropertiesCasRealm.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/PropertiesCasRealm.java new file mode 100644 index 0000000..9cbe8ea --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/PropertiesCasRealm.java @@ -0,0 +1,63 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.tomcat.CasRealm; +import org.jasig.cas.client.tomcat.PropertiesCasRealmDelegate; + +/** + * Tomcat Realm that implements {@link CasRealm} backed by properties file + * containing usernames/and roles of the following format: + *

+ * username1=role1,role2,role3
+ * username2=role1
+ * username3=role2,role3
+ * 
+ * User authentication succeeds if the name of the given principal exists as + * a username in the properties file. + * + * @author Marvin S. Addison + * @version $Revision$ + * @since 3.1.12 + * + */ +public class PropertiesCasRealm extends AbstractCasRealm { + + private final PropertiesCasRealmDelegate delegate = new PropertiesCasRealmDelegate(); + + /** + * @param path Path to properties file container username/role data. + */ + public void setPropertiesFilePath(final String path) { + this.delegate.setPropertiesFilePath(path); + } + + /** {@inheritDoc} */ + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.delegate.readProperties(); + } + + /** {@inheritDoc} */ + protected CasRealm getDelegate() { + return this.delegate; + } + +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/ProxyCallbackValve.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/ProxyCallbackValve.java new file mode 100644 index 0000000..adc98cc --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/ProxyCallbackValve.java @@ -0,0 +1,90 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import java.io.IOException; +import javax.servlet.ServletException; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.util.ReflectUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles watching a url for the proxy callback. + *

+ * Because its tough to share state between valves, we expose the storage mechanism via a static variable. + *

+ * This valve should be ordered before the authentication valves. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class ProxyCallbackValve extends ValveBase { + + private static ProxyGrantingTicketStorage PROXY_GRANTING_TICKET_STORAGE; + + /** Logger instance */ + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private String proxyGrantingTicketStorageClass; + + private String proxyCallbackUrl; + + public static ProxyGrantingTicketStorage getProxyGrantingTicketStorage() { + return PROXY_GRANTING_TICKET_STORAGE; + } + + public void setProxyGrantingTicketStorageClass(final String proxyGrantingTicketStorageClass) { + this.proxyGrantingTicketStorageClass = proxyGrantingTicketStorageClass; + } + + public void setProxyCallbackUrl(final String proxyCallbackUrl) { + this.proxyCallbackUrl = proxyCallbackUrl; + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + + try { + CommonUtils.assertNotNull(this.proxyCallbackUrl, "the proxy callback url cannot be null"); + CommonUtils.assertTrue(this.proxyCallbackUrl.startsWith("/"), "proxy callback url must start with \"/\""); + + PROXY_GRANTING_TICKET_STORAGE = ReflectUtils.newInstance(proxyGrantingTicketStorageClass); + } catch (final Exception e) { + throw new LifecycleException(e); + } + logger.info("Startup completed."); + } + + public void invoke(final Request request, final Response response) throws IOException, ServletException { + if (this.proxyCallbackUrl.equals(request.getRequestURI())) { + logger.debug("Processing proxy callback request."); + CommonUtils.readAndRespondToProxyReceptorRequest(request, response, PROXY_GRANTING_TICKET_STORAGE); + return; + } + + getNext().invoke(request, response); + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/RegexUriLogoutValve.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/RegexUriLogoutValve.java new file mode 100644 index 0000000..fc8999f --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/RegexUriLogoutValve.java @@ -0,0 +1,55 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.tomcat.LogoutHandler; +import org.jasig.cas.client.tomcat.RegexUriLogoutHandler; + +/** + * Performs CAS logout when the request URI matches a regular expression. + * + * @author Scott Battaglia + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class RegexUriLogoutValve extends AbstractLogoutValve { + + private RegexUriLogoutHandler logoutHandler = new RegexUriLogoutHandler(); + + public void setRedirectUrl(final String redirectUrl) { + this.logoutHandler.setRedirectUrl(redirectUrl); + } + + public void setLogoutUriRegex(final String regex) { + this.logoutHandler.setLogoutUriRegex(regex); + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.logoutHandler.init(); + logger.info("Startup completed."); + } + + /** {@inheritDoc} */ + protected LogoutHandler getLogoutHandler() { + return this.logoutHandler; + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Saml11Authenticator.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Saml11Authenticator.java new file mode 100644 index 0000000..fc44569 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/Saml11Authenticator.java @@ -0,0 +1,84 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.validation.Saml11TicketValidator; +import org.jasig.cas.client.validation.TicketValidator; + +/** + * CAS authenticator that uses the SAML 1.1 protocol. + * + * @author Marvin S. Addison + * @version $Revision$ + * @since 3.1.12 + * + */ +public final class Saml11Authenticator extends AbstractAuthenticator { + + public static final String AUTH_METHOD = "SAML11"; + + private static final String NAME = Saml11Authenticator.class.getName(); + + private Saml11TicketValidator ticketValidator; + + /** SAML protocol clock drift tolerance in ms */ + private int tolerance = -1; + + /** + * @param ms SAML clock drift tolerance in milliseconds. + */ + public void setTolerance(final int ms) { + this.tolerance = ms; + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Saml11TicketValidator(getCasServerUrlPrefix()); + if (this.tolerance > -1) { + this.ticketValidator.setTolerance(this.tolerance); + } + if (getEncoding() != null) { + this.ticketValidator.setEncoding(getEncoding()); + } + this.ticketValidator.setRenew(isRenew()); + } + + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + /** {@inheritDoc} */ + protected String getArtifactParameterName() { + return "SAMLart"; + } + + /** {@inheritDoc} */ + protected String getServiceParameterName() { + return "TARGET"; + } + + protected String getName() { + return NAME; + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/SingleSignOutValve.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/SingleSignOutValve.java new file mode 100644 index 0000000..02fe955 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/SingleSignOutValve.java @@ -0,0 +1,97 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import java.io.IOException; +import javax.servlet.ServletException; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.Session; +import org.apache.catalina.SessionEvent; +import org.apache.catalina.SessionListener; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.jasig.cas.client.session.SessionMappingStorage; +import org.jasig.cas.client.session.SingleSignOutHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handles logout request messages sent from the CAS server by ending the current + * HTTP session. + * + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + * + */ +public class SingleSignOutValve extends ValveBase implements SessionListener { + + /** Logger instance */ + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final SingleSignOutHandler handler = new SingleSignOutHandler(); + + public void setArtifactParameterName(final String name) { + this.handler.setArtifactParameterName(name); + } + + public void setLogoutParameterName(final String name) { + this.handler.setLogoutParameterName(name); + } + + public void setFrontLogoutParameterName(final String name) { + this.handler.setFrontLogoutParameterName(name); + } + + public void setRelayStateParameterName(final String name) { + this.handler.setRelayStateParameterName(name); + } + + public void setCasServerUrlPrefix(final String casServerUrlPrefix) { + this.handler.setCasServerUrlPrefix(casServerUrlPrefix); + } + + public void setSessionMappingStorage(final SessionMappingStorage storage) { + this.handler.setSessionMappingStorage(storage); + } + + /** {@inheritDoc} */ + public void invoke(final Request request, final Response response) throws IOException, ServletException { + if (this.handler.process(request, response)) { + getNext().invoke(request, response); + } + } + + /** {@inheritDoc} */ + public void sessionEvent(final SessionEvent event) { + if (Session.SESSION_DESTROYED_EVENT.equals(event.getType())) { + logger.debug("Cleaning up SessionMappingStorage on destroySession event"); + this.handler.getSessionMappingStorage().removeBySessionById(event.getSession().getId()); + } + } + + /** {@inheritDoc} */ + protected void startInternal() throws LifecycleException { + super.startInternal(); + logger.info("Starting..."); + this.handler.init(); + logger.info("Startup completed."); + } +} diff --git a/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/StaticUriLogoutValve.java b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/StaticUriLogoutValve.java new file mode 100644 index 0000000..516f331 --- /dev/null +++ b/cas-client-integration-tomcat-v8/src/main/java/org/jasig/cas/client/tomcat/v8/StaticUriLogoutValve.java @@ -0,0 +1,55 @@ +/* + * Licensed to Jasig under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Jasig licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v8; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.tomcat.LogoutHandler; +import org.jasig.cas.client.tomcat.StaticUriLogoutHandler; + +/** + * Monitors a specific request URI for logout requests. + * + * @author Scott Battaglia + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class StaticUriLogoutValve extends AbstractLogoutValve { + + private StaticUriLogoutHandler logoutHandler = new StaticUriLogoutHandler(); + + public void setRedirectUrl(final String redirectUrl) { + this.logoutHandler.setRedirectUrl(redirectUrl); + } + + public void setLogoutUri(final String logoutUri) { + this.logoutHandler.setLogoutUri(logoutUri); + } + + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.logoutHandler.init(); + logger.info("Startup completed."); + } + + /** {@inheritDoc} */ + protected LogoutHandler getLogoutHandler() { + return this.logoutHandler; + } +} diff --git a/pom.xml b/pom.xml index 75886fa..a5d3ba8 100644 --- a/pom.xml +++ b/pom.xml @@ -252,6 +252,7 @@ cas-client-integration-tomcat-common cas-client-integration-tomcat-v6 cas-client-integration-tomcat-v7 + cas-client-integration-tomcat-v8