This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 4b124cb4005f49d6a2d1d8b8f8a12c8778b0a659 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Jun 1 15:33:02 2022 +0100 Enable the use of Tomcat Native with OpenSSL 3 using the FIPS provider --- .../apache/catalina/core/AprLifecycleListener.java | 81 +++++++++++++++------- .../apache/catalina/core/LocalStrings.properties | 2 + webapps/docs/config/listeners.xml | 22 +++--- 3 files changed, 71 insertions(+), 34 deletions(-) diff --git a/java/org/apache/catalina/core/AprLifecycleListener.java b/java/org/apache/catalina/core/AprLifecycleListener.java index 35c83facce..d64fedc2bd 100644 --- a/java/org/apache/catalina/core/AprLifecycleListener.java +++ b/java/org/apache/catalina/core/AprLifecycleListener.java @@ -76,6 +76,11 @@ public class AprLifecycleListener implements LifecycleListener { // ---------------------------------------------- Properties + private static int tcnMajor = 0; + private static int tcnMinor = 0; + private static int tcnPatch = 0; + private static int tcnVersion = 0; + protected static String SSLEngine = "on"; //default on protected static String FIPSMode = "off"; // default off, valid only when SSLEngine="on" protected static String SSLRandomSeed = "builtin"; @@ -184,12 +189,7 @@ public class AprLifecycleListener implements LifecycleListener { fipsModeActive = false; } - private static void init() - { - int major = 0; - int minor = 0; - int patch = 0; - int apver = 0; + private static void init() { int rqver = TCN_REQUIRED_MAJOR * 1000 + TCN_REQUIRED_MINOR * 100 + TCN_REQUIRED_PATCH; int rcver = TCN_RECOMMENDED_MAJOR * 1000 + TCN_RECOMMENDED_MINOR * 100 + TCN_RECOMMENDED_PV; @@ -200,10 +200,10 @@ public class AprLifecycleListener implements LifecycleListener { try { Library.initialize(null); - major = Library.TCN_MAJOR_VERSION; - minor = Library.TCN_MINOR_VERSION; - patch = Library.TCN_PATCH_VERSION; - apver = major * 1000 + minor * 100 + patch; + tcnMajor = Library.TCN_MAJOR_VERSION; + tcnMinor = Library.TCN_MINOR_VERSION; + tcnPatch = Library.TCN_PATCH_VERSION; + tcnVersion = tcnMajor * 1000 + tcnMinor * 100 + tcnPatch; } catch (LibraryNotFoundError lnfe) { // Library not on path if (log.isDebugEnabled()) { @@ -221,7 +221,7 @@ public class AprLifecycleListener implements LifecycleListener { log.warn(sm.getString("aprListener.aprInitError", t.getMessage()), t); return; } - if (major > 1 && "off".equalsIgnoreCase(SSLEngine)) { + if (tcnMajor > 1 && "off".equalsIgnoreCase(SSLEngine)) { log.error(sm.getString("aprListener.sslRequired", SSLEngine, Library.versionString())); try { // Tomcat Native 2.x onwards requires SSL @@ -232,7 +232,7 @@ public class AprLifecycleListener implements LifecycleListener { } return; } - if (apver < rqver) { + if (tcnVersion < rqver) { log.error(sm.getString("aprListener.tcnInvalid", Library.versionString(), TCN_REQUIRED_MAJOR + "." + @@ -248,7 +248,7 @@ public class AprLifecycleListener implements LifecycleListener { } return; } - if (apver < rcver) { + if (tcnVersion < rcver) { initInfoLogMessages.add(sm.getString("aprListener.tcnVersion", Library.versionString(), TCN_REQUIRED_MAJOR + "." + @@ -290,41 +290,66 @@ public class AprLifecycleListener implements LifecycleListener { method = clazz.getMethod(methodName, paramTypes); method.invoke(null, paramValues); - if (!(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode))) { + // OpenSSL 3 onwards uses providers + boolean usingProviders = tcnMajor > 1 || (tcnVersion > 1233 && (SSL.version() & 0xF0000000L) > 2); + // Tomcat Native 1.x built with OpenSSL 1.x without explicitly enabling + // FIPS and Tomcat Native < 1.2.34 built with OpenSSL 3.x will fail if + // any calls are made to SSL.fipsModeGet or SSL.fipsModeSet + if (usingProviders || !(null == FIPSMode || "off".equalsIgnoreCase(FIPSMode))) { fipsModeActive = false; - final boolean enterFipsMode; int fipsModeState = SSL.fipsModeGet(); if(log.isDebugEnabled()) { - log.debug(sm.getString("aprListener.currentFIPSMode", - Integer.valueOf(fipsModeState))); + log.debug(sm.getString("aprListener.currentFIPSMode", Integer.valueOf(fipsModeState))); } - if ("on".equalsIgnoreCase(FIPSMode)) { + if (null == FIPSMode || "off".equalsIgnoreCase(FIPSMode)) { if (fipsModeState == FIPS_ON) { - log.info(sm.getString("aprListener.skipFIPSInitialization")); + fipsModeActive = true; + } + enterFipsMode = false; + } else if ("on".equalsIgnoreCase(FIPSMode)) { + if (fipsModeState == FIPS_ON) { + if (!usingProviders) { + log.info(sm.getString("aprListener.skipFIPSInitialization")); + } fipsModeActive = true; enterFipsMode = false; } else { - enterFipsMode = true; + if (usingProviders) { + throw new IllegalStateException(sm.getString("aprListener.FIPSProviderNotDefault", FIPSMode)); + } else { + enterFipsMode = true; + } } } else if ("require".equalsIgnoreCase(FIPSMode)) { if (fipsModeState == FIPS_ON) { fipsModeActive = true; enterFipsMode = false; } else { - throw new IllegalStateException( - sm.getString("aprListener.requireNotInFIPSMode")); + if (usingProviders) { + throw new IllegalStateException(sm.getString("aprListener.FIPSProviderNotDefault", FIPSMode)); + } else { + throw new IllegalStateException(sm.getString("aprListener.requireNotInFIPSMode")); + } } } else if ("enter".equalsIgnoreCase(FIPSMode)) { if (fipsModeState == FIPS_OFF) { - enterFipsMode = true; + if (usingProviders) { + throw new IllegalStateException(sm.getString("aprListener.FIPSProviderNotDefault", FIPSMode)); + } else { + enterFipsMode = true; + } } else { - throw new IllegalStateException(sm.getString( - "aprListener.enterAlreadyInFIPSMode", - Integer.valueOf(fipsModeState))); + if (usingProviders) { + fipsModeActive = true; + enterFipsMode = false; + } else { + throw new IllegalStateException(sm.getString( + "aprListener.enterAlreadyInFIPSMode", Integer.valueOf(fipsModeState))); + } } } else { throw new IllegalArgumentException(sm.getString( @@ -346,6 +371,10 @@ public class AprLifecycleListener implements LifecycleListener { fipsModeActive = true; log.info(sm.getString("aprListener.initializeFIPSSuccess")); } + + if (usingProviders && fipsModeActive) { + log.info(sm.getString("aprListener.usingFIPSProvider")); + } } log.info(sm.getString("aprListener.initializedOpenSSL", SSL.versionString())); diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties index 3b67c1fffd..4f64fe0a8d 100644 --- a/java/org/apache/catalina/core/LocalStrings.properties +++ b/java/org/apache/catalina/core/LocalStrings.properties @@ -74,6 +74,7 @@ aprListener.aprInitDebug=The Apache Tomcat Native library could not be found usi aprListener.aprInitError=The Apache Tomcat Native library failed to load. The error reported was [{0}] aprListener.currentFIPSMode=Current FIPS mode: [{0}] aprListener.enterAlreadyInFIPSMode=AprLifecycleListener is configured to force entering FIPS mode, but library is already in FIPS mode [{0}] +aprListener.FIPSProviderNotDefault=The FIPS provider must be configured as the default provider when the AprLifecycleListener is configured with FIPS mode [{0}] aprListener.initializeFIPSFailed=Failed to enter FIPS mode aprListener.initializeFIPSSuccess=Successfully entered FIPS mode aprListener.initializedOpenSSL=OpenSSL successfully initialized [{0}] @@ -88,6 +89,7 @@ aprListener.tcnVersion=An older version [{0}] of the Apache Tomcat Native librar aprListener.tooLateForFIPSMode=Cannot setFIPSMode: SSL has already been initialized aprListener.tooLateForSSLEngine=Cannot setSSLEngine: SSL has already been initialized aprListener.tooLateForSSLRandomSeed=Cannot setSSLRandomSeed: SSL has already been initialized +aprListener.usingFIPSProvider=Using OpenSSL with the FIPS provider as the default provider aprListener.wrongFIPSMode=Unexpected value of FIPSMode option of AprLifecycleListener: [{0}] asyncContextImpl.asyncDispatchError=Error during asynchronous dispatch diff --git a/webapps/docs/config/listeners.xml b/webapps/docs/config/listeners.xml index be2b87aac1..5fcb8028f9 100644 --- a/webapps/docs/config/listeners.xml +++ b/webapps/docs/config/listeners.xml @@ -115,17 +115,23 @@ </attribute> <attribute name="FIPSMode" required="false"> - <p>Set to <code>on</code> to request that OpenSSL be in FIPS mode - (if OpenSSL is already in FIPS mode, it will remain in FIPS mode). - Set to <code>enter</code> to force OpenSSL to enter FIPS mode (an error - will occur if OpenSSL is already in FIPS mode). + <p>The behaviour of this attribute depends on whether Tomcat Native has + been compiled against OpenSSL 1.x or OpenSSL 3.x.</p> + <p>For OpenSSL 1.x: Set to <code>on</code> to request that OpenSSL be in + FIPS mode (if OpenSSL is already in FIPS mode, it will remain in FIPS + mode). + Set to <code>enter</code> to force OpenSSL to enter FIPS mode (an + error will occur if OpenSSL is already in FIPS mode). Set to <code>require</code> to require that OpenSSL <i>already</i> be in FIPS mode (an error will occur if OpenSSL is not already in FIPS mode).</p> - <p>FIPS mode <em>requires you to have a FIPS-capable OpenSSL library which - you must build yourself</em>. - If this attribute is set to any of the above values, the <b>SSLEngine</b> - must be enabled as well.</p> + <p>For OpenSSL 3.x: <code>on</code>, <code>enter</code> and + <code>require</code> all behave the same way. If the FIPS provider is + the default provider, it will be used. If the FIPS provider is not the + default provider, an error will occur.</p> + <p>FIPS mode <em>requires you to have a FIPS-capable OpenSSL library</em>. + If this attribute is set to anything other than <code>off</code>, the + <b>SSLEngine</b> must be enabled as well.</p> <p>The default value is <code>off</code>.</p> </attribute> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org