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

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


The following commit(s) were added to refs/heads/main by this push:
     new 84afdb004c Redo loading certificate chain
84afdb004c is described below

commit 84afdb004cca8a475fa6f5505652e1fba3c693b5
Author: remm <r...@apache.org>
AuthorDate: Tue Nov 14 15:31:44 2023 +0100

    Redo loading certificate chain
    
    Use Java for loading the file, then a memory BIO to load the
    certificates one by one.
---
 .../util/net/openssl/panama/OpenSSLContext.java    | 38 ++++++++++++++++++----
 java/org/apache/tomcat/util/openssl/openssl_h.java |  8 +++++
 res/openssl/openssl-tomcat.conf                    |  1 +
 webapps/docs/changelog.xml                         |  8 +++++
 4 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java 
b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
index aeda3b0232..1a70d72c63 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
@@ -1114,7 +1114,7 @@ public class OpenSSLContext implements 
org.apache.tomcat.util.net.SSLContext {
                              *# define ERR_SYSTEM_MASK                
((unsigned int)INT_MAX)
                              *# define ERR_REASON_MASK                0X7FFFFF
                              */
-                            ((ERR_peek_last_error() & 0X7FFFFF) == 
PEM_R_NO_START_LINE())) {
+                            ((ERR_peek_last_error() & ERR_REASON_MASK()) == 
PEM_R_NO_START_LINE())) {
                         ERR_clear_error();
                         BIO_reset(certificateBIO);
                         cert = d2i_X509_bio(certificateBIO, 
MemorySegment.NULL);
@@ -1190,15 +1190,41 @@ public class OpenSSLContext implements 
org.apache.tomcat.util.net.SSLContext {
                         EC_GROUP_free(ecparams);
                     }
                 }
-                // FIXME: Ideally these should be loaded in Java but still 
processed through OpenSSL
                 // Set certificate chain file
                 if (certificate.getCertificateChainFile() != null) {
-                    var certificateChainFileNative =
-                            
localArena.allocateFrom(SSLHostConfig.adjustRelativePath(certificate.getCertificateChainFile()));
+                    byte[] certificateChainBytes = null;
+                    try (Resource resource = 
ConfigFileLoader.getSource().getResource(certificate.getCertificateChainFile()))
 {
+                        certificateChainBytes = 
resource.getInputStream().readAllBytes();
+                    } catch (IOException e) {
+                        
log.error(sm.getString("openssl.errorLoadingCertificate", 
certificate.getCertificateChainFile()), e);
+                        return false;
+                    }
                     // SSLContext.setCertificateChainFile(state.ctx,
                     //        
SSLHostConfig.adjustRelativePath(certificate.getCertificateChainFile()), false);
-                    if (SSL_CTX_use_certificate_chain_file(state.sslCtx, 
certificateChainFileNative) <= 0) {
-                        
log.error(sm.getString("openssl.errorLoadingCertificate", 
certificate.getCertificateChainFile()));
+                    MemorySegment certificateChainBytesNative = 
localArena.allocateFrom(ValueLayout.JAVA_BYTE, certificateChainBytes);
+                    MemorySegment certificateChainBIO = BIO_new(BIO_s_mem());
+                    try {
+                        if (BIO_write(certificateChainBIO, 
certificateChainBytesNative, certificateChainBytes.length) <= 0) {
+                            
log.error(sm.getString("openssl.errorLoadingCertificate", "[0]:" + 
certificate.getCertificateChainFile()));
+                            return false;
+                        }
+                        MemorySegment certChainEntry =
+                                PEM_read_bio_X509_AUX(certificateChainBIO, 
MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL);
+                        while (!MemorySegment.NULL.equals(certChainEntry)) {
+                            if (SSL_CTX_add0_chain_cert(state.sslCtx, 
certChainEntry) <= 0) {
+                                
log.error(sm.getString("openssl.errorLoadingCertificate", "[1]:" + 
certificate.getCertificateChainFile()));
+                            }
+                            certChainEntry =
+                                    PEM_read_bio_X509_AUX(certificateChainBIO, 
MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL);
+                        }
+                        // EOF is accepted, otherwise log an error
+                        if ((ERR_peek_last_error() & ERR_REASON_MASK()) == 
PEM_R_NO_START_LINE()) {
+                            ERR_clear_error();
+                        } else {
+                            
log.error(sm.getString("openssl.errorLoadingCertificate", "[2]:" + 
certificate.getCertificateChainFile()));
+                        }
+                    } finally {
+                        BIO_free(certificateChainBIO);
                     }
                 }
                 // Set revocation
diff --git a/java/org/apache/tomcat/util/openssl/openssl_h.java 
b/java/org/apache/tomcat/util/openssl/openssl_h.java
index 0fde0bf82d..1115a7737d 100644
--- a/java/org/apache/tomcat/util/openssl/openssl_h.java
+++ b/java/org/apache/tomcat/util/openssl/openssl_h.java
@@ -594,6 +594,14 @@ public class openssl_h  {
     public static int SSL_CTRL_SET_MAX_PROTO_VERSION() {
         return (int)124L;
     }
+    /**
+     * {@snippet :
+     * #define ERR_REASON_MASK 8388607
+     * }
+     */
+    public static int ERR_REASON_MASK() {
+        return (int)8388607L;
+    }
     /**
      * {@snippet :
      * #define OCSP_RESPONSE_STATUS_SUCCESSFUL 0
diff --git a/res/openssl/openssl-tomcat.conf b/res/openssl/openssl-tomcat.conf
index 9aabb7914b..a44f2f7ec3 100644
--- a/res/openssl/openssl-tomcat.conf
+++ b/res/openssl/openssl-tomcat.conf
@@ -93,6 +93,7 @@
 --include-function ERR_error_string                        # header: 
/usr/include/openssl/err.h
 --include-function ERR_get_error                           # header: 
/usr/include/openssl/err.h
 --include-function ERR_peek_last_error                     # header: 
/usr/include/openssl/err.h
+--include-constant ERR_REASON_MASK                         # header: 
/usr/include/openssl/err.h
 
 #### Extracted from: /usr/include/openssl/evp.h
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 4c4b5cb0c2..f1df89f628 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -105,6 +105,14 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 11.0.0-M15 (markt)" rtext="in development">
+  <subsection name="Coyote">
+    <changelog>
+      <fix>
+        Use Java code to load certificate chain when using OpenSSL through
+        the FFM API. (remm)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Other">
     <changelog>
       <update>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to