This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push: new f4a4ad36ad [FIX] Apply RFC-5321 syntax validation for EHLO (#1979) f4a4ad36ad is described below commit f4a4ad36adfc925da21573a44104f54c0d5eb8eb Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Fri Feb 9 14:26:36 2024 +0100 [FIX] Apply RFC-5321 syntax validation for EHLO (#1979) https://datatracker.ietf.org/doc/html/rfc5321#section-4.1.1.1 Syntax: ehlo = "EHLO" SP ( Domain / address-literal ) CRLF helo = "HELO" SP Domain CRLF Failing to do so could lead to vulnerabilities eg value injection in received headers that could lead to arbitrary Received header crafting and might allow eg to bypass some anti-virus checks. This is a simple exploit that the non security-expert I am could put together in 2 minutes but other scenarii could leverage this as well. Tests demanded substancial adaptations to be syntax compliant. --- .../apache/james/protocols/netty/NettyServer.java | 2 + .../james/protocols/smtp/core/HeloCmdHandler.java | 29 +++++ .../protocols/smtp/core/esmtp/EhloCmdHandler.java | 31 ++++- .../java/org/apache/james/LmtpIntegrationTest.java | 4 +- .../apache/james/lmtpserver/LmtpServerTest.java | 24 ++-- .../james/smtpserver/SMTPProxyProtocolTest.java | 2 +- .../apache/james/smtpserver/SMTPServerTest.java | 127 +++++++++++++++++---- .../james/smtpserver/SMTPTestConfiguration.java | 1 + 8 files changed, 178 insertions(+), 42 deletions(-) diff --git a/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java b/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java index e36f086801..ba3905e161 100644 --- a/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java +++ b/protocols/netty/src/main/java/org/apache/james/protocols/netty/NettyServer.java @@ -88,6 +88,8 @@ public class NettyServer extends AbstractAsyncServer { this.secure = secure; this.proxyRequired = proxyRequired; this.frameHandlerFactory = frameHandlerFactory; + + this.setGracefulShutdown(false); } public void setMaxConcurrentConnections(int maxCurConnections) { diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/HeloCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/HeloCmdHandler.java index 00458dda39..01753a61a6 100644 --- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/HeloCmdHandler.java +++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/HeloCmdHandler.java @@ -33,8 +33,12 @@ import org.apache.james.protocols.smtp.SMTPSession; import org.apache.james.protocols.smtp.dsn.DSNStatus; import org.apache.james.protocols.smtp.hook.HeloHook; import org.apache.james.protocols.smtp.hook.HookResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableSet; +import com.google.common.net.InetAddresses; +import com.google.common.net.InternetDomainName; /** * Handles HELO command @@ -51,6 +55,7 @@ public class HeloCmdHandler extends AbstractHookableCmdHandler<HeloHook> { DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_INVALID_ARG) + " Domain address required: " + COMMAND_NAME).immutable(); + public static final Logger LOGGER = LoggerFactory.getLogger(HeloCmdHandler.class); @Inject public HeloCmdHandler(MetricFactory metricFactory) { @@ -65,6 +70,13 @@ public class HeloCmdHandler extends AbstractHookableCmdHandler<HeloHook> { @Override protected Response doCoreCmd(SMTPSession session, String command, String parameters) { + + if (!isValid(parameters)) { + LOGGER.error("Invalid EHLO argument received: {}. Must be a domain name or an IP address.", parameters); + return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS, + DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_SYNTAX) + " Invalid domain name or ip supplied as HELO argument"); + } + session.setAttachment(SMTPSession.CURRENT_HELO_MODE, COMMAND_NAME, ProtocolSession.State.Connection); StringBuilder response = new StringBuilder(); response.append(session.getConfiguration().getHelloName()).append( @@ -73,6 +85,23 @@ public class HeloCmdHandler extends AbstractHookableCmdHandler<HeloHook> { return new SMTPResponse(SMTPRetCode.MAIL_OK, response); } + private boolean isValid(String argument) { + String hostname = unquote(argument); + + // Without [] Guava attempt to parse IPV4 + return InetAddresses.isUriInetAddress(hostname) + // Guava tries parsing IPv6 if and only if wrapped by [] + || InetAddresses.isUriInetAddress("[" + hostname + "]") + || InternetDomainName.isValid(hostname); + } + + private String unquote(String argument) { + if (argument.startsWith("[") && argument.endsWith("]")) { + return argument.substring(1, argument.length() - 1); + } + return argument; + } + @Override protected Response doFilterChecks(SMTPSession session, String command, String parameters) { diff --git a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/EhloCmdHandler.java b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/EhloCmdHandler.java index 590fdbba5a..93901990f1 100644 --- a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/EhloCmdHandler.java +++ b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/esmtp/EhloCmdHandler.java @@ -34,10 +34,14 @@ import org.apache.james.protocols.smtp.core.AbstractHookableCmdHandler; import org.apache.james.protocols.smtp.dsn.DSNStatus; import org.apache.james.protocols.smtp.hook.HeloHook; import org.apache.james.protocols.smtp.hook.HookResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import com.google.common.net.InetAddresses; +import com.google.common.net.InternetDomainName; /** * Handles EHLO command @@ -52,7 +56,8 @@ public class EhloCmdHandler extends AbstractHookableCmdHandler<HeloHook> impleme // see http://issues.apache.org/jira/browse/JAMES-419 private static final List<String> ESMTP_FEATURES = ImmutableList.of("PIPELINING", "ENHANCEDSTATUSCODES", "8BITMIME"); private static final Response DOMAIN_ADDRESS_REQUIRED = new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS, DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_INVALID_ARG) + " Domain address required: " + COMMAND_NAME).immutable(); - + private static final Logger LOGGER = LoggerFactory.getLogger(EhloCmdHandler.class); + private List<EhloExtension> ehloExtensions; @Inject @@ -71,6 +76,12 @@ public class EhloCmdHandler extends AbstractHookableCmdHandler<HeloHook> impleme * the argument passed in with the command by the SMTP client */ private Response doEHLO(SMTPSession session, String argument) { + if (!isValid(argument)) { + LOGGER.error("Invalid EHLO argument received: {}. Must be a domain name or an IP address.", argument); + return new SMTPResponse(SMTPRetCode.SYNTAX_ERROR_ARGUMENTS, + DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.DELIVERY_SYNTAX) + " Invalid domain name or ip supplied as HELO argument"); + } + SMTPResponse resp = new SMTPResponse(SMTPRetCode.MAIL_OK, new StringBuilder(session.getConfiguration().getHelloName()).append(" Hello ").append(argument) .append(" [") .append(session.getRemoteAddress().getAddress().getHostAddress()).append("])")); @@ -79,11 +90,25 @@ public class EhloCmdHandler extends AbstractHookableCmdHandler<HeloHook> impleme COMMAND_NAME, State.Connection); processExtensions(session, resp); - - return resp; + } + + private boolean isValid(String argument) { + String hostname = unquote(argument); + // Without [] Guava attempt to parse IPV4 + return InetAddresses.isUriInetAddress(hostname) + // Guava tries parsing IPv6 if and only if wrapped by [] + || InetAddresses.isUriInetAddress("[" + hostname + "]") + || InternetDomainName.isValid(hostname); + } + + private String unquote(String argument) { + if (argument.startsWith("[") && argument.endsWith("]")) { + return argument.substring(1, argument.length() - 1); + } + return argument; } @Override diff --git a/server/apps/memory-app/src/test/java/org/apache/james/LmtpIntegrationTest.java b/server/apps/memory-app/src/test/java/org/apache/james/LmtpIntegrationTest.java index a11074481a..497a404962 100644 --- a/server/apps/memory-app/src/test/java/org/apache/james/LmtpIntegrationTest.java +++ b/server/apps/memory-app/src/test/java/org/apache/james/LmtpIntegrationTest.java @@ -63,7 +63,7 @@ public class LmtpIntegrationTest { server.connect(new InetSocketAddress(LOCALHOST_IP, guiceJamesServer.getProbe(LmtpGuiceProbe.class).getLmtpPort())); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <user@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -91,7 +91,7 @@ public class LmtpIntegrationTest { server.connect(new InetSocketAddress(LOCALHOST_IP, guiceJamesServer.getProbe(LmtpGuiceProbe.class).getLmtpPort())); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <user@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); diff --git a/server/protocols/protocols-lmtp/src/test/java/org/apache/james/lmtpserver/LmtpServerTest.java b/server/protocols/protocols-lmtp/src/test/java/org/apache/james/lmtpserver/LmtpServerTest.java index d377fb6b5e..d9e99dd957 100644 --- a/server/protocols/protocols-lmtp/src/test/java/org/apache/james/lmtpserver/LmtpServerTest.java +++ b/server/protocols/protocols-lmtp/src/test/java/org/apache/james/lmtpserver/LmtpServerTest.java @@ -190,7 +190,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -215,7 +215,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -255,7 +255,7 @@ class LmtpServerTest { SocketChannel server = SocketChannel.open(); server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + "> RET=HDRS ENVID=QQ314159\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -288,7 +288,7 @@ class LmtpServerTest { SocketChannel server = SocketChannel.open(); server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); assertThat(new String(readBytes(server), StandardCharsets.UTF_8)).contains("250 DSN\r\n"); } @@ -312,7 +312,7 @@ class LmtpServerTest { SocketChannel server = SocketChannel.open(); server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + "> RET=HDRS ENVID=QQ314159\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -355,7 +355,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -381,7 +381,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -433,7 +433,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -475,7 +475,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -514,7 +514,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("LHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("LHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <bob@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); @@ -542,7 +542,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("EHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("EHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); assertThat(new String(readBytes(server), StandardCharsets.UTF_8)) .contains("500 Unable to process request: the command is unknown"); } @@ -553,7 +553,7 @@ class LmtpServerTest { server.connect(new InetSocketAddress(LOCALHOST_IP, getLmtpPort(lmtpServerFactory))); readBytes(server); - server.write(ByteBuffer.wrap(("HELO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("HELO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); assertThat(new String(readBytes(server), StandardCharsets.UTF_8)) .contains("500 Unable to process request: the command is unknown"); } diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPProxyProtocolTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPProxyProtocolTest.java index 9adbcd466c..ccef0a632b 100644 --- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPProxyProtocolTest.java +++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPProxyProtocolTest.java @@ -67,7 +67,7 @@ class SMTPProxyProtocolTest { String proxyMessage = String.format("PROXY %s %s %s %d %d\r\n", protocol, source, destination, 65535, 65535); server.write(ByteBuffer.wrap((proxyMessage).getBytes(StandardCharsets.UTF_8))); - server.write(ByteBuffer.wrap(("EHLO <" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); + server.write(ByteBuffer.wrap(("EHLO " + DOMAIN + "\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); server.write(ByteBuffer.wrap(("MAIL FROM: <user@" + DOMAIN + ">\r\n").getBytes(StandardCharsets.UTF_8))); readBytes(server); diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java index 82e687122a..1fe70d2850 100644 --- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java +++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java @@ -55,6 +55,8 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -273,7 +275,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol.sendCommand("EHLO " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("EHLO localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -351,7 +353,7 @@ public class SMTPServerTest { SMTPClient smtpProtocol = new SMTPClient(); InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("EHLO " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("EHLO localhost"); smtpProtocol.setSender("mail@localhost"); smtpProtocol.addRecipient("mail@localhost"); // Create a 1K+ message @@ -385,7 +387,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol.sendCommand("EHLO " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("EHLO localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -479,7 +481,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtp.helo(InetAddress.getLocalHost().toString()); + smtp.helo("localhost"); smtp.setSender("mail@localhost"); smtp.addRecipient("mail@localhost"); smtp.sendShortMessageData("Subject: test\r\n\r\n"); @@ -492,6 +494,83 @@ public class SMTPServerTest { .isNotNull(); } + @ParameterizedTest + @ValueSource(strings = {"good", "adomain.com", "sub.domain.com", "127.0.0.1", "[127.0.0.1]", + "fe80::1ff:fe23:4567:890a", "[fe80::1ff:fe23:4567:890a]", + "2001:db8:85a3:8d3:1319:8a2e:370:7348", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"}) + public void testValidHELO(String helo) throws Exception { + init(smtpConfiguration); + + SMTPClient smtp = newSMTPClient(); + + // no message there, yet + assertThat(testSystem.queue.getLastMail()) + .as("no mail received by mail server") + .isNull(); + + smtp.helo(helo); + + assertThat(smtp.getReplyString()) + .startsWith("250"); + } + + @ParameterizedTest + @ValueSource(strings = {"bad value", "localhost) (spoofed into received header", "localhost)", "127.0.0.1/24", + "sub..bad", "[]", ""}) + public void testInvalidHELO(String helo) throws Exception { + init(smtpConfiguration); + + SMTPClient smtp = newSMTPClient(); + + // no message there, yet + assertThat(testSystem.queue.getLastMail()) + .as("no mail received by mail server") + .isNull(); + + smtp.helo(helo); + + assertThat(smtp.getReplyString()) + .startsWith("501"); + } + + @ParameterizedTest + @ValueSource(strings = {"good", "127.0.0.1", "adomain.com", "sub.domain.com", "[abc.def]", "[124.54.67.43]", + "fe80::1ff:fe23:4567:890a", "[fe80::1ff:fe23:4567:890a]", + "2001:db8:85a3:8d3:1319:8a2e:370:7348", "[2001:db8:85a3:8d3:1319:8a2e:370:7348]"}) + public void testValidEHLO(String helo) throws Exception { + init(smtpConfiguration); + + SMTPClient smtp = newSMTPClient(); + + // no message there, yet + assertThat(testSystem.queue.getLastMail()) + .as("no mail received by mail server") + .isNull(); + + smtp.sendCommand("EHLO " + helo); + + assertThat(smtp.getReplyString()) + .startsWith("250"); + } + + @ParameterizedTest + @ValueSource(strings = {"bad value", "localhost) (spoofed into received header", "localhost)", "127.0.0.1/24", "sub..bad", "[]"}) + public void testInvalidEHLO(String helo) throws Exception { + init(smtpConfiguration); + + SMTPClient smtp = newSMTPClient(); + + // no message there, yet + assertThat(testSystem.queue.getLastMail()) + .as("no mail received by mail server") + .isNull(); + + smtp.sendCommand("EHLO " + helo); + + assertThat(smtp.getReplyString()) + .startsWith("501 5.5.2 Invalid domain name or ip supplied as HELO argument"); + } + // FIXME @Disabled @Test @@ -532,7 +611,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol.helo(InetAddress.getLocalHost().toString()); + smtpProtocol.helo("localhost"); smtpProtocol.setSender("mail@localhost"); @@ -571,8 +650,8 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol1.helo(InetAddress.getLocalHost().toString()); - smtpProtocol2.helo(InetAddress.getLocalHost().toString()); + smtpProtocol1.helo("localhost"); + smtpProtocol2.helo("localhost"); String sender1 = "mail_sender1@localhost"; String recipient1 = "mail_recipient1@localhost"; @@ -614,7 +693,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol1.helo(InetAddress.getLocalHost().toString()); + smtpProtocol1.helo("localhost"); String sender1 = "mail_sender1@localhost"; String recipient1 = "mail_recipient1@localhost"; @@ -778,7 +857,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol1.helo(InetAddress.getLocalHost().toString()); + smtpProtocol1.helo("localhost"); String sender1 = "mail_send...@xfwrqqfgfe.de"; @@ -860,7 +939,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol1.helo(InetAddress.getLocalHost().toString()); + smtpProtocol1.helo("localhost"); String sender1 = "mail_send...@xfwrqqfgfe.de"; String sender2 = "mail_send...@james.apache.org"; @@ -894,7 +973,7 @@ public class SMTPServerTest { .as("no mail received by mail server") .isNull(); - smtpProtocol1.helo(InetAddress.getLocalHost().toString()); + smtpProtocol1.helo("localhost"); String sender1 = "mail_send...@james.apache.org"; String rcpt1 = "test@localhost"; @@ -1130,7 +1209,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -1212,7 +1291,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -1296,7 +1375,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -1338,7 +1417,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -1507,7 +1586,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("ehlo localhost"); smtpProtocol.setSender("m...@sample.com"); @@ -1526,7 +1605,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("ehlo localhost"); smtpProtocol.sendCommand("MAIL FROM:<mail@localhost> SIZE=1025", null); assertThat(smtpProtocol.getReplyCode()) @@ -1548,7 +1627,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("ehlo localhost"); smtpProtocol.setSender("mail@localhost"); smtpProtocol.addRecipient("mail@localhost"); @@ -1588,7 +1667,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo " + InetAddress.getLocalHost()); + smtpProtocol.sendCommand("ehlo localhost"); smtpProtocol.setSender("mail@localhost"); smtpProtocol.addRecipient("mail@localhost"); @@ -1631,7 +1710,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); String[] capabilityRes = smtpProtocol.getReplyStrings(); List<String> capabilitieslist = new ArrayList<>(); @@ -1690,7 +1769,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); String sender = USER_LOCALHOST; @@ -1717,7 +1796,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); smtpProtocol.sendCommand("mail from:", "test@localhost"); assertThat(smtpProtocol.getReplyCode()) @@ -1733,7 +1812,7 @@ public class SMTPServerTest { smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); smtpProtocol.sendCommand("mail from:", "<test@localhost>"); assertThat(smtpProtocol.getReplyCode()) @@ -1755,7 +1834,7 @@ public class SMTPServerTest { InetSocketAddress bindedAddress = testSystem.getBindedAddress(); smtpProtocol.connect(bindedAddress.getAddress().getHostAddress(), bindedAddress.getPort()); - smtpProtocol.sendCommand("ehlo", InetAddress.getLocalHost().toString()); + smtpProtocol.sendCommand("ehlo", "localhost"); smtpProtocol.sendCommand("mail from:", "test@localhost"); assertThat(smtpProtocol.getReplyCode()) diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPTestConfiguration.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPTestConfiguration.java index 2718665d97..2aea182b69 100644 --- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPTestConfiguration.java +++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPTestConfiguration.java @@ -137,6 +137,7 @@ public class SMTPTestConfiguration extends BaseHierarchicalConfiguration { addProperty("tls.secret", "jamestest"); addProperty("auth.requireSSL", false); addProperty("verifyIdentity", verifyIdentity); + addProperty("gracefulShutdown", false); // add the rbl handler if (useRBL) { --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org