This is an automated email from the ASF dual-hosted git repository.
markt-asf 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 a5507a0006 Review "Match OpenSSL semantics for AND cipher expressions
with..."
a5507a0006 is described below
commit a5507a0006f3230708173bc3d71da070a8a09da4
Author: Mark Thomas <[email protected]>
AuthorDate: Wed Nov 4 09:13:03 2026 +0000
Review "Match OpenSSL semantics for AND cipher expressions with..."
Additional logging and tests for unknown terms
---
.../ciphers/OpenSSLCipherConfigurationParser.java | 8 ++
.../TestOpenSSLCipherConfigurationParser.java | 95 ++++++++++++++++++++++
2 files changed, 103 insertions(+)
diff --git
a/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java
b/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java
index cfeb7bced3..f98ef6c6a4 100644
---
a/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java
+++
b/java/org/apache/tomcat/util/net/openssl/ciphers/OpenSSLCipherConfigurationParser.java
@@ -789,6 +789,8 @@ public class OpenSSLCipherConfigurationParser {
String alias = element.substring(1);
if (aliases.containsKey(alias)) {
remove(ciphers, alias);
+ } else {
+
log.warn(sm.getString("opensslCipherConfigurationParser.unknownElement",
alias));
}
} else if (element.startsWith(EXCLUDE)) {
String alias = element.substring(1);
@@ -802,6 +804,8 @@ public class OpenSSLCipherConfigurationParser {
if (aliases.containsKey(alias)) {
moveToEnd(ciphers, alias);
moveToEnd(orderedAllAddedCiphers, alias);
+ } else {
+
log.warn(sm.getString("opensslCipherConfigurationParser.unknownElement",
alias));
}
} else if ("@STRENGTH".equals(element)) {
ciphers = strengthSort(ciphers);
@@ -828,6 +832,10 @@ public class OpenSSLCipherConfigurationParser {
if (result != null) {
add(ciphers, result, orderedAllAddedCiphers);
}
+ } else if (!element.isEmpty() && !element.startsWith("PROFILE=")
&& !element.startsWith("@SECLEVEL=")) {
+ // OpenSSL ignores unknown elements. Do the same but, since it
is most likely a typo, warn about it.
+ // PROFILE= is reported separately above and @SECLEVEL= is
valid for OpenSSL but is not used here.
+
log.warn(sm.getString("opensslCipherConfigurationParser.unknownElement",
element));
}
}
ciphers.removeAll(excludedCiphers);
diff --git
a/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java
b/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java
index 7f8cf44f65..52867c8064 100644
---
a/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java
+++
b/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java
@@ -16,8 +16,13 @@
*/
package org.apache.tomcat.util.net.openssl.ciphers;
+import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
import org.junit.Assert;
import org.junit.Test;
@@ -547,6 +552,96 @@ public class TestOpenSSLCipherConfigurationParser {
}
+ @Test
+ public void testIntersectionWithUnknownTermIsDiscarded() throws Exception {
+ // OpenSSL discards the whole AND element if any term is unknown,
wherever the unknown term is. The other
+ // elements are not affected.
+ testSpecification("AES128:SHA1+Nonsense");
+ testSpecification("AES128:Nonsense+SHA1");
+ testSpecification("AES128:SHA1+Nonsense+AES128");
+
+ List<String> expected =
OpenSSLCipherConfigurationParser.parseExpression("AES128");
+ Assert.assertEquals(expected,
OpenSSLCipherConfigurationParser.parseExpression("AES128:SHA1+Nonsense"));
+ Assert.assertEquals(expected,
OpenSSLCipherConfigurationParser.parseExpression("AES128:Nonsense+SHA1"));
+ Assert.assertEquals(expected,
+
OpenSSLCipherConfigurationParser.parseExpression("AES128:SHA1+Nonsense+AES128"));
+ }
+
+
+ @Test
+ public void testUnknownElementsAreIgnored() throws Exception {
+ // OpenSSL ignores unknown elements, whatever the operator
+ testSpecification("AES128:Nonsense");
+ testSpecification("AES128:!Nonsense");
+
+ List<String> expected =
OpenSSLCipherConfigurationParser.parseExpression("AES128");
+ for (String unknown : new String[] { "Nonsense", "!Nonsense",
"-Nonsense", "+Nonsense" }) {
+ Assert.assertEquals(unknown, expected,
+ OpenSSLCipherConfigurationParser.parseExpression("AES128:"
+ unknown));
+ }
+ }
+
+
+ @Test
+ public void testUnknownElementsAreLogged() {
+ String[] specifications = { "AES128:Nonsense", "AES128:!Nonsense",
"AES128:-Nonsense", "AES128:+Nonsense",
+ "AES128:SHA1+Nonsense", "AES128:Nonsense+SHA1" };
+
+ for (String specification : specifications) {
+ List<String> warnings = parseAndCaptureWarnings(specification);
+ Assert.assertEquals(specification + " logged " + warnings, 1,
warnings.size());
+ Assert.assertTrue(specification + " logged " + warnings,
warnings.get(0).contains("Nonsense"));
+ }
+ }
+
+
+ @Test
+ public void testKnownAndOtherValidElementsAreNotLogged() {
+ // Known elements, an empty element and the valid OpenSSL @SECLEVEL
element must not trigger a warning
+ String[] specifications = { "AES128:SHA1+AES128",
"AES128:!aNULL:-AES256:+SHA1:@STRENGTH", "AES128::SHA1",
+ "AES128:@SECLEVEL=1" };
+
+ for (String specification : specifications) {
+ List<String> warnings = parseAndCaptureWarnings(specification);
+ Assert.assertTrue(specification + " logged " + warnings,
warnings.isEmpty());
+ }
+ }
+
+
+ private List<String> parseAndCaptureWarnings(String specification) {
+ List<String> warnings = new ArrayList<>();
+ Logger logger =
Logger.getLogger(OpenSSLCipherConfigurationParser.class.getName());
+ Handler handler = new Handler() {
+ @Override
+ public void publish(LogRecord record) {
+ if (record.getLevel().intValue() >= Level.WARNING.intValue()) {
+ warnings.add(record.getMessage() + " " + String.join(" ",
+ record.getParameters() == null ? new String[0] :
+
java.util.Arrays.stream(record.getParameters()).map(String::valueOf)
+ .toArray(String[]::new)));
+ }
+ }
+
+ @Override
+ public void flush() {
+ // NO-OP
+ }
+
+ @Override
+ public void close() {
+ // NO-OP
+ }
+ };
+ logger.addHandler(handler);
+ try {
+ OpenSSLCipherConfigurationParser.parseExpression(specification);
+ } finally {
+ logger.removeHandler(handler);
+ }
+ return warnings;
+ }
+
+
private void testSpecificationIsEmpty(String specification) throws
Exception {
String openSSLCipherList =
TesterOpenSSL.getOpenSSLCiphersAsExpression(specification);
Assert.assertEquals(TesterOpenSSL.VERSION_STRING + " with
specification [" + specification + "] returned [" +
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]