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.DNSRequest;
024 import org.apache.james.jspf.core.DNSResponse;
025 import org.apache.james.jspf.core.SPF1Record;
026 import org.apache.james.jspf.core.SPF1Utils;
027 import org.apache.james.jspf.core.SPFCheckerDNSResponseListener;
028 import org.apache.james.jspf.core.SPFSession;
029 import org.apache.james.jspf.core.exceptions.NeutralException;
030 import org.apache.james.jspf.core.exceptions.NoneException;
031 import org.apache.james.jspf.core.exceptions.PermErrorException;
032 import org.apache.james.jspf.core.exceptions.TempErrorException;
033 import org.apache.james.jspf.core.exceptions.TimeoutException;
034
035 import java.util.List;
036
037 /**
038 * Get the raw dns txt or spf entry which contains a spf entry. If a domain
039 * publish both, and both are not equals it throws a PermError
040 */
041 public class SPFStrictCheckerRetriever extends SPFRetriever {
042
043
044 private static final String ATTRIBUTE_SPFSTRICT_CHECK_SPFRECORDS = "SPFStrictCheck.SPFRecords";
045
046 private static final class SPFStrictSPFRecordsDNSResponseListener implements SPFCheckerDNSResponseListener {
047
048 /**
049 * @see org.apache.james.jspf.core.SPFCheckerDNSResponseListener#onDNSResponse(org.apache.james.jspf.core.DNSResponse, org.apache.james.jspf.core.SPFSession)
050 */
051 @SuppressWarnings("unchecked")
052 public DNSLookupContinuation onDNSResponse(
053 DNSResponse response, SPFSession session)
054 throws PermErrorException,
055 NoneException, TempErrorException,
056 NeutralException {
057
058 List<String> spfR = (List<String>) session.getAttribute(ATTRIBUTE_SPFSTRICT_CHECK_SPFRECORDS);
059 List<String> spfTxtR = null;
060 try {
061 spfTxtR = response.getResponse();
062 } catch (TimeoutException e) {
063 throw new TempErrorException("Timeout querying dns");
064 }
065
066 String record = calculateSpfRecord(spfR, spfTxtR);
067 if (record != null) {
068 session.setAttribute(SPF1Utils.ATTRIBUTE_SPF1_RECORD, new SPF1Record(record));
069 }
070
071 return null;
072
073 }
074
075 }
076
077
078 private static final class SPFStrictCheckDNSResponseListener implements SPFCheckerDNSResponseListener {
079
080 /**
081 * @see org.apache.james.jspf.core.SPFCheckerDNSResponseListener#onDNSResponse(org.apache.james.jspf.core.DNSResponse, org.apache.james.jspf.core.SPFSession)
082 */
083 public DNSLookupContinuation onDNSResponse(
084 DNSResponse response, SPFSession session)
085 throws PermErrorException, NoneException,
086 TempErrorException, NeutralException {
087 try {
088 List<String> spfR = response.getResponse();
089
090 session.setAttribute(ATTRIBUTE_SPFSTRICT_CHECK_SPFRECORDS, spfR);
091
092 String currentDomain = session.getCurrentDomain();
093 return new DNSLookupContinuation(new DNSRequest(currentDomain, DNSRequest.TXT), new SPFStrictSPFRecordsDNSResponseListener());
094
095 } catch (TimeoutException e) {
096 throw new TempErrorException("Timeout querying dns");
097 }
098 }
099
100
101 }
102
103
104 /**
105 * @see org.apache.james.jspf.policies.SPFRetriever#checkSPF(org.apache.james.jspf.core.SPFSession)
106 */
107 public DNSLookupContinuation checkSPF(SPFSession spfData)
108 throws PermErrorException, TempErrorException, NeutralException,
109 NoneException {
110 SPF1Record res = (SPF1Record) spfData.getAttribute(SPF1Utils.ATTRIBUTE_SPF1_RECORD);
111 if (res == null) {
112 String currentDomain = spfData.getCurrentDomain();
113
114 return new DNSLookupContinuation(new DNSRequest(currentDomain, DNSRequest.SPF), new SPFStrictCheckDNSResponseListener());
115
116 }
117 return null;
118 }
119
120
121 private static String calculateSpfRecord(List<String> spfR, List<String> spfTxtR)
122 throws PermErrorException {
123 String spfR1 = null;
124 String spfR2 = null;
125 if (spfR != null) spfR1 = extractSPFRecord(spfR);
126 if (spfTxtR != null) spfR2 = extractSPFRecord(spfTxtR);
127
128 if (spfR1 != null && spfR2 == null) {
129 return spfR1;
130 } else if (spfR1 == null && spfR2 != null) {
131 return spfR2;
132 } else if (spfR1 != null && spfR2 != null) {
133 if (spfR1.toLowerCase().equals(spfR2.toLowerCase()) == false) {
134 throw new PermErrorException("Published SPF records not equals");
135 } else {
136 return spfR1;
137 }
138 } else {
139 return null;
140 }
141 }
142 }