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  
21  package org.apache.james.jspf.terms;
22  
23  import org.apache.james.jspf.core.DNSLookupContinuation;
24  import org.apache.james.jspf.core.LogEnabled;
25  import org.apache.james.jspf.core.Logger;
26  import org.apache.james.jspf.core.MacroExpand;
27  import org.apache.james.jspf.core.MacroExpandEnabled;
28  import org.apache.james.jspf.core.SPF1Constants;
29  import org.apache.james.jspf.core.SPFCheckEnabled;
30  import org.apache.james.jspf.core.SPFChecker;
31  import org.apache.james.jspf.core.SPFCheckerExceptionCatcher;
32  import org.apache.james.jspf.core.SPFSession;
33  import org.apache.james.jspf.core.SPFTermsRegexps;
34  import org.apache.james.jspf.core.exceptions.NeutralException;
35  import org.apache.james.jspf.core.exceptions.NoneException;
36  import org.apache.james.jspf.core.exceptions.PermErrorException;
37  import org.apache.james.jspf.core.exceptions.TempErrorException;
38  
39  /**
40   * This class represent the incude mechanism
41   * 
42   */
43  public class IncludeMechanism implements Mechanism, ConfigurationEnabled, LogEnabled, SPFCheckEnabled, MacroExpandEnabled {
44  
45      private final class ExpandedChecker implements SPFChecker {
46        
47          /**
48          * @see org.apache.james.jspf.core.SPFChecker#checkSPF(org.apache.james.jspf.core.SPFSession)
49          */
50          public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException,
51                  TempErrorException {
52  
53              // throws a PermErrorException that we can pass through
54              String host = macroExpand.expand(getHost(), spfData, MacroExpand.DOMAIN);
55              
56              spfData.setCurrentDomain(host);
57              
58              // On includes we should not use the explanation of the included domain
59              spfData.setIgnoreExplanation(true);
60              // set a null current result
61              spfData.setCurrentResult(null);
62              spfData.setCurrentResultExpanded(null);
63              
64              spfData.pushChecker(spfChecker);
65              
66              return null;
67          }
68      }
69  
70      private final class CleanupAndResultChecker implements SPFChecker, SPFCheckerExceptionCatcher {
71          private String previousResult;
72          private String previousResultExpanded;
73          private String previousDomain;
74  
75          private void restoreSession(SPFSession spfData) {
76              spfData.setIgnoreExplanation(false);
77              spfData.setCurrentDomain(previousDomain);
78              spfData.setCurrentResult(previousResult);
79              spfData.setCurrentResultExpanded(previousResultExpanded);
80          }
81          
82          /**
83           * @see org.apache.james.jspf.core.SPFChecker#checkSPF(org.apache.james.jspf.core.SPFSession)
84           */
85          public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException,
86                  TempErrorException, NeutralException, NoneException {
87              
88              String currentResult = spfData.getCurrentResult();
89              
90              restoreSession(spfData);
91              
92              if (currentResult == null) {
93                  throw new TempErrorException("included checkSPF returned null");
94              } else if (currentResult.equals(SPF1Constants.PASS)) {
95                  // TODO this won't work asynchronously
96                  spfData.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.TRUE);
97              } else if (currentResult.equals(SPF1Constants.FAIL) || currentResult.equals(SPF1Constants.SOFTFAIL) || currentResult.equals(SPF1Constants.NEUTRAL)) {
98                  // TODO this won't work asynchronously
99                  spfData.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.FALSE);
100             } else {
101                 throw new TempErrorException("included checkSPF returned an Illegal result");
102             }
103 
104             return null;
105         }
106 
107         /**
108          * @see org.apache.james.jspf.core.SPFCheckerExceptionCatcher#onException(java.lang.Exception, org.apache.james.jspf.core.SPFSession)
109          */
110         public void onException(Exception exception, SPFSession session)
111                 throws PermErrorException, NoneException,
112                 TempErrorException, NeutralException {
113             
114             restoreSession(session);
115             
116             if (exception instanceof NeutralException) {
117                 throw new PermErrorException("included checkSPF returned NeutralException");
118             } else if (exception instanceof NoneException) {
119                 throw new PermErrorException("included checkSPF returned NoneException");
120             } else if (exception instanceof PermErrorException){
121                 throw (PermErrorException) exception;
122             } else if (exception instanceof TempErrorException){
123                 throw (TempErrorException) exception;
124             } else if (exception instanceof RuntimeException){
125                 throw (RuntimeException) exception;
126             } else {
127                 throw new IllegalStateException(exception.getMessage());
128             }
129         }
130 
131         public SPFChecker init(SPFSession spfSession) {
132             // TODO understand what exactly we have to do now that spfData is a session
133             // and contains much more than the input data.
134             // do we need to create a new session at all?
135             // do we need to backup the session attributes and restore them?
136             this.previousResult = spfSession.getCurrentResult();
137             this.previousDomain = spfSession.getCurrentDomain();
138             this.previousResultExpanded = spfSession.getCurrentResultExpanded();
139             return this;
140         }
141     }
142 
143     /**
144      * ABNF: include = "include" ":" domain-spec
145      */
146     public static final String REGEX = "[iI][nN][cC][lL][uU][dD][eE]" + "\\:"
147             + SPFTermsRegexps.DOMAIN_SPEC_REGEX;
148 
149     protected String host;
150     
151     protected Logger log;
152 
153     private SPFChecker spfChecker;
154 
155     private MacroExpand macroExpand;
156 
157     /**
158      * @see org.apache.james.jspf.core.SPFChecker#checkSPF(org.apache.james.jspf.core.SPFSession)
159      */
160     public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException, TempErrorException, NoneException, NeutralException {
161         // update currentDepth
162         spfData.increaseCurrentDepth();
163         
164         SPFChecker cleanupAndResultHandler = new CleanupAndResultChecker().init(spfData);
165         spfData.pushChecker(cleanupAndResultHandler);
166         
167         spfData.pushChecker(new ExpandedChecker());
168         return macroExpand.checkExpand(getHost(), spfData, MacroExpand.DOMAIN);
169     }
170 
171     /**
172      * @see org.apache.james.jspf.terms.ConfigurationEnabled#config(Configuration)
173      */
174     public synchronized void config(Configuration params) throws PermErrorException {
175         if (params.groupCount() == 0) {
176             throw new PermErrorException("Include mechanism without an host");
177         }
178         host = params.group(1);
179     }
180 
181     /**
182      * @return Returns the host.
183      */
184     protected synchronized String getHost() {
185         return host;
186     }
187 
188     /**
189      * @see org.apache.james.jspf.core.LogEnabled#enableLogging(org.apache.james.jspf.core.Logger)
190      */
191     public void enableLogging(Logger logger) {
192         this.log = logger;
193     }
194 
195     /**
196      * @see java.lang.Object#toString()
197      */
198     public String toString() {
199         return "include:"+getHost();
200     }
201 
202     /**
203      * @see org.apache.james.jspf.core.SPFCheckEnabled#enableSPFChecking(org.apache.james.jspf.core.SPFChecker)
204      */
205     public void enableSPFChecking(SPFChecker checker) {
206         this.spfChecker = checker;
207     }
208 
209     /**
210      * @see org.apache.james.jspf.core.MacroExpandEnabled#enableMacroExpand(org.apache.james.jspf.core.MacroExpand)
211      */
212     public void enableMacroExpand(MacroExpand macroExpand) {
213         this.macroExpand = macroExpand;
214     }
215 }