shevek / libspf2

Implementation of the Sender Policy Framework for SMTP authorization
http://www.libspf2.net/
37 stars 32 forks source link

Increase buffers to support longer SPF records #21

Open desh-se opened 7 years ago

desh-se commented 7 years ago

We've noticed a few domains which have longer SPF records than what libspf2 support. One such example is unilever.com:

"v=spf1 include:sharepointonline.com include:unilever-uk.trclient.com include:nw010.com " "ip4:141.146.165.27 ip4:141.146.165.28 ip4:96.43.147.0/25 ip4:136.146.128.0/25 ip4:204.14.232.0/25 ip4:85.222.130.224/26 ip4:182.50.78.0/25 " "ip4:194.60.111.172 ip4:194.60.111.164 ip4:194.60.111.165 ip4:194.60.111.166 ip4:194.60.111.167 ip4:194.60.111.169 ip4:194.60.111.170 ip4:194.60.111.171 " "ip4:174.143.100.191 ip4:67.192.139.34 ip4:67.192.157.83 ip4:134.213.38.184 ip4:134.213.38.185 ip4:134.213.43.128 ip4:156.51.31.71 ip4:162.61.224.50 ip4:213.177.33.153 ip4:54.240.8.0/23 ip4:89.234.41.53 " "ip4:160.34.64.0/27 ip4:208.185.229.40/29 ip4:208.185.235.40/29 ip4:208.185.229.197 ip4:208.185.229.198 ip4:208.185.229.199 ip4:208.185.235.197 ip4:208.185.235.198 ip4:208.185.235.199 " "ip4:96.43.144.64 ip4:96.43.144.65 ip4:96.43.148.64 ip4:96.43.148.65 ip4:96.43.151.0/25 ip4:136.146.208.16/27 ip4:136.146.210.16/27 ip4:136.147.46.224/26 ip4:136.147.62.224/26 ip4:204.14.234.0/25 ip4:52.68.233.169 ip4:54.178.172.43 " "ip4:62.128.223.55 ip4:199.255.192.0/22 ip4:199.127.232.0/22 ip4:54.240.0.0/18 ip4:213.129.90.104 ip4:84.45.15.6 ip4:188.95.0.38 ip4:188.95.7.6 ip4:5.61.115.80/28 ip4:5.61.115.96/28 ip4:5.61.115.112/28 " "ip4:185.79.140.0/22 ip4:202.129.242.0/23 ip4:194.11.253.147/28 ip4:194.4.230.80/28 ip4:194.4.230.79 ip4:194.11.253.134 ip4:194.11.253.135 ip4:205.223.230.229 ip4:62.6.153.165 ip4:5.61.115.0/24 ip4:208.92.178.200 ip4:208.92.176.200 " "ip4:208.92.177.152 ip4:107.20.210.250 ip4:54.229.2.165 ip4:54.153.131.110 ip4:52.1.14.157 ip4:52.30.130.201 ip4:54.66.252.242 ip4:107.23.16.222 ip4:52.17.45.98 ip4:54.173.83.138 ip4:52.16.190.81 ip4:212.247.0.242 " "ip4:212.247.0.243 ip4:134.213.242.70 ip4:194.204.27.131 ip4:194.204.0.4 ip4:82.199.250.65 ip4:176.74.168.123 ip4:113.192.243.106 ip4:113.192.243.107 ip4:64.181.217.140 ip4:64.181.217.141 ip4:212.72.39.68 ip4:212.72.39.197 ip4:217.17.192.101 -all"

The limit seems to be SPF_MAX_MECH_LEN, which triggers SPF_E_BIG_MECH, which is ignored and thus results in a neutral result.

bdijkstra82 commented 7 years ago

SPF_MAX_MECH_LEN is 511, which IMHO is a bit draconian considering that RFC 7208 only gives a SHOULD requirement for the maximum record size limit of 512 (paragraph 3.4).

In any case the Neutral result is wrong. There is a paragraph about processing limits (11.1), alas it doesn't say specifically what should be returned in response to long records, but I think that PermError would be the best choice.

eriklax commented 7 years ago

I would suggest something like #22 to fail harder. However, this only fixes half the issue.

Should libspf2 also raise or double these limits, and how does that affect other buffers like?

https://github.com/shevek/libspf2/blob/master/src/libspf2/spf_compile.c#L62

heyyoucb commented 7 years ago

We fixed this in our code by adding a value for the maximum number of mechanisms and not looking at the total length. See the attached patch. spf_compile.c.patch.txt

hdatma commented 3 years ago

This is what I see:

>unbound-host -rvD -tTXT unilever.com | grep spf 
unilever.com has TXT record "v=spf1 include:spf.protection.outlook.com " "ip4:204.14.232.0/25 ip4:174.143.99.125 ip4:67.192.157.83 ip4:134.213.38.184/31 ip4:134.213.43.128 ip4:156.51.31.71 ip4:162.61.224.50 ip4:213.177.33.153 ip4:89.234.41.53 " "ip4:160.34.64.0/23 ip4:208.185.229.40/29 ip4:208.185.235.40/29 ip4:208.185.229.197 ip4:208.185.229.198 ip4:208.185.229.199 ip4:208.185.235.197 ip4:208.185.235.198 ip4:208.185.235.199 " "ip4:13.112.93.182 ip4:54.178.172.43 ip4:62.128.223.55 ip4:199.255.192.0/22 ip4:199.127.232.0/22 ip4:54.240.0.0/18 ip4:213.129.90.104 ip4:84.45.15.6 ip4:188.95.0.38 ip4:188.95.7.6 " "ip4:89.202.116.58 ip4:80.253.212.192/27 ip4:194.4.230.64/27 ip4:205.223.230.229 ip4:62.6.153.165 ip4:208.92.178.200 ip4:208.92.176.200 " "ip4:208.92.177.152 ip4:54.229.2.165 ip4:54.153.131.110 ip4:52.1.14.157 ip4:52.30.130.201 ip4:54.66.252.242 ip4:52.17.45.98 ip4:54.173.83.138 ip4:52.16.190.81 ip4:212.247.0.242/31 " "ip4:194.204.27.131 ip4:194.204.0.4 ip4:82.199.250.65 ip4:176.74.168.123 ip4:113.192.243.106/31 ip4:212.72.39.68 ip4:212.72.39.197 ip4:217.17.192.101 " "ip4:50.56.7.39 ip4:185.136.189.88 ip4:185.136.188.88 ip4:134.213.173.64/28 ip4:162.61.252.6 ip4:162.61.252.7 ip4:162.61.252.27 ip4:43.228.187.74 ip4:141.146.165.0/27 ip4:64.181.217.128/27 " "a:b.spf.service-now.com a:c.spf.service-now.com a:d.spf.service-now.com ip4:162.61.254.53 ip4:162.61.254.54/31 ip4:162.61.254.56/30 ip4:162.61.254.60 -all" (insecure)

>spfquery -ip 162.61.254.60 -sender unilever.com                                                                                        
neutral
Please see http://www.openspf.org/Why?id=postmaster%40unilever.com&ip=162.61.254.60&receiver=spfquery : Reason: default
spfquery: 162.61.254.60 is neither permitted nor denied by domain of unilever.com
Received-SPF: neutral (spfquery: 162.61.254.60 is neither permitted nor denied by domain of unilever.com) client-ip=162.61.254.60; envelope-from=postmaster@unilever.com;

It is not true that the given IP "is neither permitted nor denied by" the SPF policy, so the use of "neutral" is a violation of RFC 7208 section 2.6.2 and thus a bug. Patching it with "fail" would be a violation of section 2.6.4.

In the absence of EDNS0 any DNS response which exceeds 512 bytes signals truncation and prompts a retry via TCP. So it is desirable to keep TXT SPF RR within the limit, for compatibility with older systems, but unilever.com seems to be EDNS0 compliant where this limit does not apply. The hard limit for RRs is 65535 bytes by RFC 882, and unilever's record is 3x512 bytes shy.

The response should rather be fair to the fact that the RR exceeded the recommended length of 512 bytes. However, since the DNS response reached the SPF validator, and the IP is clearly authorised by the SPF policy, then the correct response should be "pass".

The patch by heyyoucb helps, but I am not sure it is the definite patch to this bug.

hdatma commented 3 years ago

This is what I see with the patched spf_compile.c:

>spfquery -ip 162.61.254.60 -sender unilever.com
pass

spfquery: domain of unilever.com designates 162.61.254.60 as permitted sender
Received-SPF: pass (spfquery: domain of unilever.com designates 162.61.254.60 as permitted sender) client-ip=162.61.254.60; envelope-from=postmaster@unilever.com;
grobian commented 2 years ago

Not sure this is relevant, but looking at this today, I noticed that on glibc it appears not to find a match for 162.61.254.60 which still is in the spf record, but on musl it doesn't get any further than the first 9 TXT entries, never finding the spf record. The glibc case seems to be that the patch referred to here once addressed -- the code changed howver -- the second is a whole different problem that libspf can only solve by not using req_query, but something else to do resolving.