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:
parent
cbe185fbab
commit
a41d865600
4 changed files with 63 additions and 8 deletions
|
@ -97,7 +97,7 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
|
||||||
props.setProperty("mail.smtp.starttls.enable", "true");
|
props.setProperty("mail.smtp.starttls.enable", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ssl || starttls) {
|
if (ssl || starttls || auth){
|
||||||
props.put("mail.smtp.ssl.protocols", SUPPORTED_SSL_PROTOCOLS);
|
props.put("mail.smtp.ssl.protocols", SUPPORTED_SSL_PROTOCOLS);
|
||||||
|
|
||||||
setupTruststore(props);
|
setupTruststore(props);
|
||||||
|
|
|
@ -17,12 +17,15 @@
|
||||||
|
|
||||||
package org.keycloak.truststore;
|
package org.keycloak.truststore;
|
||||||
|
|
||||||
|
import org.keycloak.common.enums.HostnameVerificationPolicy;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||||
|
@ -73,6 +76,22 @@ public class JSSETruststoreConfigurator {
|
||||||
return null;
|
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) {
|
if (tm == null) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (tm == null) {
|
if (tm == null) {
|
||||||
|
|
|
@ -71,7 +71,6 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
|
||||||
testRealm.setVerifyEmail(true);
|
testRealm.setVerifyEmail(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDefaultPageUriParameters() {
|
public void setDefaultPageUriParameters() {
|
||||||
super.setDefaultPageUriParameters();
|
super.setDefaultPageUriParameters();
|
||||||
|
@ -85,14 +84,20 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
|
||||||
SslMailServer.stop();
|
SslMailServer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
public void verifyEmailWithSslEnabled(Boolean opportunistic) {
|
||||||
public void verifyEmailWithSslEnabled() {
|
|
||||||
UserResource userResource = ApiUtil.findUserByUsernameId(testRealm(), "test-user@localhost");
|
UserResource userResource = ApiUtil.findUserByUsernameId(testRealm(), "test-user@localhost");
|
||||||
UserRepresentation user = userResource.toRepresentation();
|
UserRepresentation user = userResource.toRepresentation();
|
||||||
user.setEmailVerified(false);
|
user.setEmailVerified(false);
|
||||||
userResource.update(user);
|
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());
|
driver.navigate().to(oauth.getLoginFormUrl());
|
||||||
testRealmLoginPage.form().login(user.getUsername(), "password");
|
testRealmLoginPage.form().login(user.getUsername(), "password");
|
||||||
|
|
||||||
|
@ -139,6 +144,11 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
|
||||||
assertCurrentUrlStartsWith(OAuthClient.APP_AUTH_ROOT);
|
assertCurrentUrlStartsWith(OAuthClient.APP_AUTH_ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyEmailWithSslEnabled() {
|
||||||
|
verifyEmailWithSslEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void verifyEmailWithSslWrongCertificate() throws Exception {
|
public void verifyEmailWithSslWrongCertificate() throws Exception {
|
||||||
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
|
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
|
||||||
|
@ -204,4 +214,22 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
|
||||||
testingClient.testing().reenableTruststoreSpi();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ public class SslMailServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startWithSsl(String privateKey){
|
public static void startWithSsl(String privateKey, boolean enableSsl) {
|
||||||
InputStream keyStoreIS = null;
|
InputStream keyStoreIS = null;
|
||||||
try {
|
try {
|
||||||
keyStoreIS = new FileInputStream(privateKey);
|
keyStoreIS = new FileInputStream(privateKey);
|
||||||
|
@ -142,12 +142,20 @@ public class SslMailServer {
|
||||||
|
|
||||||
smtpServer.setHostName(HOST);
|
smtpServer.setHostName(HOST);
|
||||||
smtpServer.setPort(Integer.parseInt(PORT_SSL));
|
smtpServer.setPort(Integer.parseInt(PORT_SSL));
|
||||||
smtpServer.setEnableTLS(true);
|
smtpServer.setEnableTLS(enableSsl);
|
||||||
smtpServer.start();
|
smtpServer.start();
|
||||||
|
|
||||||
log.info("Started mail server (" + smtpServer.getHostName() + ":" + smtpServer.getPort() + ")");
|
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() {
|
public static Map<String, String> getServerConfiguration() {
|
||||||
serverConfiguration.put("from", FROM);
|
serverConfiguration.put("from", FROM);
|
||||||
serverConfiguration.put("host", HOST);
|
serverConfiguration.put("host", HOST);
|
||||||
|
@ -159,4 +167,4 @@ public class SslMailServer {
|
||||||
public static MimeMessage getLastReceivedMessage() throws InterruptedException {
|
public static MimeMessage getLastReceivedMessage() throws InterruptedException {
|
||||||
return messageHandlerFactory.getMessage();
|
return messageHandlerFactory.getMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue