From 67ac39227e5db83c7a4a7ad72364f3dcd30db05e Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Thu, 3 Dec 2015 16:09:04 +1100 Subject: [PATCH] Extract common base class for SSLAuthenticatorWithFallback Two Tomcat version-specific implementations of SSLAuthenticatorWithFallback exist, with much duplicate code. Extract an abstract base class 'AbstractPKIAuthenticator' and implement just the unique bits in the concrete classes. Part of: https://fedorahosted.org/pki/ticket/1359 --- .../cms/tomcat/AbstractPKIAuthenticator.java} | 35 +++-- base/server/tomcat7/src/CMakeLists.txt | 3 + .../cms/tomcat/SSLAuthenticatorWithFallback.java | 143 +++------------------ base/server/tomcat8/src/CMakeLists.txt | 3 + .../cms/tomcat/SSLAuthenticatorWithFallback.java | 140 ++------------------ 5 files changed, 51 insertions(+), 273 deletions(-) copy base/server/{tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java => tomcat/src/com/netscape/cms/tomcat/AbstractPKIAuthenticator.java} (86%) diff --git a/base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java b/base/server/tomcat/src/com/netscape/cms/tomcat/AbstractPKIAuthenticator.java similarity index 86% copy from base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java copy to base/server/tomcat/src/com/netscape/cms/tomcat/AbstractPKIAuthenticator.java index 3678791b927a9d6bca523d6a79a5fbfff1b675cf..f98377dc2322d7fa525d360a401348468f840f43 100644 --- a/base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java +++ b/base/server/tomcat/src/com/netscape/cms/tomcat/AbstractPKIAuthenticator.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletResponseWrapper; import org.apache.catalina.Container; import org.apache.catalina.Globals; import org.apache.catalina.LifecycleException; +import org.apache.catalina.Authenticator; import org.apache.catalina.authenticator.AuthenticatorBase; import org.apache.catalina.authenticator.BasicAuthenticator; import org.apache.catalina.authenticator.FormAuthenticator; @@ -37,7 +38,7 @@ import org.apache.catalina.connector.Request; /** * @author Endi S. Dewata */ -public class SSLAuthenticatorWithFallback extends AuthenticatorBase { +public abstract class AbstractPKIAuthenticator extends AuthenticatorBase { public final static String BASIC_AUTHENTICATOR = "BASIC"; public final static String FORM_AUTHENTICATOR = "FORM"; @@ -47,7 +48,7 @@ public class SSLAuthenticatorWithFallback extends AuthenticatorBase { AuthenticatorBase sslAuthenticator = new SSLAuthenticator(); AuthenticatorBase fallbackAuthenticator = new BasicAuthenticator(); - public SSLAuthenticatorWithFallback() { + public AbstractPKIAuthenticator() { log("Creating SSL authenticator with fallback"); } @@ -68,9 +69,7 @@ public class SSLAuthenticatorWithFallback extends AuthenticatorBase { } - @Override - public boolean authenticate(Request request, HttpServletResponse response) throws IOException { - + public boolean doAuthenticate(Request request, HttpServletResponse response) throws IOException { X509Certificate certs[] = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR); boolean result; @@ -84,7 +83,7 @@ public class SSLAuthenticatorWithFallback extends AuthenticatorBase { log("SSL auth return code: "+code); } }; - result = sslAuthenticator.authenticate(request, wrapper); + result = doSubAuthenticate(sslAuthenticator, request, wrapper); } else { log("Authenticating with "+fallbackMethod+" authentication"); @@ -96,30 +95,28 @@ public class SSLAuthenticatorWithFallback extends AuthenticatorBase { log("Fallback auth return code: "+code); } }; - result = fallbackAuthenticator.authenticate(request, wrapper); + result = doSubAuthenticate(fallbackAuthenticator, request, wrapper); } if (result) return true; log("Result: "+result); - String realmName = AuthenticatorBase.getRealmName(request.getContext()); - - - StringBuilder value = new StringBuilder(16); - value.append("Basic realm=\""); - if (realmName != null) { - value.append(REALM_NAME); - } else { - value.append(realmName); - } - value.append('\"'); - response.setHeader(AUTH_HEADER_NAME, value.toString()); + String realmName = doGetRealmName(request); + response.setHeader(AUTH_HEADER_NAME, + "Basic realm=\"" + (realmName == null ? REALM_NAME : realmName) + "\""); response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return false; } + public abstract boolean doSubAuthenticate( + Authenticator auth, Request req, HttpServletResponse resp) + throws IOException; + + public abstract String doGetRealmName(Request req); + + @Override protected String getAuthMethod() { return HttpServletRequest.CLIENT_CERT_AUTH; diff --git a/base/server/tomcat7/src/CMakeLists.txt b/base/server/tomcat7/src/CMakeLists.txt index 77293a654d5335ad134afaac30e4678360e0cc05..bb42bfe0a4a840f0b271a83600f79686f76cc353 100644 --- a/base/server/tomcat7/src/CMakeLists.txt +++ b/base/server/tomcat7/src/CMakeLists.txt @@ -124,8 +124,11 @@ javac(pki-tomcat7-classes com/netscape/cms/tomcat/*.java CLASSPATH ${SERVLET_JAR} ${TOMCAT_CATALINA_JAR} ${TOMCAT_UTIL_SCAN_JAR} + ${CMAKE_BINARY_DIR}/../../tomcat OUTPUT_DIR ${CMAKE_BINARY_DIR}/../../tomcat + DEPENDS + pki-tomcat-classes ) configure_file( diff --git a/base/server/tomcat7/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java b/base/server/tomcat7/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java index 20bf85d221bac3f5dbd1cac73aa9b8252a1cc6e8..38c2431d8ed0775bb2ca2b5c32ca87fc07b180c5 100644 --- a/base/server/tomcat7/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java +++ b/base/server/tomcat7/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java @@ -19,154 +19,47 @@ package com.netscape.cms.tomcat; import java.io.IOException; -import java.security.cert.X509Certificate; +import java.lang.ThreadLocal; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import org.apache.catalina.Container; -import org.apache.catalina.Globals; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.authenticator.AuthenticatorBase; -import org.apache.catalina.authenticator.BasicAuthenticator; -import org.apache.catalina.authenticator.FormAuthenticator; -import org.apache.catalina.authenticator.SSLAuthenticator; +import org.apache.catalina.Authenticator; import org.apache.catalina.connector.Request; import org.apache.catalina.deploy.LoginConfig; /** * @author Endi S. Dewata */ -public class SSLAuthenticatorWithFallback extends AuthenticatorBase { +public class SSLAuthenticatorWithFallback extends AbstractPKIAuthenticator { - public final static String BASIC_AUTHENTICATOR = "BASIC"; - public final static String FORM_AUTHENTICATOR = "FORM"; - - String fallbackMethod = BASIC_AUTHENTICATOR; - - AuthenticatorBase sslAuthenticator = new SSLAuthenticator(); - AuthenticatorBase fallbackAuthenticator = new BasicAuthenticator(); - - public SSLAuthenticatorWithFallback() { - log("Creating SSL authenticator with fallback"); - } + protected static final ThreadLocal loginConfig = + new ThreadLocal<>(); @Override public String getInfo() { return "SSL authenticator with "+fallbackMethod+" fallback."; } - public String getFallbackMethod() { - return fallbackMethod; + @Override + public boolean doSubAuthenticate( + Authenticator auth, Request req, HttpServletResponse resp) + throws IOException { + return auth.authenticate(req, resp, loginConfig.get()); } - public void setFallbackMethod(String fallbackMethod) { - log("Fallback method: "+fallbackMethod); - this.fallbackMethod = fallbackMethod; - - if (BASIC_AUTHENTICATOR.equalsIgnoreCase(fallbackMethod)) { - fallbackAuthenticator = new BasicAuthenticator(); - - } else if (FORM_AUTHENTICATOR.equalsIgnoreCase(fallbackMethod)) { - fallbackAuthenticator = new FormAuthenticator(); - } - + @Override + public String doGetRealmName(Request request /* ignored */) { + return loginConfig.get().getRealmName(); } @Override public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException { - - X509Certificate certs[] = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR); - boolean result; - - if (certs != null && certs.length > 0) { - log("Authenticate with client certificate authentication"); - HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) { - public void setHeader(String name, String value) { - log("SSL auth header: "+name+"="+value); - }; - public void sendError(int code) { - log("SSL auth return code: "+code); - } - }; - result = sslAuthenticator.authenticate(request, wrapper, config); - - } else { - log("Authenticating with "+fallbackMethod+" authentication"); - HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) { - public void setHeader(String name, String value) { - log("Fallback auth header: "+name+"="+value); - }; - public void sendError(int code) { - log("Fallback auth return code: "+code); - } - }; - result = fallbackAuthenticator.authenticate(request, wrapper, config); + loginConfig.set(config); + try { + return doAuthenticate(request, response); + } finally { + loginConfig.remove(); } - - if (result) - return true; - - log("Result: "+result); - - StringBuilder value = new StringBuilder(16); - value.append("Basic realm=\""); - if (config.getRealmName() == null) { - value.append(REALM_NAME); - } else { - value.append(config.getRealmName()); - } - value.append('\"'); - response.setHeader(AUTH_HEADER_NAME, value.toString()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - - return false; - } - - @Override - protected String getAuthMethod() { - return HttpServletRequest.CLIENT_CERT_AUTH; - }; - - @Override - public void setContainer(Container container) { - log("Setting container"); - super.setContainer(container); - sslAuthenticator.setContainer(container); - fallbackAuthenticator.setContainer(container); } - @Override - protected void initInternal() throws LifecycleException { - log("Initializing authenticators"); - - super.initInternal(); - - sslAuthenticator.setAlwaysUseSession(alwaysUseSession); - sslAuthenticator.init(); - - fallbackAuthenticator.setAlwaysUseSession(alwaysUseSession); - fallbackAuthenticator.init(); - } - - @Override - public void startInternal() throws LifecycleException { - log("Starting authenticators"); - super.startInternal(); - sslAuthenticator.start(); - fallbackAuthenticator.start(); - } - - @Override - public void stopInternal() throws LifecycleException { - log("Stopping authenticators"); - super.stopInternal(); - sslAuthenticator.stop(); - fallbackAuthenticator.stop(); - } - - public void log(String message) { - System.out.println("SSLAuthenticatorWithFallback: "+message); - } } diff --git a/base/server/tomcat8/src/CMakeLists.txt b/base/server/tomcat8/src/CMakeLists.txt index a2badac69837023ca7078cfeaa80cdf98ba2a63b..df55916bc0bc0e2bb010239115c68b8bc5ad6c84 100644 --- a/base/server/tomcat8/src/CMakeLists.txt +++ b/base/server/tomcat8/src/CMakeLists.txt @@ -124,8 +124,11 @@ javac(pki-tomcat8-classes com/netscape/cms/tomcat/*.java CLASSPATH ${SERVLET_JAR} ${TOMCAT_CATALINA_JAR} ${TOMCAT_UTIL_SCAN_JAR} + ${CMAKE_BINARY_DIR}/../../tomcat OUTPUT_DIR ${CMAKE_BINARY_DIR}/../../tomcat + DEPENDS + pki-tomcat-classes ) configure_file( diff --git a/base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java b/base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java index 3678791b927a9d6bca523d6a79a5fbfff1b675cf..12ca0bb7c5213f8e833f75bfb92826dbc8718d87 100644 --- a/base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java +++ b/base/server/tomcat8/src/com/netscape/cms/tomcat/SSLAuthenticatorWithFallback.java @@ -19,150 +19,32 @@ package com.netscape.cms.tomcat; import java.io.IOException; -import java.security.cert.X509Certificate; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import org.apache.catalina.Container; -import org.apache.catalina.Globals; -import org.apache.catalina.LifecycleException; -import org.apache.catalina.authenticator.AuthenticatorBase; -import org.apache.catalina.authenticator.BasicAuthenticator; -import org.apache.catalina.authenticator.FormAuthenticator; -import org.apache.catalina.authenticator.SSLAuthenticator; +import org.apache.catalina.Authenticator; import org.apache.catalina.connector.Request; /** * @author Endi S. Dewata */ -public class SSLAuthenticatorWithFallback extends AuthenticatorBase { +public class SSLAuthenticatorWithFallback extends AbstractPKIAuthenticator { - public final static String BASIC_AUTHENTICATOR = "BASIC"; - public final static String FORM_AUTHENTICATOR = "FORM"; - - String fallbackMethod = BASIC_AUTHENTICATOR; - - AuthenticatorBase sslAuthenticator = new SSLAuthenticator(); - AuthenticatorBase fallbackAuthenticator = new BasicAuthenticator(); - - public SSLAuthenticatorWithFallback() { - log("Creating SSL authenticator with fallback"); - } - - public String getFallbackMethod() { - return fallbackMethod; + @Override + public boolean doSubAuthenticate( + Authenticator auth, Request req, HttpServletResponse resp) + throws IOException { + return auth.authenticate(req, resp); } - public void setFallbackMethod(String fallbackMethod) { - log("Fallback method: "+fallbackMethod); - this.fallbackMethod = fallbackMethod; - - if (BASIC_AUTHENTICATOR.equalsIgnoreCase(fallbackMethod)) { - fallbackAuthenticator = new BasicAuthenticator(); - - } else if (FORM_AUTHENTICATOR.equalsIgnoreCase(fallbackMethod)) { - fallbackAuthenticator = new FormAuthenticator(); - } - + @Override + public String doGetRealmName(Request request) { + return getRealmName(request.getContext()); } @Override public boolean authenticate(Request request, HttpServletResponse response) throws IOException { - - X509Certificate certs[] = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR); - boolean result; - - if (certs != null && certs.length > 0) { - log("Authenticate with client certificate authentication"); - HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) { - public void setHeader(String name, String value) { - log("SSL auth header: "+name+"="+value); - }; - public void sendError(int code) { - log("SSL auth return code: "+code); - } - }; - result = sslAuthenticator.authenticate(request, wrapper); - - } else { - log("Authenticating with "+fallbackMethod+" authentication"); - HttpServletResponseWrapper wrapper = new HttpServletResponseWrapper(response) { - public void setHeader(String name, String value) { - log("Fallback auth header: "+name+"="+value); - }; - public void sendError(int code) { - log("Fallback auth return code: "+code); - } - }; - result = fallbackAuthenticator.authenticate(request, wrapper); - } - - if (result) - return true; - - log("Result: "+result); - String realmName = AuthenticatorBase.getRealmName(request.getContext()); - - - StringBuilder value = new StringBuilder(16); - value.append("Basic realm=\""); - if (realmName != null) { - value.append(REALM_NAME); - } else { - value.append(realmName); - } - value.append('\"'); - response.setHeader(AUTH_HEADER_NAME, value.toString()); - response.sendError(HttpServletResponse.SC_UNAUTHORIZED); - - return false; - } - - @Override - protected String getAuthMethod() { - return HttpServletRequest.CLIENT_CERT_AUTH; - }; - - @Override - public void setContainer(Container container) { - log("Setting container"); - super.setContainer(container); - sslAuthenticator.setContainer(container); - fallbackAuthenticator.setContainer(container); + return doAuthenticate(request, response); } - @Override - protected void initInternal() throws LifecycleException { - log("Initializing authenticators"); - - super.initInternal(); - - sslAuthenticator.setAlwaysUseSession(alwaysUseSession); - sslAuthenticator.init(); - - fallbackAuthenticator.setAlwaysUseSession(alwaysUseSession); - fallbackAuthenticator.init(); - } - - @Override - public void startInternal() throws LifecycleException { - log("Starting authenticators"); - super.startInternal(); - sslAuthenticator.start(); - fallbackAuthenticator.start(); - } - - @Override - public void stopInternal() throws LifecycleException { - log("Stopping authenticators"); - super.stopInternal(); - sslAuthenticator.stop(); - fallbackAuthenticator.stop(); - } - - public void log(String message) { - System.out.println("SSLAuthenticatorWithFallback: "+message); - } } -- 2.5.0