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

markt-asf 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 7b3d39addd Revert "Review "Refactor certificate loading""
7b3d39addd is described below

commit 7b3d39addd7d24e4e6034830182fd26de335da37
Author: Mark Thomas <[email protected]>
AuthorDate: Tue Nov 3 11:38:11 2026 +0000

    Revert "Review "Refactor certificate loading""
    
    This reverts commit 1b164484b95fc732c2c8e1fe8124857295c5ef96.
---
 build.xml                                          | 29 +-------
 .../util/net/openssl/panama/CertificateLoader.java | 66 +++++-------------
 .../tomcat/util/net/TestSSLHostConfigCompat.java   | 61 ----------------
 test/org/apache/tomcat/util/net/TesterSupport.java | 37 ----------
 .../net/openssl/panama/TestCertificateLoader.java  | 81 ----------------------
 5 files changed, 19 insertions(+), 255 deletions(-)

diff --git a/build.xml b/build.xml
index aa1b5f87ef..0138bb3247 100644
--- a/build.xml
+++ b/build.xml
@@ -218,11 +218,6 @@
   <!-- set above.                                                            
-->
   <property name="test.jvmarg.egd" value="-Dignore" />
 
-  <!-- Flag for building FFM and associated tests -->
-  <condition property="has-ffm">
-    <javaversion atleast="${release.java.version}" />
-  </condition>
-
   <!-- Location of OpenSSL binary (file name, not directory) -->
   <!-- The OpenSSL tests cases be disabled by specifying an invalid path here 
-->
   <property name="test.openssl.path" value="" />
@@ -1058,6 +1053,9 @@
       <exclude name="org/apache/tomcat/util/openssl/**"/>
     </javac>
     <!-- Compile internal server components that use FFM -->
+    <condition property="has-ffm">
+      <javaversion atleast="${release.java.version}" />
+    </condition>
     <javac srcdir="java" destdir="${tomcat.classes}"
            debug="${compile.debug}"
            deprecation="${compile.deprecation}"
@@ -1949,24 +1947,6 @@
       <!-- Exclude these by default as Gump can't run them because the -->
       <!-- classes on which they depend are not in any output JAR.     -->
       <exclude name="org/apache/tomcat/buildutil/**" 
unless="test.includeBuildutil"/>
-      <!-- Exclude FFM tests as they are compiled below -->
-      <exclude name="org/apache/tomcat/util/net/openssl/panama/**"/>
-      <exclude name="org/apache/tomcat/util/openssl/**"/>
-    </javac>
-    <!-- Compile tests that use FFM -->
-    <javac srcdir="test" destdir="${test.classes}"
-           debug="${compile.debug}"
-           deprecation="${compile.deprecation}"
-           release="${release.java.version}"
-           encoding="ISO-8859-1"
-           includeAntRuntime="true"
-           if:set="has-ffm" >
-      <!-- Uncomment this to show unchecked warnings:
-      <compilerarg value="-Xlint:unchecked"/>
-      -->
-      <classpath refid="tomcat.test.classpath" />
-      <include name="org/apache/tomcat/util/net/openssl/panama/**"/>
-      <include name="org/apache/tomcat/util/openssl/**"/>
     </javac>
     <copy todir="${test.classes}">
       <fileset dir="test">
@@ -2311,9 +2291,6 @@
               <exclude name="**/integration/**" 
unless="test.includeIntegration" />
               <!-- Exclude tests that require large heaps -->
               <exclude name="**/*LargeHeap.java" 
unless="${test.includeLargeHeap}" />
-              <!-- Exclude FFM tests unless FFM has been compiled -->
-              <exclude name="org/apache/tomcat/util/net/openssl/panama/**" 
unless="has-ffm"/>
-              <exclude name="org/apache/tomcat/util/openssl/**" 
unless="has-ffm"/>
             </fileset>
           </batchtest>
         </junit>
diff --git 
a/java/org/apache/tomcat/util/net/openssl/panama/CertificateLoader.java 
b/java/org/apache/tomcat/util/net/openssl/panama/CertificateLoader.java
index de27351e1b..0dc416c8d1 100644
--- a/java/org/apache/tomcat/util/net/openssl/panama/CertificateLoader.java
+++ b/java/org/apache/tomcat/util/net/openssl/panama/CertificateLoader.java
@@ -371,9 +371,19 @@ public final class CertificateLoader {
             return null;
         }
 
-        // Append the separately configured chain to the intermediates (if any)
-        // read from the certificate file.
-        chain = appendChainFile(chainFile, hostName, chain);
+        if (chainFile != null) {
+            byte[] chainBytes = readConfigFileBytes(chainFile);
+            if (chainBytes == null) {
+                
log.warn(sm.getString("certificateLoader.certificateLoadFailed", hostName, 
chainFile));
+            } else {
+                // Append the separately configured chain to the intermediates
+                // (if any) read from the certificate file.
+                MemorySegment[] extraChain = 
readX509ChainFromBytes(chainBytes);
+                chain = Arrays.copyOf(chain, chain.length + extraChain.length);
+                System.arraycopy(extraChain, 0, chain, chain.length - 
extraChain.length,
+                        extraChain.length);
+            }
+        }
 
         return new CertificateEntry(leaf, key, chain);
     }
@@ -409,15 +419,8 @@ public final class CertificateLoader {
             KeyStore keyStore = KeyStore.getInstance("PKCS12");
             keyStore.load(new ByteArrayInputStream(fileBytes),
                     (keyPassToUse != null) ? keyPassToUse.toCharArray() : 
null);
-            CertificateEntry entry = loadJavaKeyStoreKey(keyStore, 
certificate.getCertificateKeyAlias(),
-                    keyPassToUse, certFile, hostName, arena);
-            if (entry != null && certificate.getCertificateChainFile() != 
null) {
-                // Append the separately configured chain to the intermediates
-                // (if any) held by the bundle.
-                entry = new CertificateEntry(entry.leaf, entry.key,
-                        appendChainFile(certificate.getCertificateChainFile(), 
hostName, entry.chain));
-            }
-            return entry;
+            return loadJavaKeyStoreKey(keyStore, 
certificate.getCertificateKeyAlias(), keyPassToUse,
+                    certFile, hostName, arena);
         } catch (IOException e) {
             // Covers a wrong password: the JDK fails the MAC check
             log.warn(sm.getString("certificateLoader.certificateLoadFailed", 
hostName,
@@ -603,32 +606,6 @@ public final class CertificateLoader {
 
     // ------------------------------------- File and native reading helpers
 
-    /**
-     * Reads the certificates of the configured chain file and appends them to 
the given chain. A chain file that
-     * cannot be read is logged and ignored.
-     *
-     * @param chainFile The location of the chain file, or {@code null} if 
none is configured
-     * @param hostName  The host name the certificate belongs to, used for 
logging
-     * @param chain     The certificates (owned by the caller) to append to
-     *
-     * @return the chain with the certificates of the chain file appended, 
which owns all the native objects
-     */
-    private static MemorySegment[] appendChainFile(String chainFile, String 
hostName, MemorySegment[] chain) {
-        if (chainFile == null) {
-            return chain;
-        }
-        byte[] chainBytes = readConfigFileBytes(chainFile);
-        if (chainBytes == null) {
-            log.warn(sm.getString("certificateLoader.certificateLoadFailed", 
hostName, chainFile));
-            return chain;
-        }
-        MemorySegment[] extraChain = readX509ChainFromBytes(chainBytes);
-        MemorySegment[] result = Arrays.copyOf(chain, chain.length + 
extraChain.length);
-        System.arraycopy(extraChain, 0, result, chain.length, 
extraChain.length);
-        return result;
-    }
-
-
     /**
      * An OpenSSL ENGINE needs a real file. Resolves a configured location, 
relative to the Catalina base if
      * necessary, to the path of an existing file.
@@ -964,19 +941,8 @@ public final class CertificateLoader {
         KeyStore keyStore = KeyStore.getInstance("PKCS12");
         keyStore.load(new ByteArrayInputStream(fileBytes),
                 (password != null) ? password.toCharArray() : null);
-        X509Certificate[] bundleChain = getCertificateChainKeyStore(keyStore,
+        return getCertificateChainKeyStore(keyStore,
                 certificate.getCertificateKeyAlias());
-        String chainFile = certificate.getCertificateChainFile();
-        if (bundleChain == null || chainFile == null) {
-            return bundleChain;
-        }
-        // A separately configured chain file is appended to the chain
-        List<X509Certificate> chain = new 
ArrayList<>(Arrays.asList(bundleChain));
-        byte[] chainBytes = readConfigFileBytes(chainFile);
-        if (chainBytes != null) {
-            addX509Certificates(chain, 
CertificateFactory.getInstance("X.509"), chainBytes);
-        }
-        return chain.toArray(new X509Certificate[0]);
     }
 
 
diff --git a/test/org/apache/tomcat/util/net/TestSSLHostConfigCompat.java 
b/test/org/apache/tomcat/util/net/TestSSLHostConfigCompat.java
index cedb4b0206..c223dc3af9 100644
--- a/test/org/apache/tomcat/util/net/TestSSLHostConfigCompat.java
+++ b/test/org/apache/tomcat/util/net/TestSSLHostConfigCompat.java
@@ -17,17 +17,10 @@
 package org.apache.tomcat.util.net;
 
 import java.io.File;
-import java.security.cert.Certificate;
-import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Test;
@@ -268,60 +261,6 @@ public class TestSSLHostConfigCompat extends 
TomcatBaseTest {
     }
 
 
-    /*
-     * The certificates of the chain file must be sent after the certificate 
of a PKCS#12 bundle just as they are for a
-     * PEM certificate. The bundle only holds the leaf certificate so the CA 
certificate can only come from the chain
-     * file. This is a feature of the OpenSSL FFM implementation which is the 
only one that reads PKCS#12 bundles
-     * through the certificate file.
-     */
-    @Test
-    public void testHostRSAWithPkcs12AndChainFile() throws Exception {
-        Assume.assumeTrue("Only needs to be run once", storeType == 
StoreType.PEM);
-        Assume.assumeTrue("Only applies to the OpenSSL FFM implementation",
-                
"org.apache.tomcat.util.net.openssl.panama.OpenSSLImplementation".equals(sslImplementationName));
-
-        SSLHostConfig sslHostConfig = getSSLHostConfig();
-        SSLHostConfigCertificate certificate = new 
SSLHostConfigCertificate(sslHostConfig, Type.RSA);
-        
certificate.setCertificateFile(TesterSupport.createLocalhostRsaLeafOnlyPkcs12().getAbsolutePath());
-        certificate.setCertificateKeyPassword(TesterSupport.JKS_PASS);
-        
certificate.setCertificateChainFile(getPath(TesterSupport.CA_CERT_PEM));
-        sslHostConfig.addCertificate(certificate);
-
-        Tomcat tomcat = getTomcatInstance();
-        tomcat.start();
-
-        // Trust everything, the test is about what the server sends
-        SSLContext clientContext = SSLContext.getInstance("TLS");
-        clientContext.init(null, new TrustManager[] { new X509TrustManager() {
-            @Override
-            public void checkClientTrusted(X509Certificate[] chain, String 
authType) {
-                // NO-OP
-            }
-
-            @Override
-            public void checkServerTrusted(X509Certificate[] chain, String 
authType) {
-                // NO-OP
-            }
-
-            @Override
-            public X509Certificate[] getAcceptedIssuers() {
-                return new X509Certificate[0];
-            }
-        } }, null);
-
-        try (SSLSocket socket = (SSLSocket) 
clientContext.getSocketFactory().createSocket("localhost", getPort())) {
-            socket.setSoTimeout(5000);
-            socket.startHandshake();
-            Certificate[] peerCertificates = 
socket.getSession().getPeerCertificates();
-
-            Assert.assertEquals("The chain file was not sent", 2, 
peerCertificates.length);
-            X509Certificate leaf = (X509Certificate) peerCertificates[0];
-            X509Certificate ca = (X509Certificate) peerCertificates[1];
-            Assert.assertEquals(leaf.getIssuerX500Principal(), 
ca.getSubjectX500Principal());
-        }
-    }
-
-
     private void configureHostRSA() {
         SSLHostConfig sslHostConfig = getSSLHostConfig();
         switch (storeType) {
diff --git a/test/org/apache/tomcat/util/net/TesterSupport.java 
b/test/org/apache/tomcat/util/net/TesterSupport.java
index 9681bb62ca..3592567592 100644
--- a/test/org/apache/tomcat/util/net/TesterSupport.java
+++ b/test/org/apache/tomcat/util/net/TesterSupport.java
@@ -18,10 +18,8 @@ package org.apache.tomcat.util.net;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
@@ -294,41 +292,6 @@ public final class TesterSupport {
         return ks;
     }
 
-    /**
-     * Creates a PKCS#12 bundle (the file name ends with {@code .pkcs12}) that 
holds the localhost RSA private key and
-     * only its own certificate, i.e. without the certificate of the CA that 
issued it. The bundle is protected with
-     * {@link #JKS_PASS}.
-     *
-     * @return the bundle, which is deleted when the JVM exits
-     *
-     * @throws Exception if the bundle could not be created
-     */
-    public static File createLocalhostRsaLeafOnlyPkcs12() throws Exception {
-        KeyStore jks = getKeyStore(LOCALHOST_RSA_JKS);
-        String alias = null;
-        Enumeration<String> aliases = jks.aliases();
-        while (alias == null && aliases.hasMoreElements()) {
-            String candidate = aliases.nextElement();
-            if (jks.isKeyEntry(candidate)) {
-                alias = candidate;
-            }
-        }
-        Assert.assertNotNull(alias);
-        PrivateKey key = (PrivateKey) jks.getKey(alias, 
JKS_PASS.toCharArray());
-        Certificate leaf = jks.getCertificateChain(alias)[0];
-
-        KeyStore pkcs12 = KeyStore.getInstance("PKCS12");
-        pkcs12.load(null, null);
-        pkcs12.setKeyEntry("localhost", key, JKS_PASS.toCharArray(), new 
Certificate[] { leaf });
-
-        File file = File.createTempFile("tomcat-test-", ".pkcs12");
-        file.deleteOnExit();
-        try (OutputStream os = new FileOutputStream(file)) {
-            pkcs12.store(os, JKS_PASS.toCharArray());
-        }
-        return file;
-    }
-
     protected static boolean isClientRenegotiationSupported(Tomcat tomcat) {
         // Disabled for Tomcat Native (part of response to CVE-2009-3555)
         // Only JRE provided JSSE implementation supports this
diff --git 
a/test/org/apache/tomcat/util/net/openssl/panama/TestCertificateLoader.java 
b/test/org/apache/tomcat/util/net/openssl/panama/TestCertificateLoader.java
deleted file mode 100644
index 62ba3f6a04..0000000000
--- a/test/org/apache/tomcat/util/net/openssl/panama/TestCertificateLoader.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.openssl.panama;
-
-import java.io.File;
-import java.security.cert.X509Certificate;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.apache.tomcat.util.net.SSLHostConfig;
-import org.apache.tomcat.util.net.SSLHostConfigCertificate;
-import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
-import org.apache.tomcat.util.net.TesterSupport;
-
-/*
- * Only the parts of CertificateLoader that do not need the native OpenSSL 
library are tested here. Loading into
- * native objects is covered by the tests that start a connector that uses the 
OpenSSL FFM implementation.
- */
-public class TestCertificateLoader {
-
-    private static SSLHostConfigCertificate createPkcs12Certificate(String 
chainFile) throws Exception {
-        SSLHostConfig sslHostConfig = new SSLHostConfig();
-        SSLHostConfigCertificate certificate = new 
SSLHostConfigCertificate(sslHostConfig, Type.RSA);
-        
certificate.setCertificateFile(TesterSupport.createLocalhostRsaLeafOnlyPkcs12().getAbsolutePath());
-        certificate.setCertificateKeyPassword(TesterSupport.JKS_PASS);
-        if (chainFile != null) {
-            certificate.setCertificateChainFile(new 
File(chainFile).getAbsolutePath());
-        }
-        return certificate;
-    }
-
-
-    @Test
-    public void testGetCertificateChainPkcs12() throws Exception {
-        X509Certificate[] chain = 
CertificateLoader.getCertificateChain(createPkcs12Certificate(null));
-
-        // The bundle only holds the leaf certificate
-        Assert.assertNotNull(chain);
-        Assert.assertEquals(1, chain.length);
-    }
-
-
-    /*
-     * A separately configured chain file is appended to the chain of the 
bundle, as it is for a PEM certificate.
-     */
-    @Test
-    public void testGetCertificateChainPkcs12WithChainFile() throws Exception {
-        X509Certificate[] chain =
-                
CertificateLoader.getCertificateChain(createPkcs12Certificate(TesterSupport.CA_CERT_PEM));
-
-        Assert.assertNotNull(chain);
-        Assert.assertEquals(2, chain.length);
-        Assert.assertEquals(chain[0].getIssuerX500Principal(), 
chain[1].getSubjectX500Principal());
-    }
-
-
-    @Test
-    public void testGetCertificateChainPkcs12WithMissingChainFile() throws 
Exception {
-        X509Certificate[] chain = CertificateLoader.getCertificateChain(
-                
createPkcs12Certificate("test/org/apache/tomcat/util/net/does-not-exist.pem"));
-
-        // A chain file that cannot be read is ignored, as it is when loading 
the certificate
-        Assert.assertNotNull(chain);
-        Assert.assertEquals(1, chain.length);
-    }
-}


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

Reply via email to