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 }