fix: remove ANY mode modification of truststores

also note that ANY should not be used in production

closes: CVE-2025-3501

Add a test for the error (#1)

Signed-off-by: Ricardo Martin <rmartinc@redhat.com>

Update docs/guides/server/keycloak-truststore.adoc

Co-authored-by: Marek Posolda <mposolda@gmail.com>
Signed-off-by: Steven Hawkins <shawkins@redhat.com>
This commit is contained in:
Steve Hawkins
2025-04-14 13:50:08 -04:00
committed by Stian Thorgersen
parent 4ae7d60784
commit f835f49065
15 changed files with 48 additions and 54 deletions

View File

@@ -29,7 +29,7 @@ It is still possible to directly set your own `javax.net.ssl` truststore System
You may refine how hostnames are verified by TLS connections with the `tls-hostname-verifier` property.
* `DEFAULT` (the default) allows wildcards in subdomain names (e.g. *.foo.com) to match names with the same number of levels (e.g. a.foo.com, but not a.b.foo.com) - with rules and exclusions for public suffixes based upon https://publicsuffix.org/list/
* `ANY` means that the hostname is not verified.
* `ANY` means that the hostname is not verified - this mode should not be used in production.
* `WILDCARD` (deprecated) allows wildcards in subdomain names (e.g. *.foo.com) to match anything, including multiple levels (e.g. a.b.foo.com). Use DEFAULT instead.
* `STRICT` (deprecated) allows wildcards in subdomain names (e.g. *.foo.com) to match names with the same number of levels (e.g. a.foo.com, but not a.b.foo.com) - with some limited exclusions. Use DEFAULT instead.
+

View File

@@ -13,7 +13,7 @@ public class TruststoreOptions {
public static final Option<HostnameVerificationPolicy> HOSTNAME_VERIFICATION_POLICY = new OptionBuilder<>("tls-hostname-verifier", HostnameVerificationPolicy.class)
.category(OptionCategory.TRUSTSTORE)
.description("The TLS hostname verification policy for out-going HTTPS and SMTP requests.")
.description("The TLS hostname verification policy for out-going HTTPS and SMTP requests. ANY should not be used in production.")
.defaultValue(HostnameVerificationPolicy.DEFAULT)
.deprecatedValues("STRICT and WILDCARD have been deprecated, use DEFAULT instead.", HostnameVerificationPolicy.STRICT, HostnameVerificationPolicy.WILDCARD)
.build();

View File

@@ -147,8 +147,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -245,8 +245,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -147,8 +147,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -245,8 +245,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -318,8 +318,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -451,8 +451,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -319,8 +319,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -452,8 +452,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -270,8 +270,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -392,8 +392,8 @@ Truststore:
--tls-hostname-verifier <tls-hostname-verifier>
The TLS hostname verification policy for out-going HTTPS and SMTP requests.
Possible values are: ANY, WILDCARD (deprecated), STRICT (deprecated),
DEFAULT. Default: DEFAULT.
ANY should not be used in production. Possible values are: ANY, WILDCARD
(deprecated), STRICT (deprecated), DEFAULT. Default: DEFAULT.
--truststore-paths <truststore-paths>
List of pkcs12 (p12 or pfx file extensions), PEM files, or directories
containing those files that will be used as a system truststore.

View File

@@ -17,15 +17,12 @@
package org.keycloak.truststore;
import org.keycloak.common.enums.HostnameVerificationPolicy;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
@@ -76,22 +73,6 @@ public class JSSETruststoreConfigurator {
return null;
}
if (getProvider().getPolicy() == HostnameVerificationPolicy.ANY) {
return new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
}
if (tm == null) {
synchronized (this) {
if (tm == null) {

View File

@@ -18,8 +18,10 @@ package org.keycloak.testsuite.ssl;
import org.jboss.arquillian.graphene.page.Page;
import org.junit.After;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.common.enums.HostnameVerificationPolicy;
import org.keycloak.events.Details;
@@ -49,6 +51,7 @@ import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
*
* @author fkiss
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
@Page
@@ -145,12 +148,7 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
}
@Test
public void verifyEmailWithSslEnabled() {
verifyEmailWithSslEnabled(false);
}
@Test
public void verifyEmailWithSslWrongCertificate() throws Exception {
public void test01VerifyEmailWithSslWrongCertificate() throws Exception {
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
SslMailServer.startWithSsl(this.getClass().getClassLoader().getResource(SslMailServer.INVALID_KEY).getFile());
@@ -175,7 +173,17 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
}
@Test
public void verifyEmailWithSslWrongHostname() throws Exception {
public void test02VerifyEmailWithSslWrongCertificateAndAnyHostnamePolicy() throws Exception {
testingClient.testing().modifyTruststoreSpiHostnamePolicy(HostnameVerificationPolicy.ANY);
try {
test01VerifyEmailWithSslWrongCertificate();
} finally {
testingClient.testing().reenableTruststoreSpi();
}
}
@Test
public void test03erifyEmailWithSslWrongHostname() throws Exception {
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
try (RealmAttributeUpdater updater = new RealmAttributeUpdater(testRealm())
@@ -204,19 +212,24 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
}
@Test
public void verifyEmailWithSslWrongHostnameButAnyHostnamePolicy() throws Exception {
public void test04VerifyEmailWithSslEnabled() {
verifyEmailWithSslEnabled(false);
}
@Test
public void test05VerifyEmailWithSslWrongHostnameButAnyHostnamePolicy() throws Exception {
testingClient.testing().modifyTruststoreSpiHostnamePolicy(HostnameVerificationPolicy.ANY);
try (RealmAttributeUpdater updater = new RealmAttributeUpdater(testRealm())
.setSmtpServer("host", "localhost.localdomain")
.update()) {
verifyEmailWithSslEnabled();
test04VerifyEmailWithSslEnabled();
} finally {
testingClient.testing().reenableTruststoreSpi();
}
}
@Test
public void verifyEmailOpportunisticEncryptionWithAnyHostnamePolicy() throws Exception {
public void test06VerifyEmailOpportunisticEncryptionWithAnyHostnamePolicy() throws Exception {
testingClient.testing().modifyTruststoreSpiHostnamePolicy(HostnameVerificationPolicy.ANY);
try (RealmAttributeUpdater updater = new RealmAttributeUpdater(testRealm())
.setSmtpServer("host", "localhost.localdomain")