tomcat9/rhel-150720.patch

3959 lines
176 KiB
Diff

diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java b/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java
index 1ad7d3dc84..749813bc38 100644
--- a/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java
+++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLStatus.java
@@ -38,9 +38,10 @@ public class OpenSSLStatus {
private static volatile boolean useOpenSSL = true;
private static volatile boolean instanceCreated = false;
private static volatile long version = 0;
+ private static volatile int majorVersion = 0;
+ private static volatile int minorVersion = 0;
private static volatile Name name = Name.UNKNOWN;
-
public static boolean isLibraryInitialized() {
return libraryInitialized;
}
@@ -95,6 +96,34 @@ public class OpenSSLStatus {
OpenSSLStatus.version = version;
}
+ /**
+ * @return the majorVersion
+ */
+ public static int getMajorVersion() {
+ return majorVersion;
+ }
+
+ /**
+ * @param majorVersion the majorVersion to set
+ */
+ public static void setMajorVersion(int majorVersion) {
+ OpenSSLStatus.majorVersion = majorVersion;
+ }
+
+ /**
+ * @return the minorVersion
+ */
+ public static int getMinorVersion() {
+ return minorVersion;
+ }
+
+ /**
+ * @param minorVersion the minorVersion to set
+ */
+ public static void setMinorVersion(int minorVersion) {
+ OpenSSLStatus.minorVersion = minorVersion;
+ }
+
/**
* @return the library name
*/
@@ -116,4 +145,18 @@ public class OpenSSLStatus {
return Name.OPENSSL3.equals(name);
}
+ /**
+ * @return true if running with BoringSSL
+ */
+ public static boolean isBoringSSL() {
+ return Name.BORINGSSL.equals(name);
+ }
+
+ /**
+ * @return true if running with LibreSSL < 3.5
+ */
+ public static boolean isLibreSSLPre35() {
+ return Name.LIBRESSL.equals(name) && ((majorVersion == 3 && minorVersion < 5) || majorVersion < 3);
+ }
+
}
diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
index bfb9b6f20a..960fa0459f 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLEngine.java
@@ -59,6 +59,7 @@ import org.apache.tomcat.util.buf.Asn1Parser;
import org.apache.tomcat.util.http.Method;
import org.apache.tomcat.util.net.Constants;
import org.apache.tomcat.util.net.SSLUtil;
+import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser;
import org.apache.tomcat.util.openssl.SSL_CTX_set_verify$callback;
import org.apache.tomcat.util.openssl.SSL_set_info_callback$cb;
@@ -68,7 +69,7 @@ import org.apache.tomcat.util.openssl.openssl_h_Compatibility;
import org.apache.tomcat.util.res.StringManager;
/**
- * Implements a {@link SSLEngine} using <a href="https://www.openssl.org/docs/crypto/BIO_s_bio.html#EXAMPLE">OpenSSL BIO
+ * Implements a {@link SSLEngine} using <a href="https://docs.openssl.org/master/man3/BIO_s_bio/#examples">OpenSSL BIO
* abstractions</a>.
*/
public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolInfo {
@@ -137,7 +138,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
private volatile boolean destroyed;
// Use an invalid cipherSuite until the handshake is completed
- // See https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLEngine.html#getSession()
+ // See https://docs.oracle.com/en/java/javase/21/docs/api/java.base/javax/net/ssl/SSLEngine.html#getSession()
private volatile String version;
private volatile String cipher;
private volatile String applicationProtocol;
@@ -1076,7 +1077,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
case NONE -> SSL_VERIFY_NONE();
case REQUIRE -> SSL_VERIFY_FAIL_IF_NO_PEER_CERT();
case OPTIONAL ->
- certificateVerificationOptionalNoCA ? OpenSSLContext.OPTIONAL_NO_CA : SSL_VERIFY_PEER();
+ certificateVerificationOptionalNoCA ? OpenSSLContext.OPTIONAL_NO_CA : SSL_VERIFY_PEER();
};
// Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback
int value = switch (mode) {
@@ -1138,6 +1139,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
ok = 1;
openssl_h_Compatibility.SSL_set_verify_result(state.ssl, X509_V_OK());
}
+ if (ok == 0 && errnum == X509_V_ERR_UNABLE_TO_GET_CRL()) {
+ ok = 1;
+ }
/*
* Expired certificates vs. "expired" CRLs: by default, OpenSSL turns X509_V_ERR_CRL_HAS_EXPIRED into a
* "certificate_expired(45)" SSL alert, but that's not really the message we should convey to the peer (at
@@ -1168,9 +1172,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
if (ocspResponse == V_OCSP_CERTSTATUS_REVOKED()) {
ok = 0;
errnum = X509_STORE_CTX_get_error(x509ctx);
+ X509_STORE_CTX_set_error(x509ctx, X509_V_ERR_CERT_REVOKED());
} else if (ocspResponse == V_OCSP_CERTSTATUS_UNKNOWN()) {
errnum = X509_STORE_CTX_get_error(x509ctx);
- if (errnum <= 0) {
+ if (errnum != X509_V_ERR_UNABLE_TO_GET_CRL() && (errnum == X509_V_ERR_APPLICATION_VERIFICATION() || errnum != 0)) {
ok = 0;
}
}
@@ -1196,46 +1201,53 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
// don't do OCSP checking for valid self-issued certs
X509_STORE_CTX_set_error(x509ctx, X509_V_OK());
} else {
- // If we can't get the issuer, we cannot perform OCSP verification
- MemorySegment issuer = X509_STORE_CTX_get0_current_issuer(x509ctx);
- if (!MemorySegment.NULL.equals(issuer)) {
- // sslutils.c ssl_ocsp_request(x509, issuer, x509ctx);
- int nid = X509_get_ext_by_NID(x509, NID_info_access(), -1);
- if (nid >= 0) {
- try (var localArenal = Arena.ofConfined()) {
- MemorySegment ext = X509_get_ext(x509, nid);
- MemorySegment os = X509_EXTENSION_get_data(ext);
- int length = ASN1_STRING_length(os);
- MemorySegment data = ASN1_STRING_get0_data(os);
- // ocsp_urls = decode_OCSP_url(os);
- byte[] asn1String =
- data.reinterpret(length, localArenal, null).toArray(ValueLayout.JAVA_BYTE);
- Asn1Parser parser = new Asn1Parser(asn1String);
- // Parse the byte sequence
- ArrayList<String> urls = new ArrayList<>();
- try {
- parseOCSPURLs(parser, urls);
- } catch (Exception e) {
- log.error(sm.getString("engine.ocspParseError"), e);
- }
- if (!urls.isEmpty()) {
- // Use OpenSSL to build OCSP request
- for (String urlString : urls) {
- try {
- URL url = (new URI(urlString)).toURL();
- ocspResponse = processOCSPRequest(url, issuer, x509, x509ctx, localArenal);
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("engine.ocspResponse", urlString,
- Integer.toString(ocspResponse)));
+ try (var localArena = Arena.ofConfined()) {
+ // If we can't get the issuer, we cannot perform OCSP verification
+ MemorySegment x509IssuerPointer = localArena.allocateFrom(ValueLayout.ADDRESS, MemorySegment.NULL);
+ int res = X509_STORE_CTX_get1_issuer(x509IssuerPointer, x509ctx, x509);
+ if (res > 0) {
+ MemorySegment issuer = MemorySegment.NULL;
+ try {
+ issuer = x509IssuerPointer.get(ValueLayout.ADDRESS, 0);
+ // sslutils.c ssl_ocsp_request(x509, issuer, x509ctx);
+ int nid = X509_get_ext_by_NID(x509, NID_info_access(), -1);
+ if (nid >= 0) {
+ MemorySegment ext = X509_get_ext(x509, nid);
+ MemorySegment os = X509_EXTENSION_get_data(ext);
+ int length = ASN1_STRING_length(os);
+ MemorySegment data = ASN1_STRING_get0_data(os);
+ // ocsp_urls = decode_OCSP_url(os);
+ byte[] asn1String =
+ data.reinterpret(length, localArena, null).toArray(ValueLayout.JAVA_BYTE);
+ Asn1Parser parser = new Asn1Parser(asn1String);
+ // Parse the byte sequence
+ ArrayList<String> urls = new ArrayList<>();
+ try {
+ parseOCSPURLs(parser, urls);
+ } catch (Exception e) {
+ log.error(sm.getString("engine.ocspParseError"), e);
+ }
+ if (!urls.isEmpty()) {
+ // Use OpenSSL to build OCSP request
+ for (String urlString : urls) {
+ try {
+ URL url = (new URI(urlString)).toURL();
+ ocspResponse = processOCSPRequest(url, issuer, x509, x509ctx, localArena);
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("engine.ocspResponse", urlString,
+ Integer.toString(ocspResponse)));
+ }
+ } catch (MalformedURLException | URISyntaxException e) {
+ log.warn(sm.getString("engine.invalidOCSPURL", urlString));
+ }
+ if (ocspResponse != V_OCSP_CERTSTATUS_UNKNOWN()) {
+ break;
}
- } catch (MalformedURLException | URISyntaxException e) {
- log.warn(sm.getString("engine.invalidOCSPURL", urlString));
- }
- if (ocspResponse != V_OCSP_CERTSTATUS_UNKNOWN()) {
- break;
}
}
}
+ } finally {
+ X509_free(issuer);
}
}
}
@@ -1275,6 +1287,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
private static int processOCSPRequest(URL url, MemorySegment issuer, MemorySegment x509,
MemorySegment /* X509_STORE_CTX */ x509ctx, Arena localArena) {
+ if (OpenSSLStatus.Name.BORINGSSL.equals(OpenSSLStatus.getName())) {
+ return V_OCSP_CERTSTATUS_UNKNOWN();
+ }
MemorySegment ocspRequest = MemorySegment.NULL;
MemorySegment ocspResponse = MemorySegment.NULL;
MemorySegment id;
@@ -1574,7 +1589,7 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn
}
private Principal principal(Certificate[] certs) {
- return ((java.security.cert.X509Certificate) certs[0]).getIssuerX500Principal();
+ return ((java.security.cert.X509Certificate) certs[0]).getSubjectX500Principal();
}
@Override
diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java
index 7272db9cf2..c1bb2cb664 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLLibrary.java
@@ -178,6 +178,8 @@ public class OpenSSLLibrary {
initLibrary();
OpenSSLStatus.setVersion(OpenSSL_version_num());
+ OpenSSLStatus.setMajorVersion(openssl_h_Compatibility.MAJOR);
+ OpenSSLStatus.setMinorVersion(openssl_h_Compatibility.MINOR);
if (openssl_h_Compatibility.OPENSSL3) {
OpenSSLStatus.setName(OpenSSLStatus.Name.OPENSSL3);
} else if (openssl_h_Compatibility.OPENSSL) {
diff --git a/java/org/apache/tomcat/util/openssl/openssl_h.java b/java/org/apache/tomcat/util/openssl/openssl_h.java
index 0c2465b633..cbd8a5a0d4 100644
--- a/java/org/apache/tomcat/util/openssl/openssl_h.java
+++ b/java/org/apache/tomcat/util/openssl/openssl_h.java
@@ -196,6 +196,16 @@ public class openssl_h {
return X509_V_OK;
}
+ private static final int X509_V_ERR_UNABLE_TO_GET_CRL = (int) 3L;
+
+ /**
+ * {@snippet lang = c : * #define X509_V_ERR_UNABLE_TO_GET_CRL 3
+ * }
+ */
+ public static int X509_V_ERR_UNABLE_TO_GET_CRL() {
+ return X509_V_ERR_UNABLE_TO_GET_CRL;
+ }
+
private static final int X509_V_ERR_CRL_HAS_EXPIRED = (int) 12L;
/**
@@ -246,6 +256,16 @@ public class openssl_h {
return X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
}
+ private static final int X509_V_ERR_CERT_REVOKED = (int) 23L;
+
+ /**
+ * {@snippet lang = c : * #define X509_V_ERR_CERT_REVOKED 23
+ * }
+ */
+ public static int X509_V_ERR_CERT_REVOKED() {
+ return X509_V_ERR_CERT_REVOKED;
+ }
+
private static final int X509_V_ERR_CERT_UNTRUSTED = (int) 27L;
/**
@@ -266,6 +286,46 @@ public class openssl_h {
return X509_V_ERR_APPLICATION_VERIFICATION;
}
+ private static final int X509_V_ERR_OCSP_RESP_INVALID = (int) 96L;
+
+ /**
+ * {@snippet lang = c : * #define X509_V_ERR_OCSP_RESP_INVALID 96
+ * }
+ */
+ public static int X509_V_ERR_OCSP_RESP_INVALID() {
+ return X509_V_ERR_OCSP_RESP_INVALID;
+ }
+
+ private static final int X509_V_ERR_OCSP_SIGNATURE_FAILURE = (int) 97L;
+
+ /**
+ * {@snippet lang = c : * #define X509_V_ERR_OCSP_SIGNATURE_FAILURE 97
+ * }
+ */
+ public static int X509_V_ERR_OCSP_SIGNATURE_FAILURE() {
+ return X509_V_ERR_OCSP_SIGNATURE_FAILURE;
+ }
+
+ private static final int X509_V_ERR_OCSP_NOT_YET_VALID = (int) 98L;
+
+ /**
+ * {@snippet lang = c : * #define X509_V_ERR_OCSP_NOT_YET_VALID 98
+ * }
+ */
+ public static int X509_V_ERR_OCSP_NOT_YET_VALID() {
+ return X509_V_ERR_OCSP_NOT_YET_VALID;
+ }
+
+ private static final int X509_V_ERR_OCSP_HAS_EXPIRED = (int) 99L;
+
+ /**
+ * {@snippet lang = c : * #define X509_V_ERR_OCSP_HAS_EXPIRED 99
+ * }
+ */
+ public static int X509_V_ERR_OCSP_HAS_EXPIRED() {
+ return X509_V_ERR_OCSP_HAS_EXPIRED;
+ }
+
private static final int X509_V_FLAG_CRL_CHECK = (int) 4L;
/**
@@ -3071,6 +3131,66 @@ public class openssl_h {
}
}
+ private static class X509_STORE_CTX_get0_store {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ openssl_h.C_POINTER,
+ openssl_h.C_POINTER
+ );
+
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get0_store");
+
+ public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ }
+
+ /**
+ * Function descriptor for:
+ * {@snippet lang=c :
+ * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
+ * }
+ */
+ public static FunctionDescriptor X509_STORE_CTX_get0_store$descriptor() {
+ return X509_STORE_CTX_get0_store.DESC;
+ }
+
+ /**
+ * Downcall method handle for:
+ * {@snippet lang=c :
+ * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
+ * }
+ */
+ public static MethodHandle X509_STORE_CTX_get0_store$handle() {
+ return X509_STORE_CTX_get0_store.HANDLE;
+ }
+
+ /**
+ * Address for:
+ * {@snippet lang=c :
+ * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
+ * }
+ */
+ public static MemorySegment X509_STORE_CTX_get0_store$address() {
+ return X509_STORE_CTX_get0_store.ADDR;
+ }
+
+ /**
+ * {@snippet lang=c :
+ * X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
+ * }
+ */
+ public static MemorySegment X509_STORE_CTX_get0_store(MemorySegment ctx) {
+ var mh$ = X509_STORE_CTX_get0_store.HANDLE;
+ try {
+ if (TRACE_DOWNCALLS) {
+ traceDowncall("X509_STORE_CTX_get0_store", ctx);
+ }
+ return (MemorySegment)mh$.invokeExact(ctx);
+ } catch (Error | RuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+
private static class X509_STORE_CTX_get0_untrusted {
public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER);
@@ -3584,52 +3704,52 @@ public class openssl_h {
}
}
- private static class X509_STORE_CTX_get0_current_issuer {
- public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER);
+ private static class X509_STORE_CTX_get1_issuer {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_INT, openssl_h.C_POINTER, openssl_h.C_POINTER, openssl_h.C_POINTER);
- public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get0_current_issuer");
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("X509_STORE_CTX_get1_issuer");
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
}
/**
* Function descriptor for:
- * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx)
+ * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
* }
*/
- public static FunctionDescriptor X509_STORE_CTX_get0_current_issuer$descriptor() {
- return X509_STORE_CTX_get0_current_issuer.DESC;
+ public static FunctionDescriptor X509_STORE_CTX_get1_issuer$descriptor() {
+ return X509_STORE_CTX_get1_issuer.DESC;
}
/**
* Downcall method handle for:
- * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx)
+ * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
* }
*/
- public static MethodHandle X509_STORE_CTX_get0_current_issuer$handle() {
- return X509_STORE_CTX_get0_current_issuer.HANDLE;
+ public static MethodHandle X509_STORE_CTX_get1_issuer$handle() {
+ return X509_STORE_CTX_get1_issuer.HANDLE;
}
/**
* Address for:
- * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx)
+ * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
* }
*/
- public static MemorySegment X509_STORE_CTX_get0_current_issuer$address() {
- return X509_STORE_CTX_get0_current_issuer.ADDR;
+ public static MemorySegment X509_STORE_CTX_get1_issuer$address() {
+ return X509_STORE_CTX_get1_issuer.ADDR;
}
/**
- * {@snippet lang = c : * X509 *X509_STORE_CTX_get0_current_issuer(const X509_STORE_CTX *ctx)
+ * {@snippet lang = c : * int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
* }
*/
- public static MemorySegment X509_STORE_CTX_get0_current_issuer(MemorySegment ctx) {
- var mh$ = X509_STORE_CTX_get0_current_issuer.HANDLE;
+ public static int X509_STORE_CTX_get1_issuer(MemorySegment issuer, MemorySegment ctx, MemorySegment x) {
+ var mh$ = X509_STORE_CTX_get1_issuer.HANDLE;
try {
if (TRACE_DOWNCALLS) {
- traceDowncall("X509_STORE_CTX_get0_current_issuer", ctx);
+ traceDowncall("X509_STORE_CTX_get1_issuer", issuer, ctx, x);
}
- return (MemorySegment) mh$.invokeExact(ctx);
+ return (int) mh$.invokeExact(issuer, ctx, x);
} catch (Throwable ex$) {
throw new AssertionError("should not reach here", ex$);
}
@@ -8771,6 +8891,315 @@ public class openssl_h {
}
}
+ private static class OCSP_resp_get0_certs {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ openssl_h.C_POINTER,
+ openssl_h.C_POINTER
+ );
+
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_resp_get0_certs");
+
+ public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ }
+
+ /**
+ * Function descriptor for:
+ * {@snippet lang=c :
+ * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
+ * }
+ */
+ public static FunctionDescriptor OCSP_resp_get0_certs$descriptor() {
+ return OCSP_resp_get0_certs.DESC;
+ }
+
+ /**
+ * Downcall method handle for:
+ * {@snippet lang=c :
+ * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
+ * }
+ */
+ public static MethodHandle OCSP_resp_get0_certs$handle() {
+ return OCSP_resp_get0_certs.HANDLE;
+ }
+
+ /**
+ * Address for:
+ * {@snippet lang=c :
+ * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
+ * }
+ */
+ public static MemorySegment OCSP_resp_get0_certs$address() {
+ return OCSP_resp_get0_certs.ADDR;
+ }
+
+ /**
+ * {@snippet lang=c :
+ * const struct stack_st_X509 *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs)
+ * }
+ */
+ public static MemorySegment OCSP_resp_get0_certs(MemorySegment bs) {
+ var mh$ = OCSP_resp_get0_certs.HANDLE;
+ try {
+ if (TRACE_DOWNCALLS) {
+ traceDowncall("OCSP_resp_get0_certs", bs);
+ }
+ return (MemorySegment)mh$.invokeExact(bs);
+ } catch (Error | RuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+
+ private static class OCSP_basic_verify {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ openssl_h.C_INT,
+ openssl_h.C_POINTER,
+ openssl_h.C_POINTER,
+ openssl_h.C_POINTER,
+ openssl_h.C_LONG
+ );
+
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_basic_verify");
+
+ public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ }
+
+ /**
+ * Function descriptor for:
+ * {@snippet lang=c :
+ * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags)
+ * }
+ */
+ public static FunctionDescriptor OCSP_basic_verify$descriptor() {
+ return OCSP_basic_verify.DESC;
+ }
+
+ /**
+ * Downcall method handle for:
+ * {@snippet lang=c :
+ * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags)
+ * }
+ */
+ public static MethodHandle OCSP_basic_verify$handle() {
+ return OCSP_basic_verify.HANDLE;
+ }
+
+ /**
+ * Address for:
+ * {@snippet lang=c :
+ * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags)
+ * }
+ */
+ public static MemorySegment OCSP_basic_verify$address() {
+ return OCSP_basic_verify.ADDR;
+ }
+
+ /**
+ * {@snippet lang=c :
+ * int OCSP_basic_verify(OCSP_BASICRESP *bs, struct stack_st_X509 *certs, X509_STORE *st, unsigned long flags)
+ * }
+ */
+ public static int OCSP_basic_verify(MemorySegment bs, MemorySegment certs, MemorySegment st, long flags) {
+ var mh$ = OCSP_basic_verify.HANDLE;
+ try {
+ if (TRACE_DOWNCALLS) {
+ traceDowncall("OCSP_basic_verify", bs, certs, st, flags);
+ }
+ return (int)mh$.invokeExact(bs, certs, st, flags);
+ } catch (Error | RuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+
+ private static class OCSP_check_validity {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ openssl_h.C_INT,
+ openssl_h.C_POINTER,
+ openssl_h.C_POINTER,
+ openssl_h.C_LONG,
+ openssl_h.C_LONG
+ );
+
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_check_validity");
+
+ public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ }
+
+ /**
+ * Function descriptor for:
+ * {@snippet lang=c :
+ * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec)
+ * }
+ */
+ public static FunctionDescriptor OCSP_check_validity$descriptor() {
+ return OCSP_check_validity.DESC;
+ }
+
+ /**
+ * Downcall method handle for:
+ * {@snippet lang=c :
+ * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec)
+ * }
+ */
+ public static MethodHandle OCSP_check_validity$handle() {
+ return OCSP_check_validity.HANDLE;
+ }
+
+ /**
+ * Address for:
+ * {@snippet lang=c :
+ * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec)
+ * }
+ */
+ public static MemorySegment OCSP_check_validity$address() {
+ return OCSP_check_validity.ADDR;
+ }
+
+ /**
+ * {@snippet lang=c :
+ * int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec)
+ * }
+ */
+ public static int OCSP_check_validity(MemorySegment thisupd, MemorySegment nextupd, long sec, long maxsec) {
+ var mh$ = OCSP_check_validity.HANDLE;
+ try {
+ if (TRACE_DOWNCALLS) {
+ traceDowncall("OCSP_check_validity", thisupd, nextupd, sec, maxsec);
+ }
+ return (int)mh$.invokeExact(thisupd, nextupd, sec, maxsec);
+ } catch (Error | RuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+
+ private static class OCSP_request_add1_nonce {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ openssl_h.C_INT,
+ openssl_h.C_POINTER,
+ ValueLayout.JAVA_CHAR,
+ openssl_h.C_INT
+ );
+
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_request_add1_nonce");
+
+ public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ }
+
+ /**
+ * Function descriptor for:
+ * {@snippet lang=c :
+ * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
+ * }
+ */
+ public static FunctionDescriptor OCSP_request_add1_nonce$descriptor() {
+ return OCSP_request_add1_nonce.DESC;
+ }
+
+ /**
+ * Downcall method handle for:
+ * {@snippet lang=c :
+ * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
+ * }
+ */
+ public static MethodHandle OCSP_request_add1_nonce$handle() {
+ return OCSP_request_add1_nonce.HANDLE;
+ }
+
+ /**
+ * Address for:
+ * {@snippet lang=c :
+ * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
+ * }
+ */
+ public static MemorySegment OCSP_request_add1_nonce$address() {
+ return OCSP_request_add1_nonce.ADDR;
+ }
+
+ /**
+ * {@snippet lang=c :
+ * int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
+ * }
+ */
+ public static int OCSP_request_add1_nonce(MemorySegment req, char val, int len) {
+ var mh$ = OCSP_request_add1_nonce.HANDLE;
+ try {
+ if (TRACE_DOWNCALLS) {
+ traceDowncall("OCSP_request_add1_nonce", req, val, len);
+ }
+ return (int)mh$.invokeExact(req, val, len);
+ } catch (Error | RuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+
+ private static class OCSP_check_nonce {
+ public static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ openssl_h.C_INT,
+ openssl_h.C_POINTER,
+ openssl_h.C_POINTER
+ );
+
+ public static final MemorySegment ADDR = openssl_h.findOrThrow("OCSP_check_nonce");
+
+ public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ }
+
+ /**
+ * Function descriptor for:
+ * {@snippet lang=c :
+ * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
+ * }
+ */
+ public static FunctionDescriptor OCSP_check_nonce$descriptor() {
+ return OCSP_check_nonce.DESC;
+ }
+
+ /**
+ * Downcall method handle for:
+ * {@snippet lang=c :
+ * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
+ * }
+ */
+ public static MethodHandle OCSP_check_nonce$handle() {
+ return OCSP_check_nonce.HANDLE;
+ }
+
+ /**
+ * Address for:
+ * {@snippet lang=c :
+ * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
+ * }
+ */
+ public static MemorySegment OCSP_check_nonce$address() {
+ return OCSP_check_nonce.ADDR;
+ }
+
+ /**
+ * {@snippet lang=c :
+ * int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
+ * }
+ */
+ public static int OCSP_check_nonce(MemorySegment req, MemorySegment bs) {
+ var mh$ = OCSP_check_nonce.HANDLE;
+ try {
+ if (TRACE_DOWNCALLS) {
+ traceDowncall("OCSP_check_nonce", req, bs);
+ }
+ return (int)mh$.invokeExact(req, bs);
+ } catch (Error | RuntimeException ex) {
+ throw ex;
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+
private static class OCSP_cert_to_id {
public static final FunctionDescriptor DESC = FunctionDescriptor.of(openssl_h.C_POINTER, openssl_h.C_POINTER,
openssl_h.C_POINTER, openssl_h.C_POINTER);
diff --git a/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java b/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java
index 5f513182d1..e75528da40 100644
--- a/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java
+++ b/java/org/apache/tomcat/util/openssl/openssl_h_Compatibility.java
@@ -33,16 +33,45 @@ public class openssl_h_Compatibility {
public static final boolean OPENSSL3;
public static final boolean BORINGSSL;
public static final boolean LIBRESSL;
+
+ public static final int MAJOR;
+ public static final int MINOR;
+
static {
String versionString = OpenSSL_version(0).getString(0);
OPENSSL = versionString.contains("OpenSSL");
OPENSSL3 = OPENSSL && OpenSSL_version_num() >= 0x3000000fL;
BORINGSSL = versionString.contains("BoringSSL");
LIBRESSL = versionString.contains("LibreSSL");
+ int majorVersion = 0;
+ int minorVersion = 0;
+ try {
+ String[] blocks = versionString.split("\\s");
+ if (blocks.length >= 2) {
+ versionString = blocks[1];
+ }
+ String[] versionNumberStrings = versionString.split("\\.");
+ if (versionNumberStrings.length >= 2) {
+ majorVersion = Integer.parseInt(versionNumberStrings[0]);
+ minorVersion = Integer.parseInt(versionNumberStrings[1]);
+ }
+ } catch (Exception e) {
+ // Ignore, default to 0
+ } finally {
+ MAJOR = majorVersion;
+ MINOR = minorVersion;
+ }
+ }
+
+ public static boolean isLibreSSLPre35() {
+ return LIBRESSL && ((MAJOR == 3 && MINOR < 5) || MAJOR < 3);
}
// OpenSSL 1.1 FIPS_mode
public static int FIPS_mode() {
+ if (isLibreSSLPre35()) {
+ return 0;
+ }
class Holder {
static final String NAME = "FIPS_mode";
static final FunctionDescriptor DESC = FunctionDescriptor.of(JAVA_INT);
@@ -61,6 +90,9 @@ public class openssl_h_Compatibility {
// OpenSSL 1.1 FIPS_mode_set
public static int FIPS_mode_set(int r) {
+ if (isLibreSSLPre35()) {
+ return 0;
+ }
class Holder {
static final String NAME = "FIPS_mode_set";
static final FunctionDescriptor DESC = FunctionDescriptor.of(JAVA_INT, JAVA_INT);
diff --git a/res/openssl/openssl-tomcat.conf b/res/openssl/openssl-tomcat.conf
index 892f3b84af..337e7a831e 100644
--- a/res/openssl/openssl-tomcat.conf
+++ b/res/openssl/openssl-tomcat.conf
@@ -16,7 +16,7 @@
-t org.apache.tomcat.util.openssl
-lssl
# Configure include path
--I /usr/lib/gcc/x86_64-redhat-linux/14/include
+-I /usr/lib/gcc/x86_64-redhat-linux/15/include
--output ../../java
#### Extracted from: /usr/include/openssl/asn1.h
@@ -108,12 +108,17 @@
--include-function OCSP_REQUEST_free # header: /usr/include/openssl/ocsp.h
--include-function OCSP_REQUEST_new # header: /usr/include/openssl/ocsp.h
--include-function OCSP_RESPONSE_free # header: /usr/include/openssl/ocsp.h
+--include-function OCSP_basic_verify # header: /usr/include/openssl/ocsp.h
--include-function OCSP_cert_to_id # header: /usr/include/openssl/ocsp.h
+--include-function OCSP_check_validity # header: /usr/include/openssl/ocsp.h
+--include-function OCSP_check_nonce # header: /usr/include/openssl/ocsp.h
--include-function OCSP_request_add0_id # header: /usr/include/openssl/ocsp.h
+--include-function OCSP_request_add1_nonce # header: /usr/include/openssl/ocsp.h
--include-function OCSP_response_get1_basic # header: /usr/include/openssl/ocsp.h
--include-function OCSP_response_status # header: /usr/include/openssl/ocsp.h
--include-function OCSP_resp_find # header: /usr/include/openssl/ocsp.h
--include-function OCSP_resp_get0 # header: /usr/include/openssl/ocsp.h
+--include-function OCSP_resp_get0_certs # header: /usr/include/openssl/ocsp.h
--include-function OCSP_single_get0_status # header: /usr/include/openssl/ocsp.h
--include-function d2i_OCSP_RESPONSE # header: /usr/include/openssl/ocsp.h
--include-function i2d_OCSP_REQUEST # header: /usr/include/openssl/ocsp.h
@@ -342,20 +347,26 @@
--include-function X509_STORE_CTX_get_error # header: /usr/include/openssl/x509_vfy.h
--include-function X509_STORE_CTX_get_error_depth # header: /usr/include/openssl/x509_vfy.h
--include-function X509_STORE_CTX_get_ex_data # header: /usr/include/openssl/x509_vfy.h
---include-function X509_STORE_CTX_get0_current_issuer # header: /usr/include/openssl/x509_vfy.h
+--include-function X509_STORE_CTX_get0_store # header: /usr/include/openssl/x509_vfy.h
--include-function X509_STORE_CTX_get0_untrusted # header: /usr/include/openssl/x509_vfy.h
+--include-function X509_STORE_CTX_get1_issuer # header: /usr/include/openssl/x509_vfy.h
--include-function X509_STORE_CTX_set_error # header: /usr/include/openssl/x509_vfy.h
--include-function X509_STORE_set_flags # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_L_ADD_DIR # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_L_FILE_LOAD # header: /usr/include/openssl/x509_vfy.h
---include-constant X509_V_ERR_APPLICATION_VERIFICATION # header: /usr/include/openssl/x509_vfy.h
---include-constant X509_V_ERR_CERT_UNTRUSTED # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_OK # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_UNABLE_TO_GET_CRL # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_ERR_CRL_HAS_EXPIRED # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_CERT_REVOKED # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_CERT_UNTRUSTED # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_APPLICATION_VERIFICATION # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_OCSP_RESP_INVALID # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_OCSP_SIGNATURE_FAILURE # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_OCSP_NOT_YET_VALID # header: /usr/include/openssl/x509_vfy.h
+--include-constant X509_V_ERR_OCSP_HAS_EXPIRED # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_FLAG_CRL_CHECK # header: /usr/include/openssl/x509_vfy.h
--include-constant X509_V_FLAG_CRL_CHECK_ALL # header: /usr/include/openssl/x509_vfy.h
---include-constant X509_V_OK # header: /usr/include/openssl/x509_vfy.h
-
diff --git a/test/org/apache/tomcat/security/TestSecurity2017Ocsp.java b/test/org/apache/tomcat/security/TestSecurity2017Ocsp.java
new file mode 100644
index 0000000000..2187396985
--- /dev/null
+++ b/test/org/apache/tomcat/security/TestSecurity2017Ocsp.java
@@ -0,0 +1,107 @@
+/*
+ * 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.security;
+
+import java.io.IOException;
+
+import javax.net.ssl.SSLHandshakeException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.TesterSupport;
+import org.apache.tomcat.util.net.TesterSupport.SimpleServlet;
+import org.apache.tomcat.util.net.ocsp.OcspBaseTest;
+import org.apache.tomcat.util.net.ocsp.TesterOcspResponder;
+import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
+
+@RunWith(Parameterized.class)
+public class TestSecurity2017Ocsp extends OcspBaseTest {
+
+ private static TesterOcspResponder ocspResponder;
+
+ @BeforeClass
+ public static void startOcspResponder() {
+ ocspResponder = new TesterOcspResponder();
+ try {
+ ocspResponder.start();
+ } catch (IOException ioe) {
+ ocspResponder = null;
+ }
+ }
+
+
+ @AfterClass
+ public static void stopOcspResponder() {
+ if (ocspResponder != null) {
+ ocspResponder.stop();
+ ocspResponder = null;
+ }
+ }
+
+
+ /*
+ * In addition to testing Tomcat Native (where the CVE occurred), this also tests JSSE and OpenSSl via FFM.
+ */
+ @Test(expected=SSLHandshakeException.class)
+ public void testCVE_2017_15698() throws Exception {
+ if ("OpenSSL-FFM".equals(connectorName)) {
+ Assume.assumeFalse(OpenSSLStatus.isBoringSSL() || OpenSSLStatus.isLibreSSLPre35());
+ }
+ Assume.assumeNotNull(ocspResponder);
+
+ Tomcat tomcat = getTomcatInstance();
+
+ // No file system docBase required
+ Context ctx = tomcat.addContext("", null);
+
+ Tomcat.addServlet(ctx, "simple", new SimpleServlet());
+ ctx.addServletMappingDecoded("/simple", "simple");
+
+ // User a valid (non-revoked) server certificate
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_RSA_JKS, useOpenSSLTrust);
+
+ // Require client certificates and enable verification
+ SSLHostConfig sslHostConfig = tomcat.getConnector().findSslHostConfigs()[0];
+ sslHostConfig.setOcspEnabled(true);
+ sslHostConfig.setCertificateVerification("required");
+
+ // Configure a revoked client certificate with a long AIA
+ // Don't verify the server certificate
+ TesterSupport.configureClientSsl(false, TesterSupport.CLIENT_CRL_LONG_JKS);
+
+ // Disable soft-fail
+ sslHostConfig.setOcspSoftFail(false);
+
+ tomcat.start();
+
+ int rc = getUrl("https://localhost:" + getPort() + "/simple", new ByteChunk(), false);
+
+ // If the TLS handshake fails, the test won't get this far.
+ Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/TestSSLHostConfigCipher.java b/test/org/apache/tomcat/util/net/TestSSLHostConfigCipher.java
new file mode 100644
index 0000000000..75c8e90d00
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/TestSSLHostConfigCipher.java
@@ -0,0 +1,161 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.TesterServlet;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
+
+@RunWith(Parameterized.class)
+public class TestSSLHostConfigCipher extends TomcatBaseTest {
+
+ private static final String CIPHER_12_AVAILABLE = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
+ private static final String CIPHER_12_NOT_AVAILABLE = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
+ private static final String CIPHER_13_AVAILABLE = "TLS_AES_128_GCM_SHA256";
+ private static final String CIPHER_13_NOT_AVAILABLE = "TLS_AES_256_GCM_SHA384";
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+ parameterSets.add(new Object[] {
+ "JSSE", Boolean.FALSE, "org.apache.tomcat.util.net.jsse.JSSEImplementation"});
+ parameterSets.add(new Object[] {
+ "OpenSSL", Boolean.TRUE, "org.apache.tomcat.util.net.openssl.OpenSSLImplementation"});
+ parameterSets.add(new Object[] {
+ "OpenSSL-FFM", Boolean.TRUE, "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation"});
+
+ return parameterSets;
+ }
+
+ @Parameter(0)
+ public String connectorName;
+
+ @Parameter(1)
+ public boolean useOpenSSL;
+
+ @Parameter(2)
+ public String sslImplementationName;
+
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ Tomcat tomcat = getTomcatInstance();
+
+ // Server-side TLS configuration
+ TesterSupport.initSsl(tomcat);
+ TesterSupport.configureSSLImplementation(tomcat, sslImplementationName, useOpenSSL);
+
+ // Test specific, server-side cipher & protocol configuration
+ SSLHostConfig sslHostConfig = getSSLHostConfig();
+ sslHostConfig.setProtocols("+TLSv1.2+TLSv1.3");
+ sslHostConfig.setCiphers(CIPHER_12_AVAILABLE);
+ sslHostConfig.setCipherSuites(CIPHER_13_AVAILABLE);
+
+ // Simple webapp
+ Context ctxt = getProgrammaticRootContext();
+ Tomcat.addServlet(ctxt, "TesterServlet", new TesterServlet());
+ ctxt.addServletMappingDecoded("/*", "TesterServlet");
+ }
+
+
+ @Test
+ public void testTls12CipherAvailable() throws Exception {
+ if ("OpenSSL-FFM".equals(connectorName)) {
+ // The functionality works, but the two ciphers used are not available
+ Assume.assumeFalse(OpenSSLStatus.isBoringSSL());
+ }
+ // Client-side TLS configuration
+ TesterSupport.configureClientSsl(true, new String[] { CIPHER_12_AVAILABLE } );
+
+ doTest();
+ }
+
+
+ @Test(expected=SSLHandshakeException.class)
+ public void testTls12CipherNotAvailable() throws Exception {
+ if ("OpenSSL-FFM".equals(connectorName)) {
+ Assume.assumeFalse(OpenSSLStatus.isBoringSSL());
+ }
+ // Client-side TLS configuration
+ TesterSupport.configureClientSsl(true, new String[] { CIPHER_12_NOT_AVAILABLE } );
+
+ doTest();
+ }
+
+
+ @Test
+ public void testTls13CipherAvailable() throws Exception {
+ if ("OpenSSL-FFM".equals(connectorName)) {
+ Assume.assumeFalse(OpenSSLStatus.isBoringSSL());
+ }
+ // Client-side TLS configuration
+ TesterSupport.configureClientSsl(new String[] { CIPHER_13_AVAILABLE } );
+
+ doTest();
+ }
+
+
+ @Test(expected=SSLHandshakeException.class)
+ public void testTls13CipherNotAvailable() throws Exception {
+ if ("OpenSSL-FFM".equals(connectorName)) {
+ // The TLS 1.3 call might not be present
+ Assume.assumeFalse(OpenSSLStatus.isLibreSSLPre35());
+ Assume.assumeFalse(OpenSSLStatus.isBoringSSL());
+ }
+ // Client-side TLS configuration
+ TesterSupport.configureClientSsl(new String[] { CIPHER_13_NOT_AVAILABLE } );
+
+ doTest();
+ }
+
+
+ private void doTest() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ tomcat.start();
+
+ // Check a request can be made
+ ByteChunk res = getUrl("https://localhost:" + getPort() + "/");
+ Assert.assertEquals("OK", res.toString());
+ }
+
+
+ private SSLHostConfig getSSLHostConfig() {
+ Tomcat tomcat = getTomcatInstance();
+ Connector connector = tomcat.getConnector();
+ return connector.findSslHostConfigs()[0];
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/TestSsl.java b/test/org/apache/tomcat/util/net/TestSsl.java
index 5aeada0951..e21b61da93 100644
--- a/test/org/apache/tomcat/util/net/TestSsl.java
+++ b/test/org/apache/tomcat/util/net/TestSsl.java
@@ -251,7 +251,7 @@ public class TestSsl extends TomcatBaseTest {
Context ctxt = tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
ctxt.addApplicationListener(WsContextListener.class.getName());
- TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_KEYPASS_JKS,
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_KEYPASS_JKS, false,
TesterSupport.JKS_PASS, null, TesterSupport.JKS_KEY_PASS, null);
TesterSupport.configureSSLImplementation(tomcat, sslImplementationName, useOpenSSL);
@@ -274,7 +274,7 @@ public class TestSsl extends TomcatBaseTest {
Context ctxt = tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
ctxt.addApplicationListener(WsContextListener.class.getName());
- TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_KEYPASS_JKS,
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_KEYPASS_JKS, false,
null, TesterSupport.JKS_PASS_FILE, null, TesterSupport.JKS_KEY_PASS_FILE);
TesterSupport.configureSSLImplementation(tomcat, sslImplementationName, useOpenSSL);
diff --git a/test/org/apache/tomcat/util/net/TesterSupport.java b/test/org/apache/tomcat/util/net/TesterSupport.java
index 711cbadfc8..f9ff77499e 100644
--- a/test/org/apache/tomcat/util/net/TesterSupport.java
+++ b/test/org/apache/tomcat/util/net/TesterSupport.java
@@ -55,11 +55,11 @@ import org.apache.catalina.LifecycleListener;
import org.apache.catalina.authenticator.SSLAuthenticator;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.AprLifecycleListener;
-import org.apache.catalina.core.AprStatus;
import org.apache.catalina.core.OpenSSLLifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.TesterMapRealm;
import org.apache.catalina.startup.Tomcat;
+import org.apache.tomcat.jni.AprStatus;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
@@ -87,6 +87,9 @@ public final class TesterSupport {
public static final String LOCALHOST_EC_KEY_PEM = SSL_DIR + "localhost-ec-key.pem";
public static final String LOCALHOST_RSA_CERT_PEM = SSL_DIR + "localhost-rsa-cert.pem";
public static final String LOCALHOST_RSA_KEY_PEM = SSL_DIR + "localhost-rsa-key.pem";
+ public static final String DB_INDEX = SSL_DIR + "index.db";
+ public static final String OCSP_RESPONDER_RSA_CERT = SSL_DIR + "oscp-responder-rsa-cert.pem";
+ public static final String OCSP_RESPONDER_RSA_KEY = SSL_DIR + "oscp-responder-rsa-key.pem";
public static final boolean TLSV13_AVAILABLE;
public static final String ROLE = "testrole";
diff --git a/test/org/apache/tomcat/util/net/ca-cert.pem b/test/org/apache/tomcat/util/net/ca-cert.pem
index a5171578c1..e8e344f6b1 100644
--- a/test/org/apache/tomcat/util/net/ca-cert.pem
+++ b/test/org/apache/tomcat/util/net/ca-cert.pem
@@ -1,39 +1,39 @@
-----BEGIN CERTIFICATE-----
-MIIGvzCCBKegAwIBAgIUd8TEpsZJz7k3Ddw/oRfCrdlmRlcwDQYJKoZIhvcNAQEL
-BQAwgZMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNQTESMBAGA1UEBxMJV2FrZWZp
-ZWxkMScwJQYDVQQKEx5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xGjAY
-BgNVBAsTEUFwYWNoZSBUb21jYXQgUE1DMR4wHAYDVQQDExVBcGFjaGUgVG9tY2F0
-IFRlc3QgQ0EwHhcNMjUwODE3MDczNDAwWhcNMzUwODE1MDczNDAwWjCBkzELMAkG
-A1UEBhMCVVMxCzAJBgNVBAgTAk1BMRIwEAYDVQQHEwlXYWtlZmllbGQxJzAlBgNV
-BAoTHlRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbjEaMBgGA1UECxMRQXBh
-Y2hlIFRvbWNhdCBQTUMxHjAcBgNVBAMTFUFwYWNoZSBUb21jYXQgVGVzdCBDQTCC
-AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK6iRe7N1DwdOhFVwvTsB3Ed
-b1aZoylw9Zv+/JB1y6Fr4lcn1a753t+nGml67GeMOYMJk2jSSKYjudggQMx3dZV6
-fvlqgxmdDv6838ZlBfHNI/Pa/NNnIQRMCqzsOwbA7kIrbLmxYqXnv5ALP837EzsT
-A7I2Sa37vEjV5D7PaxQ0tEwrtpuibyeb/BV+0YBciKuJuZOq6SjGOvx2kQODvtUL
-L16p7qRyKXoW+euZismqavDMaV1SXDiOoeXUgmcnnPbzW/PNDRTlQt6K4GkMZdw4
-ehofzNjGKUFWk+5ENEE5xfXt7k2i5m0NMV6aQmrmezc8O35aMm+5g1IQssFuc/5L
-VXqa34xT0+wXpN2VVlnHEUP2E9ioDPKbAkbNMpsTyO5mu5CzAviJ+3IQuYs+Mix6
-1W1eJ+xQ1rLoJ8Ovmw3qv4ouuElZSqGKLaYfWPHhwuaV/fTxM5zzROV2+8j1x+tv
-n3r3nhwQT7t2VpS+dFsEB5U0c0eXl7rx+/CkqC29CG2DWtnbDV+hKQDLI1GRitRk
-p7jO1TH0TbD2oibc6RnIxw9MpiQFVqFHorVsKjr25pSvFjg1piU98p0mYZ+Kj8nZ
-YZ2our2driIdHJilvnMq9iYf1w2maflXjbKGZfu2MwnNTJbDwrFekT+oRUHbCXXX
-A2C4QvwJpnL7e7SJoKptAgMBAAGjggEHMIIBAzAdBgNVHQ4EFgQUAPKYTSEsADxA
-m4T03irwJu4yDp8wgdMGA1UdIwSByzCByIAUAPKYTSEsADxAm4T03irwJu4yDp+h
-gZmkgZYwgZMxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNQTESMBAGA1UEBxMJV2Fr
-ZWZpZWxkMScwJQYDVQQKEx5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24x
-GjAYBgNVBAsTEUFwYWNoZSBUb21jYXQgUE1DMR4wHAYDVQQDExVBcGFjaGUgVG9t
-Y2F0IFRlc3QgQ0GCFHfExKbGSc+5Nw3cP6EXwq3ZZkZXMAwGA1UdEwQFMAMBAf8w
-DQYJKoZIhvcNAQELBQADggIBAD839dBKpesTMCsiSrx1GXP6hbjXfNtKcskzlce3
-zGYDdIUFYit1gnuftvcl4u2hDCqodCn30LUE6wRQd3E2hiItOzlWufp4Rb6KZNie
-xp/A5ifu90qbJgEBlZScLDydcvkts1JTF4WuzQdKGY5MEh1OgNPj1M3cwg92UmGJ
-fGU57jnvpaJxS9IoJXIeIpmCr5dM1nk5NMY3Vt2Fg+vssHLS9t7glKQBlSa4+Ts6
-26xWINXQvJOomWWEDrs96pzZ2AHAJ+L/eExofAa6FyCXB1Oxd5M+U8A9DgehHVqi
-9r5/FMi3nS+v8UR0/4KpAUPjKAMCyZZbLFza0o0sHYWKehG/NdAUio4jKJKFCh/Z
-bQxGtPNW92N0FOQaWv3TUCbfv5bDtX6RC8b9D8u/bvUlYDYnT+c/2Z1RQHwxuoyF
-+/514VUZztpr/DBidlUlHBpqsAbRAHsoRVtn1xjTXraDRHewnvdA/AV1f+PuIKJf
-4DAnUCn7OKExUAFe87EZizdoaKu5lr0kNUhXdKKVgqGrSolHD67etEviHjAqEJdn
-mPO1aIeG3ukFGh3vp8/SFZk9J34qZ5jEl+QldIhAEFWHEX5wmZ74GatAUnOSmiHq
-xSQMB2ULGTOC1HMBUQMgelY4Qiwsa92pO1qySsZIL5npmBM9ok+o/jshCpoTCCin
-nzrk
+MIIGwjCCBKqgAwIBAgIUb23jgHGhJDQJaz0iHUfKwRV5z5kwDQYJKoZIhvcNAQEL
+BQAwgZQxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJERTETMBEGA1UEBxMKV2lsbWlu
+Z3RvbjEnMCUGA1UEChMeVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRow
+GAYDVQQLExFBcGFjaGUgVG9tY2F0IFBNQzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNh
+dCBUZXN0IENBMB4XDTI1MTIwNTE5MTIzOFoXDTM1MTIwMzE5MTIzOFowgZQxCzAJ
+BgNVBAYTAlVTMQswCQYDVQQIEwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUG
+A1UEChMeVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFB
+cGFjaGUgVG9tY2F0IFBNQzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNhdCBUZXN0IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqeIoIFXsR468dJCUYnNX
+E4DLI9J2jLIz/T1Jiq/tA9XCzA+XFqf3tlZdXLsfQhDLg0lf+wHqQfSvbQ0Gcatn
+Iw8BIvA7yq6PDKsO4cjQ2EdrkTn2JD7hJW5uUB9Je95TUUbKuNxOatihwS4DNU2J
+aoI2R2iUGasXsawVR+4qj1UJByawlsGHxFCqhVoaUKM/fKXK7LllbyHsRxuZTgab
+Spmvj2jcMxyeDN2ZjlBdsrSg+8FpYvnPKzHpdFiA6d4pxU6QJbeDeWPQ6B64yWi1
+eImFvilqZQoQ3RR/1gDjoFuLCdWK7mAvfaSXFzax1YK3D/MiCowTZ8M0iWmGqMg1
+QF6luhPL+5p8Q2/KooE3CZol0IpCUGr3cQs3FC1deL5ySNMYniXQMgxGqVE3x0i1
+Wlf5bItGY0Ha9vc+s4vmnRZxW4O+fXiuG9OXS5XjfWGAjzkJ6wXgFRJKbWDsSPkR
+Sw9j9SAsLE6cycY66eMl94QdOl6KRXVyeaLHJbRMBux7WvDXYS/eWKFHjmPYNKq6
+btIB7ELTqoMuwTAWj83bdkQgMac5fsTozKduM+C63sSg3mhmyy6yVgCX1eECqPNk
+N4K4oWdhQvKYvCp1n1EySAupZqrxudBLp/LDHRfGh7gfAZgP8hxRaoBqh2u0H8Fh
+RwSAML8zEeRH/si3G7LfXzECAwEAAaOCAQgwggEEMB0GA1UdDgQWBBSsh9yLPYrb
+iUh+bzscxnCSCRdv+TCB1AYDVR0jBIHMMIHJgBSsh9yLPYrbiUh+bzscxnCSCRdv
++aGBmqSBlzCBlDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkRFMRMwEQYDVQQHEwpX
+aWxtaW5ndG9uMScwJQYDVQQKEx5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRp
+b24xGjAYBgNVBAsTEUFwYWNoZSBUb21jYXQgUE1DMR4wHAYDVQQDExVBcGFjaGUg
+VG9tY2F0IFRlc3QgQ0GCFG9t44BxoSQ0CWs9Ih1HysEVec+ZMAwGA1UdEwQFMAMB
+Af8wDQYJKoZIhvcNAQELBQADggIBAA/DyqPhxRAluY1e1S9L2SkkrcYePjb033Wl
+ZmMVdXvf6LZtpjquNz81ThNoX5yfgV6CawDRw7COI4dAU3HOLVtOeKybm11Jq1BH
+AWmlZVQIOplgnitoEoZi8brxEpSgeyRGLKHYaW1YxshPRC5tVDKsbyYBtvmTaBtK
+dMirc36cEDkSfEe2dq+MkHgzHyyvySqTSlI/MH7CKQYBjGg2D+Gcle/BNrK02wef
+Rol9M3R3skDfV/P0NFmrfFi4B/cXt/EFxm1thMsQ6ofd0GUMGgv6fJKN1AVDihx6
+sQvbn712+54ilkcWMa3gW5L/BIxcDS+ZZiO/7T2tZ2d3tcz86gYbFkiQbWelnTmn
+FBSHno9PDgxRWZzqauKqlsczAsz5qLf8zF+GDubEcxvOgEf0wQ/vPwtSb2R4egb+
+3Vn+InqDy9/78ug497KV842jxQy2G6wZLND0q81H04t8NYQopbX4DI0hS5BJnKuV
+TM3rh4C/hNXs8kUpjusqnnV8nbBpab2R1YzEOefhgtTFdk/dHI7a5+6BKNSK55yn
+hDqgemD5p+5A6FLu3M0RDgbTZ1WdrtYDvQZrAMB10mrV0YDoDgnEzGYEc/PQwkYF
+gOeqb97mOdjf9YUJli4S4XLkZ5zn/IitEQRbnKen2VE60qIgW/UMYKTiwuSZtRaW
+gxBAeoi3
-----END CERTIFICATE-----
diff --git a/test/org/apache/tomcat/util/net/ca.jks b/test/org/apache/tomcat/util/net/ca.jks
index 615060a41f..d740b45124 100644
Binary files a/test/org/apache/tomcat/util/net/ca.jks and b/test/org/apache/tomcat/util/net/ca.jks differ
diff --git a/test/org/apache/tomcat/util/net/index.db b/test/org/apache/tomcat/util/net/index.db
new file mode 100644
index 0000000000..eb521a4242
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/index.db
@@ -0,0 +1,6 @@
+V 271205191323Z 1000 unknown /C=US/ST=DE/L=Wilmington/O=The Apache Software Foundation/OU=Apache Tomcat PMC/CN=localhost
+R 271205191327Z 251205192921Z 1001 unknown /C=US/ST=DE/L=Wilmington/O=The Apache Software Foundation/OU=Apache Tomcat PMC/CN=localhost
+V 271205191331Z 1002 unknown /C=US/ST=DE/L=Wilmington/O=The Apache Software Foundation/OU=Apache Tomcat PMC/CN=user1
+R 271205191335Z 251205192924Z 1003 unknown /C=US/ST=DE/L=Wilmington/O=The Apache Software Foundation/OU=Apache Tomcat PMC/CN=user2
+V 271205191540Z 1004 unknown /C=US/ST=DE/L=Wilmington/O=The Apache Software Foundation/OU=Apache Tomcat PMC/CN=localhost
+V 271205193355Z 1005 unknown /C=US/ST=DE/L=Wilmington/O=The Apache Software Foundation/OU=Apache Tomcat PMC/CN=OCSP Responder
diff --git a/test/org/apache/tomcat/util/net/index.db.attr b/test/org/apache/tomcat/util/net/index.db.attr
new file mode 100644
index 0000000000..3a7e39e6ee
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/index.db.attr
@@ -0,0 +1 @@
+unique_subject = no
diff --git a/test/org/apache/tomcat/util/net/localhost-crl-rsa-cert.pem b/test/org/apache/tomcat/util/net/localhost-crl-rsa-cert.pem
new file mode 100644
index 0000000000..7cfe515a25
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/localhost-crl-rsa-cert.pem
@@ -0,0 +1,108 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4097 (0x1001)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=Apache Tomcat Test CA
+ Validity
+ Not Before: Dec 5 19:13:27 2025 GMT
+ Not After : Dec 5 19:13:27 2027 GMT
+ Subject: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=localhost
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:aa:f2:ee:01:dd:21:fd:4b:f6:1e:9f:a1:a6:65:
+ 42:71:1c:db:cf:d7:47:6d:20:81:63:01:c7:6c:a2:
+ 5a:2e:17:0d:5d:d9:60:78:e5:d9:2a:9a:c0:2d:1c:
+ 2d:24:9d:b3:f6:26:a9:93:80:86:ad:0e:b0:06:4e:
+ 64:dc:11:da:70:a0:eb:47:aa:9d:39:3e:10:1c:b5:
+ fe:bc:ca:b2:5b:b8:3f:0c:a8:d4:b3:cb:9e:dd:f5:
+ 19:0e:dc:83:34:54:1d:17:b9:0d:2e:5d:4c:31:d7:
+ 9b:64:e9:40:89:de:77:75:ad:6e:86:3e:46:15:88:
+ ed:48:88:bb:a2:77:a5:05:4a:33:33:3e:bb:cb:7b:
+ f7:00:9b:eb:4e:2b:f5:4a:59:07:ff:18:5a:a1:49:
+ c2:25:48:21:03:55:64:da:d7:75:0f:e8:55:a8:61:
+ 39:ca:af:09:64:c2:c1:67:4b:ec:95:df:66:50:2d:
+ 39:45:d6:4c:8d:07:a8:3d:d1:fc:3c:46:76:92:2f:
+ 1a:b0:27:f0:0c:e8:19:2b:c6:b4:ad:62:c4:c6:21:
+ 7c:23:17:c4:13:a4:0e:7d:d3:05:3b:0b:43:ab:43:
+ 32:88:12:67:91:1b:01:e4:98:90:fc:67:88:d7:8b:
+ 8e:6b:f0:2a:59:62:d1:dc:24:38:28:8c:b7:e9:1b:
+ 7b:27
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ CB:A6:D2:18:07:CE:1A:E1:A7:F1:DC:FB:4C:A0:2C:85:AE:A5:40:A2
+ X509v3 Authority Key Identifier:
+ AC:87:DC:8B:3D:8A:DB:89:48:7E:6F:3B:1C:C6:70:92:09:17:6F:F9
+ Authority Information Access:
+ OCSP - URI:http://127.0.0.1:8888
+ X509v3 Subject Alternative Name:
+ DNS:localhost, IP Address:127.0.0.1
+ Signature Algorithm: sha256WithRSAEncryption
+ Signature Value:
+ 11:8b:03:aa:50:38:53:88:71:66:01:2f:d5:ab:82:49:ba:4d:
+ 45:5a:20:b6:f7:6e:1f:ca:77:ce:f7:93:85:ec:4d:da:ba:17:
+ 71:dc:30:7b:7f:55:35:07:88:a2:4a:47:06:9c:8c:1b:a0:33:
+ 5f:46:dd:c9:c6:f5:0e:27:48:6e:1f:0b:a0:e8:17:e4:16:3b:
+ d0:e3:0b:56:4f:5c:5f:b7:ae:fb:da:46:13:0b:fc:e8:3d:72:
+ 7e:ab:2d:19:4d:6c:09:8b:32:51:9a:7a:b8:49:70:7e:ce:ce:
+ 78:7f:95:9c:3a:8e:05:cc:29:af:0b:de:42:b8:cd:5e:56:a8:
+ 2f:78:ea:19:67:ed:a7:59:c0:ce:0a:4c:50:46:67:9a:6e:72:
+ 6b:fd:ae:00:a6:2f:9a:93:97:39:58:06:b4:05:a3:78:a9:b6:
+ df:66:22:0d:ae:5b:fd:e8:37:78:25:ac:2e:5a:a0:65:56:3e:
+ 83:04:bf:98:96:30:e1:11:f9:da:3b:6a:97:c4:77:28:d6:d7:
+ 46:27:a4:05:67:2e:f5:b8:d4:2e:c7:00:39:49:08:9b:a7:58:
+ 21:48:4c:fb:8f:dd:99:69:ea:59:bc:41:96:fd:1a:29:1a:fe:
+ 53:16:6a:2b:ac:92:51:18:ac:85:d9:7d:d5:77:ad:60:63:98:
+ 47:2c:52:ec:85:ef:ad:ff:b0:58:d7:12:7b:6f:70:2b:93:2a:
+ 92:f8:99:3c:15:7a:26:d4:79:16:05:93:9a:f4:01:bc:e6:9b:
+ a0:31:c3:d7:12:23:47:12:81:30:02:06:0c:13:ca:38:4c:63:
+ 96:2d:17:41:53:06:8b:c5:a3:8c:c3:96:b7:e2:b5:85:49:f7:
+ cd:46:01:21:ff:4f:d1:65:be:37:1b:84:7c:79:a6:e1:a8:a8:
+ d7:8c:63:34:35:45:d5:42:10:03:0f:60:fa:52:c5:39:03:26:
+ b1:41:6c:b9:53:3c:cf:8d:5d:fa:02:ac:0a:7a:04:27:28:df:
+ 33:b2:01:69:d8:3e:72:38:57:60:d3:a8:47:5f:98:55:8c:55:
+ 15:36:58:6e:c7:fc:65:a5:f8:c7:7f:1a:8c:de:b7:79:21:50:
+ 98:76:69:8a:b3:48:b0:1d:b2:91:fd:25:8f:bd:59:17:81:22:
+ bc:67:32:d5:fb:e6:c3:cd:3c:b3:79:6f:cd:1c:4a:b0:04:13:
+ 3c:af:80:53:7c:f0:c6:28:f3:37:3e:36:4d:65:ef:38:dc:00:
+ 5f:88:7e:04:34:75:66:fa:ba:6c:1f:76:b2:55:bb:21:60:fe:
+ b8:48:f8:ac:cb:6e:16:2f:75:87:44:d0:c3:6d:d5:6a:e1:e6:
+ b9:32:7e:39:a6:e6:d0:7f
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
+MQswCQYDVQQIEwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhl
+IEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9t
+Y2F0IFBNQzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNhdCBUZXN0IENBMB4XDTI1MTIw
+NTE5MTMyN1oXDTI3MTIwNTE5MTMyN1owgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQI
+EwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhlIEFwYWNoZSBT
+b2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9tY2F0IFBNQzES
+MBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAqvLuAd0h/Uv2Hp+hpmVCcRzbz9dHbSCBYwHHbKJaLhcNXdlgeOXZKprALRwt
+JJ2z9iapk4CGrQ6wBk5k3BHacKDrR6qdOT4QHLX+vMqyW7g/DKjUs8ue3fUZDtyD
+NFQdF7kNLl1MMdebZOlAid53da1uhj5GFYjtSIi7onelBUozMz67y3v3AJvrTiv1
+SlkH/xhaoUnCJUghA1Vk2td1D+hVqGE5yq8JZMLBZ0vsld9mUC05RdZMjQeoPdH8
+PEZ2ki8asCfwDOgZK8a0rWLExiF8IxfEE6QOfdMFOwtDq0MyiBJnkRsB5JiQ/GeI
+14uOa/AqWWLR3CQ4KIy36Rt7JwIDAQABo4HLMIHIMAkGA1UdEwQCMAAwLAYJYIZI
+AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW
+BBTLptIYB84a4afx3PtMoCyFrqVAojAfBgNVHSMEGDAWgBSsh9yLPYrbiUh+bzsc
+xnCSCRdv+TAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGGFWh0dHA6Ly8xMjcu
+MC4wLjE6ODg4ODAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN
+AQELBQADggIBABGLA6pQOFOIcWYBL9Wrgkm6TUVaILb3bh/Kd873k4XsTdq6F3Hc
+MHt/VTUHiKJKRwacjBugM19G3cnG9Q4nSG4fC6DoF+QWO9DjC1ZPXF+3rvvaRhML
+/Og9cn6rLRlNbAmLMlGaerhJcH7Oznh/lZw6jgXMKa8L3kK4zV5WqC946hln7adZ
+wM4KTFBGZ5pucmv9rgCmL5qTlzlYBrQFo3iptt9mIg2uW/3oN3glrC5aoGVWPoME
+v5iWMOER+do7apfEdyjW10YnpAVnLvW41C7HADlJCJunWCFITPuP3Zlp6lm8QZb9
+Gika/lMWaiusklEYrIXZfdV3rWBjmEcsUuyF763/sFjXEntvcCuTKpL4mTwVeibU
+eRYFk5r0Abzmm6Axw9cSI0cSgTACBgwTyjhMY5YtF0FTBovFo4zDlrfitYVJ981G
+ASH/T9FlvjcbhHx5puGoqNeMYzQ1RdVCEAMPYPpSxTkDJrFBbLlTPM+NXfoCrAp6
+BCco3zOyAWnYPnI4V2DTqEdfmFWMVRU2WG7H/GWl+Md/Gozet3khUJh2aYqzSLAd
+spH9JY+9WReBIrxnMtX75sPNPLN5b80cSrAEEzyvgFN88MYo8zc+Nk1l7zjcAF+I
+fgQ0dWb6umwfdrJVuyFg/rhI+KzLbhYvdYdE0MNt1Wrh5rkyfjmm5tB/
+-----END CERTIFICATE-----
diff --git a/test/org/apache/tomcat/util/net/localhost-crl-rsa-key.pem b/test/org/apache/tomcat/util/net/localhost-crl-rsa-key.pem
new file mode 100644
index 0000000000..f8de8c251b
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/localhost-crl-rsa-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCq8u4B3SH9S/Ye
+n6GmZUJxHNvP10dtIIFjAcdsolouFw1d2WB45dkqmsAtHC0knbP2JqmTgIatDrAG
+TmTcEdpwoOtHqp05PhActf68yrJbuD8MqNSzy57d9RkO3IM0VB0XuQ0uXUwx15tk
+6UCJ3nd1rW6GPkYViO1IiLuid6UFSjMzPrvLe/cAm+tOK/VKWQf/GFqhScIlSCED
+VWTa13UP6FWoYTnKrwlkwsFnS+yV32ZQLTlF1kyNB6g90fw8RnaSLxqwJ/AM6Bkr
+xrStYsTGIXwjF8QTpA590wU7C0OrQzKIEmeRGwHkmJD8Z4jXi45r8CpZYtHcJDgo
+jLfpG3snAgMBAAECggEAGwmoPlA454SjrU1HNneujhBn7dQZXne1LzEhVxvIkqCf
+wxe2C/kio3vtaFUcCL4OsCCGUqeR5X48tgqhJjOGrqis/d1M17hquPfKDhcrJZmb
+E0gCuFs8ydNRvsl+0QB6x31DyfEEs59r2waPaB7xGwIuyHnCAPbyvLWvo68zwQWs
+q3YF8Z03wPoSVxx9IrIsi01vaZGYREXmsNEX5krvd+Ku2JsQJ9NreduMg/gtegbB
+snN9MpjbydRWnwql4YzOCPaaGlQltrUFixKw6InZJRkKaSri49gEseaiSqwx31mY
+RvnWtyZfq1qRkcQm+NC9WO3cyCH38Um1egQmVpmguQKBgQDUlfAuAotMDN9aFnQ5
+DUviMyVy+ea1SDvJ3TnoaplZ4vp9pmwX5B2RPz8MzHKVLhll9h6GjAIXZuLT2Fed
+OyGUhM0Cd//+5esp0dHMKQFdzVMrhn8eGPPPBReEZtILbi3ulRJI6nsagAmKnLLN
+bik5fbcsc1KhtIUzGFbrw9ThWQKBgQDN3DTFrxP50XLc1hfs3OjP3OqZ7mqMyVXq
+JFJ4JNiFCFk/Jhqz83IuxrzoWGVmtnDjj9sdN/TsClG337xD9L3OgpS1yjjbzhi5
+wYG4cCjNxpqis097LFHqZDBBSZ9d3SWsdENqSWPbWOVLZQKrwR239m3mjCipSewI
+JRnX+1cwfwKBgQCrySoYFAg6gWBvrRtoCv2aIZiOi7DKJz/hRPsJfDLFtyySIszQ
+lY7rE3/AuOmS8XimszdBpJwACy0a4YUTUng1Swdbilr8wRDCb4Ioh65J/aTK1Fme
+ma1TShsR7ACqKfPGCwKGl6y44mRTdYLrjKyVf6horBxG/dhxTKbYyBwbqQKBgQDE
+vQPuPXFg2ivlI/L/muwg46eN704DONOUDpyGV+hZ022/rUHt4uaoD6UwhHJ8ZDWl
+NbGZzgWTpBUPHpMFexv/BcrrpdULNH9q36WCyCYm6vyUK7v1Ipky4gdADgVxpk0/
+8GkRZgw58E5K7MFNtiUZ0DieEis2BwC9k/+L65gbLwKBgG87Ag/C0un6LYMHI8gT
+DyqrsjARdlwVeyL864p3GHQbfGeQ2VTxSriEPHwSc2H1FtRsFo06P98DBjVW1xDD
+MPY8PD9MZ347rnNi1lcG42moxY6ywYesRwKaDPC98PgvaXzmm81wSyjOerwDQubi
+UQ6bYhVLe3BdVfFI8N8kSRzu
+-----END PRIVATE KEY-----
diff --git a/test/org/apache/tomcat/util/net/localhost-crl-rsa.jks b/test/org/apache/tomcat/util/net/localhost-crl-rsa.jks
new file mode 100644
index 0000000000..1519eab143
Binary files /dev/null and b/test/org/apache/tomcat/util/net/localhost-crl-rsa.jks differ
diff --git a/test/org/apache/tomcat/util/net/localhost-ec-cert.pem b/test/org/apache/tomcat/util/net/localhost-ec-cert.pem
index 341e6f72da..520b300a8b 100644
--- a/test/org/apache/tomcat/util/net/localhost-ec-cert.pem
+++ b/test/org/apache/tomcat/util/net/localhost-ec-cert.pem
@@ -1,22 +1,22 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 4113 (0x1011)
+ Serial Number: 4100 (0x1004)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=US, ST=MA, L=Wakefield, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=Apache Tomcat Test CA
+ Issuer: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=Apache Tomcat Test CA
Validity
- Not Before: Feb 16 17:59:33 2025 GMT
- Not After : Feb 16 17:59:33 2027 GMT
+ Not Before: Dec 5 19:15:40 2025 GMT
+ Not After : Dec 5 19:15:40 2027 GMT
Subject: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=localhost
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
- 04:0a:0a:c9:36:e4:18:27:f0:ef:ac:f3:8a:8b:a8:
- 9c:15:f5:71:95:94:10:bc:74:4a:c5:1e:e7:c5:fd:
- b0:b3:35:c0:5e:fe:11:2b:ae:ba:a7:a4:27:09:bd:
- 37:c5:de:bc:e7:6d:f7:de:dd:ab:ed:9d:cf:02:59:
- 1e:ba:b2:6a:b0
+ 04:4a:67:a8:52:9a:a4:a8:54:e0:0a:26:01:7b:c8:
+ 20:fc:99:99:09:b9:ce:a4:11:bd:99:0f:9d:73:b3:
+ 82:ef:9f:a9:73:31:bf:e5:f2:10:b2:b4:91:82:e1:
+ d5:9e:91:4b:e4:f2:ce:87:e1:a6:ee:6b:b5:68:39:
+ c0:c0:9a:e7:5d
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
@@ -25,62 +25,66 @@ Certificate:
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
- B2:76:F0:C0:C9:97:89:B7:00:A2:9C:AA:5B:49:D8:62:C7:2B:81:AD
+ AD:35:5C:21:09:CA:97:51:8F:CC:F2:33:B0:86:80:DF:73:4F:FD:73
X509v3 Authority Key Identifier:
- 00:F2:98:4D:21:2C:00:3C:40:9B:84:F4:DE:2A:F0:26:EE:32:0E:9F
+ AC:87:DC:8B:3D:8A:DB:89:48:7E:6F:3B:1C:C6:70:92:09:17:6F:F9
+ Authority Information Access:
+ OCSP - URI:http://127.0.0.1:8888
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
- 55:68:78:de:91:87:35:36:63:ca:bf:b1:bb:17:89:ef:01:7d:
- be:40:d6:e3:cb:45:ae:3b:7f:97:0f:5f:f4:7c:eb:2b:5d:0f:
- 2f:23:17:2d:2d:25:76:b1:1b:b8:59:24:4c:8b:0a:c7:cc:07:
- 37:f5:55:b2:20:b4:51:c9:ee:3b:0b:2f:b0:b2:d0:7f:76:30:
- 0e:46:65:63:45:67:cd:bd:42:ba:55:72:16:cd:6d:37:07:9b:
- 9c:9b:ee:cc:63:e1:32:15:c2:3c:76:05:a6:25:51:c2:a7:99:
- dd:03:36:d4:d4:75:47:50:a9:bc:e6:d6:a7:95:49:6a:54:12:
- 26:27:94:a2:67:48:8a:42:38:fd:e4:58:8b:3c:c1:67:a2:dc:
- ba:4e:72:72:f7:60:d8:ce:18:c7:56:2d:61:bf:b5:5b:f7:d8:
- b9:d5:f0:3e:62:20:2f:f1:b2:6d:0e:b0:e2:9a:60:a0:3f:8c:
- 7c:4a:ec:4f:fa:90:29:e5:b5:01:6e:20:f5:e5:d8:cd:ed:29:
- 59:e3:93:29:08:a9:a3:6b:1f:9f:6b:91:48:78:ad:03:1f:64:
- 0d:36:c7:c4:d3:40:a0:fc:cf:72:09:f5:8e:71:7b:cb:6c:fd:
- 1a:d3:02:5e:37:96:d0:41:ef:b2:2b:a9:28:18:fc:de:68:7e:
- 53:80:c4:8c:2b:90:42:de:61:ff:56:88:ea:f7:80:42:3f:cd:
- 13:46:9d:6d:70:b3:83:b9:69:35:94:a0:56:d9:3e:39:fc:b1:
- bb:f5:6d:d4:3c:22:80:86:b3:32:2a:eb:2a:c9:5d:a8:4b:b9:
- 48:70:68:d1:2c:2b:b7:bd:9c:2c:79:70:b4:e7:69:ba:32:bc:
- 97:ff:07:2a:49:78:d7:a1:6f:d0:24:96:73:1e:8c:3f:20:a2:
- 3c:fb:8f:11:e0:88:d3:86:06:6c:02:b8:a5:25:f2:10:1a:b3:
- bf:9a:ec:57:81:d4:d4:91:e1:6d:70:21:0b:6f:c0:a2:5d:49:
- 29:9c:fa:bd:78:7f:a7:3b:45:65:96:79:68:33:71:f8:a9:ea:
- 5c:69:69:b4:bf:8a:45:66:49:0d:e1:13:65:8b:27:72:cc:e6:
- 99:42:80:6c:b8:cc:6b:d8:f0:d2:71:bb:a6:f1:fa:5a:70:8a:
- 7b:df:65:4c:2f:bf:18:2c:b9:de:db:7f:e1:73:96:66:5d:73:
- aa:ef:f3:87:9e:e6:79:14:50:99:ae:bd:38:04:f2:78:54:db:
- ef:03:8a:57:9c:99:a8:57:87:c7:e7:84:19:d1:d9:4d:cf:a2:
- 8d:66:29:1a:78:a8:28:85:3e:0b:44:9e:60:d6:f0:14:92:11:
- 80:48:b5:5c:1b:81:8f:ba
+ 9a:74:81:f5:9d:87:bc:47:ea:33:a9:ef:d4:6b:6a:de:77:4e:
+ fc:41:c4:44:e7:ca:02:63:8b:a6:4f:b3:ed:14:44:8d:3f:29:
+ 3b:ee:2f:30:2b:31:bc:2f:88:64:ce:e7:4e:77:d7:d2:94:c6:
+ 31:98:ea:b8:c3:0c:23:e9:cd:00:99:2f:bd:41:bb:49:5d:ae:
+ f0:65:c7:b8:1b:c3:07:58:ea:ed:0e:ff:22:be:7b:0a:77:15:
+ 62:49:e0:7c:39:6a:9d:02:7d:b3:6d:94:eb:14:e6:75:1f:8a:
+ 40:cd:88:13:bd:42:03:49:18:ae:11:43:d5:f1:98:c5:a0:87:
+ 18:33:ae:84:c6:65:8f:61:89:be:54:d9:52:02:80:59:30:42:
+ df:02:d0:e5:44:9c:f5:36:28:3b:26:5c:a3:28:89:d2:b9:a3:
+ c7:2a:99:d3:86:b5:fd:13:6d:d7:f9:5d:7e:88:35:af:19:9e:
+ 4e:9c:8b:48:92:15:62:47:c7:c4:1e:25:4e:d5:8b:96:1f:7e:
+ cc:55:10:5f:82:1e:3f:b7:c7:ba:00:38:59:55:53:59:3c:f9:
+ 0b:2a:ab:d4:bf:0e:84:2b:71:61:be:14:4d:12:c1:8d:ab:8b:
+ 14:d7:af:b2:b4:6a:7e:b6:23:64:a2:7b:11:6b:ec:6b:1a:64:
+ ea:49:f0:a7:9f:d0:c9:47:71:fa:01:8a:3b:be:b9:6d:4a:d9:
+ 58:25:1a:a8:f6:88:35:e5:d4:98:53:48:62:f9:24:db:87:21:
+ bb:67:5f:b7:d1:60:0f:34:f5:63:f9:52:fd:f1:33:cb:5f:79:
+ 16:c8:e5:e4:c1:79:0c:d9:76:b4:44:56:ff:e7:86:a5:9f:dd:
+ 72:c6:15:4f:ed:6e:2d:1a:54:61:b3:5c:c7:26:10:98:9f:7e:
+ 77:0b:80:4c:a9:d7:bd:28:4c:3c:3b:05:67:e1:af:6d:1b:26:
+ d5:24:96:5f:01:69:84:37:1e:f2:30:3e:9d:e9:8a:fd:0f:28:
+ 56:87:d1:28:8f:32:5d:c9:96:f0:ec:14:b1:34:b9:0d:63:16:
+ 1b:26:e5:76:33:12:fe:52:f5:49:17:2d:14:06:fc:3f:4e:81:
+ b2:02:7d:e7:16:ae:62:d2:0f:1c:df:a1:50:a3:ff:3e:69:d5:
+ 7f:e7:c4:e7:6a:b8:93:b2:d8:99:9b:72:30:e9:e0:62:d6:c3:
+ c1:39:a0:1b:30:37:63:6e:b0:0f:47:20:71:8a:20:56:2f:2d:
+ a6:54:35:ee:72:38:fc:e2:bb:67:60:4f:f7:b8:79:cb:57:6e:
+ f3:7c:b3:55:03:01:41:29:48:ca:f6:a9:3a:4a:6a:26:cb:f7:
+ 21:54:fa:70:31:3d:95:d0
-----BEGIN CERTIFICATE-----
-MIIESTCCAjGgAwIBAgICEBEwDQYJKoZIhvcNAQELBQAwgZMxCzAJBgNVBAYTAlVT
-MQswCQYDVQQIEwJNQTESMBAGA1UEBxMJV2FrZWZpZWxkMScwJQYDVQQKEx5UaGUg
-QXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xGjAYBgNVBAsTEUFwYWNoZSBUb21j
-YXQgUE1DMR4wHAYDVQQDExVBcGFjaGUgVG9tY2F0IFRlc3QgQ0EwHhcNMjUwMjE2
-MTc1OTMzWhcNMjcwMjE2MTc1OTMzWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
-AkRFMRMwEQYDVQQHDApXaWxtaW5ndG9uMScwJQYDVQQKDB5UaGUgQXBhY2hlIFNv
-ZnR3YXJlIEZvdW5kYXRpb24xGjAYBgNVBAsMEUFwYWNoZSBUb21jYXQgUE1DMRIw
-EAYDVQQDDAlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQKCsk2
-5Bgn8O+s84qLqJwV9XGVlBC8dErFHufF/bCzNcBe/hErrrqnpCcJvTfF3rznbffe
-3avtnc8CWR66smqwo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVu
-U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUsnbwwMmXibcAopyq
-W0nYYscrga0wHwYDVR0jBBgwFoAUAPKYTSEsADxAm4T03irwJu4yDp8wDQYJKoZI
-hvcNAQELBQADggIBAFVoeN6RhzU2Y8q/sbsXie8Bfb5A1uPLRa47f5cPX/R86ytd
-Dy8jFy0tJXaxG7hZJEyLCsfMBzf1VbIgtFHJ7jsLL7Cy0H92MA5GZWNFZ829QrpV
-chbNbTcHm5yb7sxj4TIVwjx2BaYlUcKnmd0DNtTUdUdQqbzm1qeVSWpUEiYnlKJn
-SIpCOP3kWIs8wWei3LpOcnL3YNjOGMdWLWG/tVv32LnV8D5iIC/xsm0OsOKaYKA/
-jHxK7E/6kCnltQFuIPXl2M3tKVnjkykIqaNrH59rkUh4rQMfZA02x8TTQKD8z3IJ
-9Y5xe8ts/RrTAl43ltBB77IrqSgY/N5oflOAxIwrkELeYf9WiOr3gEI/zRNGnW1w
-s4O5aTWUoFbZPjn8sbv1bdQ8IoCGszIq6yrJXahLuUhwaNEsK7e9nCx5cLTnaboy
-vJf/BypJeNehb9AklnMejD8gojz7jxHgiNOGBmwCuKUl8hAas7+a7FeB1NSR4W1w
-IQtvwKJdSSmc+r14f6c7RWWWeWgzcfip6lxpabS/ikVmSQ3hE2WLJ3LM5plCgGy4
-zGvY8NJxu6bx+lpwinvfZUwvvxgsud7bf+FzlmZdc6rv84ee5nkUUJmuvTgE8nhU
-2+8DilecmahXh8fnhBnR2U3Poo1mKRp4qCiFPgtEnmDW8BSSEYBItVwbgY+6
+MIIEfzCCAmegAwIBAgICEAQwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
+MQswCQYDVQQIEwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhl
+IEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9t
+Y2F0IFBNQzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNhdCBUZXN0IENBMB4XDTI1MTIw
+NTE5MTU0MFoXDTI3MTIwNTE5MTU0MFowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQI
+DAJERTETMBEGA1UEBwwKV2lsbWluZ3RvbjEnMCUGA1UECgweVGhlIEFwYWNoZSBT
+b2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLDBFBcGFjaGUgVG9tY2F0IFBNQzES
+MBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESmeo
+UpqkqFTgCiYBe8gg/JmZCbnOpBG9mQ+dc7OC75+pczG/5fIQsrSRguHVnpFL5PLO
+h+Gm7mu1aDnAwJrnXaOBrzCBrDAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1P
+cGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUrTVcIQnKl1GP
+zPIzsIaA33NP/XMwHwYDVR0jBBgwFoAUrIfciz2K24lIfm87HMZwkgkXb/kwMQYI
+KwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVodHRwOi8vMTI3LjAuMC4xOjg4ODgw
+DQYJKoZIhvcNAQELBQADggIBAJp0gfWdh7xH6jOp79Rrat53TvxBxETnygJji6ZP
+s+0URI0/KTvuLzArMbwviGTO505319KUxjGY6rjDDCPpzQCZL71Bu0ldrvBlx7gb
+wwdY6u0O/yK+ewp3FWJJ4Hw5ap0CfbNtlOsU5nUfikDNiBO9QgNJGK4RQ9XxmMWg
+hxgzroTGZY9hib5U2VICgFkwQt8C0OVEnPU2KDsmXKMoidK5o8cqmdOGtf0Tbdf5
+XX6INa8Znk6ci0iSFWJHx8QeJU7Vi5YffsxVEF+CHj+3x7oAOFlVU1k8+Qsqq9S/
+DoQrcWG+FE0SwY2rixTXr7K0an62I2SiexFr7GsaZOpJ8Kef0MlHcfoBiju+uW1K
+2VglGqj2iDXl1JhTSGL5JNuHIbtnX7fRYA809WP5Uv3xM8tfeRbI5eTBeQzZdrRE
+Vv/nhqWf3XLGFU/tbi0aVGGzXMcmEJiffncLgEyp170oTDw7BWfhr20bJtUkll8B
+aYQ3HvIwPp3piv0PKFaH0SiPMl3JlvDsFLE0uQ1jFhsm5XYzEv5S9UkXLRQG/D9O
+gbICfecWrmLSDxzfoVCj/z5p1X/nxOdquJOy2JmbcjDp4GLWw8E5oBswN2NusA9H
+IHGKIFYvLaZUNe5yOPziu2dgT/e4ectXbvN8s1UDAUEpSMr2qTpKaibL9yFU+nAx
+PZXQ
-----END CERTIFICATE-----
diff --git a/test/org/apache/tomcat/util/net/localhost-ec-key.pem b/test/org/apache/tomcat/util/net/localhost-ec-key.pem
index b652c24a6e..e6621274ca 100644
--- a/test/org/apache/tomcat/util/net/localhost-ec-key.pem
+++ b/test/org/apache/tomcat/util/net/localhost-ec-key.pem
@@ -1,5 +1,8 @@
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgIGiUWTenuT85M7WD
-zpFQvWMq5xsQgZoNqmgg1BfGuyahRANCAAQKCsk25Bgn8O+s84qLqJwV9XGVlBC8
-dErFHufF/bCzNcBe/hErrrqnpCcJvTfF3rznbffe3avtnc8CWR66smqw
------END PRIVATE KEY-----
+-----BEGIN EC PARAMETERS-----
+BggqhkjOPQMBBw==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIF9PqIbcIMlMOKkaAID2L1ULbJApzzOj3WlBYuyZQqaaoAoGCCqGSM49
+AwEHoUQDQgAESmeoUpqkqFTgCiYBe8gg/JmZCbnOpBG9mQ+dc7OC75+pczG/5fIQ
+srSRguHVnpFL5PLOh+Gm7mu1aDnAwJrnXQ==
+-----END EC PRIVATE KEY-----
diff --git a/test/org/apache/tomcat/util/net/localhost-ec.jks b/test/org/apache/tomcat/util/net/localhost-ec.jks
index 0fc20baca4..e510be8894 100644
Binary files a/test/org/apache/tomcat/util/net/localhost-ec.jks and b/test/org/apache/tomcat/util/net/localhost-ec.jks differ
diff --git a/test/org/apache/tomcat/util/net/localhost-rsa-cert.pem b/test/org/apache/tomcat/util/net/localhost-rsa-cert.pem
index 488f1fb3c6..9d016d3b17 100644
--- a/test/org/apache/tomcat/util/net/localhost-rsa-cert.pem
+++ b/test/org/apache/tomcat/util/net/localhost-rsa-cert.pem
@@ -1,35 +1,35 @@
Certificate:
Data:
Version: 3 (0x2)
- Serial Number: 4112 (0x1010)
+ Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=US, ST=MA, L=Wakefield, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=Apache Tomcat Test CA
+ Issuer: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=Apache Tomcat Test CA
Validity
- Not Before: Feb 16 17:53:36 2025 GMT
- Not After : Feb 16 17:53:36 2027 GMT
+ Not Before: Dec 5 19:13:23 2025 GMT
+ Not After : Dec 5 19:13:23 2027 GMT
Subject: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
- 00:c0:40:4c:7d:58:4b:93:4a:0c:4d:ba:59:cc:50:
- a1:99:c1:ce:e3:3e:c8:a2:41:b0:e8:24:92:92:d4:
- f6:c1:31:d9:d6:41:c0:fa:de:d0:2e:59:09:75:a9:
- c3:3b:d4:56:d3:4f:79:a3:30:df:71:15:cd:d8:a7:
- 03:d6:be:fb:49:b0:cc:69:75:c4:b9:fb:a2:de:2e:
- da:30:db:72:27:1c:f9:96:e1:9f:bd:13:39:8f:da:
- a3:12:95:c7:a1:67:3e:4c:14:8c:98:03:6a:86:18:
- 8b:3a:d5:4e:09:77:7d:c1:be:6a:53:75:cc:c8:0f:
- 35:fc:4d:fd:40:63:a3:e4:10:0b:77:d9:b3:82:1b:
- 30:4c:35:02:9e:41:dc:8f:b5:70:a6:d7:be:75:1e:
- 57:a7:26:14:33:5a:e7:17:68:98:27:10:a6:9c:0c:
- 17:81:6b:d1:15:36:44:01:95:f8:91:38:9c:6d:d0:
- 97:45:0d:02:3c:c3:18:20:8d:a6:2a:e7:e0:df:8d:
- c1:81:81:71:bb:89:b2:b6:02:87:51:2c:7a:ca:9f:
- c9:ec:ab:e0:01:26:0c:dc:38:bd:17:be:2d:fe:48:
- 4c:7f:9c:42:1a:38:a0:39:60:5c:38:65:54:d4:71:
- ab:d3:a6:d0:c9:a2:a3:3c:0f:59:09:8d:8b:57:dc:
- 2b:05
+ 00:b1:da:2e:50:5c:5b:22:db:84:61:5e:e4:9d:e1:
+ a4:24:6c:92:d3:96:5a:77:52:c8:f7:cf:16:b5:60:
+ 80:a7:15:0e:12:75:1a:bc:3f:0b:54:38:96:f6:2f:
+ 0a:38:6c:21:68:da:13:49:a2:7b:7c:80:c7:aa:69:
+ fe:e3:8c:b1:ce:73:e6:5b:80:e2:36:89:49:5b:03:
+ ce:76:47:bf:35:20:ee:c6:78:df:62:aa:d1:d7:bf:
+ 91:b0:fc:aa:fd:7f:59:3f:8a:51:9f:7d:59:0f:e1:
+ d6:dc:7b:16:80:62:3f:6c:c2:2c:1b:a5:05:1e:40:
+ 90:60:20:e1:c3:6d:3f:ff:1c:73:84:92:86:59:03:
+ e5:4a:f6:d6:dc:e6:6e:68:1f:05:5f:f7:21:a9:fc:
+ 5e:e6:fc:8b:c7:36:34:18:fc:d5:70:21:54:5a:f1:
+ 10:c9:24:c8:08:92:2c:91:13:54:b1:d9:59:70:80:
+ 39:9f:8c:90:ad:c9:d2:b8:bd:a3:28:20:3f:67:35:
+ a2:d9:20:e2:3f:2e:be:3d:88:d2:3b:7d:3b:47:44:
+ 79:53:e2:52:98:72:13:ae:a2:9d:fe:68:bd:36:8c:
+ 2e:43:b1:3b:cd:50:35:3d:b5:f7:2f:43:ea:1e:c9:
+ d1:10:ac:e8:24:c1:8c:ee:e6:d0:c2:06:de:14:2d:
+ 1a:89
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
@@ -37,69 +37,72 @@ Certificate:
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
- BE:46:EA:26:EA:2A:17:93:67:DD:17:0B:57:8D:ED:A0:30:14:00:B2
+ 70:34:99:AD:29:E3:27:9D:BD:97:72:50:20:98:D2:97:B3:6C:AD:A1
X509v3 Authority Key Identifier:
- 00:F2:98:4D:21:2C:00:3C:40:9B:84:F4:DE:2A:F0:26:EE:32:0E:9F
+ AC:87:DC:8B:3D:8A:DB:89:48:7E:6F:3B:1C:C6:70:92:09:17:6F:F9
+ Authority Information Access:
+ OCSP - URI:http://127.0.0.1:8888
X509v3 Subject Alternative Name:
DNS:localhost, IP Address:127.0.0.1
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
- 90:9b:b3:66:a4:42:07:c2:68:05:aa:f3:a2:c9:66:35:45:42:
- b4:be:40:c7:90:34:71:b4:cf:79:fd:74:f7:4b:46:3f:f3:da:
- 81:3b:55:c3:62:7f:79:12:12:7f:b2:8d:72:55:d8:85:97:cf:
- 54:44:0e:9f:22:02:57:98:e9:02:a8:c7:6d:45:3e:b7:f6:7c:
- 56:58:a1:1b:0b:fa:a7:4c:57:66:92:3a:92:bd:f4:27:c6:5c:
- af:06:3b:d8:be:e9:b7:9a:d3:85:ae:9f:da:5f:59:05:bf:12:
- c9:13:49:75:25:1e:76:2d:c9:b7:c1:55:76:25:30:db:48:f4:
- c9:c4:cb:a4:dc:b6:df:13:1c:c1:44:2b:67:14:15:da:53:56:
- 18:e8:86:5a:75:89:96:a5:88:72:47:36:b5:0b:9c:51:13:50:
- c4:93:1c:a1:2b:d0:d8:0c:c7:f6:c5:30:88:93:6c:02:ff:6e:
- fe:92:ce:60:4b:17:27:e7:67:9a:d0:27:ae:4e:94:86:2a:ad:
- 99:3b:2e:6f:99:a5:d0:a1:a8:e8:3f:d1:c2:b6:1c:1a:f8:dc:
- 96:49:3b:79:be:c0:f8:3b:6a:93:d9:08:1e:3a:a9:36:0b:a1:
- 64:df:eb:fa:14:34:9b:73:25:49:29:25:e0:39:aa:49:0f:2d:
- 4b:ec:40:19:f7:44:00:47:7b:41:72:e8:5f:06:31:31:74:ca:
- 7b:98:e7:63:f8:19:ac:7e:5d:1f:5a:b4:22:d8:73:88:27:70:
- f4:18:5d:10:a9:52:6c:e3:e1:35:b0:4e:e3:91:79:63:49:86:
- 86:19:98:c4:9a:46:a8:bd:dd:5f:6a:8e:14:75:9e:e1:35:6b:
- ad:ab:83:8c:31:b6:cb:c2:cc:a5:86:4f:d9:e7:9a:cb:d6:a6:
- f5:ee:a9:8e:85:a1:85:54:3a:f6:f3:0e:b9:9f:e2:bc:5d:e5:
- eb:42:75:f1:3f:e1:a6:50:09:cc:a6:d3:c5:34:40:55:84:66:
- 61:60:99:f0:ea:f7:56:0b:fe:c7:b2:d2:ed:68:dc:0b:35:2f:
- 79:bf:f6:0a:af:2f:eb:25:8a:f2:9a:c7:72:00:04:ad:99:21:
- 08:14:b6:e4:12:f8:d0:c4:a3:55:c8:c7:ec:4f:e4:fb:4a:3e:
- 14:e4:56:cf:f8:a5:e1:b2:b2:50:8b:83:ce:fc:13:68:45:55:
- f6:1c:bc:e5:fe:f2:f2:51:0d:b7:9e:49:f2:19:3e:10:59:a3:
- dd:e0:72:ab:75:25:a0:0e:3c:b1:b9:17:ad:7e:46:9c:37:f1:
- 2a:19:be:91:54:2d:ab:3e:13:54:4c:aa:d6:05:56:b9:f6:3e:
- 19:61:cb:b3:c8:95:25:ad
+ 77:af:4a:b3:09:d8:9b:43:5a:73:78:10:ba:31:ad:a5:06:50:
+ 49:5d:14:f7:7b:1c:38:f0:3a:9b:67:b3:cb:71:52:7a:df:67:
+ fa:e1:c1:8b:18:dc:4e:bf:21:6d:58:b1:5f:df:2d:f1:ee:62:
+ a1:b6:78:dd:e2:c5:f2:4f:0b:9d:3d:cc:88:c7:26:8d:f0:41:
+ 02:ad:bd:e0:29:21:f9:0c:0a:07:cf:38:a4:f1:db:87:f7:e5:
+ ed:55:59:b5:34:7d:b4:39:70:ca:81:7a:bb:20:fa:2e:85:47:
+ 72:9c:35:f8:f2:e1:57:f9:9e:5c:9c:76:92:50:6a:c9:52:e9:
+ a0:d3:4d:41:03:f7:4f:bb:fc:5c:b8:aa:2c:7d:10:ff:3f:6c:
+ 82:e0:60:b8:d5:58:66:de:e0:db:30:b7:bf:3c:09:b9:3c:5c:
+ 36:cc:c6:d3:aa:58:9f:90:fe:e7:eb:5b:62:e2:66:a5:88:ec:
+ dd:2b:64:d1:25:08:e6:0a:49:91:5f:ac:1f:35:8d:2c:a2:71:
+ de:01:18:b0:0e:13:3d:cd:83:92:67:62:63:8a:63:bb:eb:8d:
+ f9:b7:95:b0:b6:a8:9c:14:8c:0b:00:34:8b:65:af:b7:6c:b9:
+ 1b:94:e2:54:3f:ee:87:0f:81:a9:3f:61:10:5f:ee:4d:42:b5:
+ 67:77:30:2e:04:4f:ad:5d:4e:de:e3:20:b3:8f:ca:46:98:7d:
+ 97:91:1d:4c:04:d9:bb:ae:02:3d:6f:55:dd:39:64:f3:53:86:
+ b6:4a:6a:eb:4a:7a:46:4e:0f:3b:44:8e:c2:46:c6:4b:07:1e:
+ b1:4e:8a:1c:fd:6a:06:55:2e:88:c6:85:8c:9b:c2:ea:90:e1:
+ 0b:d9:b1:af:2d:80:7f:b6:a2:c7:7a:63:7d:0a:cd:60:f6:46:
+ ea:40:3d:7d:4e:89:3e:0b:5d:22:8f:b7:3a:3a:38:18:26:a3:
+ 76:e9:cf:18:bc:c1:3c:8b:06:74:b6:f2:a8:a9:b4:cf:e1:96:
+ 54:bd:87:21:1d:20:b6:25:d1:d9:c6:fa:94:25:c6:6e:2b:1e:
+ a1:51:e3:31:ff:43:77:bd:e0:4c:6a:c2:24:97:43:99:f6:cb:
+ dd:3f:63:31:88:af:07:ef:e0:2b:3b:8e:3b:80:26:27:a6:c3:
+ 58:95:53:fa:39:14:59:42:3d:3a:e5:02:ff:0d:5b:e0:63:ad:
+ 93:72:8e:1d:55:c2:f9:49:7d:5c:cb:35:d2:11:b4:86:2d:26:
+ 61:74:1e:4d:e6:c7:97:e7:99:8b:fc:91:41:c8:9f:b8:ec:3e:
+ a3:f9:18:b5:2a:2e:1d:ee:2d:b6:cd:8f:14:be:b8:1c:6d:fd:
+ c3:59:61:66:87:e8:31:82
-----BEGIN CERTIFICATE-----
-MIIFMjCCAxqgAwIBAgICEBAwDQYJKoZIhvcNAQELBQAwgZMxCzAJBgNVBAYTAlVT
-MQswCQYDVQQIEwJNQTESMBAGA1UEBxMJV2FrZWZpZWxkMScwJQYDVQQKEx5UaGUg
-QXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xGjAYBgNVBAsTEUFwYWNoZSBUb21j
-YXQgUE1DMR4wHAYDVQQDExVBcGFjaGUgVG9tY2F0IFRlc3QgQ0EwHhcNMjUwMjE2
-MTc1MzM2WhcNMjcwMjE2MTc1MzM2WjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgT
-AkRFMRMwEQYDVQQHEwpXaWxtaW5ndG9uMScwJQYDVQQKEx5UaGUgQXBhY2hlIFNv
-ZnR3YXJlIEZvdW5kYXRpb24xGjAYBgNVBAsTEUFwYWNoZSBUb21jYXQgUE1DMRIw
-EAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQDAQEx9WEuTSgxNulnMUKGZwc7jPsiiQbDoJJKS1PbBMdnWQcD63tAuWQl1qcM7
-1FbTT3mjMN9xFc3YpwPWvvtJsMxpdcS5+6LeLtow23InHPmW4Z+9EzmP2qMSlceh
-Zz5MFIyYA2qGGIs61U4Jd33BvmpTdczIDzX8Tf1AY6PkEAt32bOCGzBMNQKeQdyP
-tXCm1751HlenJhQzWucXaJgnEKacDBeBa9EVNkQBlfiROJxt0JdFDQI8wxggjaYq
-5+DfjcGBgXG7ibK2AodRLHrKn8nsq+ABJgzcOL0Xvi3+SEx/nEIaOKA5YFw4ZVTU
-cavTptDJoqM8D1kJjYtX3CsFAgMBAAGjgZgwgZUwCQYDVR0TBAIwADAsBglghkgB
-hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE
-FL5G6ibqKheTZ90XC1eN7aAwFACyMB8GA1UdIwQYMBaAFADymE0hLAA8QJuE9N4q
-8CbuMg6fMBoGA1UdEQQTMBGCCWxvY2FsaG9zdIcEfwAAATANBgkqhkiG9w0BAQsF
-AAOCAgEAkJuzZqRCB8JoBarzoslmNUVCtL5Ax5A0cbTPef1090tGP/PagTtVw2J/
-eRISf7KNclXYhZfPVEQOnyICV5jpAqjHbUU+t/Z8VlihGwv6p0xXZpI6kr30J8Zc
-rwY72L7pt5rTha6f2l9ZBb8SyRNJdSUedi3Jt8FVdiUw20j0ycTLpNy23xMcwUQr
-ZxQV2lNWGOiGWnWJlqWIckc2tQucURNQxJMcoSvQ2AzH9sUwiJNsAv9u/pLOYEsX
-J+dnmtAnrk6UhiqtmTsub5ml0KGo6D/RwrYcGvjclkk7eb7A+Dtqk9kIHjqpNguh
-ZN/r+hQ0m3MlSSkl4DmqSQ8tS+xAGfdEAEd7QXLoXwYxMXTKe5jnY/gZrH5dH1q0
-IthziCdw9BhdEKlSbOPhNbBO45F5Y0mGhhmYxJpGqL3dX2qOFHWe4TVrrauDjDG2
-y8LMpYZP2eeay9am9e6pjoWhhVQ69vMOuZ/ivF3l60J18T/hplAJzKbTxTRAVYRm
-YWCZ8Or3Vgv+x7LS7WjcCzUveb/2Cq8v6yWK8prHcgAErZkhCBS25BL40MSjVcjH
-7E/k+0o+FORWz/il4bKyUIuDzvwTaEVV9hy85f7y8lENt55J8hk+EFmj3eByq3Ul
-oA48sbkXrX5GnDfxKhm+kVQtqz4TVEyq1gVWufY+GWHLs8iVJa0=
+MIIFZjCCA06gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
+MQswCQYDVQQIEwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhl
+IEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9t
+Y2F0IFBNQzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNhdCBUZXN0IENBMB4XDTI1MTIw
+NTE5MTMyM1oXDTI3MTIwNTE5MTMyM1owgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQI
+EwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhlIEFwYWNoZSBT
+b2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9tY2F0IFBNQzES
+MBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAsdouUFxbItuEYV7kneGkJGyS05Zad1LI988WtWCApxUOEnUavD8LVDiW9i8K
+OGwhaNoTSaJ7fIDHqmn+44yxznPmW4DiNolJWwPOdke/NSDuxnjfYqrR17+RsPyq
+/X9ZP4pRn31ZD+HW3HsWgGI/bMIsG6UFHkCQYCDhw20//xxzhJKGWQPlSvbW3OZu
+aB8FX/chqfxe5vyLxzY0GPzVcCFUWvEQySTICJIskRNUsdlZcIA5n4yQrcnSuL2j
+KCA/ZzWi2SDiPy6+PYjSO307R0R5U+JSmHITrqKd/mi9NowuQ7E7zVA1PbX3L0Pq
+HsnREKzoJMGM7ubQwgbeFC0aiQIDAQABo4HLMIHIMAkGA1UdEwQCMAAwLAYJYIZI
+AYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQW
+BBRwNJmtKeMnnb2XclAgmNKXs2ytoTAfBgNVHSMEGDAWgBSsh9yLPYrbiUh+bzsc
+xnCSCRdv+TAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGGFWh0dHA6Ly8xMjcu
+MC4wLjE6ODg4ODAaBgNVHREEEzARgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZIhvcN
+AQELBQADggIBAHevSrMJ2JtDWnN4ELoxraUGUEldFPd7HDjwOptns8txUnrfZ/rh
+wYsY3E6/IW1YsV/fLfHuYqG2eN3ixfJPC509zIjHJo3wQQKtveApIfkMCgfPOKTx
+24f35e1VWbU0fbQ5cMqBersg+i6FR3KcNfjy4Vf5nlycdpJQaslS6aDTTUED90+7
+/Fy4qix9EP8/bILgYLjVWGbe4Nswt788Cbk8XDbMxtOqWJ+Q/ufrW2LiZqWI7N0r
+ZNElCOYKSZFfrB81jSyicd4BGLAOEz3Ng5JnYmOKY7vrjfm3lbC2qJwUjAsANItl
+r7dsuRuU4lQ/7ocPgak/YRBf7k1CtWd3MC4ET61dTt7jILOPykaYfZeRHUwE2buu
+Aj1vVd05ZPNThrZKautKekZODztEjsJGxksHHrFOihz9agZVLojGhYybwuqQ4QvZ
+sa8tgH+2osd6Y30KzWD2RupAPX1OiT4LXSKPtzo6OBgmo3bpzxi8wTyLBnS28qip
+tM/hllS9hyEdILYl0dnG+pQlxm4rHqFR4zH/Q3e94ExqwiSXQ5n2y90/YzGIrwfv
+4Cs7jjuAJiemw1iVU/o5FFlCPTrlAv8NW+BjrZNyjh1VwvlJfVzLNdIRtIYtJmF0
+Hk3mx5fnmYv8kUHIn7jsPqP5GLUqLh3uLbbNjxS+uBxt/cNZYWaH6DGC
-----END CERTIFICATE-----
diff --git a/test/org/apache/tomcat/util/net/localhost-rsa-copy1.jks b/test/org/apache/tomcat/util/net/localhost-rsa-copy1.jks
index e14fa0f161..7422fd6f20 100644
Binary files a/test/org/apache/tomcat/util/net/localhost-rsa-copy1.jks and b/test/org/apache/tomcat/util/net/localhost-rsa-copy1.jks differ
diff --git a/test/org/apache/tomcat/util/net/localhost-rsa-key.pem b/test/org/apache/tomcat/util/net/localhost-rsa-key.pem
index 495d6ae75c..752f23619e 100644
--- a/test/org/apache/tomcat/util/net/localhost-rsa-key.pem
+++ b/test/org/apache/tomcat/util/net/localhost-rsa-key.pem
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
-MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAQEx9WEuTSgxN
-ulnMUKGZwc7jPsiiQbDoJJKS1PbBMdnWQcD63tAuWQl1qcM71FbTT3mjMN9xFc3Y
-pwPWvvtJsMxpdcS5+6LeLtow23InHPmW4Z+9EzmP2qMSlcehZz5MFIyYA2qGGIs6
-1U4Jd33BvmpTdczIDzX8Tf1AY6PkEAt32bOCGzBMNQKeQdyPtXCm1751HlenJhQz
-WucXaJgnEKacDBeBa9EVNkQBlfiROJxt0JdFDQI8wxggjaYq5+DfjcGBgXG7ibK2
-AodRLHrKn8nsq+ABJgzcOL0Xvi3+SEx/nEIaOKA5YFw4ZVTUcavTptDJoqM8D1kJ
-jYtX3CsFAgMBAAECggEAR6xxF9YALwRPO/c6nTp+VOV1bTEt+ZgGDTX9UzKEYBhm
-v0M6YA0Ljgvxw+UrfTW3vQYHMjj5RJ69ZIU3oCsJYjrAqpyWYEQZPz42aDqX/08F
-GiQ5unLdZe08GKSwjVMBXbnXhKDZaO7jkWaOtmbPApkr6LulQfyxwsOMpCHBqzdN
-peFcartqRkqhSYyXsMNekp9kZfZqzOkLkpFH0Qo0Y0BkK/1Bo+96iiD72FT3Cmgm
-X5JQhjap6H6v2iy0A2ERAsYwNItnauMDGQbZoYk8pyKNfQBYpHKziA/AomEDXHLE
-N42hjqTjlWfVvJ70TcQ06OcBPnpxdNrFrhYq2LSbbQKBgQD4YQE9/+hh7JrHElBq
-bmF5sR2PyYp6+G1C74b8fSXS69Aijtbtvm2KNII2lCalP0iK1UPBlBAyhrqZs+Pw
-B0fc/FGgZq1O/aM9JYUxGn+LpRfD1a73UrmKakgQj5Ph+6R2VrWSNlDYe/2hhUAB
-WUnyFrPY56bQuhy+uu1K7amatwKBgQDGJmpLSGJ4BRZS2Nb6EDJJOva+KF49cKTC
-GO8UtXXllOP2Y9e86wQ+f+/ZPC53C36hNItd6n9PG2CIpEBeDYbiv6E6a+tNWe27
-GqNCR/Rbs5MPiOm3tgbrK+eX0PT/+tKElopozp7ijIjYbjd5YbBuPDC7fr4pgBHc
-x1nSWUAcIwKBgEYsggFWT/16r7AWyImJbhjHpaZ+NpXPom8K5YRoh0s0PLXGzYqW
-BrTJaRCqgtClNIWlA2OpxXnA/u92F6w1ImSZFSbQW565omkgNKVO60I0/qXhtXFC
-+hDVPk8PgaSTSD/29427stO3FE2SLCc1ZuLy7xUVPdgy/PQWM/y7cPO5AoGBALR6
-UN5485c1qvuSnVvuXJ7uocbZpdx4ONjBNSG7lcKiNnA4yEs+FAOJK8DFW9z6D0Bt
-R3MnHwXCfc53LFl+IJluyT8ZBJzTiACfZov8VckgapX/skCt/uc8ehiBLmXo4s34
-/+AuMfFO52WaHdTk8Xm2QPzFmBbcm2hn+pvoxsfZAoGBAOxLL1iMDwMSAsECzy3s
-B337lOWxb5pE1vIDxuUHScy1GMNpQ9YFyXAwDb0RkVfbQAutu4Uj0Eto58YjtpIP
-y7Qw2vm19vVvyAjtdSTGHOhUB9v77MO8abrVBzlAgOVCGnvk3mUaCwL4uHKDMFLJ
-WePSjVhSZRNhjwootd8hbPtr
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCx2i5QXFsi24Rh
+XuSd4aQkbJLTllp3Usj3zxa1YICnFQ4SdRq8PwtUOJb2Lwo4bCFo2hNJont8gMeq
+af7jjLHOc+ZbgOI2iUlbA852R781IO7GeN9iqtHXv5Gw/Kr9f1k/ilGffVkP4dbc
+exaAYj9swiwbpQUeQJBgIOHDbT//HHOEkoZZA+VK9tbc5m5oHwVf9yGp/F7m/IvH
+NjQY/NVwIVRa8RDJJMgIkiyRE1Sx2VlwgDmfjJCtydK4vaMoID9nNaLZIOI/Lr49
+iNI7fTtHRHlT4lKYchOuop3+aL02jC5DsTvNUDU9tfcvQ+oeydEQrOgkwYzu5tDC
+Bt4ULRqJAgMBAAECggEAAqX0dvsIodFhzimzbSpMuCdZnObktgPd60UpnYpJLz5k
+fTjQc/X3lVt9zffN2KC7yILhOiTTiZ7eSHiT+AUNN/YTdIJL7cuu7Hj+SZ1QYbMr
+lpYlV2PNRH+vAShpjp4KzWsMpyZJehMmEKStHjzGgEZxWIdBqOSFgA3Tgzf5Q/NS
+OiWNgarUkwVGLDRFH99WWbVmAJEnJeB9pxEQllqb/5AkgeiDD3Mx+BwNgO5GRu4u
+z4BwB6InA4e6T+vBhnPra3qxaS3bPfna1P2Gz7jsH8xOHFt51hIVMCzeVj0/wOWL
+Ie7YinLbCAhIa5YD8F1LTvrzCGuJn+a8Rlt6AXPYDQKBgQD1O0plltNO/3y8WN1i
+c3Ox7sQfTsTj5ZFoW4U6kbAIPF5ByKTBAXdWHWxUwBxoZA+4lgYPEvdwXWPG+VXy
+JXAFbR2/JQO/yROKnodB4O73WZitt81PIHdFP7myEeN5QSjnYSvd6lIiaxe178BM
+qyO/85GgcBf/o3MAQib0UCwXHQKBgQC5qXZjspZd8nC33NP6A6HYawjkrZeVYG8S
+qPgT0ctmsb1EpihK+wU1iAJzECZuTSgoZtcRPL/N17/xgSuwk6nTUJyOdQwnmVP+
++Cfz7lcvx8Dg9FdrmjiEjFHnAYzaZ4bJP5Tub0tsUJRE/7YbhPlvlzaD95USLMKB
+IHzAQWx5XQKBgHgsmgS2qM6pvQK/uZ2pXiTwEQQWob3cnik50EwnYNBoZPhvzu0W
+Ptjgilnt2v39KwcV3do9PSy/V0oGneuQFRlTo6QsC25Mp1ri3P2XsQNd0Mgwrlf8
+XPZ+iA2PXp3pJJZetBSH48AiIvhxiRcJNve18MNiqyAHhS+3O0e2kiSxAoGAL3uY
+rKzK6iIME+nlSMbPCKNvNdTztJ9iKNqP/7mjFJOWfU0ldu+2CFfNkJHr0j/nalXK
+4TyxLTrleyV3AATz5Phz4bcrsaD0K3xZ83fcUnr66E11Yi6iD7w3YiYyWNUrUqLx
+Ov25w2zkTrU7ZNRgWtrIdX3HYUuTPyUI4r6YuH0CgYA+Qs6ZexX1Xys6qBbO2OiR
+6+eRItL12doGDDCO7tqtscf8S3VGSLk29lfwipyz6YhO46yRP2FypqVHYYhwvYuW
+ubXGUUZhzI3JBvqI0Lrtwt0KJ2QUXzfqZqO1cvKe3+gooywmemvzg5s1jZ+/Ys3b
+rQR0KWEn04xhcDMyTr/A9Q==
-----END PRIVATE KEY-----
diff --git a/test/org/apache/tomcat/util/net/localhost-rsa.jks b/test/org/apache/tomcat/util/net/localhost-rsa.jks
index 5a18bd30ad..fcb9b0c066 100644
Binary files a/test/org/apache/tomcat/util/net/localhost-rsa.jks and b/test/org/apache/tomcat/util/net/localhost-rsa.jks differ
diff --git a/test/org/apache/tomcat/util/net/ocsp-responder-rsa-cert.pem b/test/org/apache/tomcat/util/net/ocsp-responder-rsa-cert.pem
new file mode 100644
index 0000000000..02d8d5656b
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp-responder-rsa-cert.pem
@@ -0,0 +1,105 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4101 (0x1005)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=Apache Tomcat Test CA
+ Validity
+ Not Before: Dec 5 19:33:55 2025 GMT
+ Not After : Dec 5 19:33:55 2027 GMT
+ Subject: C=US, ST=DE, L=Wilmington, O=The Apache Software Foundation, OU=Apache Tomcat PMC, CN=OCSP Responder
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:9b:ae:b1:40:e5:e4:84:b6:c3:ec:93:cf:23:63:
+ 51:51:7f:bd:d3:64:1d:e0:23:bb:33:44:f1:47:c6:
+ f5:d2:4d:2a:13:2a:f4:4c:d2:44:13:56:03:73:16:
+ 30:98:be:66:b1:fb:3c:e9:9c:5a:61:25:b8:47:ef:
+ 72:04:ad:ab:6a:f8:83:fe:00:a6:c0:8b:a3:ef:34:
+ 09:4f:13:e6:fa:96:d3:2b:24:db:e3:d1:4a:40:50:
+ 5f:9f:8f:31:fa:de:42:0d:e6:a2:4a:7a:e6:a6:48:
+ 5a:97:04:b3:b9:bd:52:2e:2f:e9:02:27:1b:8f:bf:
+ 2b:19:28:e8:96:eb:29:d0:6e:39:0b:d9:bf:2a:d2:
+ 3e:65:a4:e0:87:30:ab:26:09:01:ea:4a:a7:a2:38:
+ 09:0e:f5:d3:b8:66:0a:cc:17:61:72:fb:a9:5e:e4:
+ 98:ff:30:e4:93:11:f7:6e:13:f3:76:f6:f4:44:b7:
+ a8:2a:79:b3:4f:59:d8:67:b7:c0:4c:cd:50:57:d2:
+ 09:65:f5:5e:2d:3b:e7:29:bf:e3:11:ff:37:1d:ad:
+ f2:cf:3b:ff:f7:49:d1:1a:05:1d:2b:0e:59:fe:fe:
+ e6:6a:5d:73:7f:0b:8c:b3:6d:c3:65:2a:93:f8:87:
+ b7:fd:c2:4a:e3:b8:d5:e6:55:8b:b3:e5:0e:4f:f4:
+ fa:a7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Key Usage: critical
+ Digital Signature
+ X509v3 Extended Key Usage:
+ OCSP Signing
+ X509v3 Subject Key Identifier:
+ FA:23:45:E2:94:8E:6A:88:B8:72:B1:53:EA:2A:AE:B9:39:F8:6A:C8
+ X509v3 Authority Key Identifier:
+ AC:87:DC:8B:3D:8A:DB:89:48:7E:6F:3B:1C:C6:70:92:09:17:6F:F9
+ Signature Algorithm: sha256WithRSAEncryption
+ Signature Value:
+ 3b:39:47:9e:28:f1:c0:46:eb:a8:de:0e:44:63:4d:3c:f4:59:
+ c1:a4:2a:eb:6a:e5:50:76:ea:76:f7:a9:ca:a2:cb:70:91:c9:
+ d3:c5:fd:d6:c9:86:3d:ad:f2:b8:a7:e4:b1:93:09:44:eb:27:
+ 30:01:85:13:db:0a:62:f0:0f:fa:59:de:af:93:1a:9e:df:07:
+ da:b8:ec:19:c1:c9:56:f9:a6:8e:4e:03:ae:e0:f9:d8:d2:b7:
+ d2:94:4a:70:95:b7:a8:7f:42:b2:1d:43:77:3a:9e:f8:76:93:
+ 4b:3a:48:09:5a:8b:3b:2c:38:97:ed:27:6b:d5:31:0b:f0:3d:
+ a9:dc:d4:0b:96:55:07:41:59:e1:1f:68:70:47:04:6a:11:a4:
+ 81:e7:7d:75:08:15:9f:ca:20:20:69:fe:ef:50:3f:cf:02:0b:
+ 96:4a:9e:e7:ce:08:07:8a:c0:93:a6:aa:a9:91:53:ac:5e:80:
+ 3b:bd:6f:cb:d2:7c:e3:9b:cd:ff:b0:12:ec:9a:71:48:e1:01:
+ 96:21:f4:ee:bb:f8:1d:99:77:00:68:ef:e3:bc:5d:1d:58:bc:
+ 91:88:51:39:93:b1:91:88:5c:d0:9d:0f:87:0b:0d:04:ca:be:
+ 79:05:b9:42:ae:b3:62:df:7a:02:d7:d5:4e:a8:27:8f:0b:b8:
+ 4c:aa:d5:07:a6:e4:65:b0:13:78:cd:3a:3b:10:58:49:13:d7:
+ 74:88:76:8a:77:a4:d4:24:01:61:fe:0b:46:fb:4e:15:3a:fa:
+ 2b:c3:ca:10:9c:5f:2b:f5:33:21:93:16:be:a4:c5:bd:a4:80:
+ 88:74:2a:1e:09:d4:2a:c6:af:ed:be:46:7f:b8:d7:ad:a6:e0:
+ 8f:92:ae:2b:8a:97:ca:9c:fb:21:29:48:f1:38:98:09:f9:2b:
+ 55:53:7c:99:a5:23:21:58:35:1a:36:15:67:79:80:3f:fc:94:
+ 60:94:2b:78:a5:f1:81:b4:51:5c:08:1a:50:24:21:da:0b:cc:
+ db:d7:3c:7d:d8:2c:b1:93:9d:f4:94:bb:fe:37:ad:8d:3f:06:
+ 9d:83:b0:e5:f2:ef:e4:88:75:e9:50:3a:f3:ef:aa:e4:00:54:
+ ad:1d:cd:a7:6b:ec:0e:b7:31:92:82:da:0d:4b:c3:27:ee:7a:
+ a8:f4:e0:a9:0a:f1:40:61:a0:09:a5:fb:24:f9:68:34:28:a9:
+ 1b:b6:5a:bd:aa:3a:c4:b8:89:92:ba:92:9c:81:f8:a8:ff:5a:
+ 0c:ef:af:97:b4:86:09:71:e8:13:28:1c:89:16:6f:43:de:1b:
+ 2f:1d:16:9f:37:7f:9c:5f:4e:4a:a8:22:4b:77:9e:f6:94:f8:
+ d9:05:4b:bc:a6:aa:f7:6e
+-----BEGIN CERTIFICATE-----
+MIIFFDCCAvygAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
+MQswCQYDVQQIEwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhl
+IEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9t
+Y2F0IFBNQzEeMBwGA1UEAxMVQXBhY2hlIFRvbWNhdCBUZXN0IENBMB4XDTI1MTIw
+NTE5MzM1NVoXDTI3MTIwNTE5MzM1NVowgY0xCzAJBgNVBAYTAlVTMQswCQYDVQQI
+EwJERTETMBEGA1UEBxMKV2lsbWluZ3RvbjEnMCUGA1UEChMeVGhlIEFwYWNoZSBT
+b2Z0d2FyZSBGb3VuZGF0aW9uMRowGAYDVQQLExFBcGFjaGUgVG9tY2F0IFBNQzEX
+MBUGA1UEAxMOT0NTUCBSZXNwb25kZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCbrrFA5eSEtsPsk88jY1FRf73TZB3gI7szRPFHxvXSTSoTKvRM0kQT
+VgNzFjCYvmax+zzpnFphJbhH73IEratq+IP+AKbAi6PvNAlPE+b6ltMrJNvj0UpA
+UF+fjzH63kIN5qJKeuamSFqXBLO5vVIuL+kCJxuPvysZKOiW6ynQbjkL2b8q0j5l
+pOCHMKsmCQHqSqeiOAkO9dO4ZgrMF2Fy+6le5Jj/MOSTEfduE/N29vREt6gqebNP
+Wdhnt8BMzVBX0gll9V4tO+cpv+MR/zcdrfLPO//3SdEaBR0rDln+/uZqXXN/C4yz
+bcNlKpP4h7f9wkrjuNXmVYuz5Q5P9PqnAgMBAAGjdTBzMAwGA1UdEwEB/wQCMAAw
+DgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMJMB0GA1UdDgQWBBT6
+I0XilI5qiLhysVPqKq65OfhqyDAfBgNVHSMEGDAWgBSsh9yLPYrbiUh+bzscxnCS
+CRdv+TANBgkqhkiG9w0BAQsFAAOCAgEAOzlHnijxwEbrqN4ORGNNPPRZwaQq62rl
+UHbqdvepyqLLcJHJ08X91smGPa3yuKfksZMJROsnMAGFE9sKYvAP+lner5Mant8H
+2rjsGcHJVvmmjk4DruD52NK30pRKcJW3qH9Csh1Ddzqe+HaTSzpICVqLOyw4l+0n
+a9UxC/A9qdzUC5ZVB0FZ4R9ocEcEahGkged9dQgVn8ogIGn+71A/zwILlkqe584I
+B4rAk6aqqZFTrF6AO71vy9J845vN/7AS7JpxSOEBliH07rv4HZl3AGjv47xdHVi8
+kYhROZOxkYhc0J0PhwsNBMq+eQW5Qq6zYt96AtfVTqgnjwu4TKrVB6bkZbATeM06
+OxBYSRPXdIh2inek1CQBYf4LRvtOFTr6K8PKEJxfK/UzIZMWvqTFvaSAiHQqHgnU
+Ksav7b5Gf7jXrabgj5KuK4qXypz7ISlI8TiYCfkrVVN8maUjIVg1GjYVZ3mAP/yU
+YJQreKXxgbRRXAgaUCQh2gvM29c8fdgssZOd9JS7/jetjT8GnYOw5fLv5Ih16VA6
+8++q5ABUrR3Np2vsDrcxkoLaDUvDJ+56qPTgqQrxQGGgCaX7JPloNCipG7Zavao6
+xLiJkrqSnIH4qP9aDO+vl7SGCXHoEygciRZvQ94bLx0Wnzd/nF9OSqgiS3ee9pT4
+2QVLvKaq924=
+-----END CERTIFICATE-----
diff --git a/test/org/apache/tomcat/util/net/ocsp-responder-rsa-key.pem b/test/org/apache/tomcat/util/net/ocsp-responder-rsa-key.pem
new file mode 100644
index 0000000000..1b5c681c93
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp-responder-rsa-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCbrrFA5eSEtsPs
+k88jY1FRf73TZB3gI7szRPFHxvXSTSoTKvRM0kQTVgNzFjCYvmax+zzpnFphJbhH
+73IEratq+IP+AKbAi6PvNAlPE+b6ltMrJNvj0UpAUF+fjzH63kIN5qJKeuamSFqX
+BLO5vVIuL+kCJxuPvysZKOiW6ynQbjkL2b8q0j5lpOCHMKsmCQHqSqeiOAkO9dO4
+ZgrMF2Fy+6le5Jj/MOSTEfduE/N29vREt6gqebNPWdhnt8BMzVBX0gll9V4tO+cp
+v+MR/zcdrfLPO//3SdEaBR0rDln+/uZqXXN/C4yzbcNlKpP4h7f9wkrjuNXmVYuz
+5Q5P9PqnAgMBAAECggEAALCpC3sZZLc0rh9Hm0YM7boNutqmQUCXS1ZiZWmN3GVI
+KvaVR6Pk9lr6v+9YvsyVQvO0pOpzAhw7MWJv1HJ6oIpCd4VEN/VGgEBwTB/v9atm
+ezn6GYvrctaIXfoyBAUpMMuVa5QY4qLOd/3m2AttSlQfCcnnlt8Hj2B9i3G2aTya
+EgwH9GKBoQ0FIMP3Znytx2YEj2dMk2wxApafNhxpZ302JZgvQG163UovQeGfJXvN
+d0xwtA8Xyzuv+/l1Bx8KyD0dYjeA6++khJ/oDNkM1+JKfN6qRzIhcNYWZAx6Au78
+tJwhBuUVqpbZnPkMXwyFjnAMvzSRcJrGIHdrIyPsWQKBgQDIgbcgiECHldkdrIUF
+3qKluX8g8mLTGts/wXG20iY730KThAnbxJ0ORPD5S3HZDSKZkG31ohoZHH7YT9iC
+0+pnu4bEhqtfPttXIK9q3PQh6i5jhiENc2x0NvJ0nUg8DkVqVmnmC3eIVIHfnnUU
+PDhe0GjHC02TegBFXfOFz3LDSQKBgQDGxRa4tKtB/0BeJCu4RD7pHuikt+NUKS7n
+4F3QBpyIzchjImIlHbutFwIbmUQ6C5TzEcgnTDAlJadBmljZYemaX5RN1UEPulPT
+NvSOdGdxyhJmKpFX+umUbypAcpKC6+EElaOuCUphMDOISIyooKUtJqWUXTVgO60x
+2vh94BHebwKBgGpIL/0DnEkCikLrdtukpsx35kZdlTrXio5iCNfizzd/Ybf2Do+6
+yZGNw7oxXpiyGLwTzeWdVn4nF6mrsVWv5Rm1UnuL8v0awYOOpM1db98mVg6VQ6Hw
+o/V6Rsy/rlF/MxZp1dqGC4dtXCZfxSnDvhGsIU4Y1LcuvUQHyBUO4INZAoGAPATV
+GI7NS49Uk1iervREfsXrf5lbFlWdKT0RdrgYWiKxCGYgdo6k1d4lr8m21UQcBM1w
+v5T80Kqu91swyusKy6dis6HaFHKxzwxACifR+IUIyzq9SnCkSULL4kv2O3wYJPc+
+RlXd1LzmQpeNiXmAhsKtqr/+VwGOCYjSEcgv/RcCgYBfUrsTG3dgWUVKviFzS63R
+nb0T9yKZij79HkIM0bROpaU5atTgQa/iwvSktw8mHGuJkjQZ6BqVpKHbDOq/Y/zB
+NihYIlf4WUPlQVr/sBLzfTtaxBKcnuVm1d8igKK3qQ0XuH5jk0gD6tzaU4ySTJ+P
+ldxvbWraHRcPzn08xJ6+UA==
+-----END PRIVATE KEY-----
diff --git a/test/org/apache/tomcat/util/net/ocsp/OcspBaseTest.java b/test/org/apache/tomcat/util/net/ocsp/OcspBaseTest.java
new file mode 100644
index 0000000000..a4c5617309
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/OcspBaseTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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.ocsp;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileLock;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.TesterSupport;
+import org.apache.tomcat.util.net.TesterSupport.SimpleServlet;
+import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
+
+public class OcspBaseTest extends TomcatBaseTest {
+
+ private static final File lockFile = new File("test/org/apache/tomcat/util/net/ocsp/ocsp-responder.lock");
+ private static FileLock lock = null;
+
+ @BeforeClass
+ public static void obtainOcspResponderLock() throws IOException {
+ @SuppressWarnings("resource")
+ FileOutputStream fos = new FileOutputStream(lockFile);
+ lock = fos.getChannel().lock();
+ }
+
+ @AfterClass
+ public static void releaseOcspResponderLock() throws IOException {
+ // Should not be null be in case obtaining the lock fails, avoid a second error.
+ if (lock != null) {
+ lock.release();
+ }
+ }
+
+
+ @Parameters(name = "{0} with OpenSSL trust {2}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+ parameterSets.add(new Object[] { "JSSE", Boolean.FALSE, Boolean.FALSE,
+ "org.apache.tomcat.util.net.jsse.JSSEImplementation"});
+ parameterSets.add(new Object[] { "OpenSSL", Boolean.TRUE, Boolean.TRUE,
+ "org.apache.tomcat.util.net.openssl.OpenSSLImplementation" });
+ parameterSets.add(new Object[] { "OpenSSL", Boolean.TRUE, Boolean.FALSE,
+ "org.apache.tomcat.util.net.openssl.OpenSSLImplementation" });
+ parameterSets.add(new Object[] { "OpenSSL-FFM", Boolean.TRUE, Boolean.TRUE,
+ "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation" });
+ parameterSets.add(new Object[] { "OpenSSL-FFM", Boolean.TRUE, Boolean.FALSE,
+ "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation" });
+
+ return parameterSets;
+ }
+
+ @Parameter(0)
+ public String connectorName;
+
+ @Parameter(1)
+ public boolean useOpenSSL;
+
+ @Parameter(2)
+ public boolean useOpenSSLTrust;
+
+ @Parameter(3)
+ public String sslImplementationName;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ Tomcat tomcat = getTomcatInstance();
+ TesterSupport.configureSSLImplementation(tomcat, sslImplementationName, useOpenSSL);
+ }
+
+
+ protected void doTest(boolean clientCertValid, boolean serverCertValid, ClientCertificateVerification verifyClientCert,
+ boolean verifyServerCert) throws Exception {
+
+ if ("OpenSSL-FFM".equals(connectorName)) {
+ Assume.assumeFalse(OpenSSLStatus.isBoringSSL() || OpenSSLStatus.isLibreSSLPre35());
+ }
+ Assume.assumeFalse(!useOpenSSLTrust && verifyClientCert == ClientCertificateVerification.OPTIONAL_NO_CA);
+
+ Tomcat tomcat = getTomcatInstance();
+
+ // No file system docBase required
+ Context ctx = tomcat.addContext("", null);
+
+ Tomcat.addServlet(ctx, "simple", new SimpleServlet());
+ ctx.addServletMappingDecoded("/simple", "simple");
+
+ if (serverCertValid) {
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_RSA_JKS, useOpenSSLTrust);
+ } else {
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_CRL_RSA_JKS, useOpenSSLTrust);
+ }
+ SSLHostConfig sslHostConfig = tomcat.getConnector().findSslHostConfigs()[0];
+ switch (verifyClientCert) {
+ case DEFAULT:
+ sslHostConfig.setCertificateVerification("required");
+ break;
+ case DISABLED:
+ sslHostConfig.setOcspEnabled(false);
+ sslHostConfig.setCertificateVerification("required");
+ break;
+ case ENABLED:
+ sslHostConfig.setOcspEnabled(true);
+ sslHostConfig.setCertificateVerification("required");
+ break;
+ case OPTIONAL_NO_CA:
+ sslHostConfig.setOcspEnabled(true);
+ sslHostConfig.setCertificateVerification("optionalNoCA");
+ break;
+
+ }
+
+ if (clientCertValid) {
+ TesterSupport.configureClientSsl(verifyServerCert, TesterSupport.CLIENT_JKS);
+ } else {
+ TesterSupport.configureClientSsl(verifyServerCert, TesterSupport.CLIENT_CRL_JKS);
+ }
+
+ tomcat.start();
+
+ int rc = getUrl("https://localhost:" + getPort() + "/simple", new ByteChunk(), false);
+
+ // If the TLS handshake fails, the test won't get this far.
+ Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+ }
+
+
+ protected enum ClientCertificateVerification {
+ DEFAULT,
+ ENABLED,
+ OPTIONAL_NO_CA,
+ DISABLED
+ }
+
+}
diff --git a/test/org/apache/tomcat/util/net/ocsp/TestOcspEnabled.java b/test/org/apache/tomcat/util/net/ocsp/TestOcspEnabled.java
new file mode 100644
index 0000000000..e67d934b2c
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/TestOcspEnabled.java
@@ -0,0 +1,186 @@
+/*
+ * 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.ocsp;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.channels.FileLock;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.net.ssl.SSLHandshakeException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.TesterSupport;
+import org.apache.tomcat.util.net.TesterSupport.SimpleServlet;
+
+
+@RunWith(Parameterized.class)
+public class TestOcspEnabled extends TomcatBaseTest {
+
+ private static TesterOcspResponder ocspResponder;
+ private static final File lockFile = new File("test/org/apache/tomcat/util/net/ocsp/ocsp-responder.lock");
+ private static FileLock lock = null;
+
+ @BeforeClass
+ public static void obtainOcspResponderLock() throws IOException {
+ @SuppressWarnings("resource")
+ FileOutputStream fos = new FileOutputStream(lockFile);
+ lock = fos.getChannel().lock();
+ }
+
+ @AfterClass
+ public static void releaseOcspResponderLock() throws IOException {
+ // Should not be null be in case obtaining the lock fails, avoid a second error.
+ if (lock != null) {
+ lock.release();
+ }
+ }
+
+
+ @Parameterized.Parameters(name = "{0} with OpenSSL trust {2}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+ parameterSets.add(new Object[] { "JSSE", Boolean.FALSE, Boolean.FALSE,
+ "org.apache.tomcat.util.net.jsse.JSSEImplementation"});
+ parameterSets.add(new Object[] { "OpenSSL", Boolean.TRUE, Boolean.TRUE,
+ "org.apache.tomcat.util.net.openssl.OpenSSLImplementation" });
+ parameterSets.add(new Object[] { "OpenSSL", Boolean.TRUE, Boolean.FALSE,
+ "org.apache.tomcat.util.net.openssl.OpenSSLImplementation" });
+ parameterSets.add(new Object[] { "OpenSSL-FFM", Boolean.TRUE, Boolean.TRUE,
+ "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation" });
+ parameterSets.add(new Object[] { "OpenSSL-FFM", Boolean.TRUE, Boolean.FALSE,
+ "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation" });
+
+ return parameterSets;
+ }
+
+ @Parameter(0)
+ public String connectorName;
+
+ @Parameter(1)
+ public boolean useOpenSSL;
+
+ @Parameter(2)
+ public boolean useOpenSSLTrust;
+
+ @Parameter(3)
+ public String sslImplementationName;
+
+
+ @BeforeClass
+ public static void startOcspResponder() throws IOException {
+ ocspResponder = new TesterOcspResponder();
+ ocspResponder.start();
+ }
+
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ Tomcat tomcat = getTomcatInstance();
+ TesterSupport.configureSSLImplementation(tomcat, sslImplementationName, useOpenSSL);
+ }
+
+
+ @AfterClass
+ public static void stopOcspResponder() {
+ ocspResponder.stop();
+ ocspResponder = null;
+ }
+
+
+ @Test
+ public void testValidClientValidServerVerifyNone() throws Exception {
+ doTest(true, true, false, false, HttpServletResponse.SC_OK);
+ }
+
+ @Test
+ public void testValidClientRevokedServerVerifyNone() throws Exception {
+ doTest(true, false, false, false, HttpServletResponse.SC_OK);
+ }
+
+ @Test
+ public void testRevokedClientValidServerVerifyNone() throws Exception {
+ doTest(false, true, false, false, HttpServletResponse.SC_OK);
+ }
+
+ @Test
+ public void testRevokedClientRevokedServerVerifyNone() throws Exception {
+ doTest(false, false, false, false, HttpServletResponse.SC_OK);
+ }
+
+
+ @Test
+ public void testValidClientValidServerVerifyClient() throws Exception {
+ doTest(true, true, true, false, HttpServletResponse.SC_OK);
+ }
+
+ @Test(expected = SSLHandshakeException.class)
+ public void testRevokedClientValidServerVerifyClient() throws Exception {
+ doTest(false, true, true, false, HttpServletResponse.SC_OK);
+ }
+
+
+ private void doTest(boolean clientCertValid, boolean serverCertValid, boolean verifyClientCert,
+ boolean verifyServerCert, int expectedStatusCode) throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ // No file system docBase required
+ Context ctx = tomcat.addContext("", null);
+
+ Tomcat.addServlet(ctx, "simple", new SimpleServlet());
+ ctx.addServletMappingDecoded("/simple", "simple");
+
+ if (serverCertValid) {
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_RSA_JKS, useOpenSSLTrust);
+ } else {
+ TesterSupport.initSsl(tomcat, TesterSupport.LOCALHOST_CRL_RSA_JKS, useOpenSSLTrust);
+ }
+ SSLHostConfig sslHostConfig = tomcat.getConnector().findSslHostConfigs()[0];
+ sslHostConfig.setCertificateVerification("required");
+ sslHostConfig.setOcspEnabled(verifyClientCert);
+
+ if (clientCertValid) {
+ TesterSupport.configureClientSsl(TesterSupport.CLIENT_JKS);
+ } else {
+ TesterSupport.configureClientSsl(TesterSupport.CLIENT_CRL_JKS);
+ }
+ // TODO enable client-side OCSP checks
+
+ tomcat.start();
+
+ int rc = getUrl("https://localhost:" + getPort() + "/simple", new ByteChunk(), false);
+
+ Assert.assertEquals(expectedStatusCode, rc);
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java b/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
new file mode 100644
index 0000000000..9012d7196a
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
@@ -0,0 +1,432 @@
+/*
+ * 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.ocsp;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.CRLReason;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateRevokedException;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.net.ssl.CertPathTrustManagerParameters;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.security.auth.x500.X500Principal;
+
+import jakarta.servlet.http.HttpServletResponse;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.tomcat.util.net.Constants;
+import org.apache.tomcat.util.net.SSLHostConfig;
+import org.apache.tomcat.util.net.SSLHostConfigCertificate;
+import org.apache.tomcat.util.net.TesterSupport;
+import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpServer;
+
+
+@RunWith(Parameterized.class)
+public class TestOcspIntegration extends TomcatBaseTest {
+
+ private static final String CA_CERTIFICATE_PATH = "ca-cert.pem";
+ private static final String SERVER_CERTIFICATE_PATH = "server-cert.pem";
+ private static final String SERVER_CERTIFICATE_KEY_PATH = "server-key.pem";
+ private static final String TRUSTSTORE_PATH = "trustStore.p12";
+ private static final String TRUSTSTORE_PASS = "trust-password";
+ private static final String KEYSTORE_TYPE = "PKCS12";
+ private static final String OCSP_SERVER_CERT_GOOD_RESPONSE = "ocsp-good.der";
+ private static final String OCSP_SERVER_CERT_REVOKED_RESPONSE = "ocsp-revoked.der";
+ private static final String CLIENT_KEYSTORE_PATH = "client-keystore.p12";
+ private static final String CLIENT_KEYSTORE_PASS = "client-password";
+ private static final String OCSP_CLIENT_CERT_GOOD_RESPONSE = "ocsp-client-good.der";
+ private static final String OCSP_CLIENT_CERT_REVOKED_RESPONSE = "ocsp-client-revoked.der";
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> parameters() {
+ List<Object[]> parameterSets = new ArrayList<>();
+ /*
+ * Future JSSE testing
+ parameterSets.add(new Object[] {
+ "JSSE", Boolean.FALSE, "org.apache.tomcat.util.net.jsse.JSSEImplementation"});
+ */
+ /*
+ * Disabled until a Tomcat Native release (2.0.10 onwards) is available with the OCSP fix
+ parameterSets.add(new Object[] {
+ "OpenSSL", Boolean.TRUE, "org.apache.tomcat.util.net.openssl.OpenSSLImplementation"});
+ */
+ parameterSets.add(new Object[] {
+ "OpenSSL-FFM", Boolean.TRUE, "org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation"});
+
+ return parameterSets;
+ }
+
+ @Parameter(0)
+ public String connectorName;
+
+ @Parameter(1)
+ public boolean useOpenSSL;
+
+ @Parameter(2)
+ public String sslImplementationName;
+
+
+ @Test
+ public void testOcspGood_ClientVerifiesServerCertificateOnly() throws Exception {
+ Assert.assertEquals(HttpServletResponse.SC_OK, testOCSP(OCSP_SERVER_CERT_GOOD_RESPONSE, false, true));
+ }
+
+ @Test
+ public void testOcspGood_Mutual() throws Exception {
+ testOCSPWithClientResponder(OCSP_CLIENT_CERT_GOOD_RESPONSE, () -> Assert.assertEquals(HttpServletResponse.SC_OK,
+ testOCSP(OCSP_SERVER_CERT_GOOD_RESPONSE, true, true)));
+ }
+
+ @Test
+ public void testOcspGood_ServerVerifiesClientCertificateOnly() throws Exception {
+ testOCSPWithClientResponder(OCSP_CLIENT_CERT_GOOD_RESPONSE, () -> Assert.assertEquals(HttpServletResponse.SC_OK,
+ testOCSP(OCSP_SERVER_CERT_REVOKED_RESPONSE, true, false)));
+ }
+
+ @Test(expected = CertificateRevokedException.class)
+ public void testOcspRevoked_ClientVerifiesServerCertificateOnly() throws Exception {
+ try {
+ testOCSP(OCSP_SERVER_CERT_REVOKED_RESPONSE, false, true);
+ } catch (SSLHandshakeException sslHandshakeException) {
+ handleExceptionWhenRevoked(sslHandshakeException);
+ }
+ }
+
+ @Test(expected = CertificateRevokedException.class)
+ public void testOcspRevoked_Mutual() throws Exception {
+ try {
+ // The exception is thrown before server side verification, while client does OCSP verification.
+ testOCSP(OCSP_SERVER_CERT_REVOKED_RESPONSE, true, true);
+ } catch (SSLHandshakeException sslHandshakeException) {
+ handleExceptionWhenRevoked(sslHandshakeException);
+ }
+ }
+
+ @Test(expected = SSLHandshakeException.class)
+ public void testOcspRevoked_ServerVerifiesClientCertificateOnly() throws Exception {
+ Assume.assumeFalse("BoringSSL does not support OCSP in a compatible way",
+ TesterSupport.isOpenSSLVariant(sslImplementationName, OpenSSLStatus.Name.BORINGSSL));
+ testOCSPWithClientResponder(OCSP_CLIENT_CERT_REVOKED_RESPONSE,
+ () -> testOCSP(OCSP_SERVER_CERT_GOOD_RESPONSE, true, false));
+ }
+
+ @Test
+ public void testOcsp_NoVerification() throws Exception {
+ testOCSPWithClientResponder(OCSP_CLIENT_CERT_REVOKED_RESPONSE, () -> Assert
+ .assertEquals(HttpServletResponse.SC_OK, testOCSP(OCSP_SERVER_CERT_REVOKED_RESPONSE, false, false)));
+ }
+
+ @Test
+ public void testOcspResponderUrlDiscoveryViaCertificateAIA() throws Exception {
+ final int ocspPort = 8888;
+ Assume.assumeTrue("Port " + ocspPort + " is not available.", isPortAvailable(ocspPort));
+ Assert.assertEquals(HttpServletResponse.SC_OK,
+ testOCSP(OCSP_SERVER_CERT_GOOD_RESPONSE, false, true, true, ocspPort));
+ }
+
+ public static void testLongUrlForOcspViaAIAWithTomcatNative(Tomcat tomcat) throws Exception {
+ final int ocspResponderPortForClient = 8889;
+ Assume.assumeTrue("Port " + ocspResponderPortForClient + " is not available.", isPortAvailable(ocspResponderPortForClient));
+ try (FakeOcspResponder fakeOcspResponder = new FakeOcspResponder(true, "/ocsp/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+ Files.readAllBytes(new File(getPath(OCSP_CLIENT_CERT_REVOKED_RESPONSE)).toPath()), ocspResponderPortForClient)) {
+ fakeOcspResponder.start();
+ testOCSP(tomcat, OCSP_SERVER_CERT_GOOD_RESPONSE, true, false, false, 0,
+ "org.apache.tomcat.util.net.openssl.OpenSSLImplementation", true);
+ }
+ }
+
+ @FunctionalInterface
+ private interface TestOCSPAction {
+ void execute() throws Exception;
+ }
+
+ private void testOCSPWithClientResponder(String clientResponsePath, TestOCSPAction testOCSPAction)
+ throws Exception {
+ final int ocspResponderPortForClient = 8889;
+ Assume.assumeTrue("Port " + ocspResponderPortForClient + " is not available.",
+ isPortAvailable(ocspResponderPortForClient));
+ try (FakeOcspResponder fakeOcspResponder = new FakeOcspResponder(
+ Files.readAllBytes(new File(getPath(clientResponsePath)).toPath()), ocspResponderPortForClient)) {
+ fakeOcspResponder.start();
+ testOCSPAction.execute();
+ }
+ }
+
+ private int testOCSP(String pathToOcspResponse, boolean serverSideVerificationEnabled,
+ boolean clientSideOcspVerificationEnabled) throws Exception {
+ return testOCSP(pathToOcspResponse, serverSideVerificationEnabled, clientSideOcspVerificationEnabled, false, 0);
+ }
+
+ private int testOCSP(String pathToOcspResponse, boolean serverSideVerificationEnabled,
+ boolean clientSideOcspVerificationEnabled, boolean clientDiscoversResponderFromAIA, int ocspResponderPort)
+ throws Exception {
+ return testOCSP(getTomcatInstance(), pathToOcspResponse, serverSideVerificationEnabled,
+ clientSideOcspVerificationEnabled, clientDiscoversResponderFromAIA, ocspResponderPort,
+ sslImplementationName, useOpenSSL);
+ }
+
+ private static int testOCSP(Tomcat tomcat, String pathToOcspResponse, boolean serverSideVerificationEnabled,
+ boolean clientSideOcspVerificationEnabled, boolean clientDiscoversResponderFromAIA, int ocspResponderPort,
+ String sslImplementationName, boolean useOpenSSL)
+ throws Exception {
+
+ File certificateFile = new File(getPath(SERVER_CERTIFICATE_PATH));
+ File certificateKeyFile = new File(getPath(SERVER_CERTIFICATE_KEY_PATH));
+ File certificateChainFile = new File(getPath(CA_CERTIFICATE_PATH));
+ initSsl(tomcat, serverSideVerificationEnabled, certificateFile, certificateKeyFile, certificateChainFile);
+
+ TesterSupport.configureSSLImplementation(tomcat, sslImplementationName, useOpenSSL);
+
+ Context context = tomcat.addContext("", null);
+ Tomcat.addServlet(context, "simple", new TesterSupport.SimpleServlet());
+ context.addServletMappingDecoded("/", "simple");
+
+ KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE);
+ String trustStorePass = Files.readString(new File(getPath(TRUSTSTORE_PASS)).toPath()).trim();
+ trustStore.load(new FileInputStream(new File(getPath(TRUSTSTORE_PATH)).getAbsolutePath()),
+ trustStorePass.toCharArray());
+ KeyStore clientKeystore = KeyStore.getInstance(KEYSTORE_TYPE);
+ String clientKeystorePass = Files.readString(new File(getPath(CLIENT_KEYSTORE_PASS)).toPath()).trim();
+ clientKeystore.load(new FileInputStream(new File(getPath(CLIENT_KEYSTORE_PATH)).getAbsolutePath()),
+ clientKeystorePass.toCharArray());
+ byte[] ocspResponse = Files.readAllBytes(new File(getPath(pathToOcspResponse)).toPath());
+ try (FakeOcspResponder fakeOcspResponder = new FakeOcspResponder(ocspResponse, ocspResponderPort)) {
+ fakeOcspResponder.start();
+ tomcat.start();
+
+ URL url = new URI("https://127.0.0.1:" + tomcat.getConnector().getLocalPort() + "/").toURL();
+ HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
+ SSLSocketFactory sslSocketFactory;
+ if (clientSideOcspVerificationEnabled) {
+ sslSocketFactory = buildClientSslSocketFactoryWithOcsp(
+ clientDiscoversResponderFromAIA ? null : fakeOcspResponder.url(), trustStore, clientKeystore,
+ clientKeystorePass);
+ } else {
+ sslSocketFactory = buildClientSslSocketFactoryNoOcsp(trustStore, clientKeystore, clientKeystorePass);
+ }
+ connection.setSSLSocketFactory(sslSocketFactory);
+ connection.connect();
+ return connection.getResponseCode();
+ } finally {
+ tomcat.stop();
+ }
+ }
+
+ private static void initSsl(Tomcat tomcat, boolean serverSideVerificationEnabled, File certificateFile,
+ File certificateKeyFile, File certificateChainFile) {
+ Connector connector = tomcat.getConnector();
+ connector.setSecure(true);
+ connector.setProperty("SSLEnabled", "true");
+
+ SSLHostConfig sslHostConfig = new SSLHostConfig();
+ SSLHostConfigCertificate certificate = new SSLHostConfigCertificate(sslHostConfig, SSLHostConfigCertificate.Type.UNDEFINED);
+ sslHostConfig.addCertificate(certificate);
+ certificate.setCertificateFile(certificateFile.getAbsolutePath());
+ certificate.setCertificateKeyFile(certificateKeyFile.getAbsolutePath());
+ certificate.setCertificateChainFile(certificateChainFile.getAbsolutePath());
+ if (serverSideVerificationEnabled) {
+ sslHostConfig.setCertificateVerification("required");
+ } else {
+ sslHostConfig.setCertificateVerification("optionalNoCA");
+ }
+ sslHostConfig.setCaCertificateFile(certificateChainFile.getAbsolutePath());
+ connector.addSslHostConfig(sslHostConfig);
+ }
+
+ private static SSLSocketFactory buildClientSslSocketFactoryWithOcsp(String ocspUrl, KeyStore trustStore,
+ KeyStore clientKeystore, String clientKeystorePass) throws Exception {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(clientKeystore, clientKeystorePass.toCharArray());
+ Set<TrustAnchor> trustAnchors = getTrustAnchorsFromKeystore(trustStore);
+ PKIXRevocationChecker revocationChecker =(PKIXRevocationChecker) CertPathValidator.getInstance("PKIX").getRevocationChecker();
+ if (ocspUrl != null) {
+ revocationChecker.setOcspResponder(new URI(ocspUrl));
+ }
+ revocationChecker.setOptions(EnumSet.of(PKIXRevocationChecker.Option.NO_FALLBACK));
+
+ PKIXBuilderParameters pkix = new PKIXBuilderParameters(trustAnchors, new X509CertSelector());
+ pkix.addCertPathChecker(revocationChecker);
+
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
+ trustManagerFactory.init(new CertPathTrustManagerParameters(pkix));
+ return initSSLContext(kmf, trustManagerFactory).getSocketFactory();
+ }
+
+ private static SSLSocketFactory buildClientSslSocketFactoryNoOcsp(KeyStore trustStore, KeyStore clientKeystore,
+ String clientKeystorePass) throws Exception {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(clientKeystore, clientKeystorePass.toCharArray());
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(trustStore);
+ return initSSLContext(kmf, trustManagerFactory).getSocketFactory();
+ }
+
+ private static SSLContext initSSLContext(KeyManagerFactory keyManagerFactory,
+ TrustManagerFactory trustManagerFactory) throws Exception {
+ SSLContext sslContext;
+ if (TesterSupport.isTlsv13Available()) {
+ sslContext = SSLContext.getInstance(Constants.SSL_PROTO_TLSv1_3);
+ } else {
+ sslContext = SSLContext.getInstance(Constants.SSL_PROTO_TLSv1_2);
+ }
+ sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
+ return sslContext;
+ }
+
+ private static Set<TrustAnchor> getTrustAnchorsFromKeystore(KeyStore keyStore) throws KeyStoreException {
+ Set<TrustAnchor> trustAnchors = new HashSet<>();
+ Enumeration<String> aliases = keyStore.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ Certificate certificate = keyStore.getCertificate(alias);
+ if (certificate instanceof X509Certificate) {
+ trustAnchors.add(new TrustAnchor((X509Certificate)certificate, null));
+ }
+ }
+ return trustAnchors;
+ }
+
+ private static void handleExceptionWhenRevoked(Exception exception) throws Exception {
+ if (exception.getCause().getCause() instanceof CertPathValidatorException cpe) {
+ Assert.assertEquals("REVOKED", cpe.getReason().toString());
+ Assert.assertTrue(cpe.toString().contains("reason: KEY_COMPROMISE"));
+ // Some JDKs only expose CertPathValidatorException
+ if (cpe.getCause() instanceof CertificateRevokedException) {
+ throw (CertificateRevokedException) cpe.getCause();
+ } else {
+ throw new CertificateRevokedException(new Date(), CRLReason.KEY_COMPROMISE, new X500Principal(""), new HashMap<>());
+ }
+ }
+ }
+
+ private static class FakeOcspResponder implements Closeable {
+ private final byte[] ocspResponse;
+ private HttpServer server;
+ private int port;
+ private boolean strictPath = false;
+ private String path = "/ocsp";
+
+ FakeOcspResponder(boolean strictPath, String path, byte[] ocspResponse, int port) {
+ this(ocspResponse, port);
+ this.strictPath = strictPath;
+ this.path = path;
+ }
+
+ FakeOcspResponder(byte[] ocspResponse, int port) {
+ this.ocspResponse = ocspResponse;
+ this.port = port;
+ }
+
+ void start() throws IOException {
+ server = HttpServer.create(new InetSocketAddress("127.0.0.1", port), 0);
+ server.createContext(this.path, httpExchange -> {
+ if (strictPath) {
+ String path = httpExchange.getRequestURI().getPath();
+ if (!this.path.equals(path)) {
+ httpExchange.sendResponseHeaders(404, -1);
+ httpExchange.close();
+ return;
+ }
+ }
+ byte[] body = ocspResponse;
+ Headers headers = httpExchange.getResponseHeaders();
+ headers.add("Content-Type", "application/ocsp-response");
+ httpExchange.sendResponseHeaders(HttpServletResponse.SC_OK, body.length);
+ try (OutputStream os = httpExchange.getResponseBody()) {
+ os.write(body);
+ }
+ });
+ server.start();
+ port = server.getAddress().getPort();
+ }
+
+ String url() {
+ return "http://127.0.0.1:" + port + path;
+ }
+ @Override public void close() {
+ if (server != null) {
+ server.stop(0);
+ }
+ }
+ }
+
+ private static String getPath(String file) throws IOException {
+ if (file == null) {
+ return null;
+ }
+ String packageName = TestOcspIntegration.class.getPackageName();
+ String path = packageName.replace(".", File.separator);
+ File f = new File("test" + File.separator + path + File.separator + file);
+
+ return f.getCanonicalPath();
+ }
+
+ @SuppressWarnings("unused")
+ private static boolean isPortAvailable(int port) {
+ try (ServerSocket serverSocket = new ServerSocket(port)) {
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/ocsp/TestOcspSoftFail.java b/test/org/apache/tomcat/util/net/ocsp/TestOcspSoftFail.java
new file mode 100644
index 0000000000..382db3838b
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/TestOcspSoftFail.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ocsp;
+
+import java.net.SocketException;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/*
+ * Only looking to test the Tomcat (server) side configuration of soft fail.
+ */
+@RunWith(Parameterized.class)
+public class TestOcspSoftFail extends OcspBaseTest {
+
+ @Test
+ public void testNoResponderDefaultSoftFail() throws Exception {
+ // Default behaviour should be the same for all configurations and equivalent to enabled.
+ doTest(false, false, ClientCertificateVerification.ENABLED, false, null);
+ }
+
+
+ @Test
+ public void testNoResponderWithSoftFail() throws Exception {
+ doTest(false, false, ClientCertificateVerification.ENABLED, false, Boolean.TRUE);
+ }
+
+
+ @Test(expected = SSLHandshakeException.class)
+ public void testNoResponderWithoutSoftFail() throws Exception {
+ try {
+ doTest(false, false, ClientCertificateVerification.ENABLED, false, Boolean.FALSE);
+ } catch (SocketException se) {
+ // NIO2 may throw a SocketException rather than a SSLHandshakeException
+ if (getTomcatInstance().getConnector().getProtocolHandlerClassName().contains("Nio2")) {
+ throw new SSLHandshakeException(se.getMessage());
+ } else {
+ throw se;
+ }
+ }
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/ocsp/TestOcspTimeout.java b/test/org/apache/tomcat/util/net/ocsp/TestOcspTimeout.java
new file mode 100644
index 0000000000..290b08822a
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/TestOcspTimeout.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ocsp;
+
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/*
+ * The timeout for reading an OCSP response is 15s by default for both JSSE and OpenSSL.
+ */
+@RunWith(Parameterized.class)
+public class TestOcspTimeout extends OcspBaseTest {
+
+ private static TesterOcspResponderNoResponse ocspResponder;
+
+ @BeforeClass
+ public static void startOcspResponder() {
+ /*
+ * Use shorter timeout to speed up test.
+ *
+ * Note: OpenSSL timeout set later as it requires access to SSLHostConfig.
+ */
+ System.setProperty("com.sun.security.ocsp.readtimeout", "1000ms");
+ ocspResponder = new TesterOcspResponderNoResponse();
+ ocspResponder.start();
+ }
+
+
+ @AfterClass
+ public static void stopOcspResponder() {
+ ocspResponder.stop();
+ ocspResponder = null;
+ }
+
+
+ @Test
+ public void testTimeoutWithSoftFail() throws Exception {
+ doTest(false, false, ClientCertificateVerification.ENABLED, false, Boolean.TRUE);
+ }
+
+
+ @Test(expected = SSLHandshakeException.class)
+ public void testTimeoutWithoutSoftFail() throws Exception {
+ try {
+ doTest(false, false, ClientCertificateVerification.ENABLED, false, Boolean.FALSE);
+ } catch (SocketTimeoutException | SocketException e) {
+ // May throw a SocketTimeoutException or SocketException rather than a SSLHandshakeException
+ throw new SSLHandshakeException(e.getMessage());
+ }
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponder.java b/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponder.java
new file mode 100644
index 0000000000..27def84db8
--- /dev/null
+++ b/test/org/apache/tomcat/util/net/ocsp/TesterOcspResponder.java
@@ -0,0 +1,125 @@
+/*
+ * 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.ocsp;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Assert;
+
+import org.apache.tomcat.util.net.TesterSupport;
+
+/*
+ * The OpenSSL ocsp tool is great, but it does generate a lot of output. That output needs to be swallowed, else the
+ * process will freeze when the output buffers (stdout and stderr) are full.
+ *
+ * There is a command line option to redirect stdout (which could be redirected to /dev/null), but there is no option to
+ * redirect stderr. Therefore, this class uses a couple of dedicated threads to read stdout and stderr. By default, the
+ * output is ignored, but it can be dumped to Java's stdout/stderr if required for debugging purposes.
+ */
+public class TesterOcspResponder {
+
+ private static List<String> ocspArgs = Arrays.asList("ocsp", "-port", "8888", "-text", "-index",
+ TesterSupport.DB_INDEX, "-CA", TesterSupport.CA_CERT_PEM, "-rkey", TesterSupport.OCSP_RESPONDER_RSA_KEY,
+ "-rsigner", TesterSupport.OCSP_RESPONDER_RSA_CERT, "-nmin", "60");
+
+ private Process p;
+
+ public void start() throws IOException {
+ if (p != null) {
+ throw new IllegalStateException("Already started");
+ }
+
+ String openSSLPath = System.getProperty("tomcat.test.openssl.path");
+ String openSSLLibPath = null;
+ if (openSSLPath == null || openSSLPath.length() == 0) {
+ openSSLPath = "openssl";
+ } else {
+ // Explicit OpenSSL path may also need explicit lib path
+ // (e.g. Gump needs this)
+ openSSLLibPath = openSSLPath.substring(0, openSSLPath.lastIndexOf('/'));
+ openSSLLibPath = openSSLLibPath + "/../:" + openSSLLibPath + "/../lib:" + openSSLLibPath + "/../lib64";
+ }
+ List<String> cmd = new ArrayList<>();
+ cmd.add(openSSLPath);
+ cmd.addAll(ocspArgs);
+
+ ProcessBuilder pb = new ProcessBuilder(cmd.toArray(new String[0]));
+
+ if (openSSLLibPath != null) {
+ Map<String,String> env = pb.environment();
+ String libraryPath = env.get("LD_LIBRARY_PATH");
+ if (libraryPath == null) {
+ libraryPath = openSSLLibPath;
+ } else {
+ libraryPath = libraryPath + ":" + openSSLLibPath;
+ }
+ env.put("LD_LIBRARY_PATH", libraryPath);
+ }
+
+ p = pb.start();
+
+ redirect(new BufferedReader(new InputStreamReader(p.getInputStream())) , System.out, true);
+ redirect(new BufferedReader(new InputStreamReader(p.getErrorStream())), System.err, true);
+
+ Assert.assertTrue(p.isAlive());
+ }
+
+ public void stop() {
+ if (p == null) {
+ throw new IllegalStateException("Not started");
+ }
+ p.destroy();
+
+ try {
+ if (!p.waitFor(30, TimeUnit.SECONDS)) {
+ throw new IllegalStateException("Failed to stop");
+ }
+ } catch (InterruptedException e) {
+ throw new IllegalStateException("Interrupted while waiting to stop", e);
+ }
+ }
+
+
+ private void redirect(final Reader r, final PrintStream os, final boolean swallow) {
+ /*
+ * InputStream will close when process ends. Thread will exit once stream closes.
+ */
+ new Thread( () -> {
+ char[] cbuf = new char[1024];
+ try {
+ int read;
+ while ((read = r.read(cbuf)) > 0) {
+ if (!swallow) {
+ os.print(new String(cbuf, 0, read));
+ }
+ }
+ } catch (IOException ignore) {
+ // Ignore
+ }
+
+ }).start();
+ }
+}
diff --git a/test/org/apache/tomcat/util/net/ocsp/ocsp-responder.lock b/test/org/apache/tomcat/util/net/ocsp/ocsp-responder.lock
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/test/org/apache/tomcat/util/net/user1.jks b/test/org/apache/tomcat/util/net/user1.jks
index 76625a9eab..727de3cccc 100644
Binary files a/test/org/apache/tomcat/util/net/user1.jks and b/test/org/apache/tomcat/util/net/user1.jks differ
diff --git a/test/org/apache/tomcat/util/net/user2-crl.jks b/test/org/apache/tomcat/util/net/user2-crl.jks
new file mode 100644
index 0000000000..068517b598
Binary files /dev/null and b/test/org/apache/tomcat/util/net/user2-crl.jks differ
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -104,6 +104,787 @@
They eventually become mixed with the numbered issues (i.e., numbered
issues do not "pop up" wrt. others).
-->
+<section name="Tomcat 9.0.110-redhat (pmeloni)">
+ <subsection name="Catalina">
+ <changelog>
+ <scode>
+ Refactor generation of the remote user element in the access log to
+ remove unnecessary code. (markt)
+ </scode>
+ <fix>
+ Fix a regression in the previous release that meant <code>?-</code>
+ could appear in the access log rather than <code>?</code> when the query
+ string was present but empty. (markt)
+ </fix>
+ <fix>
+ Failed precondition should make WebDAV DELETE fail. <pr>982</pr>
+ submitted by Mahmoud Alarby. (remm)
+ </fix>
+ <fix>
+ Align the escaping in <code>ExtendedAccessLogValve</code> with the other
+ <code>AccessLogValve</code> implementations. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ <bug>69848</bug>: Fix copy/paste error that meant DELETE
+ requests received via the AJP connector were processed as OPTIONS
+ requests. (markt)
+ </fix>
+ <fix>
+ Avoid various edge cases if <code>Content-Length</code> is set via
+ <code>setHeader(String,String)</code> or
+ <code>addHeader(String,String)</code> with an invalid value by always
+ clearing the previous value whether the new value is valid or not and
+ ignoring any invalid new value. (markt)
+ </fix>
+ <scode>
+ Refactor the calculation of the real index in the HPACK dynamic header
+ table implementation to reduce code duplication. (markt)
+ </scode>
+ <fix>
+ Fix various minor issues with some HTTP/2 stream error messages for
+ HTTP/2. (markt)
+ </fix>
+ <fix>
+ Consistently reject URIs containing <code>NULL</code> bytes when
+ normalizing. (markt)
+ </fix>
+ <fix>
+ Fix a few minor memory leaks on error paths reading TLS keys and
+ certificates when using FFM. (markt)
+ </fix>
+ <fix>
+ Avoid possible NPEs when using a TLS enabled custom connector. (remm)
+ </fix>
+ <fix>
+ Refactor clean-up after HTTP/2 headers have been processed to aid GC
+ after a stream reset. (markt)
+ </fix>
+ <fix>
+ Align HTTP/2 trailer fields with HTTP/1.1 and filter out any fields
+ not permitted in trailers. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <fix>
+ <bug>69993</bug>: Update the URL to the CDDL 1.0 license. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ Add escaping for URI and query string in the access log. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <update>
+ Align buffer reuse of the OpenSSLEngine for tomcat-native with the FFM
+ code. (remm)
+ </update>
+ <fix>
+ Fix an HTTP/2 header frame parsing bug that could result in a connection
+ being closed without a <code>GOAWAY</code> frame if an invalid
+ <code>HEADERS</code> frame was received. (markt)
+ </fix>
+ <fix>
+ <bug>69982</bug>: Fix a bug in the non-blocking flushing code for
+ NIO+TLS that meant that a response may not be fully written until the
+ connection is closed. Pull request <pr>966</pr> provided by Phil Clay.
+ (markt)
+ </fix>
+ <fix>
+ Ensure the HTTP/2 request header read buffer is reset (including
+ restoration to default size) after a stream reset. (markt)
+ </fix>
+ <add>
+ Provide trailer field filtering equivalent to that provided for
+ non-trailer fields. Control characters (excluding TAB), and characters
+ with code points above 255 will be replaced with a space. (markt)
+ </add>
+ <fix>
+ Align OpenSSl FFM behaviour with Tomcat Native for various OCSP edge
+ cases. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Jasper">
+ <changelog>
+ <fix>
+ <bug>69995</bug>: Make dependent ordering predictable. Patch submitted
+ by Jan Luehe. (remm)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Cluster">
+ <changelog>
+ <fix>
+ Reduce log verbosity of the Kubernetes connection attempts and failure.
+ (remm)
+ </fix>
+ <fix>
+ Better error handling for the <code>EncryptInterceptor</code>. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <update>
+ Update bnd to 7.2.3. (markt)
+ </update>
+ <update>
+ Improvements to French translations. (remm)
+ </update>
+ <update>
+ Improvements to Japanese translations provided by tak7iji. (markt)
+ </update>
+ </changelog>
+ </subsection>
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ <bug>69967</bug>: Fix inconsistencies related to
+ <code>Content-Length</code> and <code>Content-Type</code> headers when
+ accessed using the <code>getHeader</code> method and similar. (remm)
+ </fix>
+ <fix>
+ <bug>69940</bug>: Improve redirect handling in the
+ <code>LoadBalancerDrainingValve</code>. (schultz)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ <bug>69938</bug>: Avoid changing the closed state of TLS channel when
+ resetting it after close. (remm)
+ </fix>
+ <add>
+ Add an HTTP configuration setting, <code>noCompressionEncodings</code>,
+ that can be used to control which content encodings will not be
+ compressed when compression is enabled. Based on pull request
+ <pr>914</pr> by Long9725. (markt)
+ </add>
+ <fix>
+ Add size limit for OCSP responses. Based on code submitted by Chenjp.
+ (remm)
+ </fix>
+ <fix>
+ To maintain the documented alignment with the OpenSSL development
+ branch, the use of the aliases <code>SSLv3</code>, <code>EXPORT</code>,
+ <code>EXPORT40</code>, <code>EXPORT56</code>, <code>KRB5</code>,
+ <code>kFZA</code>, <code>aFZA</code>, <code>eFZA</code> and
+ <code>FZA</code> are no longer supported when setting the
+ <code>ciphers</code> attribute of an <code>SSLHostConfig</code> element.
+ (markt)
+ </fix>
+ <fix>
+ To maintain the documented alignment with the OpenSSL development
+ branch, add support for the aliases <code>ARIAGCM</code> and
+ <code>CBC</code>when setting the <code>ciphers</code> attribute of
+ an <code>SSLHostConfig</code> element. (markt)
+ </fix>
+ <add>
+ <bug>69870</bug>: Add a <code>drainTimeout</code> to the HTTP/2
+ <code>UpgradeProtocol</code> element to allow configuration of an
+ time between the two final <code>GOAWAY</code> frames sent by Tomcat
+ when closing am HTTP/2 connection. Pull request <pr>917</pr> provided by
+ Kai Burjack. (markt)
+ </add>
+ <add>
+ Log an information message if an APR Connector is used, recommending
+ that the appropriate NIO Connector is used instead. (markt)
+ </add>
+ <fix>
+ Respect the value for the <code>jdk.tls.namedGroups</code> system
+ property as the default value for the configured group list on the
+ Connector. (remm)
+ </fix>
+ <fix>
+ <bug>69964</bug>: Respect the configured cipher order, which was no
+ longer respected following the addition of TLS 1.3 specific cipher
+ configuration. TLS 1.3 ciphers will always be first in the list. (remm)
+ </fix>
+ <fix>
+ Free the x509 object in the FFM code when getting the peer certificate
+ if getting the bytes from the certificate somehow fails.
+ Pull request <pr>951</pr> provided by Chenjp. (remm)
+ </fix>
+ <fix>
+ Improve HPACK exception use, making sure <code>HpackException</code>
+ is thrown instead of unexpected types. (remm)
+ </fix>
+ <fix>
+ Update the parser for the HTTP <code>Host</code> header and
+ <code>:authority</code> pseudo header to convert the port, if any, to an
+ <code>Integer</code> rather than a <code>Long</code> to be consistent
+ with how port is exposed in the Servlet API. (markt)
+ </fix>
+ <add>
+ To aid the migration from the single <code>ciphers</code> configuration
+ attribute to the use of <code>ciphers</code> and
+ <code>cipherSuites</code>, TLS 1.3 cipher suites listed in the
+ <code>ciphers</code> attribute will be removed from the
+ <code>ciphers</code> attribute and added to the end of the
+ <code>cipherSuites</code> attribute. This behaviour will be removed in
+ Tomcat 12.0.x onwards. (markt)
+ </add>
+ <scode>
+ Replace the external OpenSSL based OCSP responder used during unit tests
+ with a Bouncy Castle based, in-process Java OCSP responder. (markt)
+ </scode>
+ <fix>
+ Relax HTTP/2 header validation and respond to invalid requests with a
+ stream reset or a 400 response as appropriate rather then with a
+ connection reset. (markt)
+ </fix>
+ <fix>
+ Add validation of chunk extensions for chunked transfer encoding.
+ (markt)
+ </fix>
+ <update>
+ Update the recommended version for Tomcat Native to 1.3.7. (markt)
+ </update>
+ <fix>
+ Align the FFM handling of OCSP <code>TRY_LATER</code> responses with
+ Tomcat Native. (remm)
+ </fix>
+ <fix>
+ Free CA certificate after calling <code>SSL_CTX_add_client_CA</code>
+ in the FFM code. Based on code from PR 44 from tomcat-native. (remm)
+ </fix>
+ <fix>
+ Free certificate chain if an error occurs, in the FFM code. (remm)
+ </fix>
+ <fix>
+ Report handshake issues as <code>SSLException</code> in the FFM
+ code, rather than <code>IllegalStateException</code>. (remm)
+ </fix>
+ <fix>
+ Fix case sensitive handling of the protocol host name. (remm)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Jasper">
+ <changelog>
+ <fix>
+ <bug>69948</bug>: Avoid ArrayOutOfBoundsException instead of
+ PropertyNotFoundException when generating a properties not found
+ exception in AstValue. Based on <pr>950</pr> submitted by Jérôme
+ Besnard. (remm)
+ </fix>
+ <add>
+ Add support for specifying Java 27 (with the value <code>27</code>) as
+ the compiler source and/or compiler target for JSP compilation. If used
+ with an Eclipse JDT compiler version that does not support these values,
+ a warning will be logged and the default will be used.
+ (markt)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="Cluster">
+ <changelog>
+ <fix>
+ <bug>69970</bug>: Support raw IPv6 in Kubernetes membership provider
+ for the service host. (remm)
+ </fix>
+ <add>
+ Add support for new algorithms provided by JPA providers to the
+ <code>EncryptInterceptor</code>. (markt)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="WebSocket">
+ <changelog>
+ <fix>
+ <bug>69972</bug>: Remove unwanted space in DIGEST authorization header.
+ Patch submitted by Stefan Kalscheuer in <pr>957</pr>. (remm)
+ </fix>
+ <fix>
+ <bug>69844</bug>: Close the connection with a protocol error if the
+ server sends masked frames. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Web applications">
+ <changelog>
+ <add>
+ <bug>69931</bug>: Add &lt;label&gt; for fields in the HTML manager
+ application. Patch provided by yukitidev. (schultz)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <update>
+ Update the internal fork of Apache Commons BCEL to 6.12.0. (markt)
+ </update>
+ <update>
+ Update Tomcat Native to 1.3.7. (markt)
+ </update>
+ <update>
+ Update Objenesis to 3.5. (markt)
+ </update>
+ <update>
+ Update Byte Buddy to 1.18.7. (markt)
+ </update>
+ <update>
+ Update BND to 7.2.1. (markt)
+ </update>
+ <update>
+ Improvements to French translations. (remm)
+ </update>
+ <update>
+ Improvements to Chinese translations provided by eaststrongox. (markt)
+ </update>
+ <update>
+ Improvements to Japanese translations provided by tak7iji. (markt)
+ </update>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ Prevent concurrent release of <code>OpenSSLEngine</code> resources and
+ the termination of the Tomcat Native library as it can cause crashes
+ during Tomcat shutdown. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <add>
+ Add property "gpg.sign.files" to optionally disable release artefact
+ signing with GPG. (rjung)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ <bug>69623</bug>: Additional fix for the long standing regression that
+ meant that calls to <code>ClassLoader.getResource().getContent()</code>
+ failed when made from within a web application with resource caching
+ enabled if the target resource was packaged in a JAR file. (markt)
+ </fix>
+ <fix>
+ Pull request <pr>923</pr>: Avoid adding multiple CSRF tokens to a URL in
+ the <code>CsrfPreventionFilter</code>. (schultz)
+ </fix>
+ <fix>
+ <bug>69918</bug>: Ensure request parameters are correctly parsed for
+ HTTP/2 requests when the content-length header is not set. (dsoumis)
+ </fix>
+ <update>
+ Update the minimum and recommended versions for Tomcat Native to 1.3.4.
+ (markt)
+ </update>
+ <add>
+ Add a new <code>ssoReauthenticationMode</code> to the Tomcat provided
+ Authenticators that provides a per Authenticator override of the SSO
+ Valve <code>requireReauthentication</code> attribute. (markt)
+ </add>
+ <fix>
+ Ensure URL encoding errors in the Rewrite Valve trigger an exception
+ rather than silently using a replacement character. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ Improve warnings when setting ciphers lists in the FFM code, mirroring
+ the tomcat-native changes. (remm)
+ </fix>
+ <fix>
+ <bug>69910</bug>: Dereference TLS objects right after closing a socket
+ to improve memory efficiency. (remm)
+ </fix>
+ <fix>
+ Relax the JSSE vs OpenSSL configuration style checks on
+ <code>SSLHostConfig</code> to reflect the existing implementation that
+ allows one configuration style to be used for the trust attributes and a
+ different style for all the other attributes. (markt)
+ </fix>
+ <fix>
+ Better warning message when <code>OpenSSLConf</code> configuration
+ elements are used with a JSSE TLS implementation. (markt)
+ </fix>
+ <fix>
+ When using OpenSSL via FFM, don't log a warning about missing CA
+ certificates unless CA certificates were configured and the
+ configuration failed. (markt)
+ </fix>
+ <add>
+ For configuration consistency between OpenSSL and JSSE TLS
+ implementations, TLSv1.3 cipher suites included in the
+ <code>ciphers</code> attribute of an <code>SSLHostConfig</code> are now
+ always ignored (previously they would be ignored with OpenSSL
+ implementations and used with JSSE implementations) and a warning is
+ logged that the cipher suite has been ignored. (markt)
+ </add>
+ <add>
+ Add the <code>ciphersuite</code> attribute to
+ <code>SSLHostConfig</code> to configure the TLSv1.3 cipher suites.
+ (markt)
+ </add>
+ <add>
+ Add OCSP support to JSSE based TLS connectors and make the use of OCSP
+ configurable per connector for both JSSE and OpenSSL based TLS
+ implementations. Align the checks performed by OpenSSL with those
+ performed by JSSE. (markt)
+ </add>
+ <add>
+ Add support for soft failure of OCSP checks with soft failure support
+ disabled by default. (markt)
+ </add>
+ <add>
+ Add support for configuring the verification flags passed to
+ <code>OCSP_basic_verify</code> when using an OpenSSL based TLS
+ implementation. (markt)
+ </add>
+ <fix>
+ Fix OpenSSL FFM code compatibility with LibreSSL versions below 3.5.
+ (remm)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Jasper">
+ <changelog>
+ <fix>
+ <bug>69333</bug>: Correct a regression in the previous fix for
+ <bug>69333</bug> and ensure that <code>reuse()</code> or
+ <code>release()</code> is always called for a tag. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Cluster">
+ <changelog>
+ <add>
+ <bug>62814</bug>: Document that human-readable names may be used for
+ <code>mapSendOptions</code> and align documentation with
+ <code>channelSendOptions</code>. Based on pull request <pr>929</pr> by
+ archan0621. (markt)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="WebSocket">
+ <changelog>
+ <fix>
+ <bug>69920</bug>: When attempting to write to a closed
+ <code>Writer</code> or <code>OutputStream</code> obtained from a
+ WebSocket session, throw an <code>IOException</code> rather than an
+ <code>IllegalStateExcpetion</code> as required by <code>Writer</code>
+ and strongly suggested by <code>OutputStream</code>. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <add>
+ Add <code>test.silent</code> property to suppress JUnit console output
+ during test execution. Useful for cleaner console output when running
+ tests with multiple threads. (csutherl)
+ </add>
+ <update>
+ Update the internal fork of Commons Pool to 2.13.1. (markt)
+ </update>
+ <update>
+ Update the internal fork of Commons DBCP to 2.14.0. (markt)
+ </update>
+ <update>
+ Update Commons Daemon to 1.5.1. (markt)
+ </update>
+ <update>
+ Update ByteBuddy to 1.18.3. (markt)
+ </update>
+ <update>
+ Update UnboundID to 7.0.4. (markt)
+ </update>
+ <update>
+ Update Checkstyle to 12.3.1. (markt)
+ </update>
+ <add>
+ Improvements to French translations. (markt)
+ </add>
+ <add>
+ Improvements to Japanese translations provided by tak7iji. (markt)
+ </add>
+ <add>
+ Improvements to Chinese translations provided by Yang. vincent.h and
+ yong hu. (markt)
+ </add>
+ <update>
+ Update Tomcat Native to 1.3.5. (markt)
+ </update>
+ <update>
+ Update bnd to 7.2.0. (markt)
+ </update>
+ </changelog>
+ </subsection>
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ <bug>69871</bug>: Increase log level to INFO for missing configuration
+ for the rewrite valve. (remm)
+ </fix>
+ <fix>
+ Add log warnings for additional Host <code>appBase</code> suspicious
+ values. (remm)
+ </fix>
+ <fix>
+ Remove hard dependency on tomcat-jni.jar for catalina.jar.
+ <code>org.apache.catalina.Connector</code> no longer requires
+ <code>org.apache.tomcat.jni.AprStatus</code> to be present. (markt)
+ </fix>
+ <add>
+ Add the ability to use a custom function to generate the client
+ identifier in the <code>CrawlerSessionManagerValve</code>. This is only
+ available programmatically. Pull request <pr>902</pr> by Brian Matzon.
+ (markt)
+ </add>
+ <fix>
+ Change the SSO reauthentication behaviour for SPNEGO authentication so
+ that a normal SPNEGO authentication is performed if the SSL Valve is
+ configured with reauthentication enabled. This is so that the delegated
+ credentials will be available to the web application. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ Don't log an incorrect certificate <code>KeyStore</code> location when
+ creating a TLS connector if the <code>KeyStore</code> instance has been
+ set directly on the connector. (markt)
+ </fix>
+ <fix>
+ HTTP/0.9 only allows GET as the HTTP method. (remm)
+ </fix>
+ <add>
+ Add <code>strictSni</code> attribute on the <code>Connector</code> to
+ allow matching the <code>SSLHostConfig</code> configuration associated
+ with the SNI host name to the <code>SSLHostConfig</code> configuration
+ matched from the HTTP protocol host name. Non matching configurations
+ will cause the request to be rejected. The attribute default value is
+ <code>true</code>, enabling the matching. (remm)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="Jasper">
+ <changelog>
+ <fix>
+ <bug>69877</bug>: Catch IllegalArgumentException when processing URIs
+ when creating the classpath to handle invalid URIs. (remm)
+ </fix>
+ <fix>
+ Fix populating the classpath with the webapp classloader repositories.
+ (remm)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Clustering">
+ <changelog>
+ <fix>
+ Correct a regression introduced in 9.0.109 that broke some clustering
+ configurations. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Web Applications">
+ <changelog>
+ <fix>
+ Manager: Fix abrupt truncation of the HTML and JSON complete server
+ status output if one or more of the web applications failed to start.
+ (schultz)
+ </fix>
+ <add>
+ Manager: Include web application state in the HTML and JSON complete
+ server status output. (markt)
+ </add>
+ <add>
+ Documentation: Expand the documentation to better explain when OCSP is
+ supported and when it is not. (markt)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="jdbc-pool">
+ <changelog>
+ <fix>
+ <bug>64083</bug>: If the underlying connection has been closed, don't
+ add it to the pool when it is returned. Pull request <pr>235</pr> by
+ Alex Panchenko. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <add>
+ Add test profile system for selective test execution. Profiles can be
+ specified via <code>-Dtest.profile=&lt;name&gt;</code> to run specific
+ test subsets without using patterns directly. Profile patterns are
+ defined in <code>test-profiles.properties</code>. (csutherl)
+ </add>
+ <update>
+ Update file extension to media type mappings to align with the current
+ list used by the Apache Web Server (httpd). (markt)
+ </update>
+ <update>
+ Update Commons Daemon to 1.5.0. (markt)
+ </update>
+ <update>
+ Update Byte Buddy to 1.18.2. (markt)
+ </update>
+ <update>
+ Update Checkstyle to 12.2.0. (markt)
+ </update>
+ <add>
+ Improvements to Spanish translations provided by White Vogel. (markt)
+ </add>
+ <add>
+ Improvements to French translations. (remm)
+ </add>
+ <add>
+ Improvements to Japanese translations provided by tak7iji. (markt)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ When generating the class path in the Loader, re-order the check on
+ individual class path components to avoid a potential
+ <code>NullPointerException</code>. Identified by Coverity Scan. (markt)
+ </fix>
+ <fix>
+ Fix SSL socket factory configuration in the JNDI realm. Based on pull
+ request <pr>915</pr> by Joshua Rogers. (remm)
+ </fix>
+ <update>
+ Add an attribute, <code>digestInRfc3112Order</code>, to
+ <code>MessageDigestCredentialHandler</code> to control the order in
+ which the credential and salt are digested. By default, the current,
+ non-RFC 3112 compliant, order of salt then credential will be used. This
+ default will change in Tomcat 12 to the RFC 3112 compliant order of
+ credential then salt. (markt)
+ </update>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ Graceful failure for OCSP on BoringSSL in the FFM code. (remm)
+ </fix>
+ <fix>
+ <bug>69866</bug>: Fix a memory leak when using a trust store with the
+ OpenSSL provider. Pull request <pr>912</pr> by aogburn. (markt)
+ </fix>
+ <fix>
+ Fix AJP message length check. Pull request <pr>916</pr> by Joshua
+ Rogers. (remm)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Jasper">
+ <changelog>
+ <fix>
+ <bug>69862</bug>: Avoid NPE unwrapping Servlet exception which would
+ hide some exception details. Patch submitted by Eric Blanquer. (remm)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Other">
+ <changelog>
+ <update>
+ Update the internal fork of Apache Commons BCEL to 6.11.0. (markt)
+ </update>
+ <update>
+ Update to Byte Buddy 1.17.8. (markt)
+ </update>
+ <update>
+ Update to Checkstyle 12.1.1. (markt)
+ </update>
+ <update>
+ Update to Jacoco 0.8.14. (markt)
+ </update>
+ <update>
+ Update to SpotBugs 4.9.8. (markt)
+ </update>
+ <update>
+ Update to JSign 7.4. (markt)
+ </update>
+ <update>
+ Update Maven Resolver Ant Tasks to 1.6.0. (rjung)
+ </update>
+ <add>
+ Improvements to French translations. (remm)
+ </add>
+ <add>
+ Improvements to Japanese translations provided by tak7iji. (markt)
+ </add>
+ </changelog>
+ </subsection>
+ <subsection name="Catalina">
+ <changelog>
+ <fix>
+ Log warnings when the SSO configuration does not comply with the
+ documentation. (remm)
+ </fix>
+ <update>
+ Deprecate the <code>RemoteAddrFilter</code> and
+ <code>RemoteAddrValve</code> in favour of the
+ <code>RemoteCIDRFilter</code> and <code>RemoteCIDRValve</code>. (markt)
+ </update>
+ <fix>
+ <bug>69837</bug>: Fix corruption of the class path generated by the
+ Loader when running on Windows. (markt)
+ </fix>
+ <fix>
+ Reject requests that map to invalid Windows file names earlier. (markt)
+ </fix>
+ <fix>
+ <bug>69839</bug>: Ensure that changes to session IDs (typically after
+ authentication) are promulgated to the SSO Valve to ensure that SSO
+ entries are fully clean-up on session expiration. Patch provided by Kim
+ Johan Andersson. (markt)
+ </fix>
+ <fix>
+ Fix a race condition in the creation of the storage location for the
+ <code>FileStore</code>. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="Coyote">
+ <changelog>
+ <fix>
+ <bug>69848</bug>: Fix copy/paste errors in 9.0.110 that meant DELETE
+ requests received via the AJP connector were processed as OPTIONS
+ requests and PROPFIND requests were processed as TRACE. (markt)
+ </fix>
+ <fix>
+ Various OCSP processing issues in the OpenSSL FFM code. (dsoumis)
+ </fix>
+ </changelog>
+ </subsection>
+ <subsection name="WebSocket">
+ <changelog>
+ <fix>
+ <bug>69845</bug>: When using <code>permessage-deflate</code> with Java
+ 25 onwards, handle the underlying <code>Inflater</code> and/or
+ <code>Deflater</code> throwing <code>IllegalStateException</code>
+ when closed rather than <code>NullPointerException</code> as they do in
+ Java 24 and earlier. (markt)
+ </fix>
+ </changelog>
+ </subsection>
+</section>
<section name="Tomcat 9.0.110 (remm)" rtext="">
<subsection name="Catalina">
<changelog>