author | James Lamb
<jlamb@atlassian.com> 2021-07-01 07:20:20 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2021-07-12 17:22:31 UTC |
parent | 96969802d81434e420b610b47230a683e425a8df |
spf.go | +17 | -1 |
spf_test.go | +2 | -0 |
diff --git a/spf.go b/spf.go index 0cf1319..9b535ed 100644 --- a/spf.go +++ b/spf.go @@ -831,7 +831,7 @@ func (r *resolution) expandMacros(s, domain string) (string, error) { case "d": str = domain case "i": - str = r.ip.String() + str = ipToMacroStr(r.ip) case "p": // This shouldn't be used, we don't want to support it, it's // risky. "unknown" is a safe value. @@ -899,3 +899,19 @@ func reverseStrings(a []string) { a[left], a[right] = a[right], a[left] } } + +func ipToMacroStr(ip net.IP) string { + if ip.To4() != nil { + return ip.String() + } + + // For IPv6 addresses, the "i" macro expands to a dot-format address. + // https://datatracker.ietf.org/doc/html/rfc7208#section-7.3 + sb := strings.Builder{} + sb.Grow(64) + for _, b := range ip.To16() { + fmt.Fprintf(&sb, "%x.%x.", b>>4, b&0xf) + } + // Return the string without the trailing ".". + return sb.String()[:sb.Len()-1] +} diff --git a/spf_test.go b/spf_test.go index 9d7a9ea..022a06c 100644 --- a/spf_test.go +++ b/spf_test.go @@ -350,12 +350,14 @@ func TestMacros(t *testing.T) { {"v=spf1 +a:vvv-%{v}-vvv", Pass, errMatchedA}, {"v=spf1 a:%{x}", PermError, errInvalidMacro}, {"v=spf1 +a:ooo-%{o7}-ooo", Pass, errMatchedA}, + {"v=spf1 exists:%{ir}.vvv -all", Pass, errMatchedExists}, } dns.Ip["sss-user@domain-sss"] = []net.IP{ip6666} dns.Ip["ooo-domain-ooo"] = []net.IP{ip6666} dns.Ip["ppp-unknown-ppp"] = []net.IP{ip6666} dns.Ip["vvv-ip6-vvv"] = []net.IP{ip6666} + dns.Ip["8.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.vvv"] = []net.IP{ip1111} for _, c := range cases { dns.Txt["domain"] = []string{c.txt}