Re: Tomcat 10.1.36 Configuration Question: Client Certificate(s) missing from servlet request object
Robert, On 2/25/25 5:59 PM, Robert Turner wrote: Tomcat 10.x uses the jakarta versions of the API, and I believe all the attributes have been renamed: "javax.servlet.request.X509Certificate" -> "jakarta.servlet.request.X509Certificate" +1 This is documented in Jakarta Servlet Specification[1] section 3.11. -chris [1] https://jakarta.ee/specifications/servlet/6.0/jakarta-servlet-spec-6.0.pdf On Tue, Feb 25, 2025 at 4:45 PM Chris Evans wrote: Hello, I need assistance with accessing client certificates from a servlet. This is not a servlet code question but a configuration question. The call to: request.getAttribute("javax.servlet.request.X509Certificate"); is not returning any certificates. The last time that I needed to do this was Tomcat 7 and a lot has changed. When connecting with a browser, a trusted connection is established. Javax.net.debug output shows my client certificate and a complete chain have been accepted. I have also limited the TLS version to TSSv1.2. What have I missed? Thanks, Chris Evans OS: Ubuntu 22-04 Tomcat Version: 10.1.36 TLS Logging: env | grep OPT CATALINA_OPTS=-Djavax.net.debug=ssl,handshake Connector Configuration: Java: @WebServlet("/hello") public class HelloServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("HelloServlet"); response.setContentType("text/html"); response.getWriter().println("Hello, World!"); // Retrieve client certificate X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); if (certs != null && certs.length > 0) { response.getWriter().println("Client Cert Subject: " + certs[0].getSubjectX500Principal()); } else { response.getWriter().println("No Client Certificate Found."); } } } WARNINGS: javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.816 UTC|SSLExtensions.java:227|Ignore impact of unsupported extension: server_name javax.net.ssl|DEBUG|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.817 UTC|SSLExtensions.java:219|Ignore unavailable extension: max_fragment_length javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.817 UTC|SSLExtensions.java:227|Ignore impact of unsupported extension: status_request javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.818 UTC|SSLExtensions.java:227|Ignore impact of unsupported extension: supported_groups javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.818 UTC|SSLExtensions.java:227|Ignore impact of unsupported extension: ec_point_formats javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.821 UTC|SSLExtensions.java:227|Ignore impact of unsupported extension: application_layer_protocol_negotiation javax.net.ssl|DEBUG|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.821 UTC|SSLExtensions.java:219|Ignore unavailable extension: status_request_v2 javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 20:34:04.823 UTC|SSLExtensions.java:227|Ignore impact of unsupported extension: extended_master_secret PROPRIETARY INFORMATION. This email may contain proprietary and privileged material for the sole use of the intended recipient. Any review or distribution of such material by others is strictly prohibited. If you are not the intended recipient please contact the sender and delete all copies. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
RE: Tomcat 10.1.36 Configuration Question: Client Certificate(s) missing from servlet request object
Thanks for the help. Best regards, Chris Evans -Original Message- From: Christopher Schultz Sent: Wednesday, February 26, 2025 7:38 AM To: users@tomcat.apache.org Subject: Re: Tomcat 10.1.36 Configuration Question: Client Certificate(s) missing from servlet request object Robert, On 2/25/25 5:59 PM, Robert Turner wrote: > Tomcat 10.x uses the jakarta versions of the API, and I believe all > the attributes have been renamed: > > "javax.servlet.request.X509Certificate" -> > "jakarta.servlet.request.X509Certificate" +1 This is documented in Jakarta Servlet Specification[1] section 3.11. -chris [1] https://jakarta.ee/specifications/servlet/6.0/jakarta-servlet-spec-6.0.pdf > On Tue, Feb 25, 2025 at 4:45 PM Chris Evans wrote: > >> >> Hello, >> >> I need assistance with accessing client certificates from a servlet. >> This is not a servlet code question but a configuration question. The call >> to: >> request.getAttribute("javax.servlet.request.X509Certificate"); >> >> is not returning any certificates. The last time that I needed to do >> this was Tomcat 7 and a lot has changed. >> >> When connecting with a browser, a trusted connection is established. >> Javax.net.debug output shows my client certificate and a complete >> chain have been accepted. >> >> I have also limited the TLS version to TSSv1.2. >> >> What have I missed? >> >> Thanks, >> >> Chris Evans >> >> OS: Ubuntu 22-04 >> Tomcat Version: 10.1.36 >> >> TLS Logging: >> env | grep OPT >> CATALINA_OPTS=-Djavax.net.debug=ssl,handshake >> >> Connector Configuration: >> >>> protocol="org.apache.coyote.http11.Http11Nio2Protocol" >> >> sslImplementationName="org.apache.tomcat.util.net.jsse.JSSEImplementation" >> maxParameterCount="1000" >> scheme="https" >> xmlValidation="true" >> maxThreads="150" >> SSLEnabled="true" >> secure="true" >>> >> > certificateVerificationDepth="4" >> truststoreFile="/home/ubuntu/tomcat/-REDACTED-.jks" >> truststorePassword="-REDACTED-" >> protocols="TLSv1.2" >> certificateVerification="required" >> >> > >> > certificateFile="/home/ubuntu/tomcat/serverCert.pem" >> >> certificateChainFile="/home/ubuntu/tomcat/serverChain.pem" >> >> certificateKeyFile="/home/ubuntu/tomcat/rsaKey.pem" >> type="RSA" /> >> >> >> >> Java: >> @WebServlet("/hello") >> public class HelloServlet extends HttpServlet { >> @Override >> protected void doGet(HttpServletRequest request, >> HttpServletResponse >> response) >> throws ServletException, IOException { >> System.out.println("HelloServlet"); >> response.setContentType("text/html"); >> response.getWriter().println("Hello, World!"); >> // Retrieve client certificate >> X509Certificate[] certs = (X509Certificate[]) >> request.getAttribute("javax.servlet.request.X509Certificate"); >> >> if (certs != null && certs.length > 0) { >> response.getWriter().println("Client Cert Subject: " + >> certs[0].getSubjectX500Principal()); >> } else { >> response.getWriter().println("No Client Certificate Found."); >> } >> >> } >> } >> >> WARNINGS: >> javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.816 UTC|SSLExtensions.java:227|Ignore impact of unsupported >> extension: server_name >> javax.net.ssl|DEBUG|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.817 >> UTC|SSLExtensions.java:219|Ignore unavailable extension: >> UTC|max_fragment_length >> javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.817 UTC|SSLExtensions.java:227|Ignore impact of unsupported >> extension: status_request >> javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.818 UTC|SSLExtensions.java:227|Ignore impact of unsupported >> extension: supported_groups >> javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.818 UTC|SSLExtensions.java:227|Ignore impact of unsupported >> extension: ec_point_formats >> javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.821 UTC|SSLExtensions.java:227|Ignore impact of unsupported >> extension: application_layer_protocol_negotiation >> javax.net.ssl|DEBUG|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.821 >> UTC|SSLExtensions.java:219|Ignore unavailable extension: >> UTC|status_request_v2 >> javax.net.ssl|WARNING|21|https-jsse-nio2-8443-exec-2|2025-02-25 >> 20:34:04.823 UTC|SSLExtensions.java:227|Ignore impact of unsupported >> extension: extended_master_secret >> >> >> PROPRIETARY INFORMATION. This email may contain proprietary and >> privileged material for the sole use of the intended recipient. Any >> rev
Re: tomcat 10.1.33 random rare 500 response status for http2 upgrade with tls
On 26/02/2025 12:04, Mark Thomas wrote: On 26/02/2025 08:16, Mark Thomas wrote: On 13/02/2025 10:04, Rémy Maucherat wrote: On Thu, Feb 13, 2025 at 9:41 AM Cenk Pekyaman wrote: We run tomcat on java17 with the embedded tomcat setup. We have http and https connectors and we have http2 upgradeProtocol for both. We recently upgraded from 9.0.88 to 10.1.24 to work on javax to jakarta migration, and after a while, upgraded to 10.1.33. After the upgrade, we started to see random and rare 500 errors for some of the http2 GET requests over https. When reproducing the error on our development machines, we could see the following trace on the server: ``` java.io.IOException: null Tomcat now sets an IO exception to trigger ReadListener.onError with an appropriate error in that case. So things seem normal so far. Following up on this. Tomcat is behaving as if the client has reset the stream before the client sent all of the data. If that is what the client is doing then this behaviour is expected. However, that then raises the question why is the reset being sent. If the client isn't resetting the stream then there is definitely a Tomcat bug here. We need to look at the test case you've provided. I'm planning on starting that today. Thanks again for the test case. It makes debugging issues so much easier when the report includes a reproducible test case. I am able to reproduce this issue with the latest 12.0.x code. It does look like there is a Tomcat bug here. I am currently working on tracking down the root cause. Found it and fixed the issue. The fix will be in the March releases. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: tomcat 10.1.33 random rare 500 response status for http2 upgrade with tls
On 13/02/2025 10:04, Rémy Maucherat wrote: On Thu, Feb 13, 2025 at 9:41 AM Cenk Pekyaman wrote: We run tomcat on java17 with the embedded tomcat setup. We have http and https connectors and we have http2 upgradeProtocol for both. We recently upgraded from 9.0.88 to 10.1.24 to work on javax to jakarta migration, and after a while, upgraded to 10.1.33. After the upgrade, we started to see random and rare 500 errors for some of the http2 GET requests over https. When reproducing the error on our development machines, we could see the following trace on the server: ``` java.io.IOException: null Tomcat now sets an IO exception to trigger ReadListener.onError with an appropriate error in that case. So things seem normal so far. Following up on this. Tomcat is behaving as if the client has reset the stream before the client sent all of the data. If that is what the client is doing then this behaviour is expected. However, that then raises the question why is the reset being sent. If the client isn't resetting the stream then there is definitely a Tomcat bug here. We need to look at the test case you've provided. I'm planning on starting that today. Now the "null" is not normal, the corresponding string exists in the resource bundle: stream.clientResetRequest=Client reset the stream before the request was fully read This is a Tomcat bug. The resource string was missing in 10.1.33 and was added for 10.1.35 onwards. Mark Rémy at org.apache.coyote.http2.Stream$StandardStreamInputBuffer.receiveReset(Stream.java:1516) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.coyote.http2.Stream.receiveReset(Stream.java:224) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.coyote.http2.Http2UpgradeHandler.close(Http2UpgradeHandler.java:1305) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.coyote.http2.Http2UpgradeHandler.upgradeDispatch(Http2UpgradeHandler.java:437) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.coyote.http2.Http2AsyncUpgradeHandler.upgradeDispatch(Http2AsyncUpgradeHandler.java:43) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.failed(Http2AsyncParser.java:337) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.coyote.http2.Http2AsyncParser$FrameCompletionHandler.failed(Http2AsyncParser.java:167) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.tomcat.util.net.SocketWrapperBase$VectoredIOCompletionHandler.failed(SocketWrapperBase.java:1148) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper$NioOperationState.run(NioEndpoint.java:1660) ~[tomcat-coyote-10.1.33.jar:10.1.33] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) [tomcat-util-10.1.33.jar:10.1.33] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-util-10.1.33.jar:10.1.33] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) [tomcat-util-10.1.33.jar:10.1.33] at java.lang.Thread.run(Thread.java:840) [?:?] ``` after further testing, we think the change https://github.com/apache/tomcat/commit/f902edf085c0c73139a66d1bfc4d5790a416b130 introduced in 10.1.29 is the reason we get 500 status. but the change seems to be doing what is intended, so we tested with multiple tomcat versions to see if there were already unexposed failures prior. and in versions like 10.1.24 we see the below error which does not result in 500 status: ``` [org.apache.coyote.http2.Http2Parser] {https-jsse-nio-8443-exec-6} Connection [92], Stream [0], Frame type [null], Error java.io.IOException: Unable to unwrap data, invalid status [CLOSED] at org.apache.tomcat.util.net.SecureNioChannel.read(SecureNioChannel.java:772) ~[tomcat-coyote-10.1.24.jar:10.1.24] at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper$NioOperationState.run(NioEndpoint.java:1609) ~[tomcat-coyote-10.1.24.jar:10.1.24] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) [tomcat-util-10.1.24.jar:10.1.24] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-util-10.1.24.jar:10.1.24] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) [tomcat-util-10.1.24.jar:10.1.24] at java.base/java.lang.Thread.run(Thread.java:840) [?:?] ``` it is not the same error, but since it is happening around the same code context NioOperationState.run, it gave us the impression that the traces might be related. We have run our reproducer with multiple versions: 10.1.24, 10.1.28, 10.1.29, 10.1.33, 10.1.35, 11.0.2. versions 10.1.29 and up show the rarer "receiveReset" issue (500 status), versions 10.1.28 and down showcase only "Unable to unwrap data" issue (no 500). We can reproduce the issue somewhat reliably with the reproducer setup we have in https://github.com/cpekyaman/java-server-http2-te
Re: tomcat 10.1.33 random rare 500 response status for http2 upgrade with tls
On 26/02/2025 08:16, Mark Thomas wrote: On 13/02/2025 10:04, Rémy Maucherat wrote: On Thu, Feb 13, 2025 at 9:41 AM Cenk Pekyaman wrote: We run tomcat on java17 with the embedded tomcat setup. We have http and https connectors and we have http2 upgradeProtocol for both. We recently upgraded from 9.0.88 to 10.1.24 to work on javax to jakarta migration, and after a while, upgraded to 10.1.33. After the upgrade, we started to see random and rare 500 errors for some of the http2 GET requests over https. When reproducing the error on our development machines, we could see the following trace on the server: ``` java.io.IOException: null Tomcat now sets an IO exception to trigger ReadListener.onError with an appropriate error in that case. So things seem normal so far. Following up on this. Tomcat is behaving as if the client has reset the stream before the client sent all of the data. If that is what the client is doing then this behaviour is expected. However, that then raises the question why is the reset being sent. If the client isn't resetting the stream then there is definitely a Tomcat bug here. We need to look at the test case you've provided. I'm planning on starting that today. Thanks again for the test case. It makes debugging issues so much easier when the report includes a reproducible test case. I am able to reproduce this issue with the latest 12.0.x code. It does look like there is a Tomcat bug here. I am currently working on tracking down the root cause. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org