git » spf » commit d075e9e

Fix DNS lookup limits in PTR field processing

author Alberto Bertogli
2022-06-17 19:28:13 UTC
committer Alberto Bertogli
2022-06-18 11:47:19 UTC
parent 6cf72fed21c88678e66758458c6e6b1197ecce52

Fix DNS lookup limits in PTR field processing

When processing PTR fields, we have to do DNS A/AAAA lookups. The RFC
defines a special logic for those, different than the other lookups
for the other mechanisms.

In particular, we must only consider the first 10 A/AAAA resource records,
and drop the rest (instead of erroring out); and those don't get counted
for the general limit.

This patch fixes that issue by adjusting the checks to match the RFC.

spf.go +10 -5
testdata/blitirispf-tests.yml +49 -1

diff --git a/spf.go b/spf.go
index 6a06443..2b748d1 100644
--- a/spf.go
+++ b/spf.go
@@ -557,14 +557,19 @@ func (r *resolution) ptrField(res Result, field, domain string) (bool, Result, e
 			}
 			return false, "", err
 		}
+
+		// Only take the first 10 names, ignore the rest.
+		// Each A/AAAA lookup in this context is NOT included in the overall
+		// count. The RFC defines this separate logic and limits.
+		// https://datatracker.ietf.org/doc/html/rfc7208#section-4.6.4
+		if len(ns) > 10 {
+			r.trace("ptr names trimmed %d down to 10", len(ns))
+			ns = ns[:10]
+		}
+
 		for _, n := range ns {
 			// Validate the record by doing a forward resolution: it has to
 			// have some A/AAAA.
-			// https://tools.ietf.org/html/rfc7208#section-5.5
-			if r.count > 10 {
-				return false, "", ErrLookupLimitReached
-			}
-			r.count++
 			addrs, err := r.resolver.LookupIPAddr(r.ctx, n)
 			if err != nil {
 				// RFC explicitly says to skip domains which error here.
diff --git a/testdata/blitirispf-tests.yml b/testdata/blitirispf-tests.yml
index 81addc3..e2246b9 100644
--- a/testdata/blitirispf-tests.yml
+++ b/testdata/blitirispf-tests.yml
@@ -1,4 +1,5 @@
-# Simple tests, used for debugging the testing infrastructure.
+# Simple tests, used for debugging the testing infrastructure; and some
+# additional tests for situations not covered by the other files.
 
 ---
 description: Simple successes
@@ -130,3 +131,50 @@ zonedata:
     - SPF: v=spf1 exists:%{h}.com ~all
   holahola.com:
     - A: 127.0.0.2
+---
+description: Only include the first 10 PTR results
+tests:
+  only-first-10-ptr:
+    description: |
+      Check that if during 'ptr' forward resolution we only consider the first
+      10 names, and ignore the rest.
+    mailfrom: "foo@domain.net"
+    host: 1.2.3.4
+    result: softfail
+zonedata:
+  domain.net:
+    - A: 127.0.0.1
+    - SPF: v=spf1 ptr ~all
+  4.3.2.1.in-addr.arpa:
+    - PTR: dom01.com
+    - PTR: dom02.com
+    - PTR: dom03.com
+    - PTR: dom04.com
+    - PTR: dom05.com
+    - PTR: dom06.com
+    - PTR: dom07.com
+    - PTR: dom08.com
+    - PTR: dom09.com
+    - PTR: dom10.com
+    # Entries below here should get dropped. They would make it pass.
+    - PTR: domain.net
+  dom01.com:
+    - A: 127.0.0.1
+  dom02.com:
+    - A: 127.0.0.2
+  dom03.com:
+    - A: 127.0.0.3
+  dom04.com:
+    - A: 127.0.0.4
+  dom05.com:
+    - A: 127.0.0.5
+  dom06.com:
+    - A: 127.0.0.6
+  dom07.com:
+    - A: 127.0.0.7
+  dom08.com:
+    - A: 127.0.0.8
+  dom09.com:
+    - A: 127.0.0.9
+  dom10.com:
+    - A: 127.0.0.10