View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.smtpserver.core.filter.fastfail;
21  
22  import java.net.UnknownHostException;
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.Iterator;
26  
27  
28  import org.apache.avalon.framework.configuration.Configuration;
29  import org.apache.avalon.framework.configuration.ConfigurationException;
30  import org.apache.avalon.framework.service.ServiceException;
31  import org.apache.avalon.framework.service.ServiceManager;
32  import org.apache.avalon.framework.service.Serviceable;
33  import org.apache.james.api.dnsservice.DNSService;
34  import org.apache.james.api.dnsservice.TemporaryResolutionException;
35  import org.apache.james.api.dnsservice.util.NetMatcher;
36  import org.apache.james.dsn.DSNStatus;
37  import org.apache.james.smtpserver.CommandHandler;
38  import org.apache.james.smtpserver.SMTPSession;
39  import org.apache.mailet.MailAddress;
40  
41  /**
42   * This class can be used to reject email with bogus MX which is send from a authorized user or an authorized
43   * network.
44   */
45  public class ValidRcptMX extends AbstractJunkHandler implements CommandHandler,
46      Serviceable {
47  
48      private DNSService dnsServer = null;
49  
50      private static final String LOCALHOST = "localhost";
51  
52      private NetMatcher bNetwork = null;
53  
54      /**
55       * @see org.apache.james.smtpserver.core.filter.fastfail.AbstractJunkHandler#configure(org.apache.avalon.framework.configuration.Configuration)
56       */
57      public void configure(Configuration arg0) throws ConfigurationException {
58  
59          Configuration[] badMX = arg0.getChildren("invalidMXNetworks");
60  
61          if (badMX.length != 0) {
62   
63              Collection bannedNetworks = new ArrayList();
64  
65              for (int i = 0; i < badMX.length; i++) {
66                  String network = badMX[i].getValue(null);
67  
68                  if (network != null) {
69                      bannedNetworks.add(network);
70                  }
71              }
72  
73              setBannedNetworks(bannedNetworks, dnsServer);
74  
75              getLogger().info("Invalid MX Networks: " + bNetwork.toString());
76  
77          } else {
78              throw new ConfigurationException(
79                  "Please configure at least on invalid MX network");
80          }
81          
82          super.configure(arg0);
83      }
84  
85      /**
86       * Set the banned networks
87       * 
88       * @param networks Collection of networks 
89       * @param dnsServer The DNSService
90       */
91      public void setBannedNetworks(Collection networks, DNSService dnsServer) {
92          bNetwork = new NetMatcher(networks, dnsServer) {
93              protected void log(String s) {
94                  getLogger().debug(s);
95              }
96  
97          };
98      }
99  
100     /**
101      * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
102      */
103     public void service(ServiceManager arg0) throws ServiceException {
104         setDNSServer((DNSService) arg0.lookup(DNSService.ROLE));
105     }
106 
107     /**
108      * @see org.apache.james.smtpserver.CommandHandler#getImplCommands()
109      */
110     public Collection getImplCommands() {
111         Collection c = new ArrayList();
112         c.add("RCPT");
113         return c;
114     }
115 
116     /**
117      * @see org.apache.james.smtpserver.CommandHandler#onCommand(SMTPSession)
118      */
119     public void onCommand(SMTPSession session) {
120         doProcessing(session);
121     }
122 
123     /**
124      * Set the DNSService
125      * 
126      * @param dnsServer
127      *                The dnsServer
128      */
129     public void setDNSServer(DNSService dnsServer) {
130         this.dnsServer = dnsServer;
131     }
132 
133     /**
134      * @see org.apache.james.smtpserver.core.filter.fastfail.AbstractJunkHandler#check(org.apache.james.smtpserver.SMTPSession)
135      */
136     protected boolean check(SMTPSession session) {
137         MailAddress rcpt = (MailAddress) session.getState().get(SMTPSession.CURRENT_RECIPIENT);
138 
139         String domain = rcpt.getHost();
140 
141         // Email should be deliver local
142         if (domain.equals(LOCALHOST)) return false;
143  
144         Iterator mx = null;
145         try {
146             mx = dnsServer.findMXRecords(domain).iterator();
147         } catch (TemporaryResolutionException e1) {
148             //  TODO: Should we reject temporary ?
149         }
150 
151         if (mx != null && mx.hasNext()) {
152             while (mx.hasNext()) {
153                 String mxRec = mx.next().toString();
154 
155                 try {
156                     String ip = dnsServer.getByName(mxRec).getHostAddress();
157 
158                     // Check for invalid MX
159                     if (bNetwork.matchInetNetwork(ip)) {
160                         return true;
161                     }
162                 } catch (UnknownHostException e) {
163                     // Ignore this
164                 }
165             }
166         }
167         return false;
168     }
169 
170     /**
171      * @see org.apache.james.smtpserver.core.filter.fastfail.AbstractJunkHandler#getJunkHandlerData(org.apache.james.smtpserver.SMTPSession)
172      */
173     public JunkHandlerData getJunkHandlerData(SMTPSession session) {
174         MailAddress rcpt = (MailAddress) session.getState().get(SMTPSession.CURRENT_RECIPIENT);
175         JunkHandlerData data = new JunkHandlerData();
176 
177         data.setRejectResponseString("530" + DSNStatus.getStatus(DSNStatus.PERMANENT, DSNStatus.SECURITY_AUTH) + " Invalid MX " + session.getRemoteIPAddress() 
178             + " for domain " + rcpt.getHost() + ". Reject email");
179        
180         data.setJunkScoreLogString("Invalid MX " + session.getRemoteIPAddress() + " for domain " + rcpt.getHost() + ". Add JunkScore: " + getScore());
181         data.setRejectLogString("Invalid MX " + session.getRemoteIPAddress() + " for domain " + rcpt.getHost() + ". Reject email");
182         data.setScoreName("ValidRcptMXCheck");
183         return data;
184     }
185 }