You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2006/05/19 17:17:41 UTC

svn commit: r407822 - in /james/server/trunk/src: conf/ java/org/apache/james/smtpserver/ test/org/apache/james/smtpserver/

Author: norman
Date: Fri May 19 08:17:40 2006
New Revision: 407822

URL: http://svn.apache.org/viewvc?rev=407822&view=rev
Log:
Add new feature to reject email when HELO/EHLO not equals reverse of the client ip. See JAMES-463

Modified:
    james/server/trunk/src/conf/james-config.xml
    james/server/trunk/src/java/org/apache/james/smtpserver/EhloCmdHandler.java
    james/server/trunk/src/java/org/apache/james/smtpserver/HeloCmdHandler.java
    james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java
    james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java

Modified: james/server/trunk/src/conf/james-config.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/src/conf/james-config.xml?rev=407822&r1=407821&r2=407822&view=diff
==============================================================================
--- james/server/trunk/src/conf/james-config.xml (original)
+++ james/server/trunk/src/conf/james-config.xml Fri May 19 08:17:40 2006
@@ -727,6 +727,12 @@
                 <checkResolvableHelo> false </checkResolvableHelo>
                 -->
                 
+                <!-- If is set to true helo is only accepted if it is equal the reverse of the -->
+                <!-- connecting client -->
+                <!--
+                <checkReverseEqualsHelo> false </checkReverseEqualsHelo>
+                -->
+                
                 <!-- If is set to true sender domain will be checked also for clients that -->
                 <!-- are allowed to relay. Default is false. -->
                 <!--
@@ -737,6 +743,12 @@
                 <!-- If is set to true ehlo is only accepted if it can be resolved -->
                 <!--
                 <checkResolvableEhlo> false </checkResolvableEhlo>
+                -->
+                
+                <!-- If is set to true ehlo is only accepted if it is equal the reverse of the -->
+                <!-- connecting client -->
+                <!--
+                <checkReverseEqualsEhlo> false </checkReverseEqualsEhlo>
                 -->
                 
                 <!-- If is set to true sender domain will be checked also for clients that -->

Modified: james/server/trunk/src/java/org/apache/james/smtpserver/EhloCmdHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/smtpserver/EhloCmdHandler.java?rev=407822&r1=407821&r2=407822&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/smtpserver/EhloCmdHandler.java (original)
+++ james/server/trunk/src/java/org/apache/james/smtpserver/EhloCmdHandler.java Fri May 19 08:17:40 2006
@@ -44,6 +44,8 @@
      * set checkResolvableEhlo to false as default value
      */
     private boolean checkResolvableEhlo = false;
+
+    private boolean checkReverseEqualsEhlo = false;
     
     private boolean checkAuthNetworks = false;
     
@@ -58,6 +60,12 @@
            setCheckResolvableEhlo(configuration.getValueAsBoolean(false));
         }
         
+        Configuration config = handlerConfiguration.getChild(
+                "checkReverseEqualsEhlo", false);
+        if (config != null) {
+            setCheckReverseEqualsEhlo(config.getValueAsBoolean(false));
+        }
+        
         Configuration configRelay = handlerConfiguration.getChild("checkAuthNetworks",false);
         if(configRelay != null) {
             setCheckAuthNetworks(configRelay.getValueAsBoolean(false));
@@ -81,10 +89,21 @@
     }
     
     /**
-     * Set to true if AuthNetworks should be included in the EHLO check
+     * Set to true to enable check for reverse equal EHLO
      * 
-     * @param checkAuthNetworks Set to true to enable
+     * @param checkReverseEqualsEhlo
+     *            Set to true for enable check
      */
+    public void setCheckReverseEqualsEhlo(boolean checkReverseEqualsEhlo) {
+        this.checkReverseEqualsEhlo = checkReverseEqualsEhlo;
+    }
+
+    /**
+	 * Set to true if AuthNetworks should be included in the EHLO check
+	 * 
+	 * @param checkAuthNetworks
+	 *            Set to true to enable
+	 */
     public void setCheckAuthNetworks(boolean checkAuthNetworks) {
         this.checkAuthNetworks = checkAuthNetworks;
     }
@@ -120,21 +139,48 @@
         StringBuffer responseBuffer = session.getResponseBuffer();
         boolean badEhlo = false;
         
-        // check for resolvable EHLO if its set in config
-        if (checkResolvableEhlo) {
-            
-            /**
-             * don't check if the ip address is allowed to relay. Only check if it is set in the config. ed.
-             */
-            if (!session.isRelayingAllowed() || checkAuthNetworks) {
-
-             
+        /**
+         * don't check if the ip address is allowed to relay. Only check if it
+         * is set in the config. ed.
+         */
+        if (!session.isRelayingAllowed() || checkAuthNetworks) {
+            // check for resolvable EHLO if its set in config
+            if (checkResolvableEhlo) {
                 // try to resolv the provided helo. If it can not resolved do not accept it.
                 try {
                     dnsServer.getByName(argument);
                 } catch (UnknownHostException e) {
                     badEhlo = true;
                     responseString = "501 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.DELIVERY_INVALID_ARG)+" Provided EHLO " + argument + " can not resolved";
+                    session.writeResponse(responseString);
+                    getLogger().info(responseString);
+                }
+            } else if (checkReverseEqualsEhlo) {
+                try {
+                    // get reverse entry
+                    String reverse = dnsServer.getByName(
+                            session.getRemoteIPAddress()).getHostName();
+
+                    if (!argument.equals(reverse)) {
+                        badEhlo = true;
+                        responseString = "501 "
+                                + DSNStatus.getStatus(DSNStatus.PERMANENT,
+                                        DSNStatus.DELIVERY_INVALID_ARG)
+                                + " Provided EHLO " + argument
+                                + " not equal reverse of "
+                                + session.getRemoteIPAddress();
+
+                        session.writeResponse(responseString);
+                        getLogger().info(responseString);
+                    }
+                } catch (UnknownHostException e) {
+                    badEhlo = true;
+                    responseString = "501 "
+                            + DSNStatus.getStatus(DSNStatus.PERMANENT,
+                                    DSNStatus.DELIVERY_INVALID_ARG)
+                            + " Ipaddress " + session.getRemoteIPAddress()
+                            + " can not resolved";
+
                     session.writeResponse(responseString);
                     getLogger().info(responseString);
                 }

Modified: james/server/trunk/src/java/org/apache/james/smtpserver/HeloCmdHandler.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/java/org/apache/james/smtpserver/HeloCmdHandler.java?rev=407822&r1=407821&r2=407822&view=diff
==============================================================================
--- james/server/trunk/src/java/org/apache/james/smtpserver/HeloCmdHandler.java (original)
+++ james/server/trunk/src/java/org/apache/james/smtpserver/HeloCmdHandler.java Fri May 19 08:17:40 2006
@@ -27,6 +27,7 @@
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.james.services.DNSServer;
+import org.apache.james.util.mail.dsn.DSNStatus;
 
 
 /**
@@ -44,6 +45,8 @@
      */
     private boolean checkResolvableHelo = false;
     
+    private boolean checkReverseEqualsHelo = false;
+    
     private boolean checkAuthNetworks = false;
     
     private DNSServer dnsServer = null;
@@ -56,6 +59,12 @@
         if(configuration != null) {
            setCheckResolvableHelo(configuration.getValueAsBoolean(false));
         }
+          
+        Configuration config = handlerConfiguration.getChild(
+                "checkReverseEqualsHelo", false);
+        if (config != null) {
+            setCheckReverseEqualsHelo(config.getValueAsBoolean(false));
+        }
         
         Configuration configRelay = handlerConfiguration.getChild("checkAuthNetworks",false);
         if(configRelay != null) {
@@ -81,6 +90,16 @@
     }
     
     /**
+     * Set to true to enable check for reverse equal HELO
+     * 
+     * @param checkReverseEqualsHelo
+     *            Set to true for enable check
+     */
+    public void setCheckReverseEqualsHelo(boolean checkReverseEqualsHelo) {
+        this.checkReverseEqualsHelo = checkReverseEqualsHelo;
+    }
+
+    /**
      * Set to true if AuthNetworks should be included in the EHLO check
      * 
      * @param checkAuthNetworks Set to true to enable
@@ -97,9 +116,7 @@
     public void setDnsServer(DNSServer dnsServer) {
         this.dnsServer = dnsServer;
     }
-
-
-       
+      
     /*
      * process HELO command
      *
@@ -121,14 +138,14 @@
         String responseString = null;
         boolean badHelo = false;
                 
-        
-        // check for resolvable HELO if its set in config
-        if (checkResolvableHelo) {
+        /**
+         * don't check if the ip address is allowed to relay. Only check if it is set in the config. ed.
+         */
+        if (!session.isRelayingAllowed() || checkAuthNetworks) {
+
+            // check for resolvable HELO if its set in config
+            if (checkResolvableHelo) {
             
-            /**
-             * don't check if the ip address is allowed to relay. Only check if it is set in the config. ed.
-             */
-            if (!session.isRelayingAllowed() || checkAuthNetworks) {
 
                 // try to resolv the provided helo. If it can not resolved do not accept it.
                 try {
@@ -140,6 +157,35 @@
                     getLogger().info(responseString);
                 } 
 
+            } else if (checkReverseEqualsHelo) {
+                try {
+                    // get reverse entry
+                    String reverse = dnsServer.getByName(
+                            session.getRemoteIPAddress()).getHostName();
+
+                    if (!argument.equals(reverse)) {
+                        badHelo = true;
+                        responseString = "501 "
+                                + DSNStatus.getStatus(DSNStatus.PERMANENT,
+                                        DSNStatus.DELIVERY_INVALID_ARG)
+                                + " Provided HELO " + argument
+                                + " not equal reverse of "
+                                + session.getRemoteIPAddress();
+
+                        session.writeResponse(responseString);
+                        getLogger().info(responseString);
+                    }
+                } catch (UnknownHostException e) {
+                    badHelo = true;
+                    responseString = "501 "
+                            + DSNStatus.getStatus(DSNStatus.PERMANENT,
+                                    DSNStatus.DELIVERY_INVALID_ARG)
+                            + " Ipaddress " + session.getRemoteIPAddress()
+                            + " can not resolved";
+
+                    session.writeResponse(responseString);
+                    getLogger().info(responseString);
+                }
             }
         }
         

Modified: james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java?rev=407822&r1=407821&r2=407822&view=diff
==============================================================================
--- james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java (original)
+++ james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java Fri May 19 08:17:40 2006
@@ -149,6 +149,8 @@
 
             public InetAddress getByName(String host) throws UnknownHostException
             {
+            	if ("127.0.0.1".equals(host)) return InetAddress.getByName("james.apache.org");
+            	
                 return InetAddress.getByName(host);
 //                throw new UnsupportedOperationException("getByName not implemented in mock for host: "+host);
             }
@@ -374,6 +376,35 @@
         smtpProtocol1.quit();
     }
     
+    public void testReverseEqualsHelo() throws Exception {
+        m_testConfiguration.setReverseEqualsHelo();
+        m_testConfiguration.setAuthorizedAddresses("192.168.0.1");
+        finishSetUp(m_testConfiguration);
+
+        SMTPClient smtpProtocol1 = new SMTPClient();
+        smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
+
+        assertTrue("first connection taken", smtpProtocol1.isConnected());
+
+        // no message there, yet
+        assertNull("no mail received by mail server", m_mailServer
+                .getLastMail());
+
+        String helo1 = "abgsfe3rsf.de";
+        String helo2 = "james.apache.org";
+
+        smtpProtocol1.sendCommand("helo", helo1);
+        // this should give a 501 code cause the helo not equal reverse of ip
+        assertEquals("expected error: helo not equals reverse of ip", 501,
+                smtpProtocol1.getReplyCode());
+
+        smtpProtocol1.sendCommand("helo", helo2);
+        // helo is resolvable. so this should give a 250 code
+        assertEquals("Helo accepted", 250, smtpProtocol1.getReplyCode());
+
+        smtpProtocol1.quit();
+    }
+    
     public void testSenderDomainResolv() throws Exception {
         m_testConfiguration.setSenderDomainResolv();
         m_testConfiguration.setAuthorizedAddresses("192.168.0.1/32");
@@ -590,6 +621,35 @@
         // this should give a 501 code cause the ehlo could not resolved
         assertEquals("expected error: ehlo could not resolved", 501, smtpProtocol1.getReplyCode());
             
+        smtpProtocol1.sendCommand("ehlo", ehlo2);
+        // ehlo is resolvable. so this should give a 250 code
+        assertEquals("ehlo accepted", 250, smtpProtocol1.getReplyCode());
+
+        smtpProtocol1.quit();
+    }
+    
+    public void testReverseEqualsEhlo() throws Exception {
+        m_testConfiguration.setReverseEqualsEhlo();
+        m_testConfiguration.setAuthorizedAddresses("192.168.0.1");
+        finishSetUp(m_testConfiguration);
+
+        SMTPClient smtpProtocol1 = new SMTPClient();
+        smtpProtocol1.connect("127.0.0.1", m_smtpListenerPort);
+
+        assertTrue("first connection taken", smtpProtocol1.isConnected());
+
+        // no message there, yet
+        assertNull("no mail received by mail server", m_mailServer
+                .getLastMail());
+
+        String ehlo1 = "abgsfe3rsf.de";
+        String ehlo2 = "james.apache.org";
+
+        smtpProtocol1.sendCommand("ehlo", ehlo1);
+        // this should give a 501 code cause the ehlo not equals reverse of ip
+        assertEquals("expected error: ehlo not equals reverse of ip", 501,
+                smtpProtocol1.getReplyCode());
+
         smtpProtocol1.sendCommand("ehlo", ehlo2);
         // ehlo is resolvable. so this should give a 250 code
         assertEquals("ehlo accepted", 250, smtpProtocol1.getReplyCode());

Modified: james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java
URL: http://svn.apache.org/viewvc/james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java?rev=407822&r1=407821&r2=407822&view=diff
==============================================================================
--- james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java (original)
+++ james/server/trunk/src/test/org/apache/james/smtpserver/SMTPTestConfiguration.java Fri May 19 08:17:40 2006
@@ -37,6 +37,8 @@
     private boolean m_checkAuthNetworks = false;
     private boolean m_checkAuthClients = false;
     private boolean m_heloEhloEnforcement = true;
+    private boolean m_reverseEqualsHelo = false;
+    private boolean m_reverseEqualsEhlo = false;
     private int m_maxRcpt = 0;
 
     
@@ -95,6 +97,14 @@
         m_ehloResolv = true; 
     }
     
+    public void setReverseEqualsHelo() {
+        m_reverseEqualsHelo = true; 
+    }
+    
+    public void setReverseEqualsEhlo() {
+        m_reverseEqualsEhlo = true; 
+    }
+    
     public void setSenderDomainResolv() {
         m_senderDomainResolv = true; 
     }
@@ -137,9 +147,11 @@
                 if (cmd != null) {
                     if ("HELO".equals(cmd)) {
                         ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkResolvableHelo",m_heloResolv+""));
+                        ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkReverseEqualsHelo",m_reverseEqualsHelo+""));
                         ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkAuthNetworks",m_checkAuthNetworks+""));
                     } else if ("EHLO".equals(cmd)) {
                         ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkResolvableEhlo",m_ehloResolv+""));
+                        ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkReverseEqualsEhlo",m_reverseEqualsEhlo+""));
                         ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkAuthNetworks",m_checkAuthNetworks+""));
                     } else if ("MAIL".equals(cmd)) {
                         ((DefaultConfiguration) heloConfig[i]).addChild(Util.getValuedConfiguration("checkValidSenderDomain",m_senderDomainResolv+""));



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org