001: /*
002: *
003: * Jsmtpd, Java SMTP daemon
004: * Copyright (C) 2005 Jean-Francois POUX, jf.poux@laposte.net
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021: package org.jsmtpd.plugins.inputIPFilters;
022:
023: import java.net.Inet4Address;
024: import java.net.InetAddress;
025: import java.util.ArrayList;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031: import org.jsmtpd.core.common.PluginInitException;
032: import org.jsmtpd.core.common.PluginStore;
033: import org.jsmtpd.core.common.acl.IACL;
034: import org.jsmtpd.core.common.dnsService.IDNSResolver;
035: import org.jsmtpd.core.common.inputIPFilter.IFilterIP;
036: import org.jsmtpd.tools.cache.ICache;
037: import org.jsmtpd.tools.cache.SimpleCache;
038:
039: /**
040: * Real Time Black
041: * @author Jean-Francois POUX
042: */
043: public class RBLFilter implements IFilterIP {
044: /**
045: * RBL servers to check
046: */
047: private List<String> serverList = new ArrayList<String>();
048: /**
049: * daemon's logger
050: */
051: private Log log = LogFactory.getLog(RBLFilter.class);
052: /**
053: * DNS service to resolve against RBL servers
054: */
055: private IDNSResolver resolver = null;
056: /**
057: * ACL instance
058: */
059: private IACL acl = null;
060: /**
061: * ACL's relayed host will bypass this plugin if set to true
062: */
063: private boolean bypassLocal = false;
064: /**
065: * RBL dns queries are slow, cache them.
066: * TODO: Write expiration cache.
067: */
068: private ICache<String, Inet4Address> cache = new SimpleCache<String, Inet4Address>(
069: 500);
070:
071: public boolean checkIP(InetAddress input) {
072:
073: if (!(input instanceof Inet4Address)) // We only work with ipv4 atm
074: return false;
075:
076: String ipString = ((Inet4Address) input).getHostAddress();
077:
078: if (bypassLocal && acl.isValidRelay(ipString))
079: return true;
080:
081: if (cache.get(ipString) != null) // Ip is in cache, check canceled
082: return true;
083:
084: // We reverse the incoming IPv4 addresss to check it against RBL server (that's the way they work)
085: String[] parts = ((Inet4Address) input).getHostAddress().split(
086: "\\.");
087: String reverse = parts[3] + "." + parts[2] + "." + parts[1]
088: + "." + parts[0];
089:
090: // For each RBL server, try to resolve. First successfull resolution fails the filter (eg it means that's the ip is blacklisted)
091: for (Iterator iter = serverList.iterator(); iter.hasNext();) {
092: String element = (String) iter.next();
093: String toCheck = reverse + "." + element;
094: log.debug("Client ip: " + ipString + " RBL filtering with "
095: + element);
096: if (resolver.exists(toCheck)) {
097: log.warn("Client ip: " + ipString
098: + " rejected by RBLFilter plugin on server "
099: + element);
100: return false;
101: }
102: }
103: cache.cache(ipString, (Inet4Address) input); // put in cache so don't resolve it next time
104: return true; // Not found, go on in the servers
105: }
106:
107: public String getPluginName() {
108: return "Real time Blacklist plugin for jsmtpd";
109: }
110:
111: public void initPlugin() throws PluginInitException {
112: resolver = PluginStore.getInstance().getResolver();
113: // Should not happen because of init order in Controler. For debugg purpose
114: if (resolver == null)
115: throw new PluginInitException();
116:
117: acl = PluginStore.getInstance().getAcl();
118:
119: if (acl == null)
120: throw new PluginInitException();
121:
122: }
123:
124: public void shutdownPlugin() {
125: // nothing to do for this plugin
126: }
127:
128: // For autoconfig from xml file
129: public void setRBLServer(String serv) {
130: serverList.add(serv);
131: }
132:
133: public void setBypassLocal(boolean b) {
134: bypassLocal = b;
135: }
136: }
|