This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new 49a2799cb3 Add support for jakarta.servlet.request.secure_protocol 49a2799cb3 is described below commit 49a2799cb3eae3b8a3e8ce6bc5b462394ab36bed Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Nov 23 12:18:56 2023 +0000 Add support for jakarta.servlet.request.secure_protocol This request attribute is new in Servlet 6.1. The Tomcat specific request attribute org.apache.tomcat.util.net.secure_protocol_version has been deprecated and will be removed in Tomcat 12. --- java/org/apache/catalina/Globals.java | 7 +++++++ java/org/apache/catalina/connector/Request.java | 11 +++++++---- java/org/apache/catalina/util/TLSUtil.java | 2 ++ java/org/apache/catalina/valves/SSLValve.java | 14 ++++++++++++++ java/org/apache/coyote/AbstractProcessor.java | 12 +++++++----- java/org/apache/coyote/ajp/AjpProcessor.java | 3 +++ java/org/apache/tomcat/util/net/SSLSupport.java | 10 ++++++++++ test/org/apache/catalina/valves/TestSSLValve.java | 11 +++++++++++ webapps/docs/changelog.xml | 6 ++++++ 9 files changed, 67 insertions(+), 9 deletions(-) diff --git a/java/org/apache/catalina/Globals.java b/java/org/apache/catalina/Globals.java index 0e52e18339..a3c127ecd1 100644 --- a/java/org/apache/catalina/Globals.java +++ b/java/org/apache/catalina/Globals.java @@ -129,6 +129,13 @@ public final class Globals { public static final String CERTIFICATES_ATTR = "jakarta.servlet.request.X509Certificate"; + /** + * The request attribute under which we store the name of the security protocol (e.g. TLSv1.3) being used on a + * secured connection (as an object of type {@link String}). + */ + public static final String SECURE_PROTOCOL_ATTR = "jakarta.servlet.request.secure_protocol"; + + /** * The request attribute under which we store the name of the cipher suite * being used on an SSL connection (as an object of type {@link String}). diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index 7883212a1c..508b279edf 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -836,6 +836,7 @@ public class Request implements HttpServletRequest { * * @param name Name of the request attribute to return */ + @SuppressWarnings("deprecation") @Override public Object getAttribute(String name) { // Special attributes @@ -860,6 +861,11 @@ public class Request implements HttpServletRequest { if (attr != null) { attributes.put(Globals.CERTIFICATES_ATTR, attr); } + attr = coyoteRequest.getAttribute(Globals.SECURE_PROTOCOL_ATTR); + if (attr != null) { + attributes.put(Globals.SECURE_PROTOCOL_ATTR, attr); + attributes.put(SSLSupport.PROTOCOL_VERSION_KEY, attr); + } attr = coyoteRequest.getAttribute(Globals.CIPHER_SUITE_ATTR); if (attr != null) { attributes.put(Globals.CIPHER_SUITE_ATTR, attr); @@ -876,10 +882,6 @@ public class Request implements HttpServletRequest { if (attr != null) { attributes.put(Globals.SSL_SESSION_MGR_ATTR, attr); } - attr = coyoteRequest.getAttribute(SSLSupport.PROTOCOL_VERSION_KEY); - if (attr != null) { - attributes.put(SSLSupport.PROTOCOL_VERSION_KEY, attr); - } attr = coyoteRequest.getAttribute(SSLSupport.REQUESTED_PROTOCOL_VERSIONS_KEY); if (attr != null) { attributes.put(SSLSupport.REQUESTED_PROTOCOL_VERSIONS_KEY, attr); @@ -911,6 +913,7 @@ public class Request implements HttpServletRequest { * <li>{@link Globals#DISPATCHER_REQUEST_PATH_ATTR}</li> * <li>{@link Globals#ASYNC_SUPPORTED_ATTR}</li> * <li>{@link Globals#CERTIFICATES_ATTR} (SSL connections only)</li> + * <li>{@link Globals#SECURE_PROTOCOL_ATTR} (SSL connections only)</li> * <li>{@link Globals#CIPHER_SUITE_ATTR} (SSL connections only)</li> * <li>{@link Globals#KEY_SIZE_ATTR} (SSL connections only)</li> * <li>{@link Globals#SSL_SESSION_ID_ATTR} (SSL connections only)</li> diff --git a/java/org/apache/catalina/util/TLSUtil.java b/java/org/apache/catalina/util/TLSUtil.java index 7f895ddb8f..43644d9082 100644 --- a/java/org/apache/catalina/util/TLSUtil.java +++ b/java/org/apache/catalina/util/TLSUtil.java @@ -32,9 +32,11 @@ public class TLSUtil { * @return {@code true} if the attribute is used to pass TLS configuration * information, otherwise {@code false} */ + @SuppressWarnings("deprecation") public static boolean isTLSRequestAttribute(String name) { switch (name) { case Globals.CERTIFICATES_ATTR: + case Globals.SECURE_PROTOCOL_ATTR: case Globals.CIPHER_SUITE_ATTR: case Globals.KEY_SIZE_ATTR: case Globals.SSL_SESSION_ID_ATTR: diff --git a/java/org/apache/catalina/valves/SSLValve.java b/java/org/apache/catalina/valves/SSLValve.java index 2daeb5e0aa..e5a8878339 100644 --- a/java/org/apache/catalina/valves/SSLValve.java +++ b/java/org/apache/catalina/valves/SSLValve.java @@ -46,6 +46,7 @@ import org.apache.tomcat.util.buf.UDecoder; * <pre> * <IfModule ssl_module> * RequestHeader set SSL_CLIENT_CERT "%{SSL_CLIENT_CERT}s" + * RequestHeader set SSL_SECURE_PROTOCOL "%{SSL_PROTOCOL}s" * RequestHeader set SSL_CIPHER "%{SSL_CIPHER}s" * RequestHeader set SSL_SESSION_ID "%{SSL_SESSION_ID}s" * RequestHeader set SSL_CIPHER_USEKEYSIZE "%{SSL_CIPHER_USEKEYSIZE}s" @@ -67,6 +68,7 @@ public class SSLValve extends ValveBase { private String sslClientCertHeader = "ssl_client_cert"; private String sslClientEscapedCertHeader = "ssl_client_escaped_cert"; + private String sslSecureProtocolHeader = "ssl_secure_protocol"; private String sslCipherHeader = "ssl_cipher"; private String sslSessionIdHeader = "ssl_session_id"; private String sslCipherUserKeySizeHeader = "ssl_cipher_usekeysize"; @@ -93,6 +95,14 @@ public class SSLValve extends ValveBase { this.sslClientEscapedCertHeader = sslClientEscapedCertHeader; } + public String getSslSecureProtocolHeader() { + return sslSecureProtocolHeader; + } + + public void setSslSecureProtocolHeader(String sslSecureProtocolHeader) { + this.sslSecureProtocolHeader = sslSecureProtocolHeader; + } + public String getSslCipherHeader() { return sslCipherHeader; } @@ -178,6 +188,10 @@ public class SSLValve extends ValveBase { request.setAttribute(Globals.CERTIFICATES_ATTR, jsseCerts); } } + headerValue = mygetHeader(request, sslSecureProtocolHeader); + if (headerValue != null) { + request.setAttribute(Globals.SECURE_PROTOCOL_ATTR, headerValue); + } headerValue = mygetHeader(request, sslCipherHeader); if (headerValue != null) { request.setAttribute(Globals.CIPHER_SUITE_ATTR, headerValue); diff --git a/java/org/apache/coyote/AbstractProcessor.java b/java/org/apache/coyote/AbstractProcessor.java index 4e26dca6e5..6cb85ffee6 100644 --- a/java/org/apache/coyote/AbstractProcessor.java +++ b/java/org/apache/coyote/AbstractProcessor.java @@ -764,10 +764,16 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement * Populate the TLS related request attributes from the {@link SSLSupport} instance associated with this processor. * Protocols that populate TLS attributes from a different source (e.g. AJP) should override this method. */ + @SuppressWarnings("deprecation") protected void populateSslRequestAttributes() { try { if (sslSupport != null) { - Object sslO = sslSupport.getCipherSuite(); + Object sslO = sslSupport.getProtocol(); + if (sslO != null) { + request.setAttribute(SSLSupport.SECURE_PROTOCOL_KEY, sslO); + request.setAttribute(SSLSupport.PROTOCOL_VERSION_KEY, sslO); + } + sslO = sslSupport.getCipherSuite(); if (sslO != null) { request.setAttribute(SSLSupport.CIPHER_SUITE_KEY, sslO); } @@ -783,10 +789,6 @@ public abstract class AbstractProcessor extends AbstractProcessorLight implement if (sslO != null) { request.setAttribute(SSLSupport.SESSION_ID_KEY, sslO); } - sslO = sslSupport.getProtocol(); - if (sslO != null) { - request.setAttribute(SSLSupport.PROTOCOL_VERSION_KEY, sslO); - } sslO = sslSupport.getRequestedProtocols(); if (sslO != null) { request.setAttribute(SSLSupport.REQUESTED_PROTOCOL_VERSIONS_KEY, sslO); diff --git a/java/org/apache/coyote/ajp/AjpProcessor.java b/java/org/apache/coyote/ajp/AjpProcessor.java index ef22da9c68..c8a070b362 100644 --- a/java/org/apache/coyote/ajp/AjpProcessor.java +++ b/java/org/apache/coyote/ajp/AjpProcessor.java @@ -132,6 +132,7 @@ public class AjpProcessor extends AbstractProcessor { // Build Map of Java Servlet to Jakarta Servlet attribute names Map<String, String> m = new HashMap<>(); + m.put("jakarta.servlet.request.secure_protocol", "jakarta.servlet.request.secure_protocol"); m.put("jakarta.servlet.request.cipher_suite", "jakarta.servlet.request.cipher_suite"); m.put("jakarta.servlet.request.key_size", "jakarta.servlet.request.key_size"); m.put("jakarta.servlet.request.ssl_session", "jakarta.servlet.request.ssl_session"); @@ -643,6 +644,7 @@ public class AjpProcessor extends AbstractProcessor { /** * After reading the request headers, we have to setup the request filters. */ + @SuppressWarnings("deprecation") private void prepareRequest() { // Translate the HTTP method code to a String. @@ -751,6 +753,7 @@ public class AjpProcessor extends AbstractProcessor { // Ignore invalid value } } else if (n.equals(Constants.SC_A_SSL_PROTOCOL)) { + request.setAttribute(SSLSupport.SECURE_PROTOCOL_KEY, v); request.setAttribute(SSLSupport.PROTOCOL_VERSION_KEY, v); } else if (n.equals("JK_LB_ACTIVATION")) { request.setAttribute(n, v); diff --git a/java/org/apache/tomcat/util/net/SSLSupport.java b/java/org/apache/tomcat/util/net/SSLSupport.java index d98e205ba4..528df94925 100644 --- a/java/org/apache/tomcat/util/net/SSLSupport.java +++ b/java/org/apache/tomcat/util/net/SSLSupport.java @@ -23,6 +23,13 @@ import java.security.cert.X509Certificate; * Defines an interface to interact with SSL sessions. */ public interface SSLSupport { + /** + * The Request attribute key for the cipher suite. + */ + String SECURE_PROTOCOL_KEY = + "jakarta.servlet.request.secure_protocol"; + + /** * The Request attribute key for the cipher suite. */ @@ -57,7 +64,10 @@ public interface SSLSupport { /** * The request attribute key under which the String indicating the protocol * that created the SSL socket is recorded - e.g. TLSv1 or TLSv1.2 etc. + * + * @deprecated Replaced by {@link #SECURE_PROTOCOL_KEY}. This constant will be removed in Tomcat 12. */ + @Deprecated String PROTOCOL_VERSION_KEY = "org.apache.tomcat.util.net.secure_protocol_version"; diff --git a/test/org/apache/catalina/valves/TestSSLValve.java b/test/org/apache/catalina/valves/TestSSLValve.java index 5c7753e1dc..702606e5db 100644 --- a/test/org/apache/catalina/valves/TestSSLValve.java +++ b/test/org/apache/catalina/valves/TestSSLValve.java @@ -268,6 +268,17 @@ public class TestSSLValve { } + @Test + public void testSslSecureProtocolHeaderPresent() throws Exception { + String protocol = "secured-with"; + mockRequest.setHeader(valve.getSslSecureProtocolHeader(), protocol); + + valve.invoke(mockRequest, null); + + Assert.assertEquals(protocol, mockRequest.getAttribute(Globals.SECURE_PROTOCOL_ATTR)); + } + + @Test public void testSslCipherHeaderPresent() throws Exception { String cipher = "ciphered-with"; diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 9ae058456d..9a7e836924 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -111,6 +111,12 @@ Background processes should not be run concurrently with lifecycle oprations of a container. (remm) </fix> + <add> + Add support for the <code>jakarta.servlet.request.secure_protocol</code> + request attribute that has been added in Jakarta Servlet 6.1. This + replaces the now deprecated Tomcat specific request attribute + <code>org.apache.tomcat.util.net.secure_protocol_version</code>. (markt) + </add> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org