This is an automated email from the ASF dual-hosted git repository.

remm pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new 175cdf4bb1 Avoid OpenSSL X509_STORE_CTX_get0_current_issuer function
175cdf4bb1 is described below

commit 175cdf4bb133fdd3e559738e7ac43c4ba9b0158b
Author: remm <[email protected]>
AuthorDate: Tue Oct 14 12:31:26 2025 +0200

    Avoid OpenSSL X509_STORE_CTX_get0_current_issuer function
    
    It is not documented and was then removed in BoringSSL.
    Use X509_STORE_CTX_get1_issuer instead, which is documented and
    available everywhere.
    OCSP is different in BoringSSL, so skip it in the spot where it makes
    sense to do it.
    Skip one (failing) test for BoringSSL.
---
 .../util/net/openssl/panama/OpenSSLEngine.java     | 83 ++++++++++++----------
 java/org/apache/tomcat/util/openssl/openssl_h.java | 34 ++++-----
 .../tomcat/util/net/ocsp/TestOcspIntegration.java  |  5 +-
 webapps/docs/changelog.xml                         |  7 ++
 4 files changed, 73 insertions(+), 56 deletions(-)

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 b1e7855530..a2cab51f1d 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;
@@ -1200,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);
                         }
                     }
                 }
@@ -1279,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;
diff --git a/java/org/apache/tomcat/util/openssl/openssl_h.java 
b/java/org/apache/tomcat/util/openssl/openssl_h.java
index 039126f12d..44edd4521d 100644
--- a/java/org/apache/tomcat/util/openssl/openssl_h.java
+++ b/java/org/apache/tomcat/util/openssl/openssl_h.java
@@ -3604,52 +3604,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$);
         }
diff --git a/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java 
b/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
index f7395be35f..44bcad84db 100644
--- a/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
+++ b/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
@@ -164,6 +164,8 @@ public class TestOcspIntegration extends TomcatBaseTest {
 
     @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));
     }
@@ -228,9 +230,6 @@ public class TestOcspIntegration extends TomcatBaseTest {
                                 String sslImplementationName, boolean 
useOpenSSL)
             throws Exception {
 
-        Assume.assumeFalse("BoringSSL does not allow supporting OCSP",
-                TesterSupport.isOpenSSLVariant(sslImplementationName, 
OpenSSLStatus.Name.BORINGSSL));
-
         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));
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index ee2bbb5cd8..221f0ea15c 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -114,6 +114,13 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="Coyote">
+    <changelog>
+      <fix>
+        Graceful failure for OCSP on BoringSSL in the FFM code. (remm)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Other">
     <changelog>
       <update>


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to