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

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


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

commit f8113f143d2123c609f2112bbcb4f1773f23c016
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 d400570079..60f9c61524 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 ad57e51fd1..dfef9e2e2c 100644
--- a/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
+++ b/test/org/apache/tomcat/util/net/ocsp/TestOcspIntegration.java
@@ -163,6 +163,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));
     }
@@ -232,9 +234,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 8a1f106c6f..8340d5a134 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