This is an automated email from the ASF dual-hosted git repository. bodewig pushed a commit to branch mailer-tls-server-check in repository https://gitbox.apache.org/repos/asf/ant.git
commit 6154296c226e07bceb944f40d7ed071a49c945c4 Author: Stefan Bodewig <bode...@apache.org> AuthorDate: Sat May 31 16:30:35 2025 +0200 improve security of TLS handling in MimeMailers Bugzilla Report https://bz.apache.org/bugzilla/show_bug.cgi?id=69416 --- WHATSNEW | 12 ++++++++ manual/Tasks/mail.html | 17 +++++++++++ manual/listeners.html | 16 ++++++++++ .../org/apache/tools/ant/listener/MailLogger.java | 27 +++++++++++++++++ .../apache/tools/ant/taskdefs/email/EmailTask.java | 29 ++++++++++++++++++ .../ant/taskdefs/email/JakartaMimeMailer.java | 9 ++++++ .../apache/tools/ant/taskdefs/email/Mailer.java | 35 ++++++++++++++++++++++ .../tools/ant/taskdefs/email/MimeMailer.java | 9 ++++++ 8 files changed, 154 insertions(+) diff --git a/WHATSNEW b/WHATSNEW index 3cba7a7b4..194e00786 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -18,6 +18,14 @@ Changes that could break older environments: the behavior of 1.10.15. Bugzilla Report 65756 + * the <mail> task as well as MailLogger will now check the server + identity as specified by RFC 2595 when JavaMail is used in + combination with TLS (plain TLS or StartTLS). + The check can be disabled with a new MailLogger property + MailLogger.tls.checkserveridentity or a new <mail> task attribute + checkServerIdentity. + Bugzilla Report 69416 + Fixed bugs: ----------- @@ -40,6 +48,10 @@ Other changes: "disallow". Github Pull Request #216 + * <mail> and MailLogger can now enforce the use of STARTLS rather + than silently fall back to unencrypted authentication via a new + MailLogger property and a new <mail> task attribute. + Bugzilla Report 69416 Changes from Ant 1.10.14 TO Ant 1.10.15 ======================================= diff --git a/manual/Tasks/mail.html b/manual/Tasks/mail.html index 3b51a64c4..2c43a6066 100644 --- a/manual/Tasks/mail.html +++ b/manual/Tasks/mail.html @@ -171,6 +171,23 @@ <h3>Parameters</h3> 1.8.0</em></td> <td>No</td> </tr> + <tr> + <td>requireStartTLS</td> + <td>(boolean) Whether the <code>STARTTLS</code> command used to switch to an encrypted + connection for authentication should be required. + <br/>Implicitly sets <q>enableStartTLS</q> to <q>true</q> if enabled. Requires JavaMail. + <br/><em>Since Ant 1.10.16</em></td> + <td>No</td> + </tr> + <tr> + <td>checkServerIdentity</td> + <td>(boolean) Whether the server's identity shall be verified + during TLS handshake. + <br/> Ignored unless <q>ssl</q> or <q>enableStartTLS</q> is <q>true</q>. + Requires JavaMail. + <br/><em>Since Ant 1.10.16</em></td> + <td>No; default is <q>true</q></td> + </tr> </table> <h3>Note regarding the attributes containing email addresses</h3> diff --git a/manual/listeners.html b/manual/listeners.html index 4c1b87801..286d58f6b 100644 --- a/manual/listeners.html +++ b/manual/listeners.html @@ -259,6 +259,22 @@ <h3 id="MailLogger">MailLogger</h3> 1.8.0</em></td> <td>No; default is <q>false</q></td> </tr> + <tr> + <td><code>MailLogger.starttls.require</code></td> + <td>on or true if <code>STARTTLS</code> should be required + (requires JavaMail). + If <q>true</q> implicitly + sets <code>MailLogger.starttls.enable</code> to <q>true</q> as well. + <br/><em>Since Ant 1.10.16</em></td> + <td>No; default is <q>false</q></td> + </tr> + <tr> + <td><code>MailLogger.tls.checkserveridentity</code></td> + <td>on or true if the identity of the server shall be chcked + during the TLS handshake (requires JavaMail). + <br/><em>Since Ant 1.10.16</em></td> + <td>No; default is <q>true</q></td> + </tr> <tr> <td><code>MailLogger.properties.file</code></td> <td>Filename of properties file that will override other values.</td> diff --git a/src/main/org/apache/tools/ant/listener/MailLogger.java b/src/main/org/apache/tools/ant/listener/MailLogger.java index 897f0000b..5a26b30a1 100644 --- a/src/main/org/apache/tools/ant/listener/MailLogger.java +++ b/src/main/org/apache/tools/ant/listener/MailLogger.java @@ -84,6 +84,11 @@ import org.apache.tools.mail.MailMessage; * <li> MailLogger.charset [no default] - character set of email</li> * <li> MailLogger.starttls.enable [default: false] - on or true if * STARTTLS should be supported (requires Java or Jakarta Mail)</li> + * <li> MailLogger.starttls.require [default: false] - on or true if + * STARTTLS should be required (requires Java or Jakarta Mail)</li> + * <li> MailLogger.tls.checkserveridentity [default: true] - on or true if + * the identity of the server shall be chcked during the TLS handshake + * (requires Java or Jakarta Mail)</li> * <li> MailLogger.properties.file [no default] - Filename of * properties file that will override other values.</li> * </ul> @@ -153,6 +158,10 @@ public class MailLogger extends DefaultLogger { "ssl", "off"))) .starttls(Project.toBoolean(getValue(properties, "starttls.enable", "off"))) + .starttlsRequired(Project.toBoolean(getValue(properties, + "starttls.require", "off"))) + .checkTlsServerIdentity(Project.toBoolean(getValue(properties, + "tls.checkserveridentity", "on"))) .from(getValue(properties, "from", null)) .replytoList(getValue(properties, "replyto", "")) .toList(getValue(properties, prefix + ".to", null)) @@ -299,6 +308,22 @@ public class MailLogger extends DefaultLogger { this.starttls = starttls; return this; } + private boolean starttlsRequired; + public boolean starttlsRequired() { + return starttlsRequired; + } + public Values starttlsRequired(boolean required) { + this.starttlsRequired = required; + return required ? starttls(required) : this; + } + private boolean checkTlsServerIdentity = true; + public boolean checkTlsServerIdentity() { + return checkTlsServerIdentity; + } + public Values checkTlsServerIdentity(boolean check) { + this.checkTlsServerIdentity = check; + return this; + } } /** @@ -400,6 +425,8 @@ public class MailLogger extends DefaultLogger { mailer.setPassword(values.password()); mailer.setSSL(values.ssl()); mailer.setEnableStartTLS(values.starttls()); + mailer.setRequireStartTLS(values.starttlsRequired()); + mailer.setCheckServerIdentity(values.checkTlsServerIdentity()); Message mymessage = new Message(!values.body().isEmpty() ? values.body() : message); mymessage.setProject(project); diff --git a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java index 5336d06fd..44e166287 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/EmailTask.java @@ -105,10 +105,14 @@ public class EmailTask extends Task { private boolean ssl = false; /** indicate if the user wishes support for STARTTLS */ private boolean starttls = false; + private boolean requireStarttls = false; /** ignore invalid recipients? */ private boolean ignoreInvalidRecipients = false; + /** more strict TLS server certificate check */ + private boolean checkServerIdentity = true; + /** * Set the user for SMTP auth; this requires JavaMail. * @@ -150,6 +154,29 @@ public class EmailTask extends Task { this.starttls = b; } + /** + * Set whether to require authentication to switch to a TLS + * connection via STARTTLS. + * + * @param b boolean; if true STARTTLS will be supported and required. + * @since Ant 1.10.16 + */ + public void setRequireStartTLS(boolean b) { + this.requireStarttls = b; + if (b) { + setEnableStartTLS(b); + } + } + + /** + * Whether the server's identity shall be verified during TLS handshake. + * @param b boolean; if true server identity will be checked. + * @since Ant 1.10.16 + */ + public void setCheckServerIdentity(boolean b) { + this.checkServerIdentity = b; + } + /** * Set the preferred encoding method. * @@ -557,6 +584,8 @@ public class EmailTask extends Task { mailer.setPassword(password); mailer.setSSL(ssl); mailer.setEnableStartTLS(starttls); + mailer.setRequireStartTLS(requireStarttls); + mailer.setCheckServerIdentity(checkServerIdentity); mailer.setMessage(message); mailer.setFrom(from); mailer.setReplyToList(replyToList); diff --git a/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java index 0055c5ffc..e41d3d805 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/JakartaMimeMailer.java @@ -155,6 +155,9 @@ public class JakartaMimeMailer extends Mailer { props.put("mail.smtp.socketFactory.port", String.valueOf(port)); } + if (shouldCheckServerIdentity()) { + props.put("mail.smtp.ssl.checkserveridentity", "true"); + } } if (user != null || password != null) { props.put("mail.smtp.auth", "true"); @@ -162,6 +165,12 @@ public class JakartaMimeMailer extends Mailer { } if (isStartTLSEnabled()) { props.put("mail.smtp.starttls.enable", "true"); + if (isStartTLSRequired()) { + props.put("mail.smtp.starttls.required", "true"); + } + if (shouldCheckServerIdentity()) { + props.put("mail.smtp.ssl.checkserveridentity", "true"); + } } sesh = Session.getInstance(props, auth); diff --git a/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java b/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java index 7c00038a3..12ee973a3 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/Mailer.java @@ -52,7 +52,9 @@ public abstract class Mailer { // CheckStyle:VisibilityModifier ON private boolean ignoreInvalidRecipients = false; private boolean starttls = false; + private boolean requireStarttls = false; private boolean portExplicitlySpecified = false; + private boolean checkServerIdentity = true; /** * Set the mail server. @@ -136,6 +138,25 @@ public abstract class Mailer { return starttls; } + /** + * Set whether to enforce authentication to switch to a TLS + * connection via STARTTLS. + * @param b boolean; if true STARTTLS will be required. + * @since Ant 1.10.16 + */ + public void setRequireStartTLS(boolean b) { + this.requireStarttls = b; + } + + /** + * Whether the server's identity shall be verified during TLS handshake. + * @param b boolean; if true server identity will be checked. + * @since Ant 1.10.16 + */ + public void setCheckServerIdentity(boolean b) { + this.checkServerIdentity = b; + } + /** * Set the message. * @@ -268,6 +289,20 @@ public abstract class Mailer { return ignoreInvalidRecipients; } + /** + * @since Ant 1.10.16 + */ + protected boolean shouldCheckServerIdentity() { + return starttls; + } + + /** + * @since Ant 1.10.16 + */ + protected boolean isStartTLSRequired() { + return requireStarttls; + } + /** * Return the current Date in a format suitable for a SMTP date * header. diff --git a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java index 6a55312d3..0d3598604 100644 --- a/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java +++ b/src/main/org/apache/tools/ant/taskdefs/email/MimeMailer.java @@ -157,6 +157,9 @@ public class MimeMailer extends Mailer { props.put("mail.smtp.socketFactory.port", String.valueOf(port)); } + if (shouldCheckServerIdentity()) { + props.put("mail.smtp.ssl.checkserveridentity", "true"); + } } if (user != null || password != null) { props.put("mail.smtp.auth", "true"); @@ -164,6 +167,12 @@ public class MimeMailer extends Mailer { } if (isStartTLSEnabled()) { props.put("mail.smtp.starttls.enable", "true"); + if (isStartTLSRequired()) { + props.put("mail.smtp.starttls.required", "true"); + } + if (shouldCheckServerIdentity()) { + props.put("mail.smtp.ssl.checkserveridentity", "true"); + } } sesh = Session.getInstance(props, auth);