1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.DNSRequest;
25 import org.apache.james.jspf.core.DNSResponse;
26 import org.apache.james.jspf.core.DNSService;
27 import org.apache.james.jspf.core.DNSServiceEnabled;
28 import org.apache.james.jspf.core.IPAddr;
29 import org.apache.james.jspf.core.MacroExpand;
30 import org.apache.james.jspf.core.SPFChecker;
31 import org.apache.james.jspf.core.SPFCheckerDNSResponseListener;
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 import org.apache.james.jspf.core.exceptions.TimeoutException;
39
40 import java.util.List;
41
42
43
44
45
46 public class PTRMechanism extends GenericMechanism implements DNSServiceEnabled, SPFCheckerDNSResponseListener {
47
48 private final class ExpandedChecker implements SPFChecker {
49 private CleanupChecker cleanupChecker = new CleanupChecker();
50
51 private final class CleanupChecker implements SPFChecker {
52
53
54
55
56 public DNSLookupContinuation checkSPF(SPFSession spfData)
57 throws PermErrorException, TempErrorException,
58 NeutralException, NoneException {
59 spfData.removeAttribute(ATTRIBUTE_DOMAIN_LIST);
60 spfData.removeAttribute(ATTRIBUTE_CURRENT_DOMAIN);
61 return null;
62 }
63 }
64
65
66
67
68 public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException,
69 TempErrorException, NeutralException, NoneException {
70
71
72 IPAddr ip = IPAddr.getAddress(spfData.getIpAddress());
73
74
75 String host = expandHost(spfData);
76
77 spfData.setAttribute(ATTRIBUTE_EXPANDED_HOST, host);
78
79 spfData.pushChecker(cleanupChecker);
80
81 return new DNSLookupContinuation(new DNSRequest(ip.getReverseIP(), DNSRequest.PTR), PTRMechanism.this);
82 }
83 }
84
85 private static final String ATTRIBUTE_CURRENT_DOMAIN = "PTRMechanism.currentDomain";
86
87 private static final String ATTRIBUTE_EXPANDED_HOST = "PTRMechanism.expandedHost";
88
89 private static final String ATTRIBUTE_DOMAIN_LIST = "PTRMechanism.domainListCheck";
90
91
92
93
94 public static final String REGEX = "[pP][tT][rR]" + "(?:\\:"
95 + SPFTermsRegexps.DOMAIN_SPEC_REGEX + ")?";
96
97 private DNSService dnsService;
98
99 private SPFChecker expandedChecker = new ExpandedChecker();
100
101
102
103
104 public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException,
105 TempErrorException, NeutralException, NoneException {
106
107 spfData.increaseCurrentDepth();
108
109 spfData.pushChecker(expandedChecker);
110 return macroExpand.checkExpand(getDomain(), spfData, MacroExpand.DOMAIN);
111 }
112
113
114
115
116 public void enableDNSService(DNSService service) {
117 this.dnsService = service;
118 }
119
120
121
122
123 public DNSLookupContinuation onDNSResponse(DNSResponse response, SPFSession spfSession)
124 throws PermErrorException, TempErrorException, NoneException, NeutralException {
125
126 List domainList = (List) spfSession.getAttribute(ATTRIBUTE_DOMAIN_LIST);
127 try {
128 if (domainList == null) {
129
130 domainList = response.getResponse();
131
132
133 if (domainList == null) {
134 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.FALSE);
135 return null;
136 }
137
138
139 if (dnsService.getRecordLimit() > 0 && domainList.size() > dnsService.getRecordLimit()) {
140
141
142 domainList = domainList.subList(0, dnsService.getRecordLimit()-1);
143
144 }
145
146 spfSession.setAttribute(ATTRIBUTE_DOMAIN_LIST, domainList);
147
148 } else {
149
150 String compareDomain = (String) spfSession.getAttribute(ATTRIBUTE_CURRENT_DOMAIN);
151 String host = (String) spfSession.getAttribute(ATTRIBUTE_EXPANDED_HOST);
152
153 List aList = response.getResponse();
154
155
156 if (aList != null) {
157 for (int j = 0; j < aList.size(); j++) {
158
159 if (IPAddr.getAddress((String) aList.get(j)).getIPAddress().equals(IPAddr.getAddress(spfSession.getIpAddress()).getIPAddress())) {
160
161 if (compareDomain.equals(host)
162 || compareDomain.endsWith("." + host)) {
163 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.TRUE);
164 return null;
165 }
166 }
167 }
168 }
169
170 }
171 } catch (TimeoutException e) {
172 throw new TempErrorException("Timeout querying the dns server");
173 }
174
175
176 if (domainList.size() > 0) {
177 String currentDomain = (String) domainList.remove(0);
178
179 DNSRequest dnsRequest;
180
181 if (IPAddr.isIPV6(spfSession.getIpAddress())) {
182
183 dnsRequest = new DNSRequest(currentDomain, DNSRequest.AAAA);
184 } else {
185
186 dnsRequest = new DNSRequest(currentDomain, DNSRequest.A);
187 }
188
189 spfSession.setAttribute(ATTRIBUTE_CURRENT_DOMAIN, currentDomain);
190
191 return new DNSLookupContinuation(dnsRequest, PTRMechanism.this);
192 } else {
193 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.FALSE);
194 return null;
195 }
196
197 }
198
199
200 }