1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.james.smtpserver.core.filter.fastfail;
23
24 import org.apache.avalon.framework.service.ServiceException;
25 import org.apache.avalon.framework.service.ServiceManager;
26 import org.apache.avalon.framework.service.Serviceable;
27 import org.apache.avalon.framework.configuration.Configuration;
28 import org.apache.avalon.framework.configuration.Configurable;
29 import org.apache.avalon.framework.configuration.ConfigurationException;
30 import org.apache.james.api.dnsservice.DNSService;
31 import org.apache.james.dsn.DSNStatus;
32 import org.apache.james.smtpserver.CommandHandler;
33 import org.apache.james.smtpserver.ConnectHandler;
34 import org.apache.james.smtpserver.SMTPSession;
35 import org.apache.james.smtpserver.junkscore.JunkScore;
36 import org.apache.mailet.MailAddress;
37
38 import java.util.ArrayList;
39 import java.util.Collection;
40 import java.util.StringTokenizer;
41
42
43
44
45 public class DNSRBLHandler
46 extends AbstractJunkHandler
47 implements ConnectHandler, CommandHandler, Configurable, Serviceable {
48
49
50
51 private String[] whitelist;
52 private String[] blacklist;
53
54 private DNSService dnsServer = null;
55
56 private boolean getDetail = false;
57
58 private String blocklistedDetail = null;
59
60 public static final String RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME = "org.apache.james.smtpserver.rbl.blocklisted";
61
62 public static final String RBL_DETAIL_MAIL_ATTRIBUTE_NAME = "org.apache.james.smtpserver.rbl.detail";
63
64
65
66
67 public void configure(Configuration handlerConfiguration) throws ConfigurationException {
68 boolean validConfig = false;
69
70 Configuration rblserverConfiguration = handlerConfiguration.getChild("rblservers", false);
71 if ( rblserverConfiguration != null ) {
72 ArrayList rblserverCollection = new ArrayList();
73 Configuration[] children = rblserverConfiguration.getChildren("whitelist");
74 if ( children != null ) {
75 for ( int i = 0 ; i < children.length ; i++ ) {
76 String rblServerName = children[i].getValue();
77 rblserverCollection.add(rblServerName);
78 if (getLogger().isInfoEnabled()) {
79 getLogger().info("Adding RBL server to whitelist: " + rblServerName);
80 }
81 }
82 if (rblserverCollection != null && rblserverCollection.size() > 0) {
83 setWhitelist((String[]) rblserverCollection.toArray(new String[rblserverCollection.size()]));
84 rblserverCollection.clear();
85 validConfig = true;
86 }
87 }
88 children = rblserverConfiguration.getChildren("blacklist");
89 if ( children != null ) {
90 for ( int i = 0 ; i < children.length ; i++ ) {
91 String rblServerName = children[i].getValue();
92 rblserverCollection.add(rblServerName);
93 if (getLogger().isInfoEnabled()) {
94 getLogger().info("Adding RBL server to blacklist: " + rblServerName);
95 }
96 }
97 if (rblserverCollection != null && rblserverCollection.size() > 0) {
98 setBlacklist((String[]) rblserverCollection.toArray(new String[rblserverCollection.size()]));
99 rblserverCollection.clear();
100 validConfig = true;
101 }
102 }
103 }
104
105
106 if (validConfig == false){
107 throw new ConfigurationException("Please configure whitelist or blacklist");
108 }
109
110 Configuration configuration = handlerConfiguration.getChild("getDetail",false);
111 if(configuration != null) {
112 getDetail = configuration.getValueAsBoolean();
113 }
114
115 super.configure(handlerConfiguration);
116
117 }
118
119
120
121
122 public void service(ServiceManager serviceMan) throws ServiceException {
123 setDNSServer((DNSService) serviceMan.lookup(DNSService.ROLE));
124 }
125
126
127
128
129
130
131 public void onConnect(SMTPSession session) {
132 checkDNSRBL(session, session.getRemoteIPAddress());
133 }
134
135
136
137
138
139
140 public void setWhitelist(String[] whitelist) {
141 this.whitelist = whitelist;
142 }
143
144
145
146
147
148
149 public void setBlacklist(String[] blacklist) {
150 this.blacklist = blacklist;
151 }
152
153
154
155
156
157
158 public void setDNSServer(DNSService dnsServer) {
159 this.dnsServer = dnsServer;
160 }
161
162
163
164
165
166
167 public void setGetDetail(boolean getDetail) {
168 this.getDetail = getDetail;
169 }
170
171
172
173
174
175
176
177
178
179 public void checkDNSRBL(SMTPSession session, String ipAddress) {
180
181
182
183
184
185 if (session.isRelayingAllowed()) {
186 getLogger().info("Ipaddress " + session.getRemoteIPAddress() + " is allowed to relay. Don't check it");
187 return;
188 }
189
190 if (whitelist != null || blacklist != null) {
191 StringBuffer sb = new StringBuffer();
192 StringTokenizer st = new StringTokenizer(ipAddress, " .", false);
193 while (st.hasMoreTokens()) {
194 sb.insert(0, st.nextToken() + ".");
195 }
196 String reversedOctets = sb.toString();
197
198 if (whitelist != null) {
199 String[] rblList = whitelist;
200 for (int i = 0 ; i < rblList.length ; i++) try {
201 dnsServer.getByName(reversedOctets + rblList[i]);
202 if (getLogger().isInfoEnabled()) {
203 getLogger().info("Connection from " + ipAddress + " whitelisted by " + rblList[i]);
204 }
205
206 return;
207 } catch (java.net.UnknownHostException uhe) {
208 if (getLogger().isDebugEnabled()) {
209 getLogger().debug("IpAddress " + session.getRemoteIPAddress() + " not listed on " + rblList[i]);
210 }
211 }
212 }
213
214 if (blacklist != null) {
215 String[] rblList = blacklist;
216 for (int i = 0 ; i < rblList.length ; i++) try {
217 dnsServer.getByName(reversedOctets + rblList[i]);
218 if (getLogger().isInfoEnabled()) {
219 getLogger().info("Connection from " + ipAddress + " restricted by " + rblList[i] + " to SMTP AUTH/postmaster/abuse.");
220 }
221
222
223 if (getDetail) {
224 Collection txt = dnsServer.findTXTRecords(reversedOctets + rblList[i]);
225
226
227 if (!txt.isEmpty()) {
228
229 String blocklistedDetail = txt.iterator().next().toString();
230
231 session.getConnectionState().put(RBL_DETAIL_MAIL_ATTRIBUTE_NAME, blocklistedDetail);
232 }
233 }
234
235 session.getConnectionState().put(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME, "true");
236 return;
237 } catch (java.net.UnknownHostException uhe) {
238
239 if (getLogger().isDebugEnabled()) {
240 getLogger().debug("unknown host exception thrown:" + rblList[i]);
241 }
242 }
243 }
244 }
245 }
246
247
248
249
250 public Collection getImplCommands() {
251 Collection commands = new ArrayList();
252 commands.add("RCPT");
253 return commands;
254 }
255
256
257
258
259 public void onCommand(SMTPSession session) {
260 doProcessing(session);
261 }
262
263
264
265
266 protected boolean check(SMTPSession session) {
267 String blocklisted = (String) session.getConnectionState().get(RBL_BLOCKLISTED_MAIL_ATTRIBUTE_NAME);
268 MailAddress recipientAddress = (MailAddress) session.getState().get(
269 SMTPSession.CURRENT_RECIPIENT);
270
271 return (blocklisted != null &&
272 !(session.isAuthRequired() && session.getUser() != null) &&
273 !(recipientAddress.getUser().equalsIgnoreCase("postmaster") || recipientAddress.getUser().equalsIgnoreCase("abuse")));
274 }
275
276
277
278
279 protected JunkScore getJunkScore(SMTPSession session) {
280 return (JunkScore) session.getConnectionState().get(JunkScore.JUNK_SCORE_SESSION);
281 }
282
283
284
285
286 public JunkHandlerData getJunkHandlerData(SMTPSession session) {
287 JunkHandlerData data = new JunkHandlerData();
288
289 data.setJunkScoreLogString("Ipaddress " + session.getRemoteIPAddress() + " listed on RBL. Add junkScore: " + getScore());
290 data.setRejectLogString("ipaddress " + session.getRemoteIPAddress() + " listed on RBL. Reject email");
291
292 if (blocklistedDetail != null) {
293 data.setRejectResponseString("530 "+ DSNStatus.getStatus(DSNStatus.PERMANENT,DSNStatus.SECURITY_AUTH) + " " + blocklistedDetail);
294 } else {
295 data.setRejectResponseString("530 "+ DSNStatus.getStatus(DSNStatus.PERMANENT,
296 DSNStatus.SECURITY_AUTH) + " Rejected: unauthenticated e-mail from " + session.getRemoteIPAddress()
297 + " is restricted. Contact the postmaster for details.");
298 }
299 data.setScoreName("DNSRBLCheck");
300 return data;
301 }
302 }