diff --git a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java index 8bb5759c93659aff09b4950fc91c2c544867774d..2541dee4d9b81844ec822bf86a2205ad8074e3ef 100644 --- a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java +++ b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilter.java @@ -22,7 +22,6 @@ import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_ import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_SSL_CERTIFICATE; import java.io.IOException; -import java.security.cert.CertificateException; import jakarta.servlet.FilterChain; import jakarta.servlet.FilterConfig; @@ -52,7 +51,7 @@ import org.slf4j.LoggerFactory; }) public class SslFilter implements Preprocessor { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + public static final Logger LOGGER = LoggerFactory.getLogger(SslFilter.class); @ObjectClassDefinition(name = "Apache Felix Http Service SSL Filter", description = "Configuration for the Http Service SSL Filter. Please consult the documentation of your proxy for the actual headers and values to use.") @@ -90,7 +89,7 @@ public class SslFilter implements Preprocessor { @Modified public void updateConfig(final Config config) { this.config = config; - logger.info("SSL filter (re)configured with: " + + LOGGER.info("SSL filter (re)configured with: " + "rewrite absolute urls = {}; SSL forward header = '{}'; SSL forward value = '{}'; SSL certificate header = '{}'", config.rewrite_absolute_urls(), config.ssl_forward_header(), config.ssl_forward_value(), config.ssl_forward_cert_header()); } @@ -114,13 +113,8 @@ public class SslFilter implements Preprocessor { HttpServletResponse httpResp = (HttpServletResponse) res; if (cfg.ssl_forward_value().equalsIgnoreCase(httpReq.getHeader(cfg.ssl_forward_header()))) { - try { - httpResp = new SslFilterResponse(httpResp, httpReq, cfg); - // In case this fails, we fall back to the original HTTP request, which is better than nothing... - httpReq = new SslFilterRequest(httpReq, httpReq.getHeader(cfg.ssl_forward_cert_header())); - } catch (final CertificateException e) { - logger.warn("Failed to create SSL filter request! Problem parsing client certificates?! Client certificate will *not* be forwarded...", e); - } + httpResp = new SslFilterResponse(httpResp, httpReq, cfg); + httpReq = new SslFilterRequest(httpReq, httpReq.getHeader(cfg.ssl_forward_cert_header())); } // forward the request making sure any certificate is removed again after the request processing gets back here diff --git a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java index 0da3a362282178bb1e9ef53ed0fba77edfe99adf..db7c4d3b88610063a7b548ed6d75585d807002d9 100644 --- a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java +++ b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterConstants.java @@ -21,8 +21,7 @@ package org.apache.felix.http.sslfilter.internal; /** * Provides constants used in the SSL filter. */ -interface SslFilterConstants -{ +interface SslFilterConstants { /** * If there is an SSL certificate associated with the request, it must be exposed by the servlet container to the * servlet programmer as an array of objects of type java.security.cert.X509Certificate and accessible via a @@ -59,6 +58,7 @@ interface SslFilterConstants * HTTP protocol/scheme. */ String HTTP = "http"; + /** * Default port used for HTTP. */ @@ -68,11 +68,16 @@ interface SslFilterConstants * HTTPS protocol/scheme. */ String HTTPS = "https"; + /** * Default port used for HTTPS. */ int HTTPS_PORT = 443; - String UTF_8 = "UTF-8"; String X_509 = "X.509"; + + /** + * The HTTP scheme prefix in an URL + */ + String HTTP_SCHEME_PREFIX = "http://"; } diff --git a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java index 93357b3e24ec8efe60be62fe4f18d30e05b2069a..7a7931ea226d390e6d7e566a9b6bfcda7bde140c 100644 --- a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java +++ b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterRequest.java @@ -21,12 +21,14 @@ package org.apache.felix.http.sslfilter.internal; import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.ATTR_SSL_CERTIFICATE; import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HDR_X_FORWARDED_PORT; import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS; -import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.UTF_8; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTPS_PORT; +import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.HTTP_SCHEME_PREFIX; import static org.apache.felix.http.sslfilter.internal.SslFilterConstants.X_509; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -37,34 +39,26 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; class SslFilterRequest extends HttpServletRequestWrapper { - // The HTTP scheme prefix in an URL - private static final String HTTP_SCHEME_PREFIX = "http://"; // pattern to convert the header to a PEM certificate for parsing // by replacing spaces with line breaks private static final Pattern HEADER_TO_CERT = Pattern.compile("(?! CERTIFICATE)(?= ) "); @SuppressWarnings("unchecked") - SslFilterRequest(final HttpServletRequest request, final String clientCertHeader) throws CertificateException { + SslFilterRequest(final HttpServletRequest request, final String clientCertHeader) { super(request); - // TODO jawi: perhaps we should make this class a little smarter wrt the given request: - // it now always assumes it should rewrite its URL, while this might not always be the - // case... - - if (clientCertHeader != null && !"".equals(clientCertHeader.trim())) { + if (clientCertHeader != null && clientCertHeader.trim().length() > 0) { final String clientCert = HEADER_TO_CERT.matcher(clientCertHeader).replaceAll("\n"); - try { - CertificateFactory fac = CertificateFactory.getInstance(X_509); - - InputStream instream = new ByteArrayInputStream(clientCert.getBytes(UTF_8)); - - Collection<X509Certificate> certs = (Collection<X509Certificate>) fac.generateCertificates(instream); - request.setAttribute(ATTR_SSL_CERTIFICATE, certs.toArray(new X509Certificate[certs.size()])); - } catch (UnsupportedEncodingException e) { - // Any JRE should support UTF-8... - throw new InternalError("UTF-8 not supported?!"); + try (InputStream instream = new ByteArrayInputStream(clientCert.getBytes(StandardCharsets.UTF_8))) { + final CertificateFactory fac = CertificateFactory.getInstance(X_509); + Collection<X509Certificate> certs = (Collection<X509Certificate>) fac.generateCertificates(instream); + request.setAttribute(ATTR_SSL_CERTIFICATE, certs.toArray(new X509Certificate[certs.size()])); + } catch ( final IOException ignore) { + // ignore - can only happen on close + } catch ( final CertificateException ce) { + SslFilter.LOGGER.warn("Failed to create SSL filter request! Problem parsing client certificates?! Client certificate will *not* be forwarded...", ce); } } } @@ -85,13 +79,13 @@ class SslFilterRequest extends HttpServletRequestWrapper { @Override public StringBuffer getRequestURL() { - StringBuffer tmp = new StringBuffer(super.getRequestURL()); + final StringBuffer result = super.getRequestURL(); // In case the request happened over http, simply insert an additional 's' // to make the request appear to be done over https... - if (tmp.indexOf(HTTP_SCHEME_PREFIX) == 0) { - tmp.insert(4, 's'); + if (result.indexOf(HTTP_SCHEME_PREFIX) == 0) { + result.insert(4, 's'); } - return tmp; + return result; } @Override @@ -99,11 +93,10 @@ class SslFilterRequest extends HttpServletRequestWrapper { int port; try { - String fwdPort = getHeader(HDR_X_FORWARDED_PORT); - port = Integer.parseInt(fwdPort); - } catch (Exception e) { + port = Integer.parseInt(getHeader(HDR_X_FORWARDED_PORT)); + } catch (final Exception e) { // Use default port - port = 443; + port = HTTPS_PORT; } return port; } diff --git a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java index 89ae257e23e5be713c8284a17ca8d27c7f14efa2..a0e5723b9deed89cbd0ec171e93a89b51702c807 100644 --- a/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java +++ b/http/sslfilter/src/main/java/org/apache/felix/http/sslfilter/internal/SslFilterResponse.java @@ -61,7 +61,7 @@ class SslFilterResponse extends HttpServletResponseWrapper { this.serverName = request.getServerName(); this.serverPort = request.getServerPort(); - String value = request.getHeader(config.ssl_forward_header()); + final String value = request.getHeader(config.ssl_forward_header()); if ((HDR_X_FORWARDED_PROTO.equalsIgnoreCase(config.ssl_forward_header()) && HTTP.equalsIgnoreCase(value)) || (HDR_X_FORWARDED_SSL.equalsIgnoreCase(config.ssl_forward_header()) && !config.ssl_forward_value().equalsIgnoreCase(value))) { diff --git a/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterRequestTest.java b/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterRequestTest.java index 8cc4f43855c192882b4f508f2a136804ea575860..d930a5cdb468e68b9283b94058d59c40ce44ba20 100644 --- a/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterRequestTest.java +++ b/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterRequestTest.java @@ -72,12 +72,10 @@ public class SslFilterRequestTest when(req.getRequestURL()).thenReturn(new StringBuffer("http://some/page")); assertEquals("http://some/page", req.getRequestURL().toString()); assertEquals("https://some/page", sreq.getRequestURL().toString()); - assertEquals("http://some/page", req.getRequestURL().toString()); when(req.getRequestURL()).thenReturn(new StringBuffer("https://some/page")); assertEquals("https://some/page", req.getRequestURL().toString()); assertEquals("https://some/page", sreq.getRequestURL().toString()); - assertEquals("https://some/page", req.getRequestURL().toString()); } @Test diff --git a/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java b/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java index 945b988845e49016e374195a2a1f9ff8450df47f..bff83c3906b681e9ced3b043e39bdd68fec9febf 100644 --- a/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java +++ b/http/sslfilter/src/test/java/org/apache/felix/http/sslfilter/internal/SslFilterResponseTest.java @@ -515,7 +515,6 @@ public class SslFilterResponseTest committed = true; } - @SuppressWarnings("deprecation") @Override public void setStatus(int sc, String sm) { status = sc; @@ -578,7 +577,6 @@ public class SslFilterResponseTest return headers.get(name); } - @SuppressWarnings("deprecation") @Override public String encodeUrl(String url) { throw new UnsupportedOperationException(); @@ -589,7 +587,6 @@ public class SslFilterResponseTest throw new UnsupportedOperationException(); } - @SuppressWarnings("deprecation") @Override public String encodeRedirectUrl(String url) { throw new UnsupportedOperationException();