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 e53b36f0a9 Fix BZ 69728. Remove incorrect h2+optional msg. Improve CLIENT-CERT msgs e53b36f0a9 is described below commit e53b36f0a96478aa0c0bbda463ca629b68af8114 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Jun 26 12:01:08 2025 +0100 Fix BZ 69728. Remove incorrect h2+optional msg. Improve CLIENT-CERT msgs https://bz.apache.org/bugzilla/show_bug.cgi?id=69728 --- .../catalina/authenticator/LocalStrings.properties | 4 +- .../catalina/authenticator/SSLAuthenticator.java | 62 +++++++++++++++------- .../apache/tomcat/util/net/AbstractEndpoint.java | 6 --- .../apache/tomcat/util/net/LocalStrings.properties | 1 - .../tomcat/util/net/LocalStrings_fr.properties | 1 - .../tomcat/util/net/LocalStrings_ja.properties | 1 - .../tomcat/util/net/LocalStrings_ko.properties | 1 - .../tomcat/util/net/LocalStrings_zh_CN.properties | 1 - webapps/docs/changelog.xml | 6 +++ 9 files changed, 51 insertions(+), 32 deletions(-) diff --git a/java/org/apache/catalina/authenticator/LocalStrings.properties b/java/org/apache/catalina/authenticator/LocalStrings.properties index 62825a2578..3736c0b345 100644 --- a/java/org/apache/catalina/authenticator/LocalStrings.properties +++ b/java/org/apache/catalina/authenticator/LocalStrings.properties @@ -89,6 +89,6 @@ spnegoAuthenticator.serviceLoginFail=Unable to login as the service principal spnegoAuthenticator.ticketValidateFail=Failed to validate client supplied ticket sslAuthenticatorValve.authFailed=Authentication with the provided certificates failed -sslAuthenticatorValve.http2=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support HTTP/2. Use of CLIENT-CERT authentication is not compatible with the use of HTTP/2. +sslAuthenticatorValve.http2=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support HTTP/2. Use of CLIENT-CERT authentication is not compatible with the use of HTTP/2 unless certificateVerification is set to required. sslAuthenticatorValve.noCertificates=No certificates are included with this request -sslAuthenticatorValve.tls13=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support TLS 1.3 using JSSE. Use of CLIENT-CERT authentication is not compatible with the use of TLS 1.3 and JSSE. +sslAuthenticatorValve.tls13=The context [{0}] in virtual host [{1}] is configured to use CLIENT-CERT authentication and [{2}] is configured to support TLS 1.3 using JSSE. Use of CLIENT-CERT authentication is not compatible with the use of TLS 1.3 and JSSE unless certificateVerification is set to required. diff --git a/java/org/apache/catalina/authenticator/SSLAuthenticator.java b/java/org/apache/catalina/authenticator/SSLAuthenticator.java index d7207510d8..c4d7012563 100644 --- a/java/org/apache/catalina/authenticator/SSLAuthenticator.java +++ b/java/org/apache/catalina/authenticator/SSLAuthenticator.java @@ -37,6 +37,7 @@ import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.Constants; import org.apache.tomcat.util.net.SSLHostConfig; +import org.apache.tomcat.util.net.SSLHostConfig.CertificateVerification; /** * An <b>Authenticator</b> and <b>Valve</b> implementation of authentication that utilizes SSL certificates to identify @@ -154,10 +155,10 @@ public class SSLAuthenticator extends AuthenticatorBase { * and an Engine but test at each stage to be safe. */ Container container = getContainer(); - if (!(container instanceof Context context2)) { + if (!(container instanceof Context context)) { return; } - container = context2.getParent(); + container = context.getParent(); if (!(container instanceof Host host)) { return; } @@ -169,28 +170,51 @@ public class SSLAuthenticator extends AuthenticatorBase { Connector[] connectors = engine.getService().findConnectors(); for (Connector connector : connectors) { - // First check for upgrade - UpgradeProtocol[] upgradeProtocols = connector.findUpgradeProtocols(); - for (UpgradeProtocol upgradeProtocol : upgradeProtocols) { - if ("h2".equals(upgradeProtocol.getAlpnName())) { - log.warn(sm.getString("sslAuthenticatorValve.http2", context2.getName(), host.getName(), connector)); + /* + * There are two underlying issues here. + * + * 1. JSSE does not implement post-handshake authentication (PHA) for TLS 1.3. That means CLIENT-CERT + * authentication will only work if the virtual host requires a certificate OR the client never requests a + * protected resource. + * + * 2. HTTP/2 does not permit re-negotiation nor PHA. That means CLIENT-CERT authentication will only work if + * the virtual host requires a certificate OR the client never requests a protected resource. + * + * We can't rely on the client never requesting a protected resource but we can check if all the virtual + * hosts are configured to require a certificate. + */ + boolean allHostsRequireCertificate = true; + for (SSLHostConfig sslHostConfig : connector.findSslHostConfigs()) { + if (sslHostConfig.getCertificateVerification() != CertificateVerification.REQUIRED) { + allHostsRequireCertificate = false; break; } } - // Then check for TLS 1.3 - SSLHostConfig[] sslHostConfigs = connector.findSslHostConfigs(); - for (SSLHostConfig sslHostConfig : sslHostConfigs) { - if (!sslHostConfig.isTls13RenegotiationAvailable()) { - String[] enabledProtocols = sslHostConfig.getEnabledProtocols(); - if (enabledProtocols == null) { - // Possibly boundOnInit is used, so use the less accurate protocols - enabledProtocols = sslHostConfig.getProtocols().toArray(new String[0]); + // Only need to check for use of HTTP/2 or TLS 1.3 if one or more hosts doesn't require a certificate + if (!allHostsRequireCertificate) { + // Check if the Connector is configured to support upgrade to HTTP/2 + UpgradeProtocol[] upgradeProtocols = connector.findUpgradeProtocols(); + for (UpgradeProtocol upgradeProtocol : upgradeProtocols) { + if ("h2".equals(upgradeProtocol.getAlpnName())) { + log.warn(sm.getString("sslAuthenticatorValve.http2", context.getName(), host.getName(), connector)); + break; } - for (String enabledProtocol : enabledProtocols) { - if (Constants.SSL_PROTO_TLSv1_3.equals(enabledProtocol)) { - log.warn(sm.getString("sslAuthenticatorValve.tls13", context2.getName(), host.getName(), - connector)); + } + + // Check if any of the virtual hosts support TLS 1.3 without supporting PHA + for (SSLHostConfig sslHostConfig : connector.findSslHostConfigs()) { + if (!sslHostConfig.isTls13RenegotiationAvailable()) { + String[] enabledProtocols = sslHostConfig.getEnabledProtocols(); + if (enabledProtocols == null) { + // Possibly boundOnInit is used, so use the less accurate protocols + enabledProtocols = sslHostConfig.getProtocols().toArray(new String[0]); + } + for (String enabledProtocol : enabledProtocols) { + if (Constants.SSL_PROTO_TLSv1_3.equals(enabledProtocol)) { + log.warn(sm.getString("sslAuthenticatorValve.tls13", context.getName(), host.getName(), + connector)); + } } } } diff --git a/java/org/apache/tomcat/util/net/AbstractEndpoint.java b/java/org/apache/tomcat/util/net/AbstractEndpoint.java index ef2b9dc1b7..14e789294e 100644 --- a/java/org/apache/tomcat/util/net/AbstractEndpoint.java +++ b/java/org/apache/tomcat/util/net/AbstractEndpoint.java @@ -396,12 +396,6 @@ public abstract class AbstractEndpoint<S, U> { */ protected void createSSLContext(SSLHostConfig sslHostConfig) throws IllegalArgumentException { - // HTTP/2 does not permit optional certificate authentication with any - // version of TLS. - if (sslHostConfig.getCertificateVerification().isOptional() && negotiableProtocols.contains("h2")) { - getLog().warn(sm.getString("sslHostConfig.certificateVerificationWithHttp2", sslHostConfig.getHostName())); - } - boolean firstCertificate = true; for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) { SSLUtil sslUtil = sslImplementation.getSSLUtil(certificate); diff --git a/java/org/apache/tomcat/util/net/LocalStrings.properties b/java/org/apache/tomcat/util/net/LocalStrings.properties index befebc70ec..1fbdfad007 100644 --- a/java/org/apache/tomcat/util/net/LocalStrings.properties +++ b/java/org/apache/tomcat/util/net/LocalStrings.properties @@ -145,7 +145,6 @@ socketWrapper.writeTimeout=Write timeout sslHostConfig.certificate.notype=Multiple certificates were specified and at least one is missing the required attribute type sslHostConfig.certificateVerificationInvalid=The certificate verification value [{0}] is not recognised -sslHostConfig.certificateVerificationWithHttp2=The TLS virtual host [{0}] is configured for optional certificate verification and the enclosing connector is configured to support upgrade to h2. HTTP/2 over TLS does not permit optional certificate verification. sslHostConfig.fileNotFound=Configured file [{0}] does not exist sslHostConfig.invalid_truststore_password=The provided trust store password could not be used to unlock and/or validate the trust store. Retrying to access the trust store with a null password which will skip validation. sslHostConfig.mismatch=The property [{0}] was set on the SSLHostConfig named [{1}] and is for the [{2}] configuration syntax but the SSLHostConfig is being used with the [{3}] configuration syntax diff --git a/java/org/apache/tomcat/util/net/LocalStrings_fr.properties b/java/org/apache/tomcat/util/net/LocalStrings_fr.properties index e8127fa44f..33bfbb254a 100644 --- a/java/org/apache/tomcat/util/net/LocalStrings_fr.properties +++ b/java/org/apache/tomcat/util/net/LocalStrings_fr.properties @@ -148,7 +148,6 @@ socketWrapper.writeTimeout=Timeout en écriture sslHostConfig.certificate.notype=Plusieurs certificats ont été spécifiés et au moins un n'a pas d'attribut type sslHostConfig.certificateVerificationInvalid=La valeur de vérification de certificat [{0}] n''est pas reconnue -sslHostConfig.certificateVerificationWithHttp2=L''hôte virtuel TLS [{0}] est configuré avec la validation optionelle du certificat, et le connecteur qui l''utilise est configuré pour supporter l''upgrade vers h2. HTTP/2 sur TLS ne permet pas la validation optionelle du certificat. sslHostConfig.fileNotFound=Le fichier [{0}] configuré n''existe pas. sslHostConfig.invalid_truststore_password=Le mot de passe de la base de confiance n'a pas pu être utilisé pour déverrouiller et ou valider celle ci, nouvel essai en utilisant un mot de passe null pour passer la validation sslHostConfig.mismatch=La propriété [{0}] a été fixée sur le SSLHostConfig nommé [{1}] et est pour la syntaxe de configuration [{2}] mais le SSLHostConfig est utilisé avec la syntaxe de configuration [{3}] diff --git a/java/org/apache/tomcat/util/net/LocalStrings_ja.properties b/java/org/apache/tomcat/util/net/LocalStrings_ja.properties index 2e196d6e62..c9475c54ac 100644 --- a/java/org/apache/tomcat/util/net/LocalStrings_ja.properties +++ b/java/org/apache/tomcat/util/net/LocalStrings_ja.properties @@ -148,7 +148,6 @@ socketWrapper.writeTimeout=書き込みタイムアウト sslHostConfig.certificate.notype=指定された複数の証明書の中に、少なくとも1つは必須要素の存在しない証明書が含まれています。 sslHostConfig.certificateVerificationInvalid=証明書検証値[{0}]が認識されません -sslHostConfig.certificateVerificationWithHttp2=TLS仮想ホスト[{0}]はオプションの証明書検証用に構成されており、コネクタはh2へのアップグレードをサポートするように構成されています。 HTTP/2 over TLSでは、オプションの証明書検証は許可されていません。 sslHostConfig.fileNotFound=構成ファイル[{0}]は存在しません sslHostConfig.invalid_truststore_password=提供されたトラストストアパスワードは、トラストストアのロック解除および検証に使用できませんでした。 検証をスキップするnullパスワードでトラストストアにアクセスしようとしました。 sslHostConfig.mismatch=[{0}] プロパティは [{1}] という名前のSSLHostConfigで設定され、[{2}] 構成構文用ですが、[{3}] 構成構文でSSLHostConfigが使用されています diff --git a/java/org/apache/tomcat/util/net/LocalStrings_ko.properties b/java/org/apache/tomcat/util/net/LocalStrings_ko.properties index 1131eb91a5..b76790a130 100644 --- a/java/org/apache/tomcat/util/net/LocalStrings_ko.properties +++ b/java/org/apache/tomcat/util/net/LocalStrings_ko.properties @@ -138,7 +138,6 @@ socketWrapper.writeTimeout=쓰기 타임아웃 sslHostConfig.certificate.notype=여러 개의 인증서들이 지정되었는데, 적어도 하나의 인증서에 필수 속성 타입이 없습니다. sslHostConfig.certificateVerificationInvalid=인증서 검증 값 [{0}]은(는) 인식되지 않는 값입니다. -sslHostConfig.certificateVerificationWithHttp2=TLS 가상 호스트 [{0}](은)는 선택적 인증서 확인을 하도록 설정되었고, 내부에 정의된 커넥터는 HTTP/2로 업그레이드를 지원하도록 설정되었습니다. TLS 기반의 HTTP/2는 선택적 인증서 확인을 허용하지 않습니다. sslHostConfig.fileNotFound=설정된 파일 [{0}]이(가) 존재하지 않습니다. sslHostConfig.invalid_truststore_password=Trust 저장소를 잠금을 풀거나 유효한지 확인하는 용도로, 제공된 Trust 저장소 비밀번호를 사용할 수 없었습니다. 널 비밀번호를 사용하여, 해당 Trust 저장소에 대한 접근을 다시 시도합니다. 이는 유효한지 확인하는 작업을 건너뛸 것입니다. sslHostConfig.mismatch=[{1}](이)라는 이름의 SSLHostConfig에 프로퍼티 [{0}]이(가) 설정되었는데, 이 프로퍼티는 [{2}] 설정 문법을 위한 것이나, 해당 SSLHostConfig은 [{3}] 설정 문법으로 사용되고 있습니다. diff --git a/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties b/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties index 5094653425..41e0583bab 100644 --- a/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties +++ b/java/org/apache/tomcat/util/net/LocalStrings_zh_CN.properties @@ -140,7 +140,6 @@ socketWrapper.writeTimeout=写入超时 sslHostConfig.certificate.notype=指定了多个证书,并且至少有一个证书缺少必需的属性类型 sslHostConfig.certificateVerificationInvalid=证书认证值[{0}]未识别 -sslHostConfig.certificateVerificationWithHttp2=TLS虚拟主机[{0}]被配置为可选的证书验证,包围的连接器被配置为支持升级到h2。HTTP/2 over TLS不允许可选的证书验证。 sslHostConfig.fileNotFound=配置文件 [{0}] 不存在 sslHostConfig.invalid_truststore_password=提供的信任存储密码无法用于解锁和/或验证信任存储。正在重试使用空密码访问信任存储,该密码将跳过验证。 sslHostConfig.mismatch=属性[{0}]是在名为[{1}]的SSLHostConfig 上设置的,用于[{2}]配置语法,但SSLHostConfig 正与[{3}]配置语法一起使用 diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index f6a20caad3..c5b998df1c 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -218,6 +218,12 @@ Fix JMX value for <code>keepAliveCount</code> on the endpoint. Also add the value of <code>useVirtualThreads</code> in JMX. (remm) </fix> + <fix> + <bug>69728</bug>: Remove incorrect warning when HTTP/2 is used with + optional certificate verification and improve the warnings when a web + application tries to use CLIENT-CERT with either HTTP/2 or a JSSE + implementation of TLS 1.3. (markt) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org