Change email checkserveridentity prop as angus mail sets it to true by default

Closes https://github.com/keycloak/keycloak/issues/22395
This commit is contained in:
rmartinc 2023-09-22 11:11:27 +02:00 committed by Marek Posolda
parent eb105a01c7
commit d90640b5a3
6 changed files with 59 additions and 20 deletions

View file

@ -185,8 +185,6 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
}
private void setupTruststore(Properties props) {
boolean checkServerIdentity = true;
JSSETruststoreConfigurator configurator = new JSSETruststoreConfigurator(session);
SSLSocketFactory factory = configurator.getSSLSocketFactory();
@ -194,13 +192,9 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
props.put("mail.smtp.ssl.socketFactory", factory);
if (configurator.getProvider().getPolicy() == HostnameVerificationPolicy.ANY) {
props.setProperty("mail.smtp.ssl.trust", "*");
checkServerIdentity = false;
props.put("mail.smtp.ssl.checkserveridentity", Boolean.FALSE.toString());
}
}
if (checkServerIdentity) {
props.put("mail.smtp.ssl.checkserveridentity", "true");
}
}
@Override

View file

@ -34,7 +34,7 @@ public class FileTruststoreProvider implements TruststoreProvider {
private final Map<X500Principal, X509Certificate> rootCertificates;
private final Map<X500Principal, X509Certificate> intermediateCertificates;
FileTruststoreProvider(KeyStore truststore, HostnameVerificationPolicy policy, Map<X500Principal, X509Certificate> rootCertificates, Map<X500Principal, X509Certificate> intermediateCertificates) {
public FileTruststoreProvider(KeyStore truststore, HostnameVerificationPolicy policy, Map<X500Principal, X509Certificate> rootCertificates, Map<X500Principal, X509Certificate> intermediateCertificates) {
this.policy = policy;
this.truststore = truststore;
this.rootCertificates = rootCertificates;

View file

@ -64,6 +64,7 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.ErrorPage;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.resource.RealmResourceProvider;
import org.keycloak.services.scheduled.ClearExpiredUserSessions;
@ -88,7 +89,9 @@ import org.keycloak.testsuite.runonserver.RunOnServer;
import org.keycloak.testsuite.runonserver.SerializationUtil;
import org.keycloak.testsuite.util.FeatureDeployerUtil;
import org.keycloak.timer.TimerProvider;
import org.keycloak.truststore.FileTruststoreProvider;
import org.keycloak.truststore.FileTruststoreProviderFactory;
import org.keycloak.truststore.HostnameVerificationPolicy;
import org.keycloak.truststore.TruststoreProvider;
import org.keycloak.util.JsonSerialization;
import org.keycloak.utils.MediaType;
@ -113,6 +116,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -122,7 +126,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.UUID;
import org.keycloak.services.ErrorResponse;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -1078,6 +1081,20 @@ public class TestingResourceProvider implements RealmResourceProvider {
factory.setProvider(null);
}
@GET
@Path("/modify-truststore-spi-hostname-policy")
@NoCache
public void modifyTruststoreSpiHostnamePolicy(@QueryParam("hostnamePolicy") final HostnameVerificationPolicy hostnamePolicy) {
FileTruststoreProviderFactory fact = (FileTruststoreProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(TruststoreProvider.class);
this.factory.truststoreProvider = fact.create(session);
FileTruststoreProvider origTrustProvider = (FileTruststoreProvider) this.factory.truststoreProvider;
TruststoreProvider newTrustProvider = new FileTruststoreProvider(
origTrustProvider.getTruststore(), hostnamePolicy,
Collections.unmodifiableMap(origTrustProvider.getRootCertificates()),
Collections.unmodifiableMap(origTrustProvider.getIntermediateCertificates()));
fact.setProvider(newTrustProvider);
}
@GET
@Path("/reenable-truststore-spi")
@NoCache

View file

@ -25,6 +25,7 @@ import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.testsuite.components.TestProvider;
import org.keycloak.testsuite.rest.representation.AuthenticatorState;
import org.keycloak.truststore.HostnameVerificationPolicy;
import org.keycloak.utils.MediaType;
import jakarta.ws.rs.Consumes;
@ -407,6 +408,15 @@ public interface TestingResource {
@NoCache
void disableTruststoreSpi();
/**
* Temporarily changes the trustore SPI with another hostname verification policy. Call reenableTruststoreSpi to revert.
* @param hostnamePolicy The hostname verification policy to set
*/
@GET
@Path("/modify-truststore-spi-hostname-policy")
@NoCache
public void modifyTruststoreSpiHostnamePolicy(@QueryParam("hostnamePolicy") final HostnameVerificationPolicy hostnamePolicy);
/**
* Re-enable truststore SPI after it was temporarily disabled by {@link #disableTruststoreSpi()}
*/

View file

@ -164,4 +164,9 @@ public class RealmAttributeUpdater extends ServerResourceUpdater<RealmAttributeU
rep.setOtpPolicyCodeReusable(isCodeReusable);
return this;
}
public RealmAttributeUpdater setSmtpServer(String name, String value) {
rep.getSmtpServer().put(name, value);
return this;
}
}

View file

@ -20,6 +20,7 @@ import org.jboss.arquillian.graphene.page.Page;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventType;
@ -33,9 +34,12 @@ import org.keycloak.testsuite.admin.ApiUtil;
import org.keycloak.testsuite.auth.page.AuthRealm;
import org.keycloak.testsuite.auth.page.login.OIDCLogin;
import org.keycloak.testsuite.auth.page.login.VerifyEmail;
import org.keycloak.testsuite.updaters.RealmAttributeUpdater;
import org.keycloak.testsuite.util.AccountHelper;
import org.keycloak.testsuite.util.MailServerConfiguration;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.SslMailServer;
import org.keycloak.truststore.HostnameVerificationPolicy;
import static org.junit.Assert.assertEquals;
import static org.keycloak.testsuite.util.MailAssert.assertEmailAndGetUrl;
@ -81,10 +85,12 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
SslMailServer.stop();
}
@Test
public void verifyEmailWithSslEnabled() {
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
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());
driver.navigate().to(oauth.getLoginFormUrl());
@ -126,11 +132,11 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
.removeDetail(Details.REDIRECT_URI)
.assertEvent();
assertCurrentUrlStartsWith(oauth.APP_AUTH_ROOT);
assertCurrentUrlStartsWith(OAuthClient.APP_AUTH_ROOT);
AccountHelper.logout(testRealm(), user.getUsername());
driver.navigate().to(oauth.getLoginFormUrl());
testRealmLoginPage.form().login(user.getUsername(), "password");
assertCurrentUrlStartsWith(oauth.APP_AUTH_ROOT);
assertCurrentUrlStartsWith(OAuthClient.APP_AUTH_ROOT);
}
@Test
@ -162,11 +168,9 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
public void verifyEmailWithSslWrongHostname() throws Exception {
UserRepresentation user = ApiUtil.findUserByUsername(testRealm(), "test-user@localhost");
RealmRepresentation realmRep = testRealm().toRepresentation();
realmRep.getSmtpServer().put("host", "localhost.localdomain");
testRealm().update(realmRep);
try {
try (RealmAttributeUpdater updater = new RealmAttributeUpdater(testRealm())
.setSmtpServer("host", "localhost.localdomain")
.update()) {
SslMailServer.startWithSsl(this.getClass().getClassLoader().getResource(SslMailServer.PRIVATE_KEY).getFile());
driver.navigate().to(oauth.getLoginFormUrl());
loginPage.form().login(user.getUsername(), "password");
@ -186,9 +190,18 @@ public class TrustStoreEmailTest extends AbstractTestRealmKeycloakTest {
// Email wasn't send, but we won't notify end user about that. Admin is aware due to the error in the logs and the SEND_VERIFY_EMAIL_ERROR event.
assertEquals("You need to verify your email address to activate your account.",
testRealmVerifyEmailPage.feedbackMessage().getText());
}
}
@Test
public void verifyEmailWithSslWrongHostnameButAnyHostnamePolicy() throws Exception {
testingClient.testing().modifyTruststoreSpiHostnamePolicy(HostnameVerificationPolicy.ANY);
try (RealmAttributeUpdater updater = new RealmAttributeUpdater(testRealm())
.setSmtpServer("host", "localhost.localdomain")
.update()) {
verifyEmailWithSslEnabled();
} finally {
realmRep.getSmtpServer().put("host", "localhost");
testRealm().update(realmRep);
testingClient.testing().reenableTruststoreSpi();
}
}
}