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     ****************************************************************/
019    
020    package org.apache.james.jspf.policies;
021    
022    import org.apache.james.jspf.core.DNSLookupContinuation;
023    import org.apache.james.jspf.core.SPF1Record;
024    import org.apache.james.jspf.core.SPF1Utils;
025    import org.apache.james.jspf.core.SPFChecker;
026    import org.apache.james.jspf.core.SPFSession;
027    import org.apache.james.jspf.core.exceptions.NeutralException;
028    import org.apache.james.jspf.core.exceptions.NoneException;
029    import org.apache.james.jspf.core.exceptions.PermErrorException;
030    import org.apache.james.jspf.core.exceptions.TempErrorException;
031    import org.xbill.DNS.Name;
032    import org.xbill.DNS.TextParseException;
033    
034    /**
035     * Run the checks on the validity of the domain
036     * This is an override filter to be executed as the first 
037     * so it should be added as the last filter.
038     */
039    public final class InitialChecksPolicy implements SPFChecker {
040        
041        /**
042         * @see org.apache.james.jspf.core.SPFChecker#checkSPF(org.apache.james.jspf.core.SPFSession)
043         */
044        public DNSLookupContinuation checkSPF(SPFSession spfData)
045                throws PermErrorException, TempErrorException, NeutralException,
046                NoneException {
047            SPF1Record res = (SPF1Record) spfData.getAttribute(SPF1Utils.ATTRIBUTE_SPF1_RECORD);
048            if (res == null) {
049    
050                // Initial checks (spec 4.3)
051                String currentDomain = spfData.getCurrentDomain();
052                if (currentDomain != null) {
053                    String[] labels = currentDomain.split("\\.");
054                    for (int i = 0; i < labels.length; i++) {
055                        if (labels[i] != null && labels[i].length() > 63) {
056                            throw new NoneException("Domain "+currentDomain+" is malformed (label longer than 63 characters)");
057                        }
058                    }
059                }
060                
061                if (spfData.getSenderDomain().indexOf('.') < 0) {
062                    throw new NoneException("Sender domain "+spfData.getSenderDomain()+" is not an FQDN.");
063                }
064                
065                try {
066                    Name.fromString(spfData.getSenderDomain());
067                } catch (TextParseException e) {
068                    throw new NoneException("Invalid sender domain: "+e.getMessage());
069                }
070            }
071            return null;
072        }
073    }