fix for SMTP email sending fails because of tls certificate verification even with tls-hostname-verifier=ANY (#27756)

Signed-off-by: Reda Bourial <reda.bourial@gmail.com>
This commit is contained in:
Reda Bourial 2024-03-20 13:27:33 +01:00 committed by Marek Posolda
parent cbe185fbab
commit a41d865600
4 changed files with 63 additions and 8 deletions

View file

@ -97,7 +97,7 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
props.setProperty("mail.smtp.starttls.enable", "true");
}
if (ssl || starttls) {
if (ssl || starttls || auth){
props.put("mail.smtp.ssl.protocols", SUPPORTED_SSL_PROTOCOLS);
setupTruststore(props);

View file

@ -17,12 +17,15 @@
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;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
@ -73,6 +76,22 @@ 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

@ -71,7 +71,6 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
testRealm.setVerifyEmail(true);
}
@Override
public void setDefaultPageUriParameters() {
super.setDefaultPageUriParameters();
@ -85,14 +84,20 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
SslMailServer.stop();
}
@Test
public void verifyEmailWithSslEnabled() {
public void verifyEmailWithSslEnabled(Boolean opportunistic) {
UserResource userResource = ApiUtil.findUserByUsernameId(testRealm(), "test-user@localhost");
UserRepresentation user = userResource.toRepresentation();
user.setEmailVerified(false);
userResource.update(user);
SslMailServer.startWithSsl(this.getClass().getClassLoader().getResource(SslMailServer.PRIVATE_KEY).getFile());
String privateKey = this.getClass().getClassLoader().getResource(opportunistic ? SslMailServer.INVALID_KEY : SslMailServer.PRIVATE_KEY).getFile();
if (opportunistic) {
SslMailServer.startWithOpportunisticSsl(privateKey);
} else {
SslMailServer.startWithSsl(privateKey);
}
driver.navigate().to(oauth.getLoginFormUrl());
testRealmLoginPage.form().login(user.getUsername(), "password");
@ -139,6 +144,11 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
assertCurrentUrlStartsWith(OAuthClient.APP_AUTH_ROOT);
}
@Test
public void verifyEmailWithSslEnabled() {
verifyEmailWithSslEnabled(false);
}
@Test
public void verifyEmailWithSslWrongCertificate() throws Exception {
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
@ -204,4 +214,22 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
testingClient.testing().reenableTruststoreSpi();
}
}
@Test
public void verifyEmailOpportunisticEncryptionWithAnyHostnamePolicy() throws Exception {
testingClient.testing().modifyTruststoreSpiHostnamePolicy(HostnameVerificationPolicy.ANY);
try (RealmAttributeUpdater updater = new RealmAttributeUpdater(testRealm())
.setSmtpServer("host", "localhost.localdomain")
.setSmtpServer("auth", "true")
.setSmtpServer("ssl", "false")
.setSmtpServer("starttls", "false")
.setSmtpServer("user", "user")
.setSmtpServer("password", "password")
.update()) {
verifyEmailWithSslEnabled(true);
} finally {
testingClient.testing().reenableTruststoreSpi();
}
}
}

View file

@ -92,7 +92,7 @@ public class SslMailServer {
}
}
public static void startWithSsl(String privateKey){
public static void startWithSsl(String privateKey, boolean enableSsl) {
InputStream keyStoreIS = null;
try {
keyStoreIS = new FileInputStream(privateKey);
@ -142,12 +142,20 @@ public class SslMailServer {
smtpServer.setHostName(HOST);
smtpServer.setPort(Integer.parseInt(PORT_SSL));
smtpServer.setEnableTLS(true);
smtpServer.setEnableTLS(enableSsl);
smtpServer.start();
log.info("Started mail server (" + smtpServer.getHostName() + ":" + smtpServer.getPort() + ")");
}
public static void startWithSsl(String privateKey) {
startWithSsl(privateKey, true);
}
public static void startWithOpportunisticSsl(String privateKey) {
startWithSsl(privateKey, false);
}
public static Map<String, String> getServerConfiguration() {
serverConfiguration.put("from", FROM);
serverConfiguration.put("host", HOST);
@ -159,4 +167,4 @@ public class SslMailServer {
public static MimeMessage getLastReceivedMessage() throws InterruptedException {
return messageHandlerFactory.getMessage();
}
}
}