Author: norman Date: Sun May 14 03:12:22 2006 New Revision: 406304 URL: http://svn.apache.org/viewcvs?rev=406304&view=rev Log: -Add a findTXTRecord to the DNSServer -Add new feature JAMES-492. -Add set methods to easy change settings in junit tests -Add junit test for DNSRBLHandler
Added: james/server/trunk/src/test/org/apache/james/smtpserver/DNSRBLHandlerTest.java Modified: james/server/trunk/src/java/org/apache/james/dnsserver/DNSServer.java james/server/trunk/src/java/org/apache/james/services/DNSServer.java james/server/trunk/src/java/org/apache/james/smtpserver/DNSRBLHandler.java james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java james/server/trunk/src/java/org/apache/james/smtpserver/SMTPSession.java james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java Modified: james/server/trunk/src/java/org/apache/james/dnsserver/DNSServer.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/dnsserver/DNSServer.java?rev=406304&r1=406303&r2=406304&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/dnsserver/DNSServer.java (original) +++ james/server/trunk/src/java/org/apache/james/dnsserver/DNSServer.java Sun May 14 03:12:22 2006 @@ -38,6 +38,7 @@ import org.xbill.DNS.RRset; import org.xbill.DNS.ResolverConfig; import org.xbill.DNS.SetResponse; +import org.xbill.DNS.TXTRecord; import org.xbill.DNS.TextParseException; import org.xbill.DNS.Type; @@ -532,5 +533,25 @@ */ public void dispose() { - } + } + + /** + * @see org.apache.james.services.DNSServer#findTXTRecords(String) + */ + public Collection findTXTRecords(String hostname){ + List txtR = new ArrayList(); + Record[] records; + + records = lookup(hostname, Type.TXT); + + if (records != null) { + for (int i = 0; i < records.length; i++) { + TXTRecord txt = (TXTRecord) records[i]; + txtR.add(txt.rdataToString()); + } + + } + return txtR; + } + } Modified: james/server/trunk/src/java/org/apache/james/services/DNSServer.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/services/DNSServer.java?rev=406304&r1=406303&r2=406304&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/services/DNSServer.java (original) +++ james/server/trunk/src/java/org/apache/james/services/DNSServer.java Sun May 14 03:12:22 2006 @@ -45,6 +45,14 @@ */ Collection findMXRecords(String hostname); + /** + * Get a collection of DNS TXT Records + * + * @param hostname The hostname to check + * @return collection of strings representing TXT record values + */ + Collection findTXTRecords(String hostname); + /** * Performs DNS lookups as needed to find servers which should or might Modified: james/server/trunk/src/java/org/apache/james/smtpserver/DNSRBLHandler.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/DNSRBLHandler.java?rev=406304&r1=406303&r2=406304&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/smtpserver/DNSRBLHandler.java (original) +++ james/server/trunk/src/java/org/apache/james/smtpserver/DNSRBLHandler.java Sun May 14 03:12:22 2006 @@ -27,6 +27,7 @@ import org.apache.james.services.DNSServer; import java.util.ArrayList; +import java.util.Collection; import java.util.StringTokenizer; /** @@ -42,6 +43,8 @@ private String[] blacklist; private DNSServer dnsServer = null; + + private boolean getDetail = false; /** * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) @@ -61,7 +64,7 @@ } } if (rblserverCollection != null && rblserverCollection.size() > 0) { - whitelist = (String[]) rblserverCollection.toArray(new String[rblserverCollection.size()]); + setWhitelist((String[]) rblserverCollection.toArray(new String[rblserverCollection.size()])); rblserverCollection.clear(); } } @@ -75,11 +78,16 @@ } } if (rblserverCollection != null && rblserverCollection.size() > 0) { - blacklist = (String[]) rblserverCollection.toArray(new String[rblserverCollection.size()]); + setBlacklist((String[]) rblserverCollection.toArray(new String[rblserverCollection.size()])); rblserverCollection.clear(); } } } + + Configuration configuration = handlerConfiguration.getChild("getDetail",false); + if(configuration != null) { + getDetail = configuration.getValueAsBoolean(); + } } @@ -87,7 +95,7 @@ * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager) */ public void service(ServiceManager serviceMan) throws ServiceException { - dnsServer = (DNSServer) serviceMan.lookup(DNSServer.ROLE); + setDNSServer((DNSServer) serviceMan.lookup(DNSServer.ROLE)); } /* @@ -99,7 +107,38 @@ boolean blocklisted = checkDNSRBL(session, session.getRemoteIPAddress()); session.setBlockListed(blocklisted); } + + /** + * Set the whitelist array + * @param whitelist The array which contains the whitelist + */ + public void setWhitelist(String[] whitelist) { + this.whitelist = whitelist; + } + + /** + * Set the blacklist array + * @param blacklist The array which contains the blacklist + */ + public void setBlacklist(String[] blacklist) { + this.blacklist = blacklist; + } + + /** + * Set the DNSServer + * @param dnsServer The DNSServer + */ + public void setDNSServer(DNSServer dnsServer) { + this.dnsServer = dnsServer; + } + /** + * + * @param getDetail + */ + public void setGetDetail(boolean getDetail) { + this.getDetail = getDetail; + } /** * @see org.apache.james.smtpserver.SMTPHandlerConfigurationData#checkDNSRBL(Socket) @@ -151,6 +190,17 @@ dnsServer.getByName(reversedOctets + rblList[i]); if (getLogger().isInfoEnabled()) { getLogger().info("Connection from " + ipAddress + " restricted by " + rblList[i] + " to SMTP AUTH/postmaster/abuse."); + } + + // we should try to retrieve details + if (getDetail) { + Collection txt = dnsServer.findTXTRecords(reversedOctets + rblList[i]); + + // Check if we found a txt record + if (!txt.isEmpty()) { + // Set the detail + session.setBlockListedDetail(txt.iterator().next().toString()); + } } return true; } catch (java.net.UnknownHostException uhe) { Modified: james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java?rev=406304&r1=406303&r2=406304&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java (original) +++ james/server/trunk/src/java/org/apache/james/smtpserver/RcptCmdHandler.java Sun May 14 03:12:22 2006 @@ -161,8 +161,13 @@ if (session.isBlockListed() && // was found in the RBL (!session.isRelayingAllowed() || (session.isAuthRequired() && session.getUser() == null)) && // Not an authorized IP or SMTP AUTH is enabled and not authenticated !(recipientAddress.getUser().equalsIgnoreCase("postmaster") || recipientAddress.getUser().equalsIgnoreCase("abuse"))) { + // trying to send e-mail to other than postmaster or abuse - responseString = "530 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Rejected: unauthenticated e-mail from " + session.getRemoteIPAddress() + " is restricted. Contact the postmaster for details."; + if (session.getBlockListedDetail() != null) { + responseString = "530 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" " + session.getBlockListedDetail(); + } else { + responseString = "530 "+DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH)+" Rejected: unauthenticated e-mail from " + session.getRemoteIPAddress() + " is restricted. Contact the postmaster for details."; + } session.writeResponse(responseString); return; } Modified: james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java?rev=406304&r1=406303&r2=406304&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java (original) +++ james/server/trunk/src/java/org/apache/james/smtpserver/SMTPHandler.java Sun May 14 03:12:22 2006 @@ -123,6 +123,11 @@ * TEMPORARY: is the sending address blocklisted */ private boolean blocklisted; + + /** + * The blocklisted detail + */ + private String blocklistedDetail = null; /** * The id associated with this particular SMTP interaction. @@ -423,6 +428,20 @@ */ public void setBlockListed(boolean blocklisted ) { this.blocklisted = blocklisted; + } + + /** + * @see org.apache.james.smtpserver.SMTPSession#getBlockListedDetail() + */ + public String getBlockListedDetail() { + return blocklistedDetail; + } + + /** + * @see org.apache.james.smtpserver.SMTPSession#setBlockListedDetail(String) + */ + public void setBlockListedDetail(String blocklistedDetail) { + this.blocklistedDetail = blocklistedDetail; } /** Modified: james/server/trunk/src/java/org/apache/james/smtpserver/SMTPSession.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/java/org/apache/james/smtpserver/SMTPSession.java?rev=406304&r1=406303&r2=406304&view=diff ============================================================================== --- james/server/trunk/src/java/org/apache/james/smtpserver/SMTPSession.java (original) +++ james/server/trunk/src/java/org/apache/james/smtpserver/SMTPSession.java Sun May 14 03:12:22 2006 @@ -172,6 +172,20 @@ boolean isBlockListed(); /** + * Set the BlockListedDetail which will be used in responseString + * + * @param detail The detail + */ + void setBlockListedDetail(String detail); + + /** + * Returns the BlockListedDetail + * + * @return The BlockListedDetail + */ + String getBlockListedDetail(); + + /** * Returns whether Relaying is allowed or not * * @return the relaying status Added: james/server/trunk/src/test/org/apache/james/smtpserver/DNSRBLHandlerTest.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/smtpserver/DNSRBLHandlerTest.java?rev=406304&view=auto ============================================================================== --- james/server/trunk/src/test/org/apache/james/smtpserver/DNSRBLHandlerTest.java (added) +++ james/server/trunk/src/test/org/apache/james/smtpserver/DNSRBLHandlerTest.java Sun May 14 03:12:22 2006 @@ -0,0 +1,367 @@ +/*********************************************************************** + * Copyright (c) 1999-2006 The Apache Software Foundation. * + * All rights reserved. * + * ------------------------------------------------------------------- * + * Licensed under the Apache License, Version 2.0 (the "License"); you * + * may not use this file except in compliance with the License. You * + * may obtain a copy of the License at: * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * + * implied. See the License for the specific language governing * + * permissions and limitations under the License. * + ***********************************************************************/ + +package org.apache.james.smtpserver; + +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import org.apache.avalon.framework.container.ContainerUtil; +import org.apache.james.services.DNSServer; +import org.apache.james.test.mock.avalon.MockLogger; +import org.apache.james.util.watchdog.Watchdog; +import org.apache.mailet.Mail; + +import junit.framework.TestCase; + +public class DNSRBLHandlerTest extends TestCase { + + private DNSServer mockedDnsServer; + + private SMTPSession mockedSMTPSession; + + private String remoteIp = "127.0.0.2"; + + private boolean relaying = false; + + protected void setUp() throws Exception { + super.setUp(); + setupMockedDnsServer(); + setRelayingAllowed(false); + } + + /** + * Set the remoteIp + * + * @param remoteIp The remoteIP to set + */ + private void setRemoteIp(String remoteIp) { + this.remoteIp = remoteIp; + } + + /** + * Set relayingAllowed + * + * @param relaying true or false + */ + private void setRelayingAllowed(boolean relaying) { + this.relaying = relaying; + } + + /** + * Setup the mocked dnsserver + * + */ + private void setupMockedDnsServer() { + mockedDnsServer = new DNSServer() { + + public Collection findMXRecords(String hostname) { + throw new UnsupportedOperationException("Unimplemented in mock"); + } + + public Collection findTXTRecords(String hostname) { + List res = new ArrayList(); + if (hostname == null) { + return res; + } + ; + if ("2.0.0.127.bl.spamcop.net".equals(hostname)) { + res + .add("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2"); + } + return res; + } + + public Iterator getSMTPHostAddresses(String domainName) { + throw new UnsupportedOperationException("Unimplemented in mock"); + } + + public InetAddress[] getAllByName(String host) + throws UnknownHostException { + throw new UnsupportedOperationException("Unimplemented in mock"); + } + + public InetAddress getByName(String host) + throws UnknownHostException { + if ("2.0.0.127.bl.spamcop.net".equals(host)) { + return InetAddress.getByName("127.0.0.1"); + } else if ("3.0.0.127.bl.spamcop.net".equals(host)) { + return InetAddress.getByName("127.0.0.1"); + } else if ("192.168.0.1.bl.spamcop.net".equals(host)) { + return InetAddress.getByName("fesdgaeg.deger"); + } + return InetAddress.getByName(host); + } + }; + } + + /** + * Setup mocked smtpsession + */ + private void setupMockedSMTPSession() { + mockedSMTPSession = new SMTPSession() { + + private String blockListedDetail = null; + + private boolean blocklisted = false; + + public void writeResponse(String respString) { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String readCommandLine() throws IOException { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public StringBuffer getResponseBuffer() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String clearResponseBuffer() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public InputStream getInputStream() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String getCommandName() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String getCommandArgument() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public Mail getMail() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public void setMail(Mail mail) { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String getRemoteHost() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String getRemoteIPAddress() { + return remoteIp; + } + + public void abortMessage() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public void endSession() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public boolean isSessionEnded() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public HashMap getState() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public void resetState() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public SMTPHandlerConfigurationData getConfigurationData() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public void setBlockListed(boolean blocklisted) { + this.blocklisted = blocklisted; + } + + public boolean isBlockListed() { + return blocklisted; + } + + public void setBlockListedDetail(String detail) { + this.blockListedDetail = detail; + } + + public String getBlockListedDetail() { + return blockListedDetail; + } + + public boolean isRelayingAllowed() { + return relaying; + } + + public boolean isAuthRequired() { + return false; + } + + public boolean useHeloEhloEnforcement() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String getUser() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public void setUser(String user) { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public Watchdog getWatchdog() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + public String getSessionID() { + throw new UnsupportedOperationException( + "Unimplemented mock service"); + } + + }; + } + + // ip is blacklisted and has txt details + public void testDNSRBL1() { + DNSRBLHandler rbl = new DNSRBLHandler(); + + ContainerUtil.enableLogging(rbl, new MockLogger()); + + setupMockedSMTPSession(); + rbl.setDNSServer(mockedDnsServer); + + rbl.setBlacklist(new String[] { "bl.spamcop.net" }); + rbl.setGetDetail(true); + rbl.onConnect(mockedSMTPSession); + assertEquals("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2", + mockedSMTPSession.getBlockListedDetail()); + assertEquals(true, mockedSMTPSession.isBlockListed()); + } + + // ip is blacklisted and has txt details but we don'T want to retrieve the txt record + public void testDNSRBL2() { + DNSRBLHandler rbl = new DNSRBLHandler(); + + ContainerUtil.enableLogging(rbl, new MockLogger()); + + setupMockedSMTPSession(); + rbl.setDNSServer(mockedDnsServer); + + rbl.setBlacklist(new String[] { "bl.spamcop.net" }); + rbl.setGetDetail(false); + rbl.onConnect(mockedSMTPSession); + assertEquals(null, mockedSMTPSession.getBlockListedDetail()); + assertEquals(true, mockedSMTPSession.isBlockListed()); + } + + // ip is allowed to relay + public void testDNSRBL3() { + DNSRBLHandler rbl = new DNSRBLHandler(); + + ContainerUtil.enableLogging(rbl, new MockLogger()); + + setRelayingAllowed(true); + setupMockedSMTPSession(); + + rbl.setDNSServer(mockedDnsServer); + + rbl.setBlacklist(new String[] { "bl.spamcop.net" }); + rbl.setGetDetail(true); + rbl.onConnect(mockedSMTPSession); + assertEquals(null, mockedSMTPSession.getBlockListedDetail()); + assertEquals(false, mockedSMTPSession.isBlockListed()); + } + + // ip not on blacklist + public void testDNSRBL4() { + DNSRBLHandler rbl = new DNSRBLHandler(); + + ContainerUtil.enableLogging(rbl, new MockLogger()); + setRemoteIp("192.168.0.1"); + setupMockedSMTPSession(); + + rbl.setDNSServer(mockedDnsServer); + + rbl.setBlacklist(new String[] { "bl.spamcop.net" }); + rbl.setGetDetail(true); + rbl.onConnect(mockedSMTPSession); + assertEquals(null, mockedSMTPSession.getBlockListedDetail()); + assertEquals(false, mockedSMTPSession.isBlockListed()); + } + + // ip on blacklist without txt details + public void testDNSRBL5() { + DNSRBLHandler rbl = new DNSRBLHandler(); + + ContainerUtil.enableLogging(rbl, new MockLogger()); + setRemoteIp("127.0.0.3"); + setupMockedSMTPSession(); + + rbl.setDNSServer(mockedDnsServer); + + rbl.setBlacklist(new String[] { "bl.spamcop.net" }); + rbl.setGetDetail(true); + rbl.onConnect(mockedSMTPSession); + assertEquals(null, mockedSMTPSession.getBlockListedDetail()); + assertEquals(true, mockedSMTPSession.isBlockListed()); + } + + // ip on whitelist + public void testDNSRBL6() { + DNSRBLHandler rbl = new DNSRBLHandler(); + + ContainerUtil.enableLogging(rbl, new MockLogger()); + setRemoteIp("127.0.0.2"); + setupMockedSMTPSession(); + + rbl.setDNSServer(mockedDnsServer); + + rbl.setWhitelist(new String[] { "bl.spamcop.net" }); + rbl.setGetDetail(true); + rbl.onConnect(mockedSMTPSession); + assertEquals(null, mockedSMTPSession.getBlockListedDetail()); + assertEquals(false, mockedSMTPSession.isBlockListed()); + } + +} Modified: james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java URL: http://svn.apache.org/viewcvs/james/server/trunk/src/test/org/apache/james/smtpserver/SMTPServerTest.java?rev=406304&r1=406303&r2=406304&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 Sun May 14 03:12:22 2006 @@ -162,6 +162,17 @@ // throw new UnsupportedOperationException("getByName not implemented in mock for host: "+host); } + public Collection findTXTRecords(String hostname) { + List res = new ArrayList(); + if (hostname == null) { + return res; + }; + if ("2.0.0.127.bl.spamcop.net".equals(hostname)) { + res.add("Blocked - see http://www.spamcop.net/bl.shtml?127.0.0.2"); + } + return res; + } + }; m_serviceManager.put(DNSServer.ROLE, dns); m_serviceManager.put(Store.ROLE, new MockStore()); --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]