You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2021/12/27 23:04:32 UTC
[logging-log4j2] branch log4j-2.3.x updated: [LOG4J2-2819] Add SSL/TLS hostname verify option
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch log4j-2.3.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
The following commit(s) were added to refs/heads/log4j-2.3.x by this push:
new 3c62f0b [LOG4J2-2819] Add SSL/TLS hostname verify option
3c62f0b is described below
commit 3c62f0bea692456b1b5039d3bcc1c3e0ba65146a
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Mon Dec 27 17:03:13 2021 -0600
[LOG4J2-2819] Add SSL/TLS hostname verify option
This backports a fix for CVE-2020-9488.
---
.../logging/log4j/core/appender/SmtpAppender.java | 295 ++++++++++++++++-----
.../apache/logging/log4j/core/net/SmtpManager.java | 68 ++++-
.../log4j/core/net/ssl/SslConfiguration.java | 49 ++--
.../log4j/core/appender/SmtpAppenderTest.java | 21 +-
src/changes/changes.xml | 6 +
src/site/xdoc/manual/appenders.xml | 4 +-
6 files changed, 343 insertions(+), 100 deletions(-)
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java
index 10668af..0f79afe 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java
@@ -17,20 +17,23 @@
package org.apache.logging.log4j.core.appender;
-import java.io.Serializable;
-
+import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
import org.apache.logging.log4j.core.filter.ThresholdFilter;
import org.apache.logging.log4j.core.layout.HtmlLayout;
import org.apache.logging.log4j.core.net.SmtpManager;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.util.Booleans;
+import java.io.Serializable;
+
/**
* Send an e-mail when a specific logging event occurs, typically on errors or
* fatal errors.
@@ -64,64 +67,232 @@ public final class SmtpAppender extends AbstractAppender {
this.manager = manager;
}
- /**
- * Create a SmtpAppender.
- *
- * @param name
- * The name of the Appender.
- * @param to
- * The comma-separated list of recipient email addresses.
- * @param cc
- * The comma-separated list of CC email addresses.
- * @param bcc
- * The comma-separated list of BCC email addresses.
- * @param from
- * The email address of the sender.
- * @param replyTo
- * The comma-separated list of reply-to email addresses.
- * @param subject The subject of the email message.
- * @param smtpProtocol The SMTP transport protocol (such as "smtps", defaults to "smtp").
- * @param smtpHost
- * The SMTP hostname to send to.
- * @param smtpPortStr
- * The SMTP port to send to.
- * @param smtpUsername
- * The username required to authenticate against the SMTP server.
- * @param smtpPassword
- * The password required to authenticate against the SMTP server.
- * @param smtpDebug
- * Enable mail session debuging on STDOUT.
- * @param bufferSizeStr
- * How many log events should be buffered for inclusion in the
- * message?
- * @param layout
- * The layout to use (defaults to HtmlLayout).
- * @param filter
- * The Filter or null (defaults to ThresholdFilter, level of
- * ERROR).
- * @param ignore If {@code "true"} (default) exceptions encountered when appending events are logged; otherwise
- * they are propagated to the caller.
- * @return The SmtpAppender.
- */
- @PluginFactory
- public static SmtpAppender createAppender(
- @PluginAttribute("name") final String name,
- @PluginAttribute("to") final String to,
- @PluginAttribute("cc") final String cc,
- @PluginAttribute("bcc") final String bcc,
- @PluginAttribute("from") final String from,
- @PluginAttribute("replyTo") final String replyTo,
- @PluginAttribute("subject") final String subject,
- @PluginAttribute("smtpProtocol") final String smtpProtocol,
- @PluginAttribute("smtpHost") final String smtpHost,
- @PluginAttribute("smtpPort") final String smtpPortStr,
- @PluginAttribute("smtpUsername") final String smtpUsername,
- @PluginAttribute("smtpPassword") final String smtpPassword,
- @PluginAttribute("smtpDebug") final String smtpDebug,
- @PluginAttribute("bufferSize") final String bufferSizeStr,
- @PluginElement("Layout") Layout<? extends Serializable> layout,
- @PluginElement("Filter") Filter filter,
- @PluginAttribute("ignoreExceptions") final String ignore) {
+ public static class Builder implements org.apache.logging.log4j.core.util.Builder<SmtpAppender> {
+ @PluginBuilderAttribute
+ @Required(message = "No name provided for SmtpAppender")
+ private String name;
+
+ @PluginElement("Filter")
+ private Filter filter = ThresholdFilter.createFilter(null, null, null);
+
+ @PluginElement("Layout")
+ private Layout<? extends Serializable> layout = HtmlLayout.createDefaultLayout();
+
+ @PluginBuilderAttribute
+ private boolean ignoreExceptions = true;
+
+ @PluginBuilderAttribute
+ private String to;
+
+ @PluginBuilderAttribute
+ private String cc;
+
+ @PluginBuilderAttribute
+ private String bcc;
+
+ @PluginBuilderAttribute
+ private String from;
+
+ @PluginBuilderAttribute
+ private String replyTo;
+
+ @PluginBuilderAttribute
+ private String subject;
+
+ @PluginBuilderAttribute
+ private String smtpProtocol = "smtp";
+
+ @PluginBuilderAttribute
+ private String smtpHost;
+
+ @PluginBuilderAttribute
+ private int smtpPort;
+
+ @PluginBuilderAttribute
+ private String smtpUsername;
+
+ @PluginBuilderAttribute(sensitive = true)
+ private String smtpPassword;
+
+ @PluginBuilderAttribute
+ private boolean smtpDebug;
+
+ @PluginBuilderAttribute
+ private int bufferSize = DEFAULT_BUFFER_SIZE;
+
+ @PluginElement("SSL")
+ private SslConfiguration sslConfiguration;
+
+ /**
+ * Name of the SmtpAppender.
+ */
+ public Builder setName(final String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Overrides the default filter. Default filter is a {@link ThresholdFilter} of level {@link Level#ERROR}.
+ */
+ public Builder setFilter(final Filter filter) {
+ this.filter = filter;
+ return this;
+ }
+
+ /**
+ * Overrides the default layout. Default layout is the {@linkplain HtmlLayout#createDefaultLayout() default HTML layout}.
+ */
+ public Builder setLayout(final Layout<? extends Serializable> layout) {
+ this.layout = layout;
+ return this;
+ }
+
+ /**
+ * Whether to ignore exceptions thrown by the SmtpAppender. Defaults to {@code true}.
+ */
+ public Builder setIgnoreExceptions(final boolean ignoreExceptions) {
+ this.ignoreExceptions = ignoreExceptions;
+ return this;
+ }
+
+ /**
+ * Comma-separated list of recipient email addresses.
+ */
+ public Builder setTo(final String to) {
+ this.to = to;
+ return this;
+ }
+
+ /**
+ * Comma-separated list of CC email addresses.
+ */
+ public Builder setCc(final String cc) {
+ this.cc = cc;
+ return this;
+ }
+
+ /**
+ * Comma-separated list of BCC email addresses.
+ */
+ public Builder setBcc(final String bcc) {
+ this.bcc = bcc;
+ return this;
+ }
+
+ /**
+ * Email address of the sender.
+ */
+ public Builder setFrom(final String from) {
+ this.from = from;
+ return this;
+ }
+
+ /**
+ * Comma-separated list of Reply-To email addresses.
+ */
+ public Builder setReplyTo(final String replyTo) {
+ this.replyTo = replyTo;
+ return this;
+ }
+
+ /**
+ * Subject template for the email messages.
+ * @see org.apache.logging.log4j.core.layout.PatternLayout
+ */
+ public Builder setSubject(final String subject) {
+ this.subject = subject;
+ return this;
+ }
+
+ /**
+ * Transport protocol to use for SMTP such as "smtp" or "smtps". Defaults to "smtp".
+ */
+ public Builder setSmtpProtocol(final String smtpProtocol) {
+ this.smtpProtocol = smtpProtocol;
+ return this;
+ }
+
+ /**
+ * Host name of SMTP server to send messages through.
+ */
+ public Builder setSmtpHost(final String smtpHost) {
+ this.smtpHost = smtpHost;
+ return this;
+ }
+
+ /**
+ * Port number of SMTP server to send messages through.
+ */
+ public Builder setSmtpPort(final int smtpPort) {
+ this.smtpPort = smtpPort;
+ return this;
+ }
+
+ /**
+ * Username to authenticate with SMTP server.
+ */
+ public Builder setSmtpUsername(final String smtpUsername) {
+ this.smtpUsername = smtpUsername;
+ return this;
+ }
+
+ /**
+ * Password to authenticate with SMTP server.
+ */
+ public Builder setSmtpPassword(final String smtpPassword) {
+ this.smtpPassword = smtpPassword;
+ return this;
+ }
+
+ /**
+ * Enables or disables mail session debugging on STDOUT. Disabled by default.
+ */
+ public Builder setSmtpDebug(final boolean smtpDebug) {
+ this.smtpDebug = smtpDebug;
+ return this;
+ }
+
+ /**
+ * Number of log events to buffer before sending an email. Defaults to {@value #DEFAULT_BUFFER_SIZE}.
+ */
+ public Builder setBufferSize(final int bufferSize) {
+ this.bufferSize = bufferSize;
+ return this;
+ }
+
+ /**
+ * Specifies an SSL configuration for smtps connections.
+ */
+ public Builder setSslConfiguration(final SslConfiguration sslConfiguration) {
+ this.sslConfiguration = sslConfiguration;
+ return this;
+ }
+
+ @Override
+ public SmtpAppender build() {
+ if (layout == null) {
+ layout = HtmlLayout.createDefaultLayout();
+ }
+ if (filter == null) {
+ filter = ThresholdFilter.createFilter(null, null, null);
+ }
+ final SmtpManager smtpManager =
+ SmtpManager.getSMTPManager(to, cc, bcc, from, replyTo, subject, smtpProtocol, smtpHost, smtpPort,
+ smtpUsername, smtpPassword, smtpDebug, filter.toString(), bufferSize, sslConfiguration);
+ return new SmtpAppender(name, filter, layout, smtpManager, ignoreExceptions);
+ }
+ }
+
+ @PluginBuilderFactory
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ @Deprecated
+ public static SmtpAppender createAppender(final String name, final String to, final String cc, final String bcc,
+ final String from, final String replyTo, final String subject, final String smtpProtocol, final String smtpHost,
+ final String smtpPortStr, final String smtpUsername, final String smtpPassword, final String smtpDebug,
+ final String bufferSizeStr, Layout<? extends Serializable> layout, Filter filter, final String ignore) {
if (name == null) {
LOGGER.error("No name provided for SmtpAppender");
return null;
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
index b939f01..04c1b13 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
@@ -35,12 +35,14 @@ import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.util.ByteArrayDataSource;
+import javax.net.ssl.SSLSocketFactory;
import org.apache.logging.log4j.LoggingException;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractManager;
import org.apache.logging.log4j.core.appender.ManagerFactory;
+import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.util.CyclicBuffer;
import org.apache.logging.log4j.core.util.NameUtil;
import org.apache.logging.log4j.core.util.NetUtils;
@@ -74,11 +76,27 @@ public class SmtpManager extends AbstractManager {
buffer.add(event);
}
- public static SmtpManager getSMTPManager(final String to, final String cc, final String bcc,
- final String from, final String replyTo,
- final String subject, String protocol, final String host,
- final int port, final String username, final String password,
- final boolean isDebug, final String filterName, final int numElements) {
+ /**
+ * @deprecated use {@link #getSMTPManager(String, String, String, String, String, String, String, String, int, String, String, boolean, String, int, SslConfiguration)}
+ */
+ @Deprecated
+ public static SmtpManager getSMTPManager(
+ final String to, final String cc, final String bcc,
+ final String from, final String replyTo,
+ final String subject, String protocol, final String host,
+ final int port, final String username, final String password,
+ final boolean isDebug, final String filterName, final int numElements) {
+ return getSMTPManager(to, cc, bcc, from, replyTo, subject, protocol, host, port, username, password, isDebug,
+ filterName, numElements, null);
+ }
+
+ public static SmtpManager getSMTPManager(
+ final String to, final String cc, final String bcc,
+ final String from, final String replyTo,
+ final String subject, String protocol, final String host,
+ final int port, final String username, final String password,
+ final boolean isDebug, final String filterName, final int numElements,
+ final SslConfiguration sslConfiguration) {
if (Strings.isEmpty(protocol)) {
protocol = "smtp";
}
@@ -122,7 +140,7 @@ public class SmtpManager extends AbstractManager {
final String name = "SMTP:" + NameUtil.md5(sb.toString());
return getManager(name, FACTORY, new FactoryData(to, cc, bcc, from, replyTo, subject,
- protocol, host, port, username, password, isDebug, numElements));
+ protocol, host, port, username, password, isDebug, numElements, sslConfiguration));
}
/**
@@ -259,10 +277,24 @@ public class SmtpManager extends AbstractManager {
private final String password;
private final boolean isDebug;
private final int numElements;
+ private final SslConfiguration sslConfiguration;
+
+ /**
+ * @deprecated use {@link #FactoryData(String, String, String, String, String, String, String, String, int, String, String, boolean, int, SslConfiguration)}
+ */
+ @Deprecated
+ public FactoryData(
+ final String to, final String cc, final String bcc, final String from, final String replyTo,
+ final String subject, final String protocol, final String host, final int port,
+ final String username, final String password, final boolean isDebug, final int numElements) {
+ this(to, cc, bcc, from, replyTo, subject, protocol, host, port, username, password, isDebug, numElements, null);
+ }
- public FactoryData(final String to, final String cc, final String bcc, final String from, final String replyTo,
- final String subject, final String protocol, final String host, final int port,
- final String username, final String password, final boolean isDebug, final int numElements) {
+ public FactoryData(
+ final String to, final String cc, final String bcc, final String from, final String replyTo,
+ final String subject, final String protocol, final String host, final int port,
+ final String username, final String password, final boolean isDebug, final int numElements,
+ final SslConfiguration sslConfiguration) {
this.to = to;
this.cc = cc;
this.bcc = bcc;
@@ -276,6 +308,7 @@ public class SmtpManager extends AbstractManager {
this.password = password;
this.isDebug = isDebug;
this.numElements = numElements;
+ this.sslConfiguration = sslConfiguration;
}
}
@@ -303,22 +336,31 @@ public class SmtpManager extends AbstractManager {
final String prefix = "mail." + data.protocol;
final Properties properties = PropertiesUtil.getSystemProperties();
- properties.put("mail.transport.protocol", data.protocol);
+ properties.setProperty("mail.transport.protocol", data.protocol);
if (properties.getProperty("mail.host") == null) {
// Prevent an UnknownHostException in Java 7
properties.put("mail.host", NetUtils.getLocalHostname());
}
if (null != data.host) {
- properties.put(prefix + ".host", data.host);
+ properties.setProperty(prefix + ".host", data.host);
}
if (data.port > 0) {
- properties.put(prefix + ".port", String.valueOf(data.port));
+ properties.setProperty(prefix + ".port", Integer.toString(data.port));
}
final Authenticator authenticator = buildAuthenticator(data.username, data.password);
if (null != authenticator) {
- properties.put(prefix + ".auth", "true");
+ properties.setProperty(prefix + ".auth", "true");
+ }
+
+ if (data.protocol.equals("smtps")) {
+ final SslConfiguration sslConfiguration = data.sslConfiguration;
+ if (sslConfiguration != null) {
+ final SSLSocketFactory sslSocketFactory = sslConfiguration.getSslSocketFactory();
+ properties.put(prefix + ".ssl.socketFactory", sslSocketFactory);
+ properties.setProperty(prefix + ".ssl.checkserveridentity", Boolean.toString(sslConfiguration.isVerifyHostName()));
+ }
}
final Session session = Session.getInstance(properties, authenticator);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
index 43464e5..b453f78 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/ssl/SslConfiguration.java
@@ -16,10 +16,11 @@
*/
package org.apache.logging.log4j.core.net.ssl;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.UnrecoverableKeyException;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginElement;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.status.StatusLogger;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -28,12 +29,10 @@ import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
-
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
-import org.apache.logging.log4j.core.config.plugins.PluginElement;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-import org.apache.logging.log4j.status.StatusLogger;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
/**
* SSL Configuration
@@ -45,12 +44,15 @@ public class SslConfiguration {
private final TrustStoreConfiguration trustStoreConfig;
private final SSLContext sslContext;
private final String protocol;
+ private final boolean verifyHostName;
- private SslConfiguration(final String protocol, final KeyStoreConfiguration keyStoreConfig,
- final TrustStoreConfiguration trustStoreConfig) {
+ private SslConfiguration(
+ final String protocol, final KeyStoreConfiguration keyStoreConfig,
+ final TrustStoreConfiguration trustStoreConfig, final boolean verifyHostName) {
this.keyStoreConfig = keyStoreConfig;
this.trustStoreConfig = trustStoreConfig;
this.protocol = protocol == null ? SslConfigurationDefaults.PROTOCOL : protocol;
+ this.verifyHostName = verifyHostName;
this.sslContext = this.createSslContext();
}
@@ -62,6 +64,10 @@ public class SslConfiguration {
return sslContext.getServerSocketFactory();
}
+ public boolean isVerifyHostName() {
+ return verifyHostName;
+ }
+
private SSLContext createSslContext() {
SSLContext context = null;
@@ -224,7 +230,16 @@ public class SslConfiguration {
trustStoreEquals = trustStoreConfig == config.trustStoreConfig;
}
- return keyStoreEquals && trustStoreEquals;
+ return keyStoreEquals && trustStoreEquals && verifyHostName == config.verifyHostName;
+ }
+
+ /**
+ * @deprecated use {@link #createSSLConfiguration(String, KeyStoreConfiguration, TrustStoreConfiguration, boolean)}
+ */
+ @Deprecated
+ public static SslConfiguration createSSLConfiguration(
+ final String protocol, final KeyStoreConfiguration keyStoreConfig, final TrustStoreConfiguration trustStoreConfig) {
+ return createSSLConfiguration(protocol, keyStoreConfig, trustStoreConfig, false);
}
/**
@@ -232,15 +247,17 @@ public class SslConfiguration {
* @param protocol The protocol, see http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
* @param keyStoreConfig The KeyStoreConfiguration.
* @param trustStoreConfig The TrustStoreConfiguration.
+ * @param verifyHostName Whether to enable TLS hostname verification
* @return a new SslConfiguration
*/
@PluginFactory
public static SslConfiguration createSSLConfiguration(
// @formatter:off
@PluginAttribute("protocol") final String protocol,
- @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig,
- @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig) {
+ @PluginElement("KeyStore") final KeyStoreConfiguration keyStoreConfig,
+ @PluginElement("TrustStore") final TrustStoreConfiguration trustStoreConfig,
+ @PluginAttribute("verifyHostName") final boolean verifyHostName) {
// @formatter:on
- return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig);
+ return new SslConfiguration(protocol, keyStoreConfig, trustStoreConfig, verifyHostName);
}
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SmtpAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SmtpAppenderTest.java
index cead991..5d4383f 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SmtpAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/SmtpAppenderTest.java
@@ -39,8 +39,6 @@ import static org.junit.Assert.*;
public class SmtpAppenderTest {
private static final String HOST = "localhost";
- private static final int PORTNUM = AvailablePortFinder.getNextAvailable();
- private static final String PORT = String.valueOf(PORTNUM);
@Test
public void testMessageFactorySetFrom() throws MessagingException {
@@ -131,10 +129,19 @@ public class SmtpAppenderTest {
@Test
public void testDelivery() {
- final SmtpAppender appender = SmtpAppender.createAppender("Test",
- "to@example.com", "cc@example.com", "bcc@example.com",
- "from@example.com", "replyTo@example.com", "Subject", null,
- HOST, PORT, null, null, "false", "3", null, null, "true");
+ int smtpPort = AvailablePortFinder.getNextAvailable();
+ final SmtpAppender appender = SmtpAppender.newBuilder()
+ .setName("Test")
+ .setTo("to@example.com")
+ .setCc("cc@example.com")
+ .setBcc("bcc@example.com")
+ .setFrom("from@example.com")
+ .setReplyTo("replyTo@example.com")
+ .setSubject("Subject")
+ .setSmtpHost(HOST)
+ .setSmtpPort(smtpPort)
+ .setBufferSize(3)
+ .build();
appender.start();
final LoggerContext context = (LoggerContext) LogManager.getContext();
@@ -143,7 +150,7 @@ public class SmtpAppenderTest {
root.setAdditive(false);
root.setLevel(Level.DEBUG);
- final SimpleSmtpServer server = SimpleSmtpServer.start(PORTNUM);
+ final SimpleSmtpServer server = SimpleSmtpServer.start(smtpPort);
root.debug("Debug message #1");
root.debug("Debug message #2");
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index c5d89a9..4a8a8c7 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -23,6 +23,12 @@
<title>Changes</title>
</properties>
<body>
+ <release version="2.3.2" date="2021-12-xx" description="GA Release 2.3.2">
+ <action issue="LOG4J2-2819" dev="mattsicker" type="fix">
+ Add support for specifying an SSL configuration for SmtpAppender.
+ Backport fix for CVE-2020-9488 to allow SSL/TLS hostname verification.
+ </action>
+ </release>
<release version="2.3.1" date="2021-12-20" description="GA Release 2.3.1">
<action issue="LOG4J2-3242" dev="rgoers, ggregory" type="fix">
Limit JNDI to the java protocol only. JNDI will remain disabled by default. Rename JNDI enablement property from
diff --git a/src/site/xdoc/manual/appenders.xml b/src/site/xdoc/manual/appenders.xml
index b451501..76ce2b7 100644
--- a/src/site/xdoc/manual/appenders.xml
+++ b/src/site/xdoc/manual/appenders.xml
@@ -2919,7 +2919,7 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
<Appenders>
<Socket name="socket" host="localhost" port="9500">
<SerializedLayout />
- <SSL>
+ <SSL verifyHostName="true">
<KeyStore location="log4j2-keystore.jks" password="changeme"/>
<TrustStore location="truststore.jks" password="changeme"/>
</SSL>
@@ -3143,7 +3143,7 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<TLSSyslog name="bsd" host="localhost" port="6514">
- <SSL>
+ <SSL verifyHostName="true">
<KeyStore location="log4j2-keystore.jks" password="changeme"/>
<TrustStore location="truststore.jks" password="changeme"/>
</SSL>