001: /****************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one *
003: * or more contributor license agreements. See the NOTICE file *
004: * distributed with this work for additional information *
005: * regarding copyright ownership. The ASF licenses this file *
006: * to you under the Apache License, Version 2.0 (the *
007: * "License"); you may not use this file except in compliance *
008: * with the License. You may obtain a copy of the License at *
009: * *
010: * http://www.apache.org/licenses/LICENSE-2.0 *
011: * *
012: * Unless required by applicable law or agreed to in writing, *
013: * software distributed under the License is distributed on an *
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
015: * KIND, either express or implied. See the License for the *
016: * specific language governing permissions and limitations *
017: * under the License. *
018: ****************************************************************/package org.apache.james.smtpserver;
019:
020: import org.apache.avalon.framework.logger.AbstractLogEnabled;
021: import org.apache.avalon.framework.configuration.Configuration;
022: import org.apache.avalon.framework.configuration.Configurable;
023: import org.apache.avalon.framework.configuration.ConfigurationException;
024: import java.util.ArrayList;
025: import java.util.StringTokenizer;
026:
027: /**
028: * Connect handler for DNSRBL processing
029: */
030: public class DNSRBLHandler extends AbstractLogEnabled implements
031: ConnectHandler, Configurable {
032: /**
033: * The lists of rbl servers to be checked to limit spam
034: */
035: private String[] whitelist;
036: private String[] blacklist;
037:
038: /**
039: * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
040: */
041: public void configure(Configuration handlerConfiguration)
042: throws ConfigurationException {
043:
044: Configuration rblserverConfiguration = handlerConfiguration
045: .getChild("rblservers", false);
046: if (rblserverConfiguration != null) {
047: ArrayList rblserverCollection = new ArrayList();
048: Configuration[] children = rblserverConfiguration
049: .getChildren("whitelist");
050: if (children != null) {
051: for (int i = 0; i < children.length; i++) {
052: String rblServerName = children[i].getValue();
053: rblserverCollection.add(rblServerName);
054: if (getLogger().isInfoEnabled()) {
055: getLogger().info(
056: "Adding RBL server to whitelist: "
057: + rblServerName);
058: }
059: }
060: if (rblserverCollection != null
061: && rblserverCollection.size() > 0) {
062: whitelist = (String[]) rblserverCollection
063: .toArray(new String[rblserverCollection
064: .size()]);
065: rblserverCollection.clear();
066: }
067: }
068: children = rblserverConfiguration.getChildren("blacklist");
069: if (children != null) {
070: for (int i = 0; i < children.length; i++) {
071: String rblServerName = children[i].getValue();
072: rblserverCollection.add(rblServerName);
073: if (getLogger().isInfoEnabled()) {
074: getLogger().info(
075: "Adding RBL server to blacklist: "
076: + rblServerName);
077: }
078: }
079: if (rblserverCollection != null
080: && rblserverCollection.size() > 0) {
081: blacklist = (String[]) rblserverCollection
082: .toArray(new String[rblserverCollection
083: .size()]);
084: rblserverCollection.clear();
085: }
086: }
087: }
088:
089: }
090:
091: /*
092: * check if the remote Ip address is block listed
093: *
094: * @see org.apache.james.smtpserver.ConnectHandler#onConnect(SMTPSession)
095: **/
096: public void onConnect(SMTPSession session) {
097: boolean blocklisted = checkDNSRBL(session, session
098: .getRemoteIPAddress());
099: session.setBlockListed(blocklisted);
100: }
101:
102: /**
103: * @see org.apache.james.smtpserver.SMTPHandlerConfigurationData#checkDNSRBL(Socket)
104: */
105: /*
106: * This checks DNSRBL whitelists and blacklists. If the remote IP is whitelisted
107: * it will be permitted to send e-mail, otherwise if the remote IP is blacklisted,
108: * the sender will only be permitted to send e-mail to postmaster (RFC 2821) or
109: * abuse (RFC 2142), unless authenticated.
110: */
111:
112: public boolean checkDNSRBL(SMTPSession session, String ipAddress) {
113:
114: /*
115: * don't check against rbllists if the client is allowed to relay..
116: * This whould make no sense.
117: */
118: if (session.isRelayingAllowed()) {
119: getLogger().info(
120: "Ipaddress " + session.getRemoteIPAddress()
121: + " is allowed to relay. Don't check it");
122: return false;
123: }
124:
125: if (whitelist != null || blacklist != null) {
126: StringBuffer sb = new StringBuffer();
127: StringTokenizer st = new StringTokenizer(ipAddress, " .",
128: false);
129: while (st.hasMoreTokens()) {
130: sb.insert(0, st.nextToken() + ".");
131: }
132: String reversedOctets = sb.toString();
133:
134: if (whitelist != null) {
135: String[] rblList = whitelist;
136: for (int i = 0; i < rblList.length; i++)
137: try {
138: java.net.InetAddress addr = org.apache.james.dnsserver.DNSServer
139: .getByName(reversedOctets + rblList[i]);
140: if (getLogger().isInfoEnabled()) {
141: getLogger().info(
142: "Connection from " + ipAddress
143: + " whitelisted by "
144: + rblList[i]);
145: }
146:
147: /* Ihis code may be helpful if admins need to debug why they are getting weird
148: behavior from the blocklists. Also, it might help them to know what IP is
149: returned, since zones often use that to indicate interesting information.
150:
151: The next version of this code already handles the associated TXT record,
152: so this code is just temporary for this release.
153: */
154: if (getLogger().isDebugEnabled()) {
155: getLogger().debug(
156: "Whitelist addr = "
157: + addr.toString());
158: }
159:
160: return false;
161: } catch (java.net.UnknownHostException uhe) {
162: if (getLogger().isDebugEnabled()) {
163: getLogger().debug(
164: "unknown host exception thrown:"
165: + reversedOctets
166: + rblList[i]);
167: }
168: }
169: }
170:
171: if (blacklist != null) {
172: String[] rblList = blacklist;
173: for (int i = 0; i < rblList.length; i++)
174: try {
175: java.net.InetAddress addr = org.apache.james.dnsserver.DNSServer
176: .getByName(reversedOctets + rblList[i]);
177: if (getLogger().isInfoEnabled()) {
178: getLogger()
179: .info(
180: "Connection from "
181: + ipAddress
182: + " restricted by "
183: + rblList[i]
184: + " to SMTP AUTH/postmaster/abuse.");
185: }
186:
187: /* Ihis code may be helpful if admins need to debug why they are getting weird
188: behavior from the blocklists. Also, it might help them to know what IP is
189: returned, since zones often use that to indicate interesting information.
190:
191: The next version of this code already handles the associated TXT record,
192: so this code is just temporary for this release.
193: */
194: if (getLogger().isDebugEnabled()) {
195: getLogger().debug(
196: "Blacklist addr = "
197: + addr.toString());
198: }
199:
200: return true;
201: } catch (java.net.UnknownHostException uhe) {
202: // if it is unknown, it isn't blocked
203: if (getLogger().isDebugEnabled()) {
204: getLogger().debug(
205: "unknown host exception thrown:"
206: + reversedOctets
207: + rblList[i]);
208: }
209: }
210: }
211: }
212: return false;
213: }
214:
215: }
|