This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new 15a76156ce Fix OpenSSL with OpenSSL trust, server cert in a keys tore
and a CRL
15a76156ce is described below
commit 15a76156ced9f6a6306ef7d6f2e343034231a2de
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Aug 12 21:48:27 2026 +0100
Fix OpenSSL with OpenSSL trust, server cert in a keys tore and a CRL
---
.../tomcat/util/net/openssl/OpenSSLContext.java | 8 +-
.../util/net/openssl/panama/OpenSSLContext.java | 55 ++++-----
.../org/apache/tomcat/util/net/TestCrlSupport.java | 124 +++++++++++++++++++++
test/org/apache/tomcat/util/net/TesterSupport.java | 36 ++++--
test/org/apache/tomcat/util/net/empty-crl.pem | 18 +++
test/org/apache/tomcat/util/net/populated-crl.pem | 20 ++++
webapps/docs/changelog.xml | 4 +
7 files changed, 225 insertions(+), 40 deletions(-)
diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
b/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
index 5061088b9b..18102be9c7 100644
--- a/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
+++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
@@ -537,10 +537,6 @@ public class OpenSSLContext implements
org.apache.tomcat.util.net.SSLContext {
// Set certificate chain file
SSLContext.setCertificateChainFile(state.ctx,
SSLHostConfig.adjustRelativePath(certificate.getCertificateChainFile()), false);
- // Set revocation
- SSLContext.setCARevocation(state.ctx,
-
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile()),
-
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath()));
} else {
String alias = certificate.getCertificateKeyAlias();
X509KeyManager x509KeyManager =
certificate.getCertificateKeyManager();
@@ -561,6 +557,10 @@ public class OpenSSLContext implements
org.apache.tomcat.util.net.SSLContext {
SSLContext.addChainCertificateRaw(state.ctx,
chain[i].getEncoded());
}
}
+ // Set revocation
+ SSLContext.setCARevocation(state.ctx,
+
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile()),
+
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath()));
}
diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
index 976985472c..48e4296632 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
@@ -1199,31 +1199,6 @@ public class OpenSSLContext implements
org.apache.tomcat.util.net.SSLContext {
BIO_free(certificateChainBIO);
}
}
- // Set revocation
- MemorySegment certificateStore =
SSL_CTX_get_cert_store(state.sslCtx);
- if (sslHostConfig.getCertificateRevocationListFile() != null) {
- MemorySegment x509Lookup =
X509_STORE_add_lookup(certificateStore, X509_LOOKUP_file());
- var certificateRevocationListFileNative =
localArena.allocateFrom(
-
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile()));
- if (X509_LOOKUP_load_file(x509Lookup,
certificateRevocationListFileNative,
- X509_FILETYPE_PEM()) <= 0) {
- throw new IllegalArgumentException(sm.getString(
-
"openssl.errorLoadingCertificateRevocationListWithError",
-
sslHostConfig.getCertificateRevocationListFile(),
OpenSSLLibrary.getLastError()));
- }
- }
- if (sslHostConfig.getCertificateRevocationListPath() != null) {
- MemorySegment x509Lookup =
X509_STORE_add_lookup(certificateStore, X509_LOOKUP_hash_dir());
- var certificateRevocationListPathNative =
localArena.allocateFrom(
-
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath()));
- if (X509_LOOKUP_add_dir(x509Lookup,
certificateRevocationListPathNative,
- X509_FILETYPE_PEM()) <= 0) {
- throw new IllegalArgumentException(sm.getString(
-
"openssl.errorLoadingCertificateRevocationListWithError",
-
sslHostConfig.getCertificateRevocationListPath(),
OpenSSLLibrary.getLastError()));
- }
- }
- X509_STORE_set_flags(certificateStore, X509_V_FLAG_CRL_CHECK()
| X509_V_FLAG_CRL_CHECK_ALL());
} finally {
BIO_free(certificateBIO);
}
@@ -1318,6 +1293,36 @@ public class OpenSSLContext implements
org.apache.tomcat.util.net.SSLContext {
BIO_free(keyBIO);
}
}
+ // Set revocation
+ boolean crlPresent = false;
+ MemorySegment certificateStore = SSL_CTX_get_cert_store(state.sslCtx);
+ if (sslHostConfig.getCertificateRevocationListFile() != null) {
+ MemorySegment x509Lookup = X509_STORE_add_lookup(certificateStore,
X509_LOOKUP_file());
+ var certificateRevocationListFileNative = localArena.allocateFrom(
+
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListFile()));
+ if (X509_LOOKUP_load_file(x509Lookup,
certificateRevocationListFileNative,
+ X509_FILETYPE_PEM()) <= 0) {
+ throw new IllegalArgumentException(sm.getString(
+
"openssl.errorLoadingCertificateRevocationListWithError",
+ sslHostConfig.getCertificateRevocationListFile(),
OpenSSLLibrary.getLastError()));
+ }
+ crlPresent = true;
+ }
+ if (sslHostConfig.getCertificateRevocationListPath() != null) {
+ MemorySegment x509Lookup = X509_STORE_add_lookup(certificateStore,
X509_LOOKUP_hash_dir());
+ var certificateRevocationListPathNative = localArena.allocateFrom(
+
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateRevocationListPath()));
+ if (X509_LOOKUP_add_dir(x509Lookup,
certificateRevocationListPathNative,
+ X509_FILETYPE_PEM()) <= 0) {
+ throw new IllegalArgumentException(sm.getString(
+
"openssl.errorLoadingCertificateRevocationListWithError",
+ sslHostConfig.getCertificateRevocationListPath(),
OpenSSLLibrary.getLastError()));
+ }
+ crlPresent = true;
+ }
+ if (crlPresent) {
+ X509_STORE_set_flags(certificateStore, X509_V_FLAG_CRL_CHECK() |
X509_V_FLAG_CRL_CHECK_ALL());
+ }
return true;
}
diff --git a/test/org/apache/tomcat/util/net/TestCrlSupport.java
b/test/org/apache/tomcat/util/net/TestCrlSupport.java
new file mode 100644
index 0000000000..aee75538af
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/TestCrlSupport.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.net;
+
+import java.io.File;
+import java.net.SocketException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+
+@RunWith(Parameterized.class)
+public class TestCrlSupport extends TomcatBaseTest {
+
+ @Parameters(name = "{0} with OpenSSL trust {2}, revoked cert {4}, CRL {5}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+ for (Boolean clientCertificateIsRevoked : booleans) {
+ for (Boolean crlIsPopulated : booleans) {
+ parameterSets.add(new Object[] { "JSSE", Boolean.FALSE,
Boolean.FALSE,
+ "org.apache.tomcat.util.net.jsse.JSSEImplementation",
clientCertificateIsRevoked, crlIsPopulated});
+ parameterSets.add(new Object[] { "OpenSSL", Boolean.TRUE,
Boolean.TRUE,
+
"org.apache.tomcat.util.net.openssl.OpenSSLImplementation",
clientCertificateIsRevoked, crlIsPopulated });
+ parameterSets.add(new Object[] { "OpenSSL", Boolean.TRUE,
Boolean.FALSE,
+
"org.apache.tomcat.util.net.openssl.OpenSSLImplementation",
clientCertificateIsRevoked, crlIsPopulated });
+ parameterSets.add(new Object[] { "OpenSSL-FFM", Boolean.TRUE,
Boolean.TRUE,
+
"org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation",
clientCertificateIsRevoked, crlIsPopulated });
+ parameterSets.add(new Object[] { "OpenSSL-FFM", Boolean.TRUE,
Boolean.FALSE,
+
"org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation",
clientCertificateIsRevoked, crlIsPopulated });
+ }
+ }
+
+ return parameterSets;
+ }
+
+ @Parameter(0)
+ public String connectorName;
+
+ @Parameter(1)
+ public boolean useOpenSSL;
+
+ @Parameter(2)
+ public boolean useOpenSSLTrust;
+
+ @Parameter(3)
+ public String sslImplementationName;
+
+ @Parameter(4)
+ public boolean clientCertificateIsRevoked;
+
+ @Parameter(5)
+ public boolean crlIsPopulated;
+
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ Tomcat tomcat = getTomcatInstance();
+ TesterSupport.configureSSLImplementation(tomcat,
sslImplementationName, useOpenSSL);
+ TesterSupport.configureClientCertContext(tomcat, useOpenSSLTrust,
TesterSupport.CLIENT_JKS, TesterSupport.CLIENT_CRL_JKS);
+ // Configure the CRL
+ if (crlIsPopulated) {
+
tomcat.getConnector().findSslHostConfigs()[0].setCertificateRevocationListFile(
+ new File(TesterSupport.POPULATED_CRL).getAbsolutePath());
+ } else {
+
tomcat.getConnector().findSslHostConfigs()[0].setCertificateRevocationListFile(
+ new File(TesterSupport.EMPTY_CRL).getAbsolutePath());
+ }
+ }
+
+
+ @Test
+ public void testCrlClient() throws Exception {
+ if (clientCertificateIsRevoked) {
+ TesterSupport.configureClientSsl(false,
TesterSupport.CLIENT_CRL_JKS);
+ } else {
+ TesterSupport.configureClientSsl(false, TesterSupport.CLIENT_JKS);
+ }
+
+ getTomcatInstance().start();
+
+ // Protected resource
+ String body;
+ try {
+ ByteChunk res = getUrl("https://localhost:" + getPort() +
"/protected");
+ body = res.toString();
+ } catch (SSLHandshakeException | SocketException e) {
+ // May be observed when client certificate is rejected
+ body = "FAILED";
+ }
+
+ if (!clientCertificateIsRevoked || !crlIsPopulated) {
+ Assert.assertEquals("OK-" + TesterSupport.ROLE, body);
+ } else {
+ Assert.assertFalse(body, body.startsWith("OK-"));
+ }
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/TesterSupport.java
b/test/org/apache/tomcat/util/net/TesterSupport.java
index 63ce9a3585..9de53b213b 100644
--- a/test/org/apache/tomcat/util/net/TesterSupport.java
+++ b/test/org/apache/tomcat/util/net/TesterSupport.java
@@ -105,6 +105,8 @@ public final class TesterSupport {
public static final String LOCALHOST_CRL_RSA_JKS = SSL_DIR +
"localhost-crl-rsa.jks";
public static final String CLIENT_CRL_JKS = SSL_DIR + "user2-crl.jks";
public static final String CLIENT_CRL_LONG_JKS = SSL_DIR +
"user3-crl-long.jks";
+ public static final String EMPTY_CRL = SSL_DIR + "empty-crl.pem";
+ public static final String POPULATED_CRL = SSL_DIR + "populated-crl.pem";
public static final boolean TLSV13_AVAILABLE;
public static final String ROLE = "testrole";
@@ -318,7 +320,11 @@ public final class TesterSupport {
}
public static void configureClientCertContext(Tomcat tomcat) {
- initSsl(tomcat);
+ configureClientCertContext(tomcat, false, CLIENT_JKS);
+ }
+
+ public static void configureClientCertContext(Tomcat tomcat, boolean
useOpenSSLTrust, String... keyStores) {
+ initSsl(tomcat, useOpenSSLTrust);
/* When running on Java 11, TLSv1.3 is enabled by default. The JSSE
* implementation of TLSv1.3 does not support
@@ -356,17 +362,25 @@ public final class TesterSupport {
throw new RuntimeException(ex);
}
- String cn = "NOTFOUND";
- try {
- KeyStore ks = getKeyStore(CLIENT_JKS);
- X509Certificate cert =
(X509Certificate)ks.getCertificate(CLIENT_ALIAS);
- cn = cert.getSubjectX500Principal().toString();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
+ // Add the user for each certificate in each key store to the realm
and assign each user the standard role
+ for (String keyStore : keyStores) {
+ String cn = "NOTFOUND";
+ try {
+ KeyStore ks = getKeyStore(keyStore);
+ Enumeration<String> aliases = ks.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ X509Certificate cert =
(X509Certificate)ks.getCertificate(alias);
+ cn = cert.getSubjectX500Principal().toString();
+
+ realm.addUser(cn, "not used");
+ realm.addUserRole(cn, ROLE);
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
- realm.addUser(cn, "not used");
- realm.addUserRole(cn, ROLE);
+ }
ctx.setRealm(realm);
// Configure the authenticator
diff --git a/test/org/apache/tomcat/util/net/empty-crl.pem
b/test/org/apache/tomcat/util/net/empty-crl.pem
new file mode 100644
index 0000000000..e4b6c011d8
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/empty-crl.pem
@@ -0,0 +1,18 @@
+-----BEGIN X509 CRL-----
+MIIC7zCB2AIBATANBgkqhkiG9w0BAQUFADCBlDELMAkGA1UEBhMCVVMxCzAJBgNV
+BAgTAkRFMRMwEQYDVQQHEwpXaWxtaW5ndG9uMScwJQYDVQQKEx5UaGUgQXBhY2hl
+IFNvZnR3YXJlIEZvdW5kYXRpb24xGjAYBgNVBAsTEUFwYWNoZSBUb21jYXQgUE1D
+MR4wHAYDVQQDExVBcGFjaGUgVG9tY2F0IFRlc3QgQ0EXDTI2MDgxMjEzMTkyMloX
+DTI4MDgxMTEzMTkyMlqgDzANMAsGA1UdFAQEAgIQADANBgkqhkiG9w0BAQUFAAOC
+AgEAHh0y6uXKHskWDcgUa0/7qA7xI9qArf3Zgxjdzp02Ys8drYh1mq9SDAfLYwNP
+nPFF0B+dTGVWo0/WzllykMZkhS3qbOu1EhBEobxBidc2yatqsGMqmT6otxr1JtFh
+LRdPWo4/g5SrU1lu4rH7L+7tI2aDBogqYbO4uW09fZ3MM1MCMxEt+KUTs40WKmAy
+QrC9b2hjviVKl+3WwmZRRx1aVewercmCwNeZXh9B8qLvB/Py8dJEymZhaBKy2Rs/
+1uN0P5vJ57eAUoNe9XRZm41opqDGyPdRX5QgFjlIhmaTgQ9HxVLCwRHTD7mPEjBZ
+OUDPPvzBmWux4TJRGo/H/xlIEzdEiY8xnM0xJSMPHHw4nWwVo7ggMfvGYol2ojA4
+CDYEw03T85RwCeerYeVLz9b8PCkcDHjqlJzkEu0NtK2XibWiSECh5psK30KYzH0G
+c6QLY20tDbwl6mJxBB6nvDdPNF8a6qq2+AyygZt2lKzxEWRbvL4mqukW9neFOc5m
+LLT0SGLvULEAG3WEOGPL2zgCsNKrfu54PbjaOBzCFFlZc2Sizi2+Mlik0ThSGjaa
+AXlviXQ6mQ0bLHAelkXBRKGT/gNbDRfvx1BSFL6hYXWRyM97KW5S9P4iFne/Biwu
+ovgWmYNtZ0N6vv1SBxaEVtO7Yy5bHEFpoZsme9Hl04/Ezr0=
+-----END X509 CRL-----
diff --git a/test/org/apache/tomcat/util/net/populated-crl.pem
b/test/org/apache/tomcat/util/net/populated-crl.pem
new file mode 100644
index 0000000000..a007012f9a
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/populated-crl.pem
@@ -0,0 +1,20 @@
+-----BEGIN X509 CRL-----
+MIIDMTCCARkCAQEwDQYJKoZIhvcNAQEFBQAwgZQxCzAJBgNVBAYTAlVTMQswCQYD
+VQQIEwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhlIEFwYWNo
+ZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9tY2F0IFBN
+QzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNhdCBUZXN0IENBFw0yNjA4MTIxMzE5MjJa
+Fw0yODA4MTExMzE5MjJaMD8wEwICEAEXDTI2MDgxMjEzMTkyMlowEwICEAMXDTI2
+MDgxMjEzMTkyMlowEwICEAYXDTI2MDgxMjEzMTkyMlqgDzANMAsGA1UdFAQEAgIQ
+ATANBgkqhkiG9w0BAQUFAAOCAgEAFiLND1ZwZ0qIuuIA9NxHjkoqULtnbUxTAQzH
+ZYD3/TYtM1mrvs/dXZh8MYfW/dMtdEq4lV79BoJVYFGVzNhweO5xet66BHwAXehp
+6GFDu7n88Q/oSfvv14WtlyNrpJObYHRJPXDzEqSdamQSQKzn+Yjf3VQATKZFG73P
+ltxDTYfT0OGjrwcpyqqVtteJ11FOgrJ2LORFp+i2eQxWsjxZJjcL+xZmM49sVWns
+7KK1FKmy3QdDCezG2tgAym+j/wqTj1el1aLBLt7Wn6w1W6XSM7TEtHCuonpYnbhy
+GZuDcGYlcco9xZZi8Xu6Kvx2usJsm6odQI4GIa4a/4p2JMz3vGsiuOfEreVz8z6e
+Y1RR9rlzrhbW9cgX3cROoUarai3Gpj97DFMQxtBYkOGlpm5K50NROPNNYk/UBUCD
+LgxukOIqQd8DYx843GoJfqKXl/AlO4YwqWLtwWRSuNZ7QUmG6S4Af4BUBuZ3yEze
+oihjTcIt46ICjrUZZ1ATZpf0lUGi048Cp4ww60pNJZ/PbO5JcpEShUKCsKr5z8XK
+K7sRWnhzEi9HCNLUqjXZ/xeI4UAK86wT24n+dZbLZ51Nsj4KIsReQubX/ucZ3WrL
+U869KvDeSkMWtbm9iRX/wYJQvDePtNy6uxEr01C2F/WHtWgH2wAma73F4qxbndy3
+hAYNg4M=
+-----END X509 CRL-----
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index a4da61fc1f..e873955495 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -243,6 +243,10 @@
Small per performance optimisation. Don't waste cycles swallowing an
AJP
response body when the connection is going to be closed. (markt)
</fix>
+ <fix>
+ Fix OpenSSL support for CRLs when using OpenSSL trust with the server
+ key held in a Java key store. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]