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.IPAddr;
27 import org.apache.james.jspf.core.Inet6Util;
28 import org.apache.james.jspf.core.MacroExpand;
29 import org.apache.james.jspf.core.SPFChecker;
30 import org.apache.james.jspf.core.SPFCheckerDNSResponseListener;
31 import org.apache.james.jspf.core.SPFSession;
32 import org.apache.james.jspf.core.SPFTermsRegexps;
33 import org.apache.james.jspf.core.exceptions.NeutralException;
34 import org.apache.james.jspf.core.exceptions.NoneException;
35 import org.apache.james.jspf.core.exceptions.PermErrorException;
36 import org.apache.james.jspf.core.exceptions.TempErrorException;
37 import org.apache.james.jspf.core.exceptions.TimeoutException;
38
39 import java.util.ArrayList;
40 import java.util.List;
41
42
43
44
45
46 public class AMechanism extends GenericMechanism implements SPFCheckerDNSResponseListener {
47
48 private static final String ATTRIBUTE_AMECHANISM_IPV4CHECK = "AMechanism.ipv4check";
49
50
51
52
53 public static final String REGEX = "[aA]" + "(?:\\:"
54 + SPFTermsRegexps.DOMAIN_SPEC_REGEX + ")?" + "(?:"
55 + DUAL_CIDR_LENGTH_REGEX + ")?";
56
57 private int ip4cidr;
58
59 private int ip6cidr;
60
61 private SPFChecker expandedChecker = new ExpandedChecker();
62
63 private final class ExpandedChecker implements SPFChecker {
64
65
66
67
68 public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException,
69 TempErrorException, NeutralException, NoneException {
70
71 String host = expandHost(spfData);
72
73
74 try {
75 boolean validIPV4Address = Inet6Util.isValidIPV4Address(spfData.getIpAddress());
76 spfData.setAttribute(ATTRIBUTE_AMECHANISM_IPV4CHECK, Boolean.valueOf(validIPV4Address));
77 if (validIPV4Address) {
78
79 List aRecords = getARecords(host);
80 if (aRecords == null) {
81 try {
82 DNSRequest request = new DNSRequest(host, DNSRequest.A);
83 return new DNSLookupContinuation(request, AMechanism.this);
84 } catch (NoneException e) {
85 return onDNSResponse(new DNSResponse(aRecords), spfData);
86 }
87 } else {
88 return onDNSResponse(new DNSResponse(aRecords), spfData);
89 }
90
91 } else {
92
93 List aaaaRecords = getAAAARecords(host);
94 if (aaaaRecords == null) {
95 try {
96 DNSRequest request = new DNSRequest(host, DNSRequest.AAAA);
97 return new DNSLookupContinuation(request, AMechanism.this);
98 } catch (NoneException e) {
99 return onDNSResponse(new DNSResponse(aaaaRecords), spfData);
100 }
101 } else {
102 return onDNSResponse(new DNSResponse(aaaaRecords), spfData);
103 }
104
105 }
106
107
108 } catch (Exception e) {
109 log.debug("No valid ipAddress: ",e);
110 throw new PermErrorException("No valid ipAddress: "
111 + spfData.getIpAddress());
112 }
113
114 }
115 }
116
117
118
119
120 public DNSLookupContinuation checkSPF(SPFSession spfData) throws PermErrorException, TempErrorException, NeutralException, NoneException {
121
122 spfData.increaseCurrentDepth();
123
124 spfData.pushChecker(expandedChecker);
125
126 return macroExpand.checkExpand(getDomain(), spfData, MacroExpand.DOMAIN);
127 }
128
129
130
131
132 public synchronized void config(Configuration params) throws PermErrorException {
133 super.config(params);
134 if (params.groupCount() >= 2 && params.group(2) != null) {
135 ip4cidr = Integer.parseInt(params.group(2));
136 if (ip4cidr > 32) {
137 throw new PermErrorException("Ivalid IP4 CIDR length");
138 }
139 } else {
140 ip4cidr = 32;
141 }
142 if (params.groupCount() >= 3 && params.group(3) != null) {
143 ip6cidr = Integer.parseInt(params.group(3).toString());
144 if (ip6cidr > 128) {
145 throw new PermErrorException("Ivalid IP6 CIDR length");
146 }
147 } else {
148 ip6cidr = 128;
149 }
150 }
151
152
153
154
155
156
157
158
159
160
161
162 public boolean checkAddressList(IPAddr checkAddress, List addressList, int cidr) throws PermErrorException {
163
164 for (int i = 0; i < addressList.size(); i++) {
165 String ip = (String) addressList.get(i);
166
167
168 if (ip != null) {
169
170
171 IPAddr ipAddr = IPAddr.getAddress(ip, checkAddress.getMaskLength());
172 if (checkAddress.getMaskedIPAddress().equals(
173 ipAddr.getMaskedIPAddress())) {
174 return true;
175 }
176 }
177 }
178 return false;
179 }
180
181
182
183
184 protected synchronized int getIp4cidr() {
185 return ip4cidr;
186 }
187
188
189
190
191 protected synchronized int getIp6cidr() {
192 return ip6cidr;
193 }
194
195
196
197
198 public String toString() {
199 return toString("a");
200 }
201
202
203
204
205 protected String toString(String mechKey) {
206 StringBuffer res = new StringBuffer();
207 res.append(mechKey);
208 if (getDomain() != null) {
209 res.append(":"+getDomain());
210 }
211 if (getIp4cidr() != 32) {
212 res.append("/"+getIp4cidr());
213 }
214 if (getIp6cidr() != 128) {
215 res.append("//"+getIp4cidr());
216 }
217 return res.toString();
218 }
219
220
221
222
223
224 public List getAAAARecords(String strServer) {
225 List listAAAAData = null;
226 if (IPAddr.isIPV6(strServer)) {
227
228 listAAAAData = new ArrayList();
229 listAAAAData.add(strServer);
230 }
231 return listAAAAData;
232 }
233
234
235
236
237
238
239
240
241
242 public List getARecords(String strServer) {
243 List listAData = null;
244 if (IPAddr.isIPAddr(strServer)) {
245 listAData = new ArrayList();
246 listAData.add(strServer);
247 }
248 return listAData;
249 }
250
251
252
253
254 public DNSLookupContinuation onDNSResponse(DNSResponse response, SPFSession spfSession)
255 throws PermErrorException, TempErrorException, NoneException, NeutralException {
256 List listAData = null;
257 try {
258 listAData = response.getResponse();
259 } catch (TimeoutException e) {
260 throw new TempErrorException("Timeout querying dns server");
261 }
262
263 if (listAData == null) {
264 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.FALSE);
265 return null;
266 }
267
268 Boolean ipv4check = (Boolean) spfSession.getAttribute(ATTRIBUTE_AMECHANISM_IPV4CHECK);
269 if (ipv4check.booleanValue()) {
270
271 IPAddr checkAddress = IPAddr.getAddress(spfSession.getIpAddress(),
272 getIp4cidr());
273
274 if (checkAddressList(checkAddress, listAData, getIp4cidr())) {
275 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.TRUE);
276 return null;
277 }
278
279 } else {
280
281 IPAddr checkAddress = IPAddr.getAddress(spfSession.getIpAddress(),
282 getIp6cidr());
283
284 if (checkAddressList(checkAddress, listAData, getIp6cidr())) {
285 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.TRUE);
286 return null;
287 }
288
289 }
290
291 spfSession.setAttribute(Directive.ATTRIBUTE_MECHANISM_RESULT, Boolean.FALSE);
292 return null;
293 }
294
295 }