pax_global_header00006660000000000000000000000064141462275120014516gustar00rootroot0000000000000052 comment=1bd7bc8bd40d633f9e51980e04a1264bb16082a8 golang-blitiri-go-spf-1.3.0/000077500000000000000000000000001414622751200156135ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/.gitignore000066400000000000000000000003451414622751200176050ustar00rootroot00000000000000# Ignore anything beginning with a dot: these are usually temporary or # unimportant. .* # Exceptions to the rule above: files we care about that would otherwise be # excluded. !.gitignore # go-fuzz build artifacts. *-fuzz.zip golang-blitiri-go-spf-1.3.0/.gitlab-ci.yml000066400000000000000000000010511414622751200202440ustar00rootroot00000000000000# Configuration for the GitLab CI. # Go tests, on various Go versions. .golang_template: &golang stage: test script: - go test ./... - go test -race ./... golang_1.15: <<: *golang image: golang:1.15 # Oldest supported version (for now). golang_latest: <<: *golang image: golang:latest coverage: <<: *golang image: golang:latest script: - go test -covermode=count -coverprofile=coverage.out - go get github.com/mattn/goveralls - goveralls -coverprofile=coverage.out -service=gitlab -repotoken=$COVERALLS_TOKEN golang-blitiri-go-spf-1.3.0/LICENSE000066400000000000000000000022041414622751200166160ustar00rootroot00000000000000 Licensed under the MIT licence, which is reproduced below (from https://opensource.org/licenses/MIT). ----- Copyright (c) 2016 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-blitiri-go-spf-1.3.0/README.md000066400000000000000000000032511414622751200170730ustar00rootroot00000000000000 # blitiri.com.ar/go/spf [![GoDoc](https://godoc.org/blitiri.com.ar/go/spf?status.svg)](https://pkg.go.dev/blitiri.com.ar/go/spf) [![Build Status](https://gitlab.com/albertito/spf/badges/master/pipeline.svg)](https://gitlab.com/albertito/spf/-/commits/master) [![Go Report Card](https://goreportcard.com/badge/github.com/albertito/spf)](https://goreportcard.com/report/github.com/albertito/spf) [![Coverage Status](https://coveralls.io/repos/github/albertito/spf/badge.svg?branch=next)](https://coveralls.io/github/albertito/spf) [spf](https://godoc.org/blitiri.com.ar/go/spf) is an open source implementation of the Sender Policy Framework (SPF) in Go. It is used by the [chasquid](https://blitiri.com.ar/p/chasquid/) and [maddy](https://maddy.email) SMTP servers. ## Example The API is quite simple: it has only one main function to perform the SPF check, similar to the one suggested in the [RFC](https://tools.ietf.org/html/rfc7208). ```go // Check if `sender` is authorized to send from the given `ip`. The `domain` // is used if the sender doesn't have one. result, err := spf.CheckHostWithSender(ip, domain, sender) if result == spf.Fail { // Not authorized to use the domain. } ``` See the [package documentation](https://pkg.go.dev/blitiri.com.ar/go/spf) for more details. ## Status The API should be considered stable. Major version changes will be announced to the mailing list (details below). ## Contact If you have any questions, comments or patches please send them to the mailing list, `chasquid@googlegroups.com`. To subscribe, send an email to `chasquid+subscribe@googlegroups.com`. You can also browse the [archives](https://groups.google.com/forum/#!forum/chasquid). golang-blitiri-go-spf-1.3.0/cmd/000077500000000000000000000000001414622751200163565ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/cmd/spf-check/000077500000000000000000000000001414622751200202215ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/cmd/spf-check/.gitignore000066400000000000000000000000121414622751200222020ustar00rootroot00000000000000spf-check golang-blitiri-go-spf-1.3.0/cmd/spf-check/spf-check.go000066400000000000000000000024401414622751200224130ustar00rootroot00000000000000// +build ignore // Command line tool to perform SPF checks. // // For development and experimentation only. // No backwards compatibility guarantees. package main import ( "context" "flag" "fmt" "net" "os" "blitiri.com.ar/go/spf" ) var ( debug = flag.Bool("debug", false, "include debugging output") dnsAddr = flag.String("dns_addr", "", "address of the DNS server to use") ) func main() { flag.Usage = func() { fmt.Printf("Usage: spf-check [options] 1.2.3.4 name@sender.com\n\n") flag.PrintDefaults() } flag.Parse() args := flag.Args() if len(args) < 2 { flag.Usage() os.Exit(1) } opts := []spf.Option{} if *debug { traceF := func(f string, a ...interface{}) { fmt.Printf("debug: "+f+"\n", a...) } opts = append(opts, spf.WithTraceFunc(traceF)) } if *dnsAddr != "" { dialFunc := func(ctx context.Context, network, addr string) (net.Conn, error) { return (&net.Dialer{}).DialContext(ctx, network, *dnsAddr) } opts = append(opts, spf.WithResolver( &net.Resolver{ PreferGo: true, Dial: dialFunc, })) } ip := net.ParseIP(args[0]) sender := args[1] fmt.Printf("Sender: %v\n", sender) fmt.Printf("IP: %v\n", ip) r, err := spf.CheckHostWithSender(ip, "", sender, opts...) fmt.Printf("Result: %v\n", r) fmt.Printf("Error: %v\n", err) } golang-blitiri-go-spf-1.3.0/fuzz.go000066400000000000000000000027301414622751200171420ustar00rootroot00000000000000// Fuzz testing for package spf. // // Run it with: // // go-fuzz-build blitiri.com.ar/go/spf // go-fuzz -bin=./spf-fuzz.zip -workdir=testdata/fuzz // // +build gofuzz package spf import ( "net" "blitiri.com.ar/go/spf/internal/dnstest" ) // Parsed IP addresses, for convenience. var ( ip1110 = net.ParseIP("1.1.1.0") ip1111 = net.ParseIP("1.1.1.1") ip6666 = net.ParseIP("2001:db8::68") ip6660 = net.ParseIP("2001:db8::0") ) // DNS resolver to use. Will be initialized once with the expected fixtures, // and then reused on each fuzz run. var dns = dnstest.NewResolver() func init() { dns.Ip["d1111"] = []net.IP{ip1111} dns.Ip["d1110"] = []net.IP{ip1110} dns.Mx["d1110"] = []*net.MX{{"d1110", 5}, {"nothing", 10}} dns.Ip["d6666"] = []net.IP{ip6666} dns.Ip["d6660"] = []net.IP{ip6660} dns.Mx["d6660"] = []*net.MX{{"d6660", 5}, {"nothing", 10}} dns.Addr["2001:db8::68"] = []string{"sonlas6.", "domain.", "d6666."} dns.Addr["1.1.1.1"] = []string{"lalala.", "domain.", "d1111."} } func Fuzz(data []byte) int { // The domain's TXT record comes from the fuzzer. dns.Txt["domain"] = []string{string(data)} v4result, _ := CheckHostWithSender( ip1111, "helo", "domain", WithResolver(dns)) v6result, _ := CheckHostWithSender( ip6666, "helo", "domain", WithResolver(dns)) // Raise priority if any of the results was something other than // PermError, as it means the data was better formed. if v4result != PermError || v6result != PermError { return 1 } return 0 } golang-blitiri-go-spf-1.3.0/go.mod000066400000000000000000000001071414622751200167170ustar00rootroot00000000000000module blitiri.com.ar/go/spf go 1.15 require gopkg.in/yaml.v2 v2.3.0 golang-blitiri-go-spf-1.3.0/go.sum000066400000000000000000000005501414622751200167460ustar00rootroot00000000000000gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= golang-blitiri-go-spf-1.3.0/internal/000077500000000000000000000000001414622751200174275ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/internal/dnstest/000077500000000000000000000000001414622751200211135ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/internal/dnstest/dns.go000066400000000000000000000040461414622751200222320ustar00rootroot00000000000000// DNS resolver for testing purposes. // // In the future, when go fuzz can make use of _test.go files, we can rename // this file dns_test.go and remove this extra package entirely. // Until then, unfortunately this is the most reasonable way to share these // helpers between go and fuzz tests. package dnstest import ( "context" "net" "strings" ) // Testing DNS resolver. // // Not exported since this is not part of the public API and only used // internally on tests. // type TestResolver struct { Txt map[string][]string Mx map[string][]*net.MX Ip map[string][]net.IP Addr map[string][]string Errors map[string]error } func NewResolver() *TestResolver { return &TestResolver{ Txt: map[string][]string{}, Mx: map[string][]*net.MX{}, Ip: map[string][]net.IP{}, Addr: map[string][]string{}, Errors: map[string]error{}, } } func (r *TestResolver) LookupTXT(ctx context.Context, domain string) (txts []string, err error) { if ctx.Err() != nil { return nil, ctx.Err() } domain = strings.ToLower(domain) domain = strings.TrimRight(domain, ".") return r.Txt[domain], r.Errors[domain] } func (r *TestResolver) LookupMX(ctx context.Context, domain string) (mxs []*net.MX, err error) { if ctx.Err() != nil { return nil, ctx.Err() } domain = strings.ToLower(domain) domain = strings.TrimRight(domain, ".") return r.Mx[domain], r.Errors[domain] } func (r *TestResolver) LookupIPAddr(ctx context.Context, host string) (as []net.IPAddr, err error) { if ctx.Err() != nil { return nil, ctx.Err() } host = strings.ToLower(host) host = strings.TrimRight(host, ".") return ipsToAddrs(r.Ip[host]), r.Errors[host] } func ipsToAddrs(ips []net.IP) []net.IPAddr { as := []net.IPAddr{} for _, ip := range ips { as = append(as, net.IPAddr{IP: ip, Zone: ""}) } return as } func (r *TestResolver) LookupAddr(ctx context.Context, host string) (addrs []string, err error) { if ctx.Err() != nil { return nil, ctx.Err() } host = strings.ToLower(host) host = strings.TrimRight(host, ".") return r.Addr[host], r.Errors[host] } golang-blitiri-go-spf-1.3.0/spf.go000066400000000000000000000630511414622751200167370ustar00rootroot00000000000000// Package spf implements SPF (Sender Policy Framework) lookup and validation. // // Sender Policy Framework (SPF) is a simple email-validation system designed // to detect email spoofing by providing a mechanism to allow receiving mail // exchangers to check that incoming mail from a domain comes from a host // authorized by that domain's administrators [Wikipedia]. // // This package is intended to be used by SMTP servers to implement SPF // validation. // // All mechanisms and modifiers are supported: // all // include // a // mx // ptr // ip4 // ip6 // exists // redirect // exp (ignored) // Macros // // References: // https://tools.ietf.org/html/rfc7208 // https://en.wikipedia.org/wiki/Sender_Policy_Framework package spf // import "blitiri.com.ar/go/spf" import ( "context" "errors" "fmt" "net" "net/url" "regexp" "strconv" "strings" ) // The Result of an SPF check. Note the values have meaning, we use them in // headers. https://tools.ietf.org/html/rfc7208#section-8 type Result string // Valid results. var ( // https://tools.ietf.org/html/rfc7208#section-8.1 // Not able to reach any conclusion. None = Result("none") // https://tools.ietf.org/html/rfc7208#section-8.2 // No definite assertion (positive or negative). Neutral = Result("neutral") // https://tools.ietf.org/html/rfc7208#section-8.3 // Client is authorized to inject mail. Pass = Result("pass") // https://tools.ietf.org/html/rfc7208#section-8.4 // Client is *not* authorized to use the domain Fail = Result("fail") // https://tools.ietf.org/html/rfc7208#section-8.5 // Not authorized, but unwilling to make a strong policy statement/ SoftFail = Result("softfail") // https://tools.ietf.org/html/rfc7208#section-8.6 // Transient error while performing the check. TempError = Result("temperror") // https://tools.ietf.org/html/rfc7208#section-8.7 // Records could not be correctly interpreted. PermError = Result("permerror") ) var qualToResult = map[byte]Result{ '+': Pass, '-': Fail, '~': SoftFail, '?': Neutral, } // Errors returned by the library. Note that the errors returned in different // situations may change over time, and new ones may be added. Be careful // about over-relying on these. var ( // Errors related to an invalid SPF record. ErrUnknownField = errors.New("unknown field") ErrInvalidIP = errors.New("invalid ipX value") ErrInvalidMask = errors.New("invalid mask") ErrInvalidMacro = errors.New("invalid macro") ErrInvalidDomain = errors.New("invalid domain") // Errors related to DNS lookups. // Note that the library functions may also return net.DNSError. ErrNoResult = errors.New("no DNS record found") ErrLookupLimitReached = errors.New("lookup limit reached") ErrTooManyMXRecords = errors.New("too many MX records") ErrMultipleRecords = errors.New("multiple matching DNS records") // Errors returned on a successful match. ErrMatchedAll = errors.New("matched all") ErrMatchedA = errors.New("matched a") ErrMatchedIP = errors.New("matched ip") ErrMatchedMX = errors.New("matched mx") ErrMatchedPTR = errors.New("matched ptr") ErrMatchedExists = errors.New("matched exists") ) // Default value for the maximum number of DNS lookups while resolving SPF. // RFC is quite clear 10 must be the maximum allowed. // https://tools.ietf.org/html/rfc7208#section-4.6.4 const defaultMaxLookups = 10 // TraceFunc is the type of tracing functions. type TraceFunc func(f string, a ...interface{}) var ( nullTrace = func(f string, a ...interface{}) {} defaultTrace = nullTrace ) // Option type, for setting options. Users are expected to treat this as an // opaque type and not rely on the implementation, which is subject to change. type Option func(*resolution) // CheckHost fetches SPF records for `domain`, parses them, and evaluates them // to determine if `ip` is permitted to send mail for it. // Because it doesn't receive enough information to handle macros well, its // usage is not recommended, but remains supported for backwards // compatibility. // // The function returns a Result, which corresponds with the SPF result for // the check as per RFC, as well as an error for debugging purposes. Note that // the error may be non-nil even on successful checks. // // Reference: https://tools.ietf.org/html/rfc7208#section-4 // // Deprecated: use CheckHostWithSender instead. func CheckHost(ip net.IP, domain string) (Result, error) { r := &resolution{ ip: ip, maxcount: defaultMaxLookups, helo: domain, sender: "@" + domain, ctx: context.TODO(), resolver: defaultResolver, trace: defaultTrace, } return r.Check(domain) } // CheckHostWithSender fetches SPF records for `sender`'s domain, parses them, // and evaluates them to determine if `ip` is permitted to send mail for it. // The `helo` domain is used if the sender has no domain part. // // The `opts` optional parameter can be used to adjust some specific // behaviours, such as the maximum number of DNS lookups allowed. // // The function returns a Result, which corresponds with the SPF result for // the check as per RFC, as well as an error for debugging purposes. Note that // the error may be non-nil even on successful checks. // // Reference: https://tools.ietf.org/html/rfc7208#section-4 func CheckHostWithSender(ip net.IP, helo, sender string, opts ...Option) (Result, error) { _, domain := split(sender) if domain == "" { domain = helo } r := &resolution{ ip: ip, maxcount: defaultMaxLookups, helo: helo, sender: sender, ctx: context.TODO(), resolver: defaultResolver, trace: defaultTrace, } for _, opt := range opts { opt(r) } return r.Check(domain) } // OverrideLookupLimit overrides the maximum number of DNS lookups allowed // during SPF evaluation. Note that using this violates the RFC, which is // quite explicit that the maximum allowed MUST be 10 (the default). Please // use with care. // // This is EXPERIMENTAL for now, and the API is subject to change. func OverrideLookupLimit(limit uint) Option { return func(r *resolution) { r.maxcount = limit } } // WithContext is an option to set the context for this operation, which will // be passed along to the resolver functions and other external calls if // needed. // // This is EXPERIMENTAL for now, and the API is subject to change. func WithContext(ctx context.Context) Option { return func(r *resolution) { r.ctx = ctx } } // DNSResolver implements the methods we use to resolve DNS queries. // It is intentionally compatible with *net.Resolver. type DNSResolver interface { LookupTXT(ctx context.Context, name string) ([]string, error) LookupMX(ctx context.Context, name string) ([]*net.MX, error) LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error) LookupAddr(ctx context.Context, addr string) (names []string, err error) } var defaultResolver DNSResolver = net.DefaultResolver // WithResolver sets the resolver to use for DNS lookups. It can be useful for // testing, and for customize DNS resolution specifically for this library. // // The default is to use net.DefaultResolver, which should be appropriate for // most users. // // This is EXPERIMENTAL for now, and the API is subject to change. func WithResolver(resolver DNSResolver) Option { return func(r *resolution) { r.resolver = resolver } } // WithTraceFunc sets the resolver's trace function. // // This can be used for debugging. The trace messages are NOT machine // parseable, and are NOT stable. They should also NOT be included in // user-visible output, as they may include sensitive details. // // This is EXPERIMENTAL for now, and the API is subject to change. func WithTraceFunc(trace TraceFunc) Option { return func(r *resolution) { r.trace = trace } } // split an user@domain address into user and domain. func split(addr string) (string, string) { ps := strings.SplitN(addr, "@", 2) if len(ps) != 2 { return addr, "" } return ps[0], ps[1] } type resolution struct { ip net.IP count uint maxcount uint helo string sender string // Result of doing a reverse lookup for ip (so we only do it once). ipNames []string // Context for this resolution. ctx context.Context // DNS resolver to use. resolver DNSResolver // Trace function, used for debugging. trace TraceFunc } var aField = regexp.MustCompile(`^(a$|a:|a/)`) var mxField = regexp.MustCompile(`^(mx$|mx:|mx/)`) var ptrField = regexp.MustCompile(`^(ptr$|ptr:)`) func (r *resolution) Check(domain string) (Result, error) { r.count++ r.trace("check %q %d", domain, r.count) txt, err := r.getDNSRecord(domain) if err != nil { if isTemporary(err) { r.trace("dns temp error: %v", err) return TempError, err } if err == ErrMultipleRecords { r.trace("multiple dns records") return PermError, err } // Could not resolve the name, it may be missing the record. // https://tools.ietf.org/html/rfc7208#section-2.6.1 r.trace("dns perm error: %v", err) return None, err } r.trace("dns record %q", txt) if txt == "" { // No record => None. // https://tools.ietf.org/html/rfc7208#section-4.5 return None, ErrNoResult } fields := strings.Split(txt, " ") // redirects must be handled after the rest; instead of having two loops, // we just move them to the end. var newfields, redirects []string for _, field := range fields { if strings.HasPrefix(field, "redirect=") { redirects = append(redirects, field) } else { newfields = append(newfields, field) } } if len(redirects) > 1 { // At most a single redirect is allowed. // https://tools.ietf.org/html/rfc7208#section-6 return PermError, ErrInvalidDomain } fields = append(newfields, redirects...) for _, field := range fields { if field == "" { continue } // The version check should be case-insensitive (it's a // case-insensitive constant in the standard). // https://tools.ietf.org/html/rfc7208#section-12 if strings.HasPrefix(field, "v=") || strings.HasPrefix(field, "V=") { continue } // Limit the number of resolutions. // https://tools.ietf.org/html/rfc7208#section-4.6.4 if r.count > r.maxcount { r.trace("lookup limit reached") return PermError, ErrLookupLimitReached } // See if we have a qualifier, defaulting to + (pass). // https://tools.ietf.org/html/rfc7208#section-4.6.2 result, ok := qualToResult[field[0]] if ok { field = field[1:] } else { result = Pass } // Mechanism and modifier names are case-insensitive. // https://tools.ietf.org/html/rfc7208#section-4.6.1 lfield := strings.ToLower(field) if lfield == "all" { // https://tools.ietf.org/html/rfc7208#section-5.1 r.trace("%v matched all", result) return result, ErrMatchedAll } else if strings.HasPrefix(lfield, "include:") { if ok, res, err := r.includeField(result, field, domain); ok { r.trace("include ok, %v %v", res, err) return res, err } } else if aField.MatchString(lfield) { if ok, res, err := r.aField(result, field, domain); ok { r.trace("a ok, %v %v", res, err) return res, err } } else if mxField.MatchString(lfield) { if ok, res, err := r.mxField(result, field, domain); ok { r.trace("mx ok, %v %v", res, err) return res, err } } else if strings.HasPrefix(lfield, "ip4:") || strings.HasPrefix(lfield, "ip6:") { if ok, res, err := r.ipField(result, field); ok { r.trace("ip ok, %v %v", res, err) return res, err } } else if ptrField.MatchString(lfield) { if ok, res, err := r.ptrField(result, field, domain); ok { r.trace("ptr ok, %v %v", res, err) return res, err } } else if strings.HasPrefix(lfield, "exists:") { if ok, res, err := r.existsField(result, field, domain); ok { r.trace("exists ok, %v %v", res, err) return res, err } } else if strings.HasPrefix(lfield, "exp=") { r.trace("exp= not used, skipping") continue } else if strings.HasPrefix(lfield, "redirect=") { r.trace("redirect, %q", field) return r.redirectField(field, domain) } else { // http://www.openspf.org/SPF_Record_Syntax r.trace("permerror, unknown field") return PermError, ErrUnknownField } } // Got to the end of the evaluation without a result => Neutral. // https://tools.ietf.org/html/rfc7208#section-4.7 r.trace("fallback to neutral") return Neutral, nil } // getDNSRecord gets TXT records from the given domain, and returns the SPF // (if any). Note that at most one SPF is allowed per a given domain: // https://tools.ietf.org/html/rfc7208#section-3 // https://tools.ietf.org/html/rfc7208#section-3.2 // https://tools.ietf.org/html/rfc7208#section-4.5 func (r *resolution) getDNSRecord(domain string) (string, error) { txts, err := r.resolver.LookupTXT(r.ctx, domain) if err != nil { return "", err } records := []string{} for _, txt := range txts { // The version check should be case-insensitive (it's a // case-insensitive constant in the standard). // https://tools.ietf.org/html/rfc7208#section-12 if strings.HasPrefix(strings.ToLower(txt), "v=spf1 ") { records = append(records, txt) } // An empty record is explicitly allowed: // https://tools.ietf.org/html/rfc7208#section-4.5 if strings.ToLower(txt) == "v=spf1" { records = append(records, txt) } } // 0 records is ok, handled by the parent. // 1 record is what we expect, return the record. // More than that, it's a permanent error: // https://tools.ietf.org/html/rfc7208#section-4.5 l := len(records) if l == 0 { return "", nil } else if l == 1 { return records[0], nil } return "", ErrMultipleRecords } func isTemporary(err error) bool { derr, ok := err.(*net.DNSError) return ok && derr.Temporary() } // ipField processes an "ip" field. func (r *resolution) ipField(res Result, field string) (bool, Result, error) { fip := field[4:] if strings.Contains(fip, "/") { _, ipnet, err := net.ParseCIDR(fip) if err != nil { return true, PermError, ErrInvalidMask } if ipnet.Contains(r.ip) { return true, res, ErrMatchedIP } } else { ip := net.ParseIP(fip) if ip == nil { return true, PermError, ErrInvalidIP } if ip.Equal(r.ip) { return true, res, ErrMatchedIP } } return false, "", nil } // ptrField processes a "ptr" field. func (r *resolution) ptrField(res Result, field, domain string) (bool, Result, error) { // Extract the domain if the field is in the form "ptr:domain". ptrDomain := domain if len(field) >= 4 { ptrDomain = field[4:] } ptrDomain, err := r.expandMacros(ptrDomain, domain) if err != nil { return true, PermError, ErrInvalidMacro } if ptrDomain == "" { return true, PermError, ErrInvalidDomain } if r.ipNames == nil { r.ipNames = []string{} r.count++ ns, err := r.resolver.LookupAddr(r.ctx, r.ip.String()) if err != nil { // https://tools.ietf.org/html/rfc7208#section-5 if isTemporary(err) { return true, TempError, err } return false, "", err } 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. continue } r.trace("ptr forward resolution %q -> %q", n, addrs) if len(addrs) > 0 { // Append the lower-case variants so we do a case-insensitive // lookup below. r.ipNames = append(r.ipNames, strings.ToLower(n)) } } } r.trace("ptr evaluating %q in %q", ptrDomain, r.ipNames) ptrDomain = strings.ToLower(ptrDomain) for _, n := range r.ipNames { if strings.HasSuffix(n, ptrDomain+".") { return true, res, ErrMatchedPTR } } return false, "", nil } // existsField processes a "exists" field. // https://tools.ietf.org/html/rfc7208#section-5.7 func (r *resolution) existsField(res Result, field, domain string) (bool, Result, error) { // The field is in the form "exists:". eDomain := field[7:] eDomain, err := r.expandMacros(eDomain, domain) if err != nil { return true, PermError, ErrInvalidMacro } if eDomain == "" { return true, PermError, ErrInvalidDomain } r.count++ ips, err := r.resolver.LookupIPAddr(r.ctx, eDomain) if err != nil { // https://tools.ietf.org/html/rfc7208#section-5 if isTemporary(err) { return true, TempError, err } return false, "", err } // Exists only counts if there are IPv4 matches. for _, ip := range ips { if ip.IP.To4() != nil { return true, res, ErrMatchedExists } } return false, "", nil } // includeField processes an "include" field. func (r *resolution) includeField(res Result, field, domain string) (bool, Result, error) { // https://tools.ietf.org/html/rfc7208#section-5.2 incdomain := field[len("include:"):] incdomain, err := r.expandMacros(incdomain, domain) if err != nil { return true, PermError, ErrInvalidMacro } ir, err := r.Check(incdomain) switch ir { case Pass: return true, res, err case Fail, SoftFail, Neutral: return false, ir, err case TempError: return true, TempError, err case PermError: return true, PermError, err case None: return true, PermError, err } return false, "", fmt.Errorf("this should never be reached") } type dualMasks struct { v4 net.IPMask v6 net.IPMask } func ipMatch(ip, tomatch net.IP, masks dualMasks) bool { mask := net.IPMask(nil) if tomatch.To4() != nil && masks.v4 != nil { mask = masks.v4 } else if tomatch.To4() == nil && masks.v6 != nil { mask = masks.v6 } if mask != nil { ipnet := net.IPNet{IP: tomatch, Mask: mask} return ipnet.Contains(ip) } return ip.Equal(tomatch) } var aRegexp = regexp.MustCompile(`^[aA](:([^/]+))?(/(\w+))?(//(\w+))?$`) var mxRegexp = regexp.MustCompile(`^[mM][xX](:([^/]+))?(/(\w+))?(//(\w+))?$`) func domainAndMask(re *regexp.Regexp, field, domain string) (string, dualMasks, error) { masks := dualMasks{} groups := re.FindStringSubmatch(field) if groups != nil { if groups[2] != "" { domain = groups[2] } if groups[4] != "" { i, err := strconv.Atoi(groups[4]) mask4 := net.CIDRMask(i, 32) if err != nil || mask4 == nil { return "", masks, ErrInvalidMask } masks.v4 = mask4 } if groups[6] != "" { i, err := strconv.Atoi(groups[6]) mask6 := net.CIDRMask(i, 128) if err != nil || mask6 == nil { return "", masks, ErrInvalidMask } masks.v6 = mask6 } } // Test to catch malformed entries: if there's a /, there must be at least // one mask. if strings.Contains(field, "/") && masks.v4 == nil && masks.v6 == nil { return "", masks, ErrInvalidMask } return domain, masks, nil } // aField processes an "a" field. func (r *resolution) aField(res Result, field, domain string) (bool, Result, error) { // https://tools.ietf.org/html/rfc7208#section-5.3 aDomain, masks, err := domainAndMask(aRegexp, field, domain) r.trace("masks on %q, %q: %q %v", field, domain, aDomain, masks) if err != nil { return true, PermError, err } aDomain, err = r.expandMacros(aDomain, domain) if err != nil { return true, PermError, ErrInvalidMacro } r.count++ ips, err := r.resolver.LookupIPAddr(r.ctx, aDomain) if err != nil { // https://tools.ietf.org/html/rfc7208#section-5 if isTemporary(err) { return true, TempError, err } return false, "", err } for _, ip := range ips { if ipMatch(r.ip, ip.IP, masks) { r.trace("a matched %v, %v, %v", r.ip, ip.IP, masks) return true, res, ErrMatchedA } } return false, "", nil } // mxField processes an "mx" field. func (r *resolution) mxField(res Result, field, domain string) (bool, Result, error) { // https://tools.ietf.org/html/rfc7208#section-5.4 mxDomain, masks, err := domainAndMask(mxRegexp, field, domain) r.trace("masks on %q, %q: %q %v", field, domain, mxDomain, masks) if err != nil { return true, PermError, err } mxDomain, err = r.expandMacros(mxDomain, domain) if err != nil { return true, PermError, ErrInvalidMacro } r.count++ mxs, err := r.resolver.LookupMX(r.ctx, mxDomain) if err != nil { // https://tools.ietf.org/html/rfc7208#section-5 if isTemporary(err) { return true, TempError, err } return false, "", err } // There's an explicit maximum of 10 MX records per match. // https://tools.ietf.org/html/rfc7208#section-4.6.4 if len(mxs) > 10 { return true, PermError, ErrTooManyMXRecords } mxips := []net.IP{} for _, mx := range mxs { r.count++ ips, err := r.resolver.LookupIPAddr(r.ctx, mx.Host) if err != nil { // https://tools.ietf.org/html/rfc7208#section-5 if isTemporary(err) { return true, TempError, err } return false, "", err } for _, ipaddr := range ips { mxips = append(mxips, ipaddr.IP) } } for _, ip := range mxips { if ipMatch(r.ip, ip, masks) { r.trace("mx matched %v, %v, %v", r.ip, ip, masks) return true, res, ErrMatchedMX } } return false, "", nil } // redirectField processes a "redirect=" field. func (r *resolution) redirectField(field, domain string) (Result, error) { rDomain := field[len("redirect="):] rDomain, err := r.expandMacros(rDomain, domain) if err != nil { return PermError, ErrInvalidMacro } if rDomain == "" { return PermError, ErrInvalidDomain } // https://tools.ietf.org/html/rfc7208#section-6.1 result, err := r.Check(rDomain) if result == None { result = PermError } return result, err } // Group extraction of macro-string from the formal specification. // https://tools.ietf.org/html/rfc7208#section-7.1 var macroRegexp = regexp.MustCompile( `([slodiphcrtvSLODIPHCRTV])([0-9]+)?([rR])?([-.+,/_=]+)?`) // Expand macros, return the expanded string. // This expects to be passed the domain-spec within a field, not an entire // field or larger (that has problematic security implications). // https://tools.ietf.org/html/rfc7208#section-7 func (r *resolution) expandMacros(s, domain string) (string, error) { // Macros/domains shouldn't contain CIDR. Our parsing should prevent it // from happening in case where it matters (a, mx), but for the ones which // doesn't, prevent them from sneaking through. if strings.Contains(s, "/") { r.trace("macro contains /") return "", ErrInvalidDomain } // Bypass the complex logic if there are no macros present. if !strings.Contains(s, "%") { return s, nil } // Are we processing the character right after "%"? afterPercent := false // Are we inside a macro definition (%{...}) ? inMacroDefinition := false // Macro string, where we accumulate the values inside the definition. macroS := "" var err error n := "" for _, c := range s { if afterPercent { afterPercent = false switch c { case '%': n += "%" continue case '_': n += " " continue case '-': n += "%20" continue case '{': inMacroDefinition = true continue } return "", ErrInvalidMacro } if inMacroDefinition { if c != '}' { macroS += string(c) continue } inMacroDefinition = false // Extract letter, digit transformer, reverse transformer, and // delimiters. groups := macroRegexp.FindStringSubmatch(macroS) r.trace("macro %q: %q", macroS, groups) macroS = "" if groups == nil { return "", ErrInvalidMacro } letter := groups[1] digits := 0 if groups[2] != "" { // Use 0 as "no digits given"; an explicit value of 0 is not // valid. digits, err = strconv.Atoi(groups[2]) if err != nil || digits <= 0 { return "", ErrInvalidMacro } } reverse := groups[3] == "r" || groups[3] == "R" delimiters := groups[4] if delimiters == "" { // By default, split strings by ".". delimiters = "." } // Uppercase letters indicate URL escaping of the results. urlEscape := letter == strings.ToUpper(letter) letter = strings.ToLower(letter) str := "" switch letter { case "s": str = r.sender case "l": str, _ = split(r.sender) case "o": _, str = split(r.sender) case "d": str = domain case "i": 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. // https://tools.ietf.org/html/rfc7208#section-7.3 str = "unknown" case "v": if r.ip.To4() != nil { str = "in-addr" } else { str = "ip6" } case "h": str = r.helo default: // c, r, t are allowed in exp only, and we don't expand macros // in exp so they are just as invalid as the rest. return "", ErrInvalidMacro } // Split str using the given separators. splitFunc := func(r rune) bool { return strings.ContainsRune(delimiters, r) } split := strings.FieldsFunc(str, splitFunc) // Reverse if requested. if reverse { reverseStrings(split) } // Leave the last $digits fields, if given. if digits > 0 { if digits > len(split) { digits = len(split) } split = split[len(split)-digits:] } // Join back, always with "." str = strings.Join(split, ".") // Escape if requested. Note this doesn't strictly escape ALL // unreserved characters, it's the closest we can get without // reimplmenting it ourselves. if urlEscape { str = url.QueryEscape(str) } n += str continue } if c == '%' { afterPercent = true continue } n += string(c) } r.trace("macro expanded %q to %q", s, n) return n, nil } func reverseStrings(a []string) { for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 { 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] } golang-blitiri-go-spf-1.3.0/spf_test.go000066400000000000000000000450631414622751200200010ustar00rootroot00000000000000package spf import ( "context" "fmt" "net" "testing" "blitiri.com.ar/go/spf/internal/dnstest" ) func NewDefaultResolver() *dnstest.TestResolver { dns := dnstest.NewResolver() defaultResolver = dns return dns } func init() { // Override the default resolver to make sure the tests are not using the // one from net. Individual tests will override this as well, but just in // case. NewDefaultResolver() } var ip1110 = net.ParseIP("1.1.1.0") var ip1111 = net.ParseIP("1.1.1.1") var ip6666 = net.ParseIP("2001:db8::68") var ip6660 = net.ParseIP("2001:db8::0") func TestBasic(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf cases := []struct { txt string res Result err error }{ {"", None, ErrNoResult}, {"blah", None, ErrNoResult}, {"v=spf1", Neutral, nil}, {"v=spf1 ", Neutral, nil}, {"v=spf1 -", PermError, ErrUnknownField}, {"v=spf1 all", Pass, ErrMatchedAll}, {"v=spf1 exp=blah +all", Pass, ErrMatchedAll}, {"v=spf1 +all", Pass, ErrMatchedAll}, {"v=spf1 -all ", Fail, ErrMatchedAll}, {"v=spf1 ~all", SoftFail, ErrMatchedAll}, {"v=spf1 ?all", Neutral, ErrMatchedAll}, {"v=spf1 a ~all", SoftFail, ErrMatchedAll}, {"v=spf1 a/24", Neutral, nil}, {"v=spf1 a:d1110/24", Pass, ErrMatchedA}, {"v=spf1 a:d1110/montoto", PermError, ErrInvalidMask}, {"v=spf1 a:d1110/99", PermError, ErrInvalidMask}, {"v=spf1 a:d1110/32", Neutral, nil}, {"v=spf1 a:d1110", Neutral, nil}, {"v=spf1 a:d1111", Pass, ErrMatchedA}, {"v=spf1 a:nothing/24", Neutral, nil}, {"v=spf1 mx", Neutral, nil}, {"v=spf1 mx/24", Neutral, nil}, {"v=spf1 mx:a/montoto ~all", PermError, ErrInvalidMask}, {"v=spf1 mx:d1110/24 ~all", Pass, ErrMatchedMX}, {"v=spf1 mx:d1110/24//100 ~all", Pass, ErrMatchedMX}, {"v=spf1 mx:d1110/24//129 ~all", PermError, ErrInvalidMask}, {"v=spf1 mx:d1110/24/100 ~all", PermError, ErrInvalidMask}, {"v=spf1 mx:d1110/99 ~all", PermError, ErrInvalidMask}, {"v=spf1 ip4:1.2.3.4 ~all", SoftFail, ErrMatchedAll}, {"v=spf1 ip6:12 ~all", PermError, ErrInvalidIP}, {"v=spf1 ip4:1.1.1.1 -all", Pass, ErrMatchedIP}, {"v=spf1 ip4:1.1.1.1/24 -all", Pass, ErrMatchedIP}, {"v=spf1 ip4:1.1.1.1/lala -all", PermError, ErrInvalidMask}, {"v=spf1 ip4:1.1.1.1/33 -all", PermError, ErrInvalidMask}, {"v=spf1 include:doesnotexist", PermError, ErrNoResult}, {"v=spf1 ptr -all", Pass, ErrMatchedPTR}, {"v=spf1 ptr:d1111 -all", Pass, ErrMatchedPTR}, {"v=spf1 ptr:lalala -all", Pass, ErrMatchedPTR}, {"v=spf1 ptr:doesnotexist -all", Fail, ErrMatchedAll}, {"v=spf1 blah", PermError, ErrUnknownField}, {"v=spf1 exists:d1111 -all", Pass, ErrMatchedExists}, {"v=spf1 redirect=", PermError, ErrInvalidDomain}, } dns.Ip["d1111"] = []net.IP{ip1111} dns.Ip["d1110"] = []net.IP{ip1110} dns.Mx["d1110"] = []*net.MX{mx("d1110", 5), mx("nothing", 10)} dns.Addr["1.1.1.1"] = []string{"lalala.", "xx.domain.", "d1111."} dns.Ip["lalala"] = []net.IP{ip1111} dns.Ip["xx.domain"] = []net.IP{ip1111} for _, c := range cases { dns.Txt["domain"] = []string{c.txt} res, err := CheckHost(ip1111, "domain") if (res == TempError || res == PermError) && (err == nil) { t.Errorf("%q: expected error, got nil", c.txt) } if res != c.res { t.Errorf("%q: expected %q, got %q", c.txt, c.res, res) } if err != c.err { t.Errorf("%q: expected error [%v], got [%v]", c.txt, c.err, err) } } } func TestIPv6(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf cases := []struct { txt string res Result err error }{ {"v=spf1 all", Pass, ErrMatchedAll}, {"v=spf1 a ~all", SoftFail, ErrMatchedAll}, {"v=spf1 a/24", Neutral, nil}, {"v=spf1 a:d6660//24", Pass, ErrMatchedA}, {"v=spf1 a:d6660/24//100", Pass, ErrMatchedA}, {"v=spf1 a:d6660", Neutral, nil}, {"v=spf1 a:d6666", Pass, ErrMatchedA}, {"v=spf1 a:nothing//24", Neutral, nil}, {"v=spf1 mx:d6660//24 ~all", Pass, ErrMatchedMX}, {"v=spf1 mx:d6660/24//100 ~all", Pass, ErrMatchedMX}, {"v=spf1 mx:d6660/24/100 ~all", PermError, ErrInvalidMask}, {"v=spf1 ip6:2001:db8::68 ~all", Pass, ErrMatchedIP}, {"v=spf1 ip6:2001:db8::1/24 ~all", Pass, ErrMatchedIP}, {"v=spf1 ip6:2001:db8::1/100 ~all", Pass, ErrMatchedIP}, {"v=spf1 ptr -all", Pass, ErrMatchedPTR}, {"v=spf1 ptr:d6666 -all", Pass, ErrMatchedPTR}, {"v=spf1 ptr:sonlas6 -all", Pass, ErrMatchedPTR}, {"v=spf1 ptr:sonlas7 -all", Fail, ErrMatchedAll}, } dns.Ip["d6666"] = []net.IP{ip6666} dns.Ip["d6660"] = []net.IP{ip6660} dns.Mx["d6660"] = []*net.MX{mx("d6660", 5), mx("nothing", 10)} dns.Addr["2001:db8::68"] = []string{"sonlas6.", "domain.", "d6666."} dns.Ip["domain"] = []net.IP{ip1111} dns.Ip["sonlas6"] = []net.IP{ip6666} for _, c := range cases { dns.Txt["domain"] = []string{c.txt} res, err := CheckHost(ip6666, "domain") if (res == TempError || res == PermError) && (err == nil) { t.Errorf("%q: expected error, got nil", c.txt) } if res != c.res { t.Errorf("%q: expected %q, got %q", c.txt, c.res, res) } if err != c.err { t.Errorf("%q: expected error [%v], got [%v]", c.txt, c.err, err) } } } func TestInclude(t *testing.T) { // Test that the include is doing a recursive lookup. // If we got a match on 1.1.1.1, is because include:domain2 did not match. dns := NewDefaultResolver() dns.Txt["domain"] = []string{"v=spf1 include:domain2 ip4:1.1.1.1"} defaultTrace = t.Logf cases := []struct { txt string res Result err error }{ {"", PermError, ErrNoResult}, {"v=spf1 all", Pass, ErrMatchedAll}, // domain2 did not pass, so continued and matched parent's ip4. {"v=spf1", Pass, ErrMatchedIP}, {"v=spf1 -all", Pass, ErrMatchedIP}, } for _, c := range cases { dns.Txt["domain2"] = []string{c.txt} res, err := CheckHost(ip1111, "domain") if res != c.res || err != c.err { t.Errorf("%q: expected [%v/%v], got [%v/%v]", c.txt, c.res, c.err, res, err) } } } func TestRecursionLimit(t *testing.T) { dns := NewDefaultResolver() dns.Txt["domain"] = []string{"v=spf1 include:domain ~all"} defaultTrace = t.Logf res, err := CheckHost(ip1111, "domain") if res != PermError || err != ErrLookupLimitReached { t.Errorf("expected permerror, got %v (%v)", res, err) } } func TestRedirect(t *testing.T) { dns := NewDefaultResolver() dns.Txt["domain"] = []string{"v=spf1 redirect=domain2"} dns.Txt["domain2"] = []string{"v=spf1 ip4:1.1.1.1 -all"} defaultTrace = t.Logf res, err := CheckHost(ip1111, "domain") if res != Pass { t.Errorf("expected pass, got %v (%v)", res, err) } } func TestInvalidRedirect(t *testing.T) { // Redirect to a non-existing host; the inner check returns None, but due // to the redirection, this lookup should return PermError. // https://tools.ietf.org/html/rfc7208#section-6.1 dns := NewDefaultResolver() dns.Txt["domain"] = []string{"v=spf1 redirect=doesnotexist"} defaultTrace = t.Logf res, err := CheckHost(ip1111, "doesnotexist") if res != None { t.Errorf("expected none, got %v (%v)", res, err) } res, err = CheckHost(ip1111, "domain") if res != PermError || err != ErrNoResult { t.Errorf("expected permerror, got %v (%v)", res, err) } } func TestRedirectOrder(t *testing.T) { // We should only check redirects after all mechanisms, even if the // redirect modifier appears before them. dns := NewDefaultResolver() dns.Txt["faildom"] = []string{"v=spf1 -all"} defaultTrace = t.Logf dns.Txt["domain"] = []string{"v=spf1 redirect=faildom"} res, err := CheckHost(ip1111, "domain") if res != Fail || err != ErrMatchedAll { t.Errorf("expected fail, got %v (%v)", res, err) } dns.Txt["domain"] = []string{"v=spf1 redirect=faildom all"} res, err = CheckHost(ip1111, "domain") if res != Pass || err != ErrMatchedAll { t.Errorf("expected pass, got %v (%v)", res, err) } } func TestNoRecord(t *testing.T) { dns := NewDefaultResolver() dns.Txt["d1"] = []string{""} dns.Txt["d2"] = []string{"loco", "v=spf2"} dns.Errors["nospf"] = fmt.Errorf("no such domain") defaultTrace = t.Logf for _, domain := range []string{"d1", "d2", "d3", "nospf"} { res, err := CheckHost(ip1111, domain) if res != None { t.Errorf("expected none, got %v (%v)", res, err) } } } func TestDNSTemporaryErrors(t *testing.T) { dns := NewDefaultResolver() dnsError := &net.DNSError{ Err: "temporary error for testing", IsTemporary: true, } // Domain "tmperr" will fail resolution with a temporary error. dns.Errors["tmperr"] = dnsError dns.Errors["1.1.1.1"] = dnsError dns.Mx["tmpmx"] = []*net.MX{mx("tmperr", 10)} defaultTrace = t.Logf cases := []struct { txt string res Result }{ {"v=spf1 include:tmperr", TempError}, {"v=spf1 a:tmperr", TempError}, {"v=spf1 mx:tmperr", TempError}, {"v=spf1 ptr:tmperr", TempError}, {"v=spf1 mx:tmpmx", TempError}, } for _, c := range cases { dns.Txt["domain"] = []string{c.txt} res, err := CheckHost(ip1111, "domain") if res != c.res { t.Errorf("%q: expected %v, got %v (%v)", c.txt, c.res, res, err) } } } func TestDNSPermanentErrors(t *testing.T) { dns := NewDefaultResolver() dnsError := &net.DNSError{ Err: "permanent error for testing", IsTemporary: false, } // Domain "tmperr" will fail resolution with a temporary error. dns.Errors["tmperr"] = dnsError dns.Errors["1.1.1.1"] = dnsError dns.Mx["tmpmx"] = []*net.MX{mx("tmperr", 10)} defaultTrace = t.Logf cases := []struct { txt string res Result }{ {"v=spf1 include:tmperr", PermError}, {"v=spf1 a:tmperr", Neutral}, {"v=spf1 mx:tmperr", Neutral}, {"v=spf1 ptr:tmperr", Neutral}, {"v=spf1 mx:tmpmx", Neutral}, } for _, c := range cases { dns.Txt["domain"] = []string{c.txt} res, err := CheckHost(ip1111, "domain") if res != c.res { t.Errorf("%q: expected %v, got %v (%v)", c.txt, c.res, res, err) } } } func TestMacros(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf // Most of the cases are covered by the standard test suite, so this is // targeted at gaps in coverage. cases := []struct { txt string res Result err error }{ {"v=spf1 ptr:%{fff} -all", PermError, ErrInvalidMacro}, {"v=spf1 mx:%{fff} -all", PermError, ErrInvalidMacro}, {"v=spf1 redirect=%{fff}", PermError, ErrInvalidMacro}, {"v=spf1 a:%{o0}", PermError, ErrInvalidMacro}, {"v=spf1 +a:sss-%{s}-sss", Pass, ErrMatchedA}, {"v=spf1 +a:ooo-%{o}-ooo", Pass, ErrMatchedA}, {"v=spf1 +a:OOO-%{O}-OOO", Pass, ErrMatchedA}, {"v=spf1 +a:ppp-%{p}-ppp", Pass, ErrMatchedA}, {"v=spf1 +a:hhh-%{h}-hhh", Pass, ErrMatchedA}, {"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["hhh-helo-hhh"] = []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} res, err := CheckHostWithSender(ip6666, "helo", "user@domain") if (res == TempError || res == PermError) && (err == nil) { t.Errorf("%q: expected error, got nil", c.txt) } if res != c.res { t.Errorf("%q: expected %q, got %q", c.txt, c.res, res) } if err != c.err { t.Errorf("%q: expected error [%v], got [%v]", c.txt, c.err, err) } } } func TestMacrosV4(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf // Like TestMacros above, but specifically for IPv4. // It's easier to have a separate suite. // While at it, test some of the reversals, for variety. cases := []struct { txt string res Result err error }{ {"v=spf1 +a:sr-%{sr}-sr", Pass, ErrMatchedA}, {"v=spf1 +a:sra-%{sr.}-sra", Pass, ErrMatchedA}, {"v=spf1 +a:o7-%{o7}-o7", Pass, ErrMatchedA}, {"v=spf1 +a:o1-%{o1}-o1", Pass, ErrMatchedA}, {"v=spf1 +a:o1r-%{o1r}-o1r", Pass, ErrMatchedA}, {"v=spf1 +a:vvv-%{v}-vvv", Pass, ErrMatchedA}, } dns.Ip["sr-com.user@domain-sr"] = []net.IP{ip1111} dns.Ip["sra-com.user@domain-sra"] = []net.IP{ip1111} dns.Ip["o7-domain.com-o7"] = []net.IP{ip1111} dns.Ip["o1-com-o1"] = []net.IP{ip1111} dns.Ip["o1r-domain-o1r"] = []net.IP{ip1111} dns.Ip["vvv-in-addr-vvv"] = []net.IP{ip1111} for _, c := range cases { dns.Txt["domain.com"] = []string{c.txt} res, err := CheckHostWithSender(ip1111, "helo", "user@domain.com") if (res == TempError || res == PermError) && (err == nil) { t.Errorf("%q: expected error, got nil", c.txt) } if res != c.res { t.Errorf("%q: expected %q, got %q", c.txt, c.res, res) } if err != c.err { t.Errorf("%q: expected error [%v], got [%v]", c.txt, c.err, err) } } } func mx(host string, pref uint16) *net.MX { return &net.MX{Host: host, Pref: pref} } func mkDM(v4, v6 int) dualMasks { return dualMasks{net.CIDRMask(v4, 32), net.CIDRMask(v6, 128)} } func TestIPMatchHelper(t *testing.T) { cases := []struct { ip net.IP tomatch net.IP masks dualMasks ok bool }{ {ip1111, ip1110, mkDM(24, -1), true}, {ip1111, ip1111, mkDM(-1, -1), true}, {ip1111, ip1110, mkDM(-1, -1), false}, {ip1111, ip1110, mkDM(32, -1), false}, {ip1111, ip1110, mkDM(99, -1), false}, {ip6666, ip6660, mkDM(-1, 100), true}, {ip6666, ip6666, mkDM(-1, -1), true}, {ip6666, ip6660, mkDM(-1, -1), false}, {ip6666, ip6660, mkDM(-1, 128), false}, {ip6666, ip6660, mkDM(-1, 200), false}, } for _, c := range cases { ok := ipMatch(c.ip, c.tomatch, c.masks) if ok != c.ok { t.Errorf("[%s %s/%v]: expected %v, got %v", c.ip, c.tomatch, c.masks, c.ok, ok) } } } func TestInvalidMacro(t *testing.T) { // Test that the macro expansion detects some invalid macros. macros := []string{ "%{x}", "%{z}", "%{c}", "%{r}", "%{t}", } for _, macro := range macros { r := resolution{ ip: ip1111, count: 0, sender: "sender.com", trace: t.Logf, } out, err := r.expandMacros(macro, "sender.com") if out != "" || err != ErrInvalidMacro { t.Errorf(`[%s]:expected ""/%v, got %q/%v`, macro, ErrInvalidMacro, out, err) } } } // Test that the null tracer doesn't cause unexpected issues, since all the // other tests override it. func TestNullTrace(t *testing.T) { dns := NewDefaultResolver() defaultTrace = nullTrace dns.Txt["domain1"] = []string{"v=spf1 include:domain2"} dns.Txt["domain2"] = []string{"v=spf1 +all"} // Do a normal resolution, check it passes. res, err := CheckHostWithSender(ip1111, "helo", "user@domain1") if res != Pass { t.Errorf("expected pass, got %q / %q", res, err) } } func TestOverrideLookupLimit(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf dns.Txt["domain1"] = []string{"v=spf1 include:domain2"} dns.Txt["domain2"] = []string{"v=spf1 include:domain3"} dns.Txt["domain3"] = []string{"v=spf1 include:domain4"} dns.Txt["domain4"] = []string{"v=spf1 +all"} // The default of 10 should be enough. res, err := CheckHostWithSender(ip1111, "helo", "user@domain1") if res != Pass { t.Errorf("expected pass, got %q / %q", res, err) } // Set the limit to 4, which is enough. res, err = CheckHostWithSender(ip1111, "helo", "user@domain1", OverrideLookupLimit(4)) if res != Pass { t.Errorf("expected pass, got %q / %q", res, err) } // Set the limit to 3, which is not enough. res, err = CheckHostWithSender(ip1111, "helo", "user@domain1", OverrideLookupLimit(3)) if res != PermError || err != ErrLookupLimitReached { t.Errorf("expected permerror/lookup limit reached, got %q / %q", res, err) } } func TestWithContext(t *testing.T) { dns := NewDefaultResolver() defaultTrace = t.Logf dns.Txt["domain1"] = []string{"v=spf1 include:domain2"} dns.Txt["domain2"] = []string{"v=spf1 +all"} // With a normal context. ctx := context.Background() res, err := CheckHostWithSender(ip1111, "helo", "user@domain1", WithContext(ctx)) if res != Pass { t.Errorf("expected pass, got %q / %q", res, err) } // With a cancelled context. ctx, cancelF := context.WithCancel(context.Background()) cancelF() res, err = CheckHostWithSender(ip1111, "helo", "user@domain1", WithContext(ctx)) if res != None || err != context.Canceled { t.Errorf("expected none/context cancelled, got %q / %q", res, err) } } func TestWithResolver(t *testing.T) { // Use a custom resolver, making sure it's different from the default. defaultResolver = dnstest.NewResolver() dns := dnstest.NewResolver() defaultTrace = t.Logf dns.Txt["domain1"] = []string{"v=spf1 include:domain2"} dns.Txt["domain2"] = []string{"v=spf1 +all"} res, err := CheckHostWithSender(ip1111, "helo", "user@domain1", WithResolver(dns)) if res != Pass { t.Errorf("expected pass, got %q / %q", res, err) } } // Test some corner cases when resolver.LookupIPAddr returns an invalid // address. This can happen if using a buggy custom resolver. func TestBadResolverResponse(t *testing.T) { dns := dnstest.NewResolver() defaultTrace = t.Logf // When LookupIPAddr returns an invalid ip, for an "a" field. dns.Ip["domain1"] = []net.IP{nil} dns.Txt["domain1"] = []string{"v=spf1 a:domain1 -all"} res, err := CheckHostWithSender(ip1111, "helo", "user@domain1", WithResolver(dns)) if res != Fail { t.Errorf("expected fail, got %q / %q", res, err) } // Same as above, except the field has a mask. dns.Ip["domain1"] = []net.IP{nil} dns.Txt["domain1"] = []string{"v=spf1 a:domain1//24 -all"} res, err = CheckHostWithSender(ip1111, "helo", "user@domain1", WithResolver(dns)) if res != Fail { t.Errorf("expected fail, got %q / %q", res, err) } // When LookupIPAddr returns an invalid ip, for an "mx" field. dns.Ip["mx.domain1"] = []net.IP{nil} dns.Mx["domain1"] = []*net.MX{mx("mx.domain1", 5)} dns.Txt["domain1"] = []string{"v=spf1 mx:domain1 -all"} res, err = CheckHostWithSender(ip1111, "helo", "user@domain1", WithResolver(dns)) if res != Fail { t.Errorf("expected fail, got %q / %q", res, err) } // Same as above, except the field has a mask. dns.Ip["mx.domain1"] = []net.IP{nil} dns.Mx["domain1"] = []*net.MX{mx("mx.domain1", 5)} dns.Txt["domain1"] = []string{"v=spf1 mx:domain1//24 -all"} res, err = CheckHostWithSender(ip1111, "helo", "user@domain1", WithResolver(dns)) if res != Fail { t.Errorf("expected fail, got %q / %q", res, err) } } func TestWithTraceFunc(t *testing.T) { calls := 0 var trace TraceFunc = func(f string, a ...interface{}) { calls++ t.Logf("tracing "+f, a...) } dns := NewDefaultResolver() dns.Txt["domain1"] = []string{"v=spf1 include:domain2"} dns.Txt["domain2"] = []string{"v=spf1 +all"} // Do a normal resolution, check it passes. res, err := CheckHostWithSender(ip1111, "helo", "user@domain1", WithTraceFunc(trace)) if res != Pass { t.Errorf("expected pass, got %q / %q", res, err) } if calls == 0 { t.Errorf("expected >0 trace function calls, got 0") } } golang-blitiri-go-spf-1.3.0/testdata/000077500000000000000000000000001414622751200174245ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/testdata/blitirispf-tests.yml000066400000000000000000000063401414622751200234610ustar00rootroot00000000000000# Simple tests, used for debugging the testing infrastructure. --- description: Simple successes tests: test1: description: Straightforward sucesss helo: example.net mailfrom: "foobar@example.net" host: 1.2.3.4 result: pass test2: description: HELO is set, but expected to be ignored helo: blargh mailfrom: "foobar@example.net" host: 1.2.3.4 result: pass zonedata: example.net: - SPF: v=spf1 +all --- description: Simple failures tests: test1: description: Straightforward failure helo: example.net mailfrom: "foobar@example.net" host: 1.2.3.4 result: fail test2: description: HELO is set, but expected to be ignored helo: blargh mailfrom: "foobar@example.net" host: 1.2.3.4 result: fail zonedata: example.net: - SPF: v=spf1 -all --- description: Regexp edge cases for "a", "mx" and "ptr" tests: ipv6-with-a: description: | Send from an ip6 address that has "a:" inside. If we incorrectly parse the "ip6" as "a", this results in a permerror since the host doesn't match. mailfrom: "foobar@a1.net" host: a::a result: pass bad-a-mask: description: | If we incorrectly parse the "ip6" as "a", this results in a permerror due to an invalid mask. mailfrom: "foobar@a2.net" host: 2001:db8:ff0:100::2 result: softfail exp-contains-mx: description: exp= contains mx:, which should be ignored. mailfrom: "foobar@expmx.net" host: 1.2.3.4 result: softfail exp-contains-ptr: description: | exp= contains ptr:, which should be ignored. Note this test case involves unusual/invalid domains. mailfrom: "foobar@expptr.net" host: 1.2.3.4 result: softfail zonedata: a1.net: - SPF: v=spf1 ip6:a::a ~all a2.net: - SPF: v=spf1 ip6:1a0a:cccc::/29 ~all expmx.net: - SPF: v=spf1 exp=mx:mymx.com ~all - MX: [10, mymx.com] mymx.com: - A: 1.2.3.4 expptr.net: - SPF: v=spf1 exp=ptr:lalala.com ~all 4.3.2.1.in-addr.arpa: - PTR: ptr:lalala.com. ptr:lalala.com: - A: 1.2.3.4 --- description: Error on PTR forward resolution tests: broken-ptr-forward: description: | Check that if during 'ptr' forward resolution we get an error, we skip the domain (and consequently fail the check). mailfrom: "foo@domain.net" host: 1.2.3.4 result: softfail zonedata: domain.net: - SPF: v=spf1 ptr:lalala.com ~all 4.3.2.1.in-addr.arpa: - PTR: lalala.com lalala.com: - TIMEOUT: true --- description: Permanent error on 'exists' resolution tests: exists-perm-error: description: | Check that if, during an 'exists' forward resolution we get an error, we fail the check. mailfrom: "foo@domain.net" host: 1.2.3.4 result: softfail zonedata: domain.net: - SPF: v=spf1 exists:lalala.com ~all lalala.com: - SERVFAIL: true --- description: Resolve H macros correctly tests: resolve-h-macros: description: | Check that '%{h}' macros are correctly resolved to the HELO/EHLO and not the sender domain. mailfrom: "foo@domain.net" helo: holahola host: 1.2.3.4 result: pass zonedata: domain.net: - SPF: v=spf1 exists:%{h}.com ~all holahola.com: - A: 127.0.0.2 golang-blitiri-go-spf-1.3.0/testdata/fuzz/000077500000000000000000000000001414622751200204225ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/000077500000000000000000000000001414622751200217355ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/00411bf44dbea39f3278c2cface16398f239e7ca-12000066400000000000000000000000531414622751200276730ustar00rootroot00000000000000v=spf1 ip6:1:b:6:1:b:6:1:0/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/00cf37c4fa061abb08aeed0981d8d0e26a1e1323-4000066400000000000000000000000301414622751200275540ustar00rootroot00000000000000v=spf1 include:domain golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/01438665d70f99814773625c2b18eb2104f4ea13-5000066400000000000000000000000271414622751200270210ustar00rootroot00000000000000v=spf1 𫞵𫞵𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0175b61366f0bae34f123456ba2bf7154a6af668-3000066400000000000000000000000201414622751200272740ustar00rootroot00000000000000v=spf1 mx:%{I} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/02c83942c0ae728b90c0a9ea44de2781e884d1bb000066400000000000000000000000161414622751200273100ustar00rootroot00000000000000v=spf1 a:%{o0}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/031baaf383cfebcacc31eeb3c4d060743adc6be0-3000066400000000000000000000000171414622751200301320ustar00rootroot00000000000000v=spf1 ÕóÕïï4golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/03279b4fd8a0a693cc9bf81bcd225fcae6101d24-9000066400000000000000000000000411414622751200276040ustar00rootroot00000000000000v=spf1 a/ a/ a/ a/ a/ a/ a/ a/ a/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/048ed20064c6350703216668dd23ea6bb5f66315000066400000000000000000000000241414622751200267210ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1/0golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/04c9de854b93f2607c3fd25a5559cd3e4db9c1e8000066400000000000000000000000351414622751200274150ustar00rootroot00000000000000v=spf1 exists:%{I_}%{O_}%{l-}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0556fcf18a86a09f6048c933b57e54cb9f2c3d20-11000066400000000000000000000000571414622751200274710ustar00rootroot00000000000000v=spf1 ip6:::1 ip6:Cafe:Babe:0:: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0646a02a7b4f134295dccc4f3b6d4f74a98fd107-5000066400000000000000000000000311414622751200274510ustar00rootroot00000000000000v=spf1 include:domain golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/06bec983ccd57eed211cbd4bda8583ace4c45c8c-7000066400000000000000000000000211414622751200301130ustar00rootroot00000000000000v=spf1 mx mx a mxgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/079ead839c297839a931cdea8b00dde0de22049a-1000066400000000000000000000000241414622751200275350ustar00rootroot00000000000000v=spf1 mx:%{{.%{i} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/07d761d89cec1e613b391dae889ac55b2dceec9e-14000066400000000000000000000000651414622751200300610ustar00rootroot00000000000000v=spf1 mx:ó‚‚‚ó‚‚‚ó‚‚‚ó‚‚‚ó‚‚‚ó‚‚‚ó‚‚½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/07e9ac18500412e857ac88d53d2d14fa38763489-2000066400000000000000000000000321414622751200271660ustar00rootroot00000000000000v=spf1 mx:d1¤ÞÐEa110~al+-lgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0845f1c9d86392058834dd993061f55fd35986a3-13000066400000000000000000000000521414622751200271360ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ip6:::/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0864783451aeddd592bf6840e0329f46598ed9d7-4000066400000000000000000000000341414622751200272750ustar00rootroot00000000000000v=spf1 ip6:6:1:8:1::6:1:8:0.golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/08ba70fdee26f6942453c1420b4823fcac5821b1-1000066400000000000000000000000251414622751200273540ustar00rootroot00000000000000v=spf1 ip4:1.71160442golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/096680e0fa303a874fe940143073b3b606d11482000066400000000000000000000000231414622751200266360ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4:golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0a2058b18f2a5fb7c02077742dc8874d015c6f53-4000066400000000000000000000000471414622751200272340ustar00rootroot00000000000000v=spf1 redirect=%{d0027755927159263581}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0a2060a21e9dfea36b635404b1dfa34ad9540063-23000066400000000000000000000000401414622751200274140ustar00rootroot00000000000000v=spf1 a:%%%%%%%% include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0a7b5cdc8eac7830d419515b47c11a0cbcf0bdd3-11000066400000000000000000000000341414622751200300020ustar00rootroot00000000000000v=spf1 a:ÅÅ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0ae0ed61b45093f6121612116ac41e611b7ca57c-13000066400000000000000000000000341414622751200273350ustar00rootroot00000000000000v=spf1 mx:Aa‚ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0b23284bbc74c7e72dcad1e56ad2c0c422c76f6c-2000066400000000000000000000000301414622751200276470ustar00rootroot00000000000000v=spf1 include:domain 1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0b5b6a45778d16db6c3a53ec6d96d8ddb70cbf3b-3000066400000000000000000000000371414622751200277620ustar00rootroot00000000000000v=spf1 a/-110718626451492305703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0c4314c16a99b6d5be7b506088e5194bc01edf1e-9000066400000000000000000000000511414622751200274540ustar00rootroot00000000000000v=spf1 a:d1110/1 a:d1110/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0c5f76d791418c99ac7dc9148ebffe4b226037d2000066400000000000000000000000171414622751200273370ustar00rootroot00000000000000v=spf1 a:%{H} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0ce9a737495f56e975b86c862d1b2ce62b0997bc-4000066400000000000000000000000151414622751200274300ustar00rootroot00000000000000v=spf1 óó‚‚)golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0d45f75bc08ac9bf702effdb893ca87c801a7294-4000066400000000000000000000000211414622751200276240ustar00rootroot00000000000000v=spf1 mx1 mx/ a/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0e5d97173ab36db60868cd5b0ac136c4657e0c79-13000066400000000000000000000000541414622751200274630ustar00rootroot00000000000000v=spf1 a:%{IR}%{IR}%{IR}%{IR} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0e955ff9c6d5c2d145779ddc32e8af92f3fce15c-2000066400000000000000000000000121414622751200277170ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/0f2c4e38efb96812b9ab096bcdd0a4d295879169-2000066400000000000000000000000261414622751200274750ustar00rootroot00000000000000v=spf1 redirect=%{d1:}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/107174d48130ff0c7b15437e348ba16d8649b3dc-15000066400000000000000000000000351414622751200273150ustar00rootroot00000000000000v=spf1 ip6:1:: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1079f2c1b9f8fe829d185321520db4489ddc2a80-12000066400000000000000000000000411414622751200274020ustar00rootroot00000000000000v=spf1 mx:%{i}%{i} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/10af261a4eba5d6a09178858f7f7b2bdc8a4d2ed-6000066400000000000000000000000311414622751200276730ustar00rootroot00000000000000v=spf1 include:domain âgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/113d1b233d0b182ce8dec943a01a213dbc1bfc32-4000066400000000000000000000000131414622751200275360ustar00rootroot00000000000000v=spf1 ó‚‚golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/115c29a6c848857a691de2267b7d3ac92ce5f384-2000066400000000000000000000000121414622751200273320ustar00rootroot00000000000000v=spf1 a agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/124eddd031bfaecce3884922d2180332032e4156-5000066400000000000000000000000701414622751200272700ustar00rootroot00000000000000v=spf1 óh¿½½ñ¿/½ï½ï¿)½½½¶€¿½ñ¿/½ÿñ¿/½ï½ï¿)½½½¶€¿½ñ¿/½ÿgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1266c0d0f5c4ca735e3a71c9edff3d4e5aca9bbd000066400000000000000000000000241414622751200277430ustar00rootroot00000000000000v=spf1 mx:d6660/24 lgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1344b11657d8c0b3d0d7f6e76c0d728905615894000066400000000000000000000000201414622751200267410ustar00rootroot00000000000000v=spf1 exists:%(golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1380aa5a0953cae35d64ff6c145b5c0a3ba84228-20000066400000000000000000000000651414622751200275130ustar00rootroot00000000000000v=spf1 mx:ó mx:ó‚ó‚ó‚ó€ó‚‚ó‚ó‚ó‚ó‚‚ó‚ó‚ó€ó‚‚ó‚ó‚ó‚ó‚/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/13d1473f6d375e492efdf7d50e696907721bf5d1-11000066400000000000000000000000341414622751200274200ustar00rootroot00000000000000v=spf1 a:%{V} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/157b209632435b7b661b3438c96d1e8548550476-6000066400000000000000000000000201414622751200266670ustar00rootroot00000000000000v=spf1 óóø‘‚ógolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/159729fed614b134e57b677bc72474f6463d362b-6000066400000000000000000000000321414622751200272000ustar00rootroot00000000000000v=spf1 include:domain ²golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/15da32d2909f118a0fc25ca4dccf07b03ff3c483-6000066400000000000000000000000531414622751200275760ustar00rootroot00000000000000v=spf1 𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/15f3b6fef4391fd987ffc0ddf0c449046f0898b2-3000066400000000000000000000000151414622751200275640ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/160f80a8549044c6e3aca7b9d1e3964238615667-6000066400000000000000000000000231414622751200271110ustar00rootroot00000000000000v=spf1 ó‚‚‚ó‚‚‚ó‚‚€golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/16524c09938afe9f06450277c89b75b6f31c3cb4-21000066400000000000000000000000401414622751200273300ustar00rootroot00000000000000v=spf1 a:%_%_%_%_ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1677b850a2b9471330774daab8ee651332ba4373-6000066400000000000000000000000401414622751200271440ustar00rootroot00000000000000v=spf1 mx:d1110/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/176cbdaa14dd6b36843f55f3f52d93bacd4e5955-13000066400000000000000000000000411414622751200277020ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/182f3cb4545f1f16b4a58f54db1a64c6f94d7db8-2000066400000000000000000000000341414622751200275440ustar00rootroot00000000000000v=spf1 a/071862645a4B361qZ_ugolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1845de197b696ae69aa7a1a800bc3658f3b93946-2000066400000000000000000000000121414622751200273300ustar00rootroot00000000000000v=spf1 a/Cgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/190b3bd4bd8de1bda728ed60865624b5177f554c-5000066400000000000000000000000121414622751200274560ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/193c50b3e52fe33fe67cb982ade55dbecb14896d-11000066400000000000000000000000441414622751200277670ustar00rootroot00000000000000v=spf1 a: a: a: a: a: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/19530aae226c629fa64a142ade8d8edcaef2bc8a000066400000000000000000000000251414622751200276620ustar00rootroot00000000000000v=spf1 a:sr-%{sr}-sr golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/198de5285b908cd3f854185f75003361dc2e735e-11000066400000000000000000000000431414622751200272550ustar00rootroot00000000000000v=spf1 mx mx mx mx mx mx mx mx mx mgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/19b7f4b8fe98a86a6a4b845dfb7a803ae7198274-6000066400000000000000000000000141414622751200275110ustar00rootroot00000000000000v=spf1 ½ golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/19f2ae36f0113911c2f2caf4d94425ead0cf12d5-12000066400000000000000000000000331414622751200275700ustar00rootroot00000000000000v=spf1 mx:Ó³ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1aa7c2119ab155decb1e32c8efc1102a23030355-4000066400000000000000000000000201414622751200273740ustar00rootroot00000000000000v=spf1 a/-4 a/-1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1abffb38597e7d7ca8287c59af3a580dd94082bc-16000066400000000000000000000000351414622751200277240ustar00rootroot00000000000000v=spf1 ptr ptr include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1af13087f6bb92df8764a5b00eb5c0561dc8b840-4000066400000000000000000000000301414622751200274420ustar00rootroot00000000000000v=spf1 a: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1b2840abfb70a1fb6b0ca9e8cd79b1d0aab1d7da-5000066400000000000000000000000151414622751200301370ustar00rootroot00000000000000v=spf1 óó‚Â)golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1bc7b6182a4b27c3e44ef85bb4c3f023b5895445-10000066400000000000000000000000421414622751200274470ustar00rootroot00000000000000v=spf1 mx mx mx: a mx mx a a mx mxgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1c9cf133f11bf274dd446ff4245b8f53a8911374-4000066400000000000000000000000161414622751200273220ustar00rootroot00000000000000v=spf1 óó‚�golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1d765a2f64502be5ce3b5af46b730baf5f571c5f-15000066400000000000000000000000641414622751200276750ustar00rootroot00000000000000v=spf1 a:%{I}%{I}%{I}%{I}%{I}%{I}%{I} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1e7da528e7ea94d28e0b06b9ad59d3e5f0176505-13000066400000000000000000000000321414622751200275430ustar00rootroot00000000000000v=spf1 Gía: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1ec151f32d7f2c3dc2a0a080076d58907c5d9936-1000066400000000000000000000000361414622751200273100ustar00rootroot00000000000000v=spf1 ip6:1::1.2.3.4 ip6:::F.golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/1fb9a5465af43f2c57e70ca491cfe4e18b057e03000066400000000000000000000000151414622751200273730ustar00rootroot00000000000000v=spf1 a:%{v}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/201fd81935a2589e34ead502b014bc0f6f7bc997-4000066400000000000000000000000161414622751200273750ustar00rootroot00000000000000v=spf1 ó‚‚ó‚‚ïgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/20f917fc7cf15d12876ee3a7091d886878528861-6000066400000000000000000000000151414622751200271400ustar00rootroot00000000000000v=spf1 mxó‚­)golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/21057897c2a43f23eba4b7a7ec4105fcfe16c000-2000066400000000000000000000000221414622751200274240ustar00rootroot00000000000000v=spf1 ÕóÕïïïïïï4golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/21295637cfffaceb4887c0f9575ae03901b496f2-13000066400000000000000000000000261414622751200274770ustar00rootroot00000000000000v=spf1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2136c0d1947b42b3db810eed459886dd7e2fa578-13000066400000000000000000000000531414622751200274710ustar00rootroot00000000000000v=spf1 a/1107186261862645451 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/21505c4e4d334b454dc5eebce4ebacdf7637e7d0-6000066400000000000000000000000321414622751200277470ustar00rootroot00000000000000v=spf1 a/-1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2257d0500932ac25815c565e3eb907d10fc0b277-6000066400000000000000000000000341414622751200271410ustar00rootroot00000000000000v=spf1 mxó‚­) include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/245dd24e4b3d44f11b3c0558b1e40b37099a854a-4000066400000000000000000000000211414622751200272730ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/246db128b29bc81da0d3e9ec5e5cf8a3ed09a338-1000066400000000000000000000000151414622751200276700ustar00rootroot00000000000000v=spf1 mx/24lgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/25b17e0f6aa9f73463b5a125f94427462931c764000066400000000000000000000000131414622751200267400ustar00rootroot00000000000000v=spf1 ip6:golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/261144f593cb8f1c9efddc3ad230fc5328461f64-2000066400000000000000000000000571414622751200274620ustar00rootroot00000000000000v=spf1 a/0xAAdecEcFRCodeServerFailureEDCfddaFcbgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/26c5e455a3b81a4d3a09b80f4b46ec10896b48e1-5000066400000000000000000000000161414622751200273720ustar00rootroot00000000000000v=spf1 a/1 a/fgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/26ef2aac1d567ca7f26c5ca33f35b7105854cbcd-1000066400000000000000000000000351414622751200276610ustar00rootroot00000000000000v=spf1 a/0xAAdecEcFEDCfddaFcbgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/277313194b11458746bc9563ff021603f86026be-5000066400000000000000000000000521414622751200267400ustar00rootroot00000000000000v=spf1 a/1107186265149230545149230570spf13golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/28ffad3f6a424067d4d18ec1247140b443b4afcd-2000066400000000000000000000000251414622751200275160ustar00rootroot00000000000000v=spf1 redirect=%{ïd}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/29874695932eb1c2f99f7e132ae49b7344217e09-1000066400000000000000000000000441414622751200271270ustar00rootroot00000000000000v=spf1 exists:%{p.should.example.comgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/29e28385d0d3df9278eef7e091f5eef38a77299a-14000066400000000000000000000000421414622751200276060ustar00rootroot00000000000000v=spf1 exists:d6660 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2a18fe68ef661a1fc3be98b97172e74e9921953f-12000066400000000000000000000000541414622751200275160ustar00rootroot00000000000000v=spf1 a:%{I=}%{I=}%{I=}%{I=} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2ab0225495089b6fa60083d05140b5ce80dd1096-8000066400000000000000000000000211414622751200271330ustar00rootroot00000000000000v=spf1 ½½½½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2ad9cbaa3fa9a83192bab623d544ced459390b15-17000066400000000000000000000000521414622751200276660ustar00rootroot00000000000000v=spf1 ip6::: ip6::: ip6::: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2c34d594739876049e7ad50a5b30becd1dee9f6d-5000066400000000000000000000000331414622751200275530ustar00rootroot00000000000000v=spf1 𗞵𗞵𗞵𗞵𗞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2c614e3b2bc205fc21f286208ad90f5852a3a3c0000066400000000000000000000000301414622751200271770ustar00rootroot00000000000000v=spf1 ip6:2001:db8::1/2golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2cb1af576215fede0d684c6b3794579865999d6d-2000066400000000000000000000000161414622751200273610ustar00rootroot00000000000000v=spf1 mx/ a/Cgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2ce45a34e51535f32ece92b6c504e2baafbd6b8f-2000066400000000000000000000000341414622751200277420ustar00rootroot00000000000000v=spf1 a/0_AAdecEcFEDCfddaFcgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2dd167b87fa68dfbbb01dd347eaf5fb26668a6a8-4000066400000000000000000000000331414622751200277660ustar00rootroot00000000000000v=spf1 mx:d1¬1ÞÐEa110~allPegolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2dee827f4fa52b8e782790a06e69e3149c0ac7df-2000066400000000000000000000000121414622751200275510ustar00rootroot00000000000000v=spf1 Õó‚golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2e761908b14b9886eadf46c97bef3443c4f34279000066400000000000000000000000351414622751200272110ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1 redirect=egolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2e92f60a822db191e6a3696047757d19b87b442e-2000066400000000000000000000000521414622751200271710ustar00rootroot00000000000000v=spf1 a/ecEcFEDCfddaFcxAAdecEcFEDCfddaFcbgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2e9e26ae6d47e762073b4ee9631156e9a31fc053-10000066400000000000000000000000341414622751200274030ustar00rootroot00000000000000v=spf1 ip6::: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2f6dea636578de2c87a881fea9375167c07bef69-3000066400000000000000000000000241414622751200275150ustar00rootroot00000000000000v=spf1 redirect=%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2f90dd963ee0a06299d1a626e91c06a1e2ce426a-1000066400000000000000000000000231414622751200274420ustar00rootroot00000000000000v=spf1 exists:%{ir}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/2fa9261819c9517006f54dfec93077a5ffeefc8d-5000066400000000000000000000001051414622751200275650ustar00rootroot00000000000000v=spf1 mx:d1¬1ÞÐEa867361737988403547205962240695953369140625110~allPegolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3033e7b46da95858f3ed9ca0446e84028f94cbb1-14000066400000000000000000000000471414622751200274760ustar00rootroot00000000000000v=spf1 ip6:::/1 ip6:::/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/309a479231ac2f99ab6a3f5f89b9e1f6c915fe3e-9000066400000000000000000000000341414622751200275700ustar00rootroot00000000000000v=spf1 a/107_8107_86564func2golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/30c46fec4d22edd4d1148041840693900926fc98-2000066400000000000000000000000341414622751200271570ustar00rootroot00000000000000v=spf1 a/0xecEcFEDCfddaFcb__golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/316359122b01ab00929f7a7aea0291f66f227598-7000066400000000000000000000000321414622751200270710ustar00rootroot00000000000000v=spf1 a/4 a/4 a/4 a/4 a/1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/31e0d230a07f7ba48c522c9d0f1bff66e37d9c5d-7000066400000000000000000000000531414622751200276140ustar00rootroot00000000000000v=spf1 mx1 mx1 mx/ mx/ mx1 mx1 mx/ mx/ mx//golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/32ae1061275f98e132845ab4973ec066c5652dd3-3000066400000000000000000000000361414622751200271600ustar00rootroot00000000000000v=spf1 mx:d1¤ÞÐEa110~al+-lPe.(golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/334d89acc8738699117dd37ba157f822e0ec2d17-13000066400000000000000000000000311414622751200274120ustar00rootroot00000000000000v=spf1 ía: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/338e1b5e0a09e5f518cfd79791fa93f8017d6b57-10000066400000000000000000000000441414622751200275020ustar00rootroot00000000000000v=spf1 mx:ÞÐQÞÐQïQï)½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/351f1e33b980a8c83d1d7b18a177458fd5a26dfe-14000066400000000000000000000000731414622751200275510ustar00rootroot00000000000000v=spf1 a:%{IR}%{IR}%{IR}%{IR}%{IR}%{IR}%{IR} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/354fe722065c1cd0ab4032ee1048731740d31bcd-24000066400000000000000000000000461414622751200273440ustar00rootroot00000000000000v=spf1 a:%%%%%%%%%%%%%% include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/35e9e0e05acc1088fb73dafbb69ba6cb1594d8ec-1000066400000000000000000000000071414622751200300340ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/35ee7e5ddb6e8ae9a243785b8139e0e73ba636b7-12000066400000000000000000000000601414622751200276360ustar00rootroot00000000000000v=spf1 mx:ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚×ó‚‚½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/36a4254e1961ad0fca4c222636abe6a814bcf850-10000066400000000000000000000001171414622751200275120ustar00rootroot00000000000000v=spf1 𫞵𫶵𫞵𫞵𫞵𫶵𫞵𫞵𫎵𫞵𫞵𫞵𫞵𫎵𫞵𫞵𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/377fa2d8517cb2e0b76535bc38b5d8c47d0d5283-13000066400000000000000000000000351414622751200274640ustar00rootroot00000000000000v=spf1 ip6:::/1 ip4:1.2.3.0/0golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/37c95310204accca732a0e73a4d5adea8c5e5fce-8000066400000000000000000000000231414622751200277340ustar00rootroot00000000000000v=spf1 mx mx a a mxgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/37d1952e25d8fe4fa79a0fe4f50b90087eb75ceb-11000066400000000000000000000000341414622751200277120ustar00rootroot00000000000000v=spf1 a:%%%% include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/382cef3168021f6d496ec419b439a6fbb1b4ce35-7000066400000000000000000000000531414622751200274640ustar00rootroot00000000000000v=spf1 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3898299a8b2a624638b68bb2a84da413fd22a3a7-9000066400000000000000000000001271414622751200273320ustar00rootroot00000000000000v=spf1 mx:�������ï5551115123125782702118158340454101J625¿½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/38f649f7346700239d5522449476b86083d76219-7000066400000000000000000000000321414622751200265550ustar00rootroot00000000000000v=spf1 include:domain ôâgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/392cfa3036a12606981bea810dfa3e3037e1c335-1000066400000000000000000000000351414622751200272660ustar00rootroot00000000000000v=spf1 exists:%{i}%{ser.%{d2}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/39615f91d3139087871dea5423785d06b9b510a7000066400000000000000000000000231414622751200266660ustar00rootroot00000000000000v=spf1 mx:a/montotogolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3a1ac72b5fae00487171fbbf7e8ed23e9cfa2801-4000066400000000000000000000000061414622751200276620ustar00rootroot00000000000000ÅÅÅgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3a98f3c661d7d5f7e4fceb7738b85f493364af5f-1000066400000000000000000000000171414622751200276000ustar00rootroot00000000000000v=spf1 ip4:1:F.golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3acf06a7395f978f44fe56f8b3677aef69eb95c0000066400000000000000000000000161414622751200274440ustar00rootroot00000000000000v=spf1 ip6:CB/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3b32c5fe3ad89b114b25bbed3a5a1f3671946259-14000066400000000000000000000000501414622751200275250ustar00rootroot00000000000000v=spf1 a:%-%-%-%-%-%-%-%- include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3b5dab0aa1953bea3b79dce43b97a9a05b2ad778-19000066400000000000000000000000371414622751200300340ustar00rootroot00000000000000v=spf1 mx:ó‚‚ó‚ó‚ó€ó‚‚ó‚ó‚ó‚ó‚/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3bc13ee064af8ab5dae4d4c06a5daecc5a7c221b000066400000000000000000000000151414622751200277760ustar00rootroot00000000000000v=spf1 a//129golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3c208a50d0fe369bbf2dc88be86a0fb911f9efda-8000066400000000000000000000000331414622751200300420ustar00rootroot00000000000000v=spf1 ó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3c757915c56d6e6261b56366ec4cb21ed2ffea62-5000066400000000000000000000000161414622751200274670ustar00rootroot00000000000000v=spf1 â  golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3d21efa964a356b0cab7875359464aea0dc6ad0f-8000066400000000000000000000000531414622751200276130ustar00rootroot00000000000000v=spf1 𫞵𫶵𫞵𫞵𫎵𫞵𫞵𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3d6ae04fe800272eb51288db6176ce8f46a42bf1-1000066400000000000000000000000201414622751200274430ustar00rootroot00000000000000v=spf1 ptr ptr -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3e704e64145afc057e4f02234b55c772718c161c-4000066400000000000000000000000361414622751200271500ustar00rootroot00000000000000v=spf1 ÕóÕïïïïïïïïïÕóÕïïÕóÕïïgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3ee74f7037ce9790e2162c3ce5e6bafa89dfc65b-5000066400000000000000000000000301414622751200277150ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3f40bd478e8379ac87548da7017d4a4b7d30254f-11000066400000000000000000000000361414622751200274110ustar00rootroot00000000000000v=spf1 mx:%{i}‚ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3f6e987ce012be6005576673865864ec7e99d3a1-6000066400000000000000000000000131414622751200272130ustar00rootroot00000000000000v=spf1 ½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3f82cc6f3d954c07aab89004e03b634d34dbf462-14000066400000000000000000000001131414622751200275270ustar00rootroot00000000000000v=spf1 a/1_7_7_1_7_7_1_4_7_7_1_0_4_7_7_1_1_7_7_1_7_7_1_4_7_7_1_0_4_7_7_1_7_golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/3fdb0915e3ddb50a67a2bbd242fdd8fca9809e4f000066400000000000000000000000401414622751200276700ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ip6:::FFFF:1.golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/40008dcd4553ae76a44b29bca36088ab89c1dee2-13000066400000000000000000000000371414622751200276100ustar00rootroot00000000000000v=spf1 ip6:1::/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/402e4e9ad96ea7d59a4659e12e606f05e305932c-11000066400000000000000000000000341414622751200274060ustar00rootroot00000000000000v=spf1 a/1_7_107_861_7_8107_golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/40c31e4805ee2897df4430511b8287f842a41737-16000066400000000000000000000000471414622751200271130ustar00rootroot00000000000000v=spf1 ip6:::1:b:6:1:b:6 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/41236d8c1423ef106d6854b3f198ec0972ecace3-2000066400000000000000000000001151414622751200273740ustar00rootroot00000000000000v=spf1 ip6:2006:2001:db8:2001:db::1f1 ip6:2001:db8:2001:db::1f1 ip6:2001:db88golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4160602921c7d135ae47b10c4777dce5feb6b4f5-14000066400000000000000000000000501414622751200274470ustar00rootroot00000000000000v=spf1 a:%{p}%{p}%{p}%{p} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4167d538cfc03975c215cfaf40929c93842867b6-4000066400000000000000000000000341414622751200272040ustar00rootroot00000000000000v=spf1 ip6:CAF:CAFE:BE:BABEigolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/421a3ef0790b962fc48296c328c19921791ee25f-3000066400000000000000000000000151414622751200271730ustar00rootroot00000000000000v=spf1 ﻽￯golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/43b520e9d15b1406a66f15cf7049d473669d349f-12000066400000000000000000000000331414622751200272470ustar00rootroot00000000000000v=spf1 aGía: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/43ec78237974dab44efdd20f7fc7e17e0084eec5-3000066400000000000000000000000301414622751200276270ustar00rootroot00000000000000v=spf1 ip6:::1:b:6:1:8:8golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4503e3f4c0c8727025ee51d06e5832243c70a9e7-3000066400000000000000000000000121414622751200271450ustar00rootroot00000000000000v=spf1 ÕóÕgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/45f58a2e37b8c691e40ea6f26408d6f5e6234d6a-7000066400000000000000000000001131414622751200274140ustar00rootroot00000000000000v=spf1 óñ¿ï½ï¿ñ¿ñ¿ï½ï¿óñ¿óñ¿ï½ï¿ñ¿ñ¿ï½ï¿óñ¿ï½ï¿ñ¿ñ¿ï½ï¿ï½ï¿ñ¿ñ¿ï½ï¿ñ¿/½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/461d4557426af8b282e79ce5d6bb25916f98a706-13000066400000000000000000000000341414622751200273460ustar00rootroot00000000000000v=spf1 mxó‚‚‚ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4677a5eff032ececff3c72e905271d34af4a4a1b-7000066400000000000000000000000721414622751200276750ustar00rootroot00000000000000v=spf1 ￯﻽￯﻽﻽￯﻽￯﻽﻽￯﻽﻽￯﻽﻽￯golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/46af4d8af841946ea02faebfadfcf2e282b63e15-10000066400000000000000000000001121414622751200301100ustar00rootroot00000000000000v=spf1 a:%{¿½½½½½½ï1½ï555¿1151231257827021181583€454101%J&25 e½½de:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/46c5b1a9ad5133f42174f2474c4845fa094b0ae9000066400000000000000000000000211414622751200271440ustar00rootroot00000000000000v=spf1 redirect=egolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/46f3c6f8dbf187794e8cad8748192684ced6ebbe-1000066400000000000000000000000171414622751200276630ustar00rootroot00000000000000v=spf1 a:%%%% -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/475e8ffdb31020d60e29cffc34013fe2a2ca5c8f-4000066400000000000000000000000111414622751200276560ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/485b5dfc7b96f912c1b98ddccb9127f167fd997c-11000066400000000000000000000002131414622751200277350ustar00rootroot00000000000000v=spf1 ó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«žµó‚‚‚ó«žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó‚‚‚ó«žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó¿žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó‚‚‚ó«žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó«¿½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/486e98cf7b182565ddd3095d5f57b68ec12d91f6-4000066400000000000000000000000321414622751200274350ustar00rootroot00000000000000v=spf1 ó¿½ï¿/½ï½ï¿)½½½¶€ÿgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4a88aeeef6ee62498731df98ef39a181ca031d7f-1000066400000000000000000000000301414622751200276370ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ip6:.golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4ada9982255464020458f90c31409f083dd3cec4-5000066400000000000000000000000301414622751200271530ustar00rootroot00000000000000v=spf1 include:domain Ågolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4b44d6f2f223de32f6d97221017c72b135b6fc8f-8000066400000000000000000000000341414622751200273770ustar00rootroot00000000000000v=spf1 a/+554551866include:dgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4b4906e4bf471486b1a1ebddfb9bbbd4f375939f-1000066400000000000000000000000231414622751200277030ustar00rootroot00000000000000v=spf1 mx:d1110~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4b9765f8f632dfebc4eeff12147cffd66cf29f1e-4000066400000000000000000000000301414622751200300650ustar00rootroot00000000000000v=spf1 aÊ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4c6d20565dc5823444f3be8860a98d4e58b8fe3d-20000066400000000000000000000000361414622751200275030ustar00rootroot00000000000000v=spf1 a:%%%_%_ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4c754e7f659c7041831fe8af2e6ea197ecb71fee000066400000000000000000000000121414622751200275000ustar00rootroot00000000000000v=spf1 ptrgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4ca27bea96aa9b43cd75e990b3aaf486e184d731-3000066400000000000000000000000211414622751200276160ustar00rootroot00000000000000v=spf1 Õóó‚‚)golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4ca8520bd82b4ac343bb4e1cd7e9950d10b238c7-7000066400000000000000000000000151414622751200275200ustar00rootroot00000000000000v=spf1 ½½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4cc5a579d3fcdf1e05d673591d322edd04ce43c4-10000066400000000000000000000000411414622751200276670ustar00rootroot00000000000000v=spf1 a::/1 a:0/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4d26846d4153063a9af7a8f839b188ff037ef53c-1000066400000000000000000000000311414622751200273350ustar00rootroot00000000000000v=spf1 mx:d6660/1 a:d1111golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4df53e976f13c312ab2ec5721ebe7f42e7c5f314-14000066400000000000000000000000411414622751200276150ustar00rootroot00000000000000v=spf1 ptr:e ptr:4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4e623b674b72c0ccb74be1a22452b492076e305b-14000066400000000000000000000000531414622751200273540ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ip6:4::/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4f62290526f37f0c23a89db6d711726773e0a7b3-4000066400000000000000000000001021414622751200271560ustar00rootroot00000000000000v=spf1 mx:%{78800500929355621337890%%{363797880709171295166015625}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/4ff3cabbe468bac11f8bb34a4bb9e2e98c8efefa-3000066400000000000000000000000271414622751200303420ustar00rootroot00000000000000v=spf1 include:domain golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/50ae7645c456657f3cc80cb4583543de6cad4771-2000066400000000000000000000000101414622751200273200ustar00rootroot00000000000000v=spf1 \golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/50f714a03a1b2d022e689425d03f454d82b30c9f-1000066400000000000000000000000241414622751200272100ustar00rootroot00000000000000v=spf1 redirect=%{d}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/51c669411f5eb38639755018ac9f20f44e912a2c-13000066400000000000000000000000351414622751200272450ustar00rootroot00000000000000v=spf1 a:d6660 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/522509938b7f74a2c32b5ccc319b1bc9506ed08b000066400000000000000000000000241414622751200272270ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1 -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/527ba1667ccfa821072b2398d968f48e514a129c-3000066400000000000000000000000341414622751200272460ustar00rootroot00000000000000v=spf1 óh¿½ï¿/½ï½ï¿)½½½¶€ÿgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/52b82bd1069487c6717cc5d7a643ef643b33efc3-12000066400000000000000000000000341414622751200274650ustar00rootroot00000000000000v=spf1 mx:á¼­ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/52c9f09174d10e2046bd2bc56d08a7cfa1b94c88-2000066400000000000000000000000121414622751200274440ustar00rootroot00000000000000v=spf1 ï¿¿golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/52ccacd4bf39b5336bdd46704462e94181e2757d000066400000000000000000000000151414622751200272400ustar00rootroot00000000000000v=spf1 a//3 -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/53c9798f3a3093cc4829925722019dff356aebbc000066400000000000000000000000331414622751200271750ustar00rootroot00000000000000v=spf1 -include:_spfh.%{d2}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5594ae6ef897d6063f01e0adf41caceff607c7e2-7000066400000000000000000000000341414622751200277130ustar00rootroot00000000000000v=spf1 a/1107J86564func2contgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5637f99d2a8d09e94609bf972de37a1f74b31b9b-5000066400000000000000000000000141414622751200274310ustar00rootroot00000000000000v=spf1 ÕóÕøgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/56628f9e0351e9b115c764ffbe94c19efaeb0389-3000066400000000000000000000000311414622751200275000ustar00rootroot00000000000000v=spf1 redirect=%{l3}%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/56a1bc1c7a3649800dbe3280f23d247155155e51000066400000000000000000000000261414622751200267760ustar00rootroot00000000000000v=spf1 a:ppp-%{p}-ppp golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/56d71aa7952234711b33c3afbccc1207d73eeb14-2000066400000000000000000000000121414622751200274220ustar00rootroot00000000000000v=spf1 ï¼­golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5710e8c342174148ee462f030f4cac29e664c767-2000066400000000000000000000000121414622751200271550ustar00rootroot00000000000000v=spf1 ó‚golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/574189fe1098971730f7f8ba309a172e4325bc2f000066400000000000000000000000161414622751200270330ustar00rootroot00000000000000v=spf1 a:%{o1}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/58a9b1b0abcd5cf81ddd1a0ad4488b363729fb2b-1000066400000000000000000000000541414622751200277400ustar00rootroot00000000000000v=spf1 exists:%{i}%{l82350949848729030}%{d2}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/59093d3787922a8015fb0e8d81df61675c82278e-2000066400000000000000000000000131414622751200271230ustar00rootroot00000000000000v=spf1 mx/+golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/595d366d1274aefa2271820ff4ef2da05cddc6bc-10000066400000000000000000000000551414622751200277500ustar00rootroot00000000000000v=spf1 ½½½½½½½½½½½½½½½½½½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/598f7b8e006d6633a74f959a5466655a27fbd478000066400000000000000000000000221414622751200270570ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5c68ecddd321d7279a3b0e620317935b7d4e8ce1-2000066400000000000000000000000651414622751200274620ustar00rootroot00000000000000v=spf1 ip4:1862645a4B361qZ_usk_cs__68t____gWGu__k_y-golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5ceab670fb0fb39a5c23d2f611f7d217e756f423-9000066400000000000000000000001121414622751200275330ustar00rootroot00000000000000v=spf1 𫞵𫶵𫞵𫞵𫞵𫶵𫞵𫞵𫎵𫞵𫞵ð«žð«Žµð«žµð«žµð«žµð«žµgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5d1cfec0c5dadf382dc141d47562d2ffe79615b8-2000066400000000000000000000000311414622751200276750ustar00rootroot00000000000000v=spf1 ������golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5d7e1ee1c59f39bc3e122815c4944b0e39914898-6000066400000000000000000000000421414622751200272640ustar00rootroot00000000000000v=spf1 ￯﻽￯﻽﻽￯﻽﻽￯golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5ec5c2a5a29cbff4a99457cdc0e178c81b284f73-12000066400000000000000000000000351414622751200277110ustar00rootroot00000000000000v=spf1 mx:ó‚‚‚ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5ed2b1d1a581990d92eb9175ff45e1ffb6f2a2cd-6000066400000000000000000000000341414622751200277050ustar00rootroot00000000000000v=spf1 include:domain 7 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5f5bf6d1cdcce6a626a65df489dfcc07f788bd85-2000066400000000000000000000000131414622751200300640ustar00rootroot00000000000000v=spf1 𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/5fdf397505b4fc0d3761721f15489860dd65b2b6-1000066400000000000000000000000221414622751200272450ustar00rootroot00000000000000v=spf1 exists:%{r}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/60658aaa3f93cd568bdf81690c1c0d3640d124be000066400000000000000000000000231414622751200273030ustar00rootroot00000000000000v=spf1 a:%%%_%_%- -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/60b77bed79cf2f081d781270f6c64500c65f2141-1000066400000000000000000000000221414622751200272310ustar00rootroot00000000000000v=spf1 ip6:e:e:0:$golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/60f915049f6f1a9cc5ac4ef693fa3e9094321cc4-13000066400000000000000000000000311414622751200275440ustar00rootroot00000000000000v=spf1 ptr include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/61c4b104c84b6d8d909e3b0290c6af0c12388bf3-1000066400000000000000000000000221414622751200273560ustar00rootroot00000000000000v=spf1 exists:%{V}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/620a8868eec3a22ace93f372a6337d579f55d866-6000066400000000000000000000000341414622751200273470ustar00rootroot00000000000000v=spf1 a/1107J8656421492contgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/62246f1db31d1d885c74e8060e344ca1759a1545-1000066400000000000000000000000131414622751200271450ustar00rootroot00000000000000v=spf1 a/-1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/62645dad2ddf207c474064e153fd468adf0d7403-7000066400000000000000000000001131414622751200273720ustar00rootroot00000000000000v=spf1 𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵𗞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6273611346aa5c20c3ce44cae49017f9124aa5de-12000066400000000000000000000000341414622751200274310ustar00rootroot00000000000000v=spf1 a/1_7_7_1_4_7_7_1_07_golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/627d548125420021aa6578008ecf12cbfb4115c8-7000066400000000000000000000000311414622751200271320ustar00rootroot00000000000000v=spf1 include:domain ç ²golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/632efcbdcb1acc95d5438c0465d1974675f9529c-15000066400000000000000000000001141414622751200275570ustar00rootroot00000000000000v=spf1 a:%{V}%{V}%{V}%{V}%{V}%{V}%{V}%{V}%{V}%{V}%{V}%{V}%{V} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/63c66382abda05c270d4103e259d7efaf9e77bbb-5000066400000000000000000000000611414622751200276140ustar00rootroot00000000000000v=spf1 ÕóÕïïïïïïïïïÕóÕïïÕÕïïïïïïïïïÕóÕïïÕóÕïóÕïïgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/63d6872579dc76522b1003f2a21320d38d953410-13000066400000000000000000000000261414622751200270040ustar00rootroot00000000000000v=spf1 +include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6432d829ef0ce88b09ab309f0784f4bf23730f9f-4000066400000000000000000000000211414622751200274130ustar00rootroot00000000000000v=spf1 ÕóÕó‚�golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/66db2560a9ac8dac4bf979cb47812b01decf06eb000066400000000000000000000000151414622751200276120ustar00rootroot00000000000000v=spf1 ptr:%}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/66e8dd891c16ec4c27e041b82c3115a92ad5832a000066400000000000000000000000271414622751200272320ustar00rootroot00000000000000v=spf1 mx:d1110/24//129golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/67950ee5ca4bd409b333f587498af2bc6cf6f0a8-5000066400000000000000000000000421414622751200275560ustar00rootroot00000000000000v=spf1 mx:d1110/218626451492305703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/67e6e2e608167be0596021157131b64ad7b91da2-2000066400000000000000000000000331414622751200271450ustar00rootroot00000000000000v=spf1 ip6:1:8:1:b::6:1:8:8golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/67e9e013657986390e1fe563584321c7e062a435-1000066400000000000000000000000221414622751200267520ustar00rootroot00000000000000v=spf1 a/moC”ntotogolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6896ec67b390b407509284648c9aa7c474a04039-8000066400000000000000000000000411414622751200270420ustar00rootroot00000000000000v=spf1 ½ptr: ½ptr: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/689da1b392dfdb3776bb8ffa04f5d731638e92f3-3000066400000000000000000000000251414622751200275610ustar00rootroot00000000000000v=spf1 redirect=%{dr}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6977a2fdabe378064fef5e1fd941faf4d8d4c4b5000066400000000000000000000000311414622751200276360ustar00rootroot00000000000000v=spf1 ip6:2001:db8::68 lgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6980033ab26f3cc54dbfe98d88535bcc707142fd-3000066400000000000000000000000171414622751200274670ustar00rootroot00000000000000v=spf1 mx1 mx/Cgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6a2815028adf404edc3f4b1cc38c1b4de687b80e-7000066400000000000000000000000471414622751200276140ustar00rootroot00000000000000v=spf1 𫞵𫞵𫞵𫞵𫞵𫞵𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6a956db6d33cbf2fcf72a99e692b4c198281aa13-3000066400000000000000000000000361414622751200275510ustar00rootroot00000000000000v=spf1 include:domain ÕÕÕÕgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6a96f7df5daf601f47990aef577392392f4a664a-4000066400000000000000000000000271414622751200274350ustar00rootroot00000000000000v=spf1 redirect=%{d}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6bb4c18efdc2f761e270d1fb94c68de69d3db79b-1000066400000000000000000000000351414622751200277750ustar00rootroot00000000000000v=spf1 pt•uaißr:d6666l-allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6cb70020584efe94d39ec4c86c331b987bced76d-5000066400000000000000000000000241414622751200275570ustar00rootroot00000000000000v=spf1 ó‚‚ó‚‚ó‚‚ó‚‚ïgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6d7bb009e8728bd239a22e5319974b3a5b87614e-1000066400000000000000000000000401414622751200272430ustar00rootroot00000000000000v=spf1 ip6:Cafe:Babe:6:Cafe:B0: golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6d9c90e1d0e3649b67945b2d0406f339540cf98c-12000066400000000000000000000000401414622751200273330ustar00rootroot00000000000000v=spf1 a:%{s}%{s} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6ef264dc7512c4232e16d8db5eb28eb1b0250d4d-16000066400000000000000000000001141414622751200276010ustar00rootroot00000000000000v=spf1 a:%{I}%{I}%{I}%{I}%{I}%{I}%{I}%{I}%{I}%{I}%{I}%{I}%{I} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/6fce1d04d6f69c32320685a4a9c0349fc05c8ebb-2000066400000000000000000000000151414622751200275320ustar00rootroot00000000000000v=spf1 ÿÿ€«¶golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7161abeb77fc6476927a2472ef098aa104c045de-5000066400000000000000000000000201414622751200273720ustar00rootroot00000000000000v=spf1 \\\\\\\\\golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/72640f46c1303246ecca69b3e6866c471f32645b000066400000000000000000000000141414622751200270150ustar00rootroot00000000000000v=spf1 ip4:/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/72dd6c39431c5518730e9d9484962bc778fb2544-22000066400000000000000000000000461414622751200272140ustar00rootroot00000000000000v=spf1 a:%_%_%_%_%_%_%_ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/73463692358cdf893e7cf552b3b2b5e311b85305000066400000000000000000000000211414622751200270230ustar00rootroot00000000000000v=spf1 mx:d1110/2golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/737ebd2b89624cd21e3f0721b456355588f4ece8-12000066400000000000000000000000521414622751200274150ustar00rootroot00000000000000v=spf1 exp=‚ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/739f18ee4881e1138630b0d7ffadc8d041040476-13000066400000000000000000000000341414622751200273200ustar00rootroot00000000000000v=spf1 ip6:94304040/74348449golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/73e1afe5697623bdcfe1211204f7e0fb951a4c32-6000066400000000000000000000000401414622751200274430ustar00rootroot00000000000000v=spf1 redirect=%{l}%{l}%{l}%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/74391ecf9d5baefd2cd7535363ced8e5cafdfb4a-12000066400000000000000000000000401414622751200302650ustar00rootroot00000000000000v=spf1 a:%{V}%{V} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/755e57e00fb8fe9343195c109153983b458c48f1-15000066400000000000000000000000511414622751200272050ustar00rootroot00000000000000v=spf1 ip4:4::/4 ip6:4::/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/756598fcdae09b8a543f39a9dd1aee7468ec07bc-11000066400000000000000000000000321414622751200300010ustar00rootroot00000000000000v=spf1 a:%- include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/75a64f372534aebaf3838c8cab4260113be8fa08-7000066400000000000000000000000471414622751200274560ustar00rootroot00000000000000v=spf1 ptr:½ ptr:½ ptr:½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7652ffe29e111d0db9410539df17d79bc238208c-13000066400000000000000000000001101414622751200273760ustar00rootroot00000000000000v=spf1 a:d1110/32 a:d1110/5 a:d1110/1 a:d1110/1 a:d1110/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/777410981fb83bfc115b9d73658384744ca5b9aa-13000066400000000000000000000000311414622751200273330ustar00rootroot00000000000000v=spf1 a:d6660//1 a:d1111golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/77adc4c141f7dd876302adc5983bbde56337d906-1000066400000000000000000000000211414622751200274610ustar00rootroot00000000000000v=spf1 a:%{o}%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/77bb421687cc142f2f7a00ff7000f32ac2eeeef9-3000066400000000000000000000000421414622751200276030ustar00rootroot00000000000000v=spf1 ���������golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/77cc93fcf61cd9d6662ef18d4ebf9e5b9751781e-2000066400000000000000000000000101414622751200276540ustar00rootroot00000000000000v=spf1 ógolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/794406f33696ace311f39f658bf82d68621203de-5000066400000000000000000000000471414622751200272050ustar00rootroot00000000000000v=spf1 ptr:½ ptr:½ ptra: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7949acda013fef8a8ac8159d6956f06da5498bb8-1000066400000000000000000000000311414622751200275630ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ip6:::golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/79550c23af893e793e1d2781a8fc252f601a5b8e-7000066400000000000000000000000441414622751200273370ustar00rootroot00000000000000v=spf1 include:domain 7 7  golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7a02070902448225aff2b49eadd31e52be253870-4000066400000000000000000000000131414622751200272130ustar00rootroot00000000000000v=spf1 \\\\golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7aa0a78cf5866b022ec350c48ee9ff1f3f2cffb8-6000066400000000000000000000000301414622751200277650ustar00rootroot00000000000000v=spf1 \\\\\\\\\\\\\\\\\golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7b240b945ea1c29125653542c1f293550fd3efea-2000066400000000000000000000000441414622751200273050ustar00rootroot00000000000000v=spf1 exists:%{{82350949848729030-}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7be59d49de0d3d7a60ecd3b1ff47053082cd9dbf-4000066400000000000000000000000311414622751200277600ustar00rootroot00000000000000v=spf1 include:domain â‚golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7bef4f9bf55a5b438de0d3676f7a4a06897999cf-12000066400000000000000000000000431414622751200276640ustar00rootroot00000000000000v=spf1 ip6::: ip6::: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7c47587b4bbec9f37bf2ffd00c146a531e8ece00-2000066400000000000000000000000301414622751200276670ustar00rootroot00000000000000v=spf1 mx:%{i}%{i}%{i} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7cb312d9ce11e08ae0a60571635410ae5469dd4e000066400000000000000000000000111414622751200272110ustar00rootroot00000000000000v=spf1 l golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7d884e5b6f9dc98e899115e691cd826b3cc3a232-4000066400000000000000000000000231414622751200274330ustar00rootroot00000000000000v=spf1 𗞵𗞵𗞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7e265eeca3402d2943bd206b4c6226c1d1ff8c32-3000066400000000000000000000000171414622751200274370ustar00rootroot00000000000000v=spf1 𗞵𗞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7e754abadb7626d1b3776736f275db37751a8229-5000066400000000000000000000001601414622751200272560ustar00rootroot00000000000000v=spf1 �����������������������������������golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7f3742ba9ae6dba0322c0d7a442610680e5ced0f-10000066400000000000000000000000411414622751200275650ustar00rootroot00000000000000v=spf1 mx:ÕÕÕÕ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7f532ba7aff56bd68a6dae1c144764732fda8873-5000066400000000000000000000000221414622751200275500ustar00rootroot00000000000000v=spf1 mx1 mx/ mx/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7f5b9fea2aabe47c7d5fa23f72a3d6f67967c789-1000066400000000000000000000000151414622751200277300ustar00rootroot00000000000000v=spf1 ip6:::golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7f94a20a3d14ae96187abe57face44d86ff654d1-12000066400000000000000000000000541414622751200277120ustar00rootroot00000000000000v=spf1 a:%{I}%{i}%{i}%{i}%{i} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/7faf5ae33da6badb519834e598cdbc10c35f0835-7000066400000000000000000000000511414622751200276770ustar00rootroot00000000000000v=spf1 ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/80381ec0dd66440317fa79bd0ab362ba82719e65-7000066400000000000000000000000441414622751200273150ustar00rootroot00000000000000v=spf1 redirect=%{l}%{l}%{l}%{l}%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/803ef28eca844e4f18371148de536af8d94e182f-2000066400000000000000000000000151414622751200274200ustar00rootroot00000000000000v=spf1 mx:4 agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/808d8bc898a22d6dc2724c9523b59034256fe597-3000066400000000000000000000000151414622751200272040ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/80ac09e7f0993b0086e842b1684a3cf6b7ed2dae-14000066400000000000000000000000311414622751200276200ustar00rootroot00000000000000v=spf1 Ga: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/80d071bba183948fd3cb643b9ac6356a4f78ded1-6000066400000000000000000000000321414622751200275410ustar00rootroot00000000000000v=spf1 mx1 mx1 mx/ mx/ mx/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/81b936e916edaf4f077c21175dedf1c67a281c4d-11000066400000000000000000000000471414622751200276270ustar00rootroot00000000000000v=spf1 mx:ÕÕÕÕÕÕÕ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/828c73a6223be952748d5fdb5246ddc8d1072236-3000066400000000000000000000000741414622751200272510ustar00rootroot00000000000000v=spf1 ip6:2006:2001:8:2001::11 ip6:2001:8:2001::116:2001:88golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/837dce66ca9aaa4d4995ac40d00fe066c2a1c4f8000066400000000000000000000000351414622751200275310ustar00rootroot00000000000000v=spf1 a/exAAdecEcFEDCfddaFcbgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/838423f0949b7ed6bb1656550dbfe62c6ca7f196000066400000000000000000000000171414622751200272600ustar00rootroot00000000000000v=spf1 include:golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/84ad86ae4a2dc2f61c974f4de865f88b42f8eacc-10000066400000000000000000000000441414622751200300620ustar00rootroot00000000000000v=spf1 a:%{I}%{i}%{i} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/859199c9754e10f22cd1e8841ab2a80c75566cf6000066400000000000000000000000371414622751200271230ustar00rootroot00000000000000v=spf1 ptr:ae ptr:ae exp=ae al golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/85c7a4d79af67f0a01b9a00a52be6d4d5279ac55-5000066400000000000000000000000341414622751200275340ustar00rootroot00000000000000v=spf1 redirect=%{l}%{l}%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/85d61d763d07622fbecaea3c97ed3fcb5be2d69f-11000066400000000000000000000001071414622751200301300ustar00rootroot00000000000000v=spf1 a:d1110/1 a:d1110/1 a:d1110/1 a:d1110/1 a:d1110/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/869b75c33d0c2cda002c62bfae7f15ff0e79a88c-2000066400000000000000000000000631414622751200276770ustar00rootroot00000000000000v=spf1 a:noth¿½pf1Iïi¿g/½ïn½ï¿(BADINDEX)½½pf1I½½24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8709b73da7598cd719e92c2ac3033f417b607a56000066400000000000000000000000141414622751200271070ustar00rootroot00000000000000v=spf1 ptr:dgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8720a8ba3df38ed0888e218c974e0e034f762e71-11000066400000000000000000000001111414622751200274070ustar00rootroot00000000000000v=spf1 ½½½½½½½½½½½½½½½½½½½½½½½½½½½½½½½½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/88165e348fbb0dddac43be4d6625224722f87133000066400000000000000000000000171414622751200271570ustar00rootroot00000000000000v=spf1 exists:/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8927772091f444bee910b24247e9ff25c95d58fb-12000066400000000000000000000000341414622751200273500ustar00rootroot00000000000000v=spf1 a:%{p} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/89797fe777479f9c9d65954ac2fd590731fc804c-2000066400000000000000000000000631414622751200273260ustar00rootroot00000000000000v=spf1 m11102230246251565404236316680908203125x/24lgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8a2bcea52de4fad8ffd0827e4a2dc12a44de4926-1000066400000000000000000000000541414622751200300270ustar00rootroot00000000000000v=spf1 a/-110723edb1862645149230ÿ57031258::6golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8a2ed564fcca3c565439075767ff8684ac49ac8a-4000066400000000000000000000000231414622751200275050ustar00rootroot00000000000000v=spf1 𫞵𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8aa2ae9ccfc3c3920a4333084aa3c3b92e80b087-3000066400000000000000000000000221414622751200275070ustar00rootroot00000000000000v=spf1 ÕóÕó‚‚�golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8ac59d1ab0b3a5fac14b352f92584f4dea4a9b2e-19000066400000000000000000000000331414622751200300270ustar00rootroot00000000000000v=spf1 V= V= include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8b29df6acaf2fcc4f29d3b709f85c3cb17717867000066400000000000000000000000141414622751200275000ustar00rootroot00000000000000v=spf1 a/4 -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8b2bb8cd4f6eb4a879d359d84345308003e3362b-14000066400000000000000000000000641414622751200274100ustar00rootroot00000000000000v=spf1 a:%{V}%{V}%{V}%{V}%{V}%{V}%{V} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8bde59e5dcbea61da549b56ab78536f314eaf270-4000066400000000000000000000000361414622751200277070ustar00rootroot00000000000000v=spf1 a/110718626451492305703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8c190342c9ce178aa2030cfe9000a63e58005f3a-7000066400000000000000000000000201414622751200272660ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8c40888b73dd06e8f4d972b5e3542226b966e6fe-1000066400000000000000000000000221414622751200273460ustar00rootroot00000000000000v=spf1 /ÕBó‚`!44golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8c4f9dfe76423ff4683bdd5058779d9101f24b79-15000066400000000000000000000000431414622751200274430ustar00rootroot00000000000000v=spf1 ip6:::1.2.3.4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8ca3a2b7da51ce13aca07b6bc6a587c4efed0d53-15000066400000000000000000000000431414622751200301540ustar00rootroot00000000000000v=spf1 mx:ó‚ó‚ó‚ó‚z½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8cd0357fbfa90ec0e69c17b10c374a1223924d17-12000066400000000000000000000000111414622751200274340ustar00rootroot00000000000000v=spf1  golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8cd9b00e5b14dcc74e3e389691552b26b35e590c-5000066400000000000000000000000211414622751200274010ustar00rootroot00000000000000v=spf1 ÕÕÕÕÕgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8cebd1fdd0164acca4c62330f79f3c02d9a60763-2000066400000000000000000000000231414622751200275760ustar00rootroot00000000000000v=spf1 ip6:1::1.3:/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8cff895127532675e2b4105f5c65be8de5be6306-4000066400000000000000000000000421414622751200273360ustar00rootroot00000000000000v=spf1 óh¿½ñ¿/½ï½ï¿)½½½¶€¿½ñ¿/½ÿgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8d029147e2084816fb319802ea77b01efd391b54-13000066400000000000000000000000531414622751200272400ustar00rootroot00000000000000v=spf1 a/1_7_7_1_7_7_1_4_7_7_1_0_4_7_7_1_7_golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8d6aece1b5f58b476ce948504782e0b1d4a90149-6000066400000000000000000000000501414622751200274120ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8e053980cb3e6f47e74cc8f2bdeae555e8fea559-3000066400000000000000000000000471414622751200277340ustar00rootroot00000000000000v=spf1 redirect=%{d4027755927159263581}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8e59eb0d01a975d66f10113cdbaa95304313e420-12000066400000000000000000000000421414622751200273460ustar00rootroot00000000000000v=spf1 a:%{IR}%{IR} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8e6cb36297f26f8fa23daa259eb12b61ab100fec-1000066400000000000000000000000101414622751200276520ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8ea434243522f18f9835c93d8593cf5a8be51521-4000066400000000000000000000000131414622751200271730ustar00rootroot00000000000000v=spf1  âgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/8ef23048dcf25f403e61a34d72a6c327d2927fe4-3000066400000000000000000000000151414622751200273760ustar00rootroot00000000000000v=spf1 â‚‚â‚‚golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/906833637b8b72be70013f4922eff2836bbece00-9000066400000000000000000000000311414622751200273170ustar00rootroot00000000000000v=spf1 ½½½½½½½½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9164a7c22279e6b8ff72aea10563c56aa2b13f88000066400000000000000000000000251414622751200272370ustar00rootroot00000000000000v=spf1 ip6:::1.1.1.1/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/91c2784bafbbc998e0bd22a4285540852ad966ed000066400000000000000000000000171414622751200273270ustar00rootroot00000000000000v=spf1 a:%{h} +golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/92180f784e583d9201c52bcd251686c1ce420493-13000066400000000000000000000000341414622751200271600ustar00rootroot00000000000000v=spf1 mx:ï¼­ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/923156e1b572d3a1a88c85b6f4e0001658257dbe-1000066400000000000000000000000121414622751200272240ustar00rootroot00000000000000v=spf1 á¼­golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9362b24013a5f29755c8140c47724dce20d8aa92000066400000000000000000000000141414622751200270040ustar00rootroot00000000000000v=spf1 ptr -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/93830b163ebb827cf93a17d1ef59613eb8f240b1-6000066400000000000000000000000141414622751200273760ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/94820540f7b8dd7d056c7872b24464bc28e22f90-6000066400000000000000000000000311414622751200271710ustar00rootroot00000000000000v=spf1 ÕÕÕÕÕÕÕÕÕgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9625cf271d4bea92494cc6c08d37605675fdf9fd-1000066400000000000000000000000241414622751200275030ustar00rootroot00000000000000v=spf1 mx:%{i}%{i} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9651d650fafafaef76745a776a998bb96241b8fa-1000066400000000000000000000000151414622751200275650ustar00rootroot00000000000000v=spf1 a: mx:golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/97c03960e91dde1ab193ea2d82ff742fcc3ddbad-1000066400000000000000000000000211414622751200300250ustar00rootroot00000000000000v=spf1 ip6:::1../golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/97d3dd37d1f19b7bd31b1eac4a6257dba655c41c-1000066400000000000000000000000561414622751200276660ustar00rootroot00000000000000v=spf1 mx/355271367880050092935562133789062533golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/97d69f2939425aec568d67ad8617d134cd9d2965000066400000000000000000000000201414622751200271400ustar00rootroot00000000000000v=spf1 mx:%{fff}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/98cc679b25e4a323f7023b3e53fbf770030528c5-4000066400000000000000000000000341414622751200272370ustar00rootroot00000000000000v=spf1 ip6:1:b:6:1:b:6:1:8:8golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/98cd39213ce1336e8bcba3b49ecd1cfc7e4a1d16-5000066400000000000000000000000271414622751200277540ustar00rootroot00000000000000v=spf1 a/-1 a/-4 a a/-1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9a34fb50762330df190864d0ddb25e15e042e662-4000066400000000000000000000000201414622751200272170ustar00rootroot00000000000000v=spf1 ￯﻽￯golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9a9d5cb818c6f69cf9df6da156aa00e3eac1da59-6000066400000000000000000000000271414622751200300530ustar00rootroot00000000000000v=spf1 ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚ógolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9aaf904c7427b850ea7a57316cf41c4e5d34a1a5-12000066400000000000000000000000321414622751200275240ustar00rootroot00000000000000v=spf1 Òmx: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9abcdf6390b0613fff3e3decb747d6e93a89a36a000066400000000000000000000000361414622751200276320ustar00rootroot00000000000000v=spf1 mx mx a mx a mx a ptr agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9b858a7cba052affb1e7682e9f3b49292abe736b-10000066400000000000000000000001171414622751200277120ustar00rootroot00000000000000v=spf1 ó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó‚‚‚ó«žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó«¿½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9c8c99cb61c1c4d741328197f647ed8aab6a4c1c-1000066400000000000000000000000121414622751200275420ustar00rootroot00000000000000v=spf1 a/-golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9cf1b9b09464e4499ed3dcb2d9140f85bc1a9ca1-13000066400000000000000000000000401414622751200277010ustar00rootroot00000000000000v=spf1 a:%{p}%{p} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9d12f3efb61be364e1606de5b629553a60985713-1000066400000000000000000000000261414622751200272440ustar00rootroot00000000000000v=spf1 p6:2001:db8::68golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9e319cac94086116535095207d04b5c224e59526-15000066400000000000000000000000421414622751200270210ustar00rootroot00000000000000v=spf1 a:d6660//128 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9f4f35b562b1335d5226eb15f579b40f78902b08000066400000000000000000000000141414622751200270230ustar00rootroot00000000000000v=spf1 0a: -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/9f971c708dcddd95fad64e2cce4b5a3beff74e55-16000066400000000000000000000000401414622751200302230ustar00rootroot00000000000000v=spf1 ip6:1::1/6 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a1c703c19dcb0dd1393a1aa550dab9d22064411a-13000066400000000000000000000000501414622751200275370ustar00rootroot00000000000000v=spf1 a:%{V}%{V}%{V}%{V} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a1c93210c3cd9aa445842cbb7c8b8db89700eb5c-8000066400000000000000000000001521414622751200276110ustar00rootroot00000000000000v=spf1 ￯﻽￯﻽￯﻽￯﻽﻽﻽￯﻽﻽￯﻽﻽￯﻽﻽﻽￯﻽﻽￯﻽﻽￯﻽﻽￯golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a3ca5b314a00a0468e38b3f02e5d5324f7b2df22-5000066400000000000000000000000261414622751200274220ustar00rootroot00000000000000v=spf1 ￯﻽￯﻽￯golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a3dc3b202c007a96d2a9392d3088e35d3b6656ab-7000066400000000000000000000000501414622751200273610ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a3ed7c1bdbf2a23bca4ce8320d99d56c39d5ceb9000066400000000000000000000000221414622751200277460ustar00rootroot00000000000000v=spf1 mx:d6660/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a4501217ce3dd66c7722843d546ac04d8157d655-5000066400000000000000000000000431414622751200271560ustar00rootroot00000000000000v=spf1 ip6:CF:CAFE:BAF:CAFE:BEBABEigolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a4f0f97a227003aa1442f010c1ab4b11b75eb8a2-4000066400000000000000000000000721414622751200274020ustar00rootroot00000000000000v=spf1 �����������������golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a5555f3e52f2a50dc83da59781278cab8af8f43a-1000066400000000000000000000000161414622751200275430ustar00rootroot00000000000000v=spf1 ip6:1.1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a55848179e2ef78c5d48df2b55174fd2c94216f3-5000066400000000000000000000000231414622751200273470ustar00rootroot00000000000000v=spf1 ÕóÕóø‘‚Õgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a66793d056da563f93a724bffffb4046343be07a-14000066400000000000000000000000531414622751200275440ustar00rootroot00000000000000v=spf1 a/+107186261862645451 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a7446b3e3a4aed6193665967f0857bc9a62a3715-3000066400000000000000000000000321414622751200272500ustar00rootroot00000000000000v=spf1 exists:%{645149230}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a80eeb54e51f5a7ff6bbfa7ecaf41690555c8779-1000066400000000000000000000000231414622751200277140ustar00rootroot00000000000000v=spf1 mx:d1110/4 ~golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a8865f15dc42b146da6aad2fc9f74eae1dd255fd-19000066400000000000000000000000551414622751200301300ustar00rootroot00000000000000v=spf1 ptr ptr ptr ptr ptr ptr include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a911eff5c6cd79e98ead8dfabd2d4e6f468e6837-2000066400000000000000000000000541414622751200301020ustar00rootroot00000000000000v=spf1 ip6:eff:ffff:ffff:ffff:ffff:ffff:ffffgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a93f5beaa58d9a1a6524ef74a724d1af206a3bfa000066400000000000000000000000201414622751200275730ustar00rootroot00000000000000v=spf1 include:/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a9895ef31ad26725518daeeaf172dd8434b7b926000066400000000000000000000001011414622751200273260ustar00rootroot00000000000000v=spf1 exists:%{p}.should.example.com exists:%{p}.ok.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a9949b17b74723c2633356fd6ea8e58c0988cf39-16000066400000000000000000000000511414622751200273620ustar00rootroot00000000000000v=spf1 mx:ó‚ó‚ó‚ó‚ó‚ó‚ó‚z½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a9cc0118e3aaec859d8ebc0230521844f4a9e941000066400000000000000000000000121414622751200273040ustar00rootroot00000000000000v=spf1 a/2golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a9ec7cbe37eef444da71026fb51aed63343beae8-5000066400000000000000000000000601414622751200300330ustar00rootroot00000000000000v=spf1 a/1107186564214923 a/11071865642149205703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/a9f36515a6f362c384c12c7633f7d940204833a7000066400000000000000000000000241414622751200267370ustar00rootroot00000000000000v=spf1 mx:d6660//100golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/aa24926aa5504d84c2bc24ccbdce190657dc542d-6000066400000000000000000000000331414622751200275750ustar00rootroot00000000000000v=spf1 𫞵𫞵𫞵𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/aa540d18eefc008c3114d2b93278edc1be1ff1f3-1000066400000000000000000000000571414622751200276560ustar00rootroot00000000000000v=spf1 ip6:2001:db8:2001:db::1f1 ip6:2001:db8:8golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/aa6c9169f459f167c749030c9d1987afd3d6cd74-12000066400000000000000000000000501414622751200275070ustar00rootroot00000000000000v=spf1 ip6:::1 ip6:e::0/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/aaed2222466dce9a6d3426ccd625cc9dec66b753-7000066400000000000000000000000501414622751200276770ustar00rootroot00000000000000v=spf1 mx:����� include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ab1143a7650029d54d16c3086123cf8c62ae0e03-14000066400000000000000000000000771414622751200272730ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ip6:::/4 ip4:1.2.3.4 ip6:::/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ab4ae974caed9ac3dd1fdd26aeccd792b8a8eef3000066400000000000000000000000241414622751200302600ustar00rootroot00000000000000v=spf1 mx:d1110/24 ~golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ac6f486856003dabf941a7b559667829730f4b85000066400000000000000000000000151414622751200270440ustar00rootroot00000000000000v=spf1 ip6::/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/acca12db014f6aea3028a84f6c5866f647b2d4cc000066400000000000000000000000221414622751200275150ustar00rootroot00000000000000v=spf1 redirect=%}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/accc8bc507abbfb1ec387e67d264bd2663eebfb7000066400000000000000000000000141414622751200300310ustar00rootroot00000000000000v=spf1 -a: +golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/acd182846170dcef1c7546d4ab6a98490796f113-2000066400000000000000000000000301414622751200273210ustar00rootroot00000000000000v=spf1 ip6:1::1 ip6:1::8golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ad152c49557a64647f046f959dcc68bf93658dc3000066400000000000000000000000311414622751200272110ustar00rootroot00000000000000v=spf1 ip6:Cafe:Babe:0:: golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/adee88e332493162e4c544440c41ab05fc55caba-8000066400000000000000000000000411414622751200275170ustar00rootroot00000000000000v=spf1 include:domain    golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ae8ea51dda8860b90e3f7caae055efc79af00d1d-2000066400000000000000000000000231414622751200301040ustar00rootroot00000000000000v=spf1 mx:%{{ÿi} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/af313e5429328f99a3e14fe6ed7d2d7171b4f8b0-1000066400000000000000000000000171414622751200274660ustar00rootroot00000000000000v=spf1 mx:0/4 agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/af836fcd042d6927a687fc3d9a840d970d920696-8000066400000000000000000000001111414622751200273500ustar00rootroot00000000000000v=spf1 ÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕÕgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b00876a702c3af1b72c5b0b4220f0aff86419453-7000066400000000000000000000000321414622751200272670ustar00rootroot00000000000000v=spf1 a/+1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b01623ff6afbb38f9413d06ea47dfe8c11ee7829-6000066400000000000000000000000671414622751200276350ustar00rootroot00000000000000v=spf1 óhñ¿/ï½ï¿)ñ¿/ñ¿/ï½ï¿)óhñ¿/ï½ï¿)ñ¿/ñ¿/ï½ï¿)ñ¿/½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b0e49cd5a0eea69e8e80d9e712acbd263cbf0568-13000066400000000000000000000000451414622751200300430ustar00rootroot00000000000000v=spf1 ip6:::1 ip6:::0 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b0f5dc28d923c125a2f3eb76f7502201ace60e7c-12000066400000000000000000000000331414622751200275730ustar00rootroot00000000000000v=spf1 mx//1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b0fa0056db33c9338bd4dc90a73c48c4553d9894-5000066400000000000000000000000331414622751200274010ustar00rootroot00000000000000v=spf1 include:domain  golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b100873d47c1870d8711f29c28431fea30c4ec4c-1000066400000000000000000000000251414622751200273010ustar00rootroot00000000000000v=spf1 ip6:2001:29538golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b145fe0a881625a35bab0b433476a0c021165c61-1000066400000000000000000000000171414622751200271710ustar00rootroot00000000000000v=spf1 a:%%%%%%golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b15a623eeb971a4e7734a44a7e8ed23e87963af4-1000066400000000000000000000000201414622751200274620ustar00rootroot00000000000000v=spf1 aaoaeaeamgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b17aa7e8ad6c575f52c22192fc3fd1eec24e997c-16000066400000000000000000000000471414622751200277760ustar00rootroot00000000000000v=spf1 ip6:1::1 ip6:1::b include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b1f947edcc1ef0f288fd926baf4a95e8b9d97775-5000066400000000000000000000000111414622751200277370ustar00rootroot00000000000000v=spf1 ½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b2c7175d14c4ab51e25dae9ce2d45bbcfde9c0aa-9000066400000000000000000000000561414622751200301640ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b2ce5c9c42e721bded3c31f0438bf9d366636ece-2000066400000000000000000000000251414622751200276760ustar00rootroot00000000000000v=spf1 redirect=%{da}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b2d7f31602f04aa2ab5287fd1a47262719c8b66e000066400000000000000000000000271414622751200272260ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4/32 -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b307e1380f2f39d76abefed30d6272c44624f8b7-4000066400000000000000000000000311414622751200274570ustar00rootroot00000000000000v=spf1 exp= redirect=%{D}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b36467ce1bf29b7c3258c6e0ea1987c5e0989ac4-13000066400000000000000000000000411414622751200275550ustar00rootroot00000000000000v=spf1 mx:d6660//1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b488275d23ef85adb645e037d8f7524ac51b3e5f000066400000000000000000000000341414622751200273310ustar00rootroot00000000000000v=spf1 redirect=doesnotexistgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b5a98679ef576a7410544e1e367ecd869cbc56ee-7000066400000000000000000000000331414622751200275200ustar00rootroot00000000000000v=spf1 ½ptr: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b6507f7406c96d99dd64e849129d39069c85f9a9-11000066400000000000000000000000501414622751200273140ustar00rootroot00000000000000v=spf1 a:%{I}%{i}%{i}%{i} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b6f608755614309cd073ff4b9ff12ffdddbc7aef-10000066400000000000000000000000461414622751200300540ustar00rootroot00000000000000v=spf1 mx:ó‚‚ó‚‚ó‚‚ó‚‚5 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b70ea87f1e3a7a71c74c0d1c9a82752b4046c658-8000066400000000000000000000000411414622751200273760ustar00rootroot00000000000000v=spf1 a/4 a/4 a/4 a/4 a/4 a/ a/1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b817cf09acdda44e8d910c19dd59a705ea223067-14000066400000000000000000000000261414622751200276150ustar00rootroot00000000000000v=spf1 a:d6666 a:d1111golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b8855d0c786eba4683fbf8cde3459b8a9101d2ea-8000066400000000000000000000000341414622751200276370ustar00rootroot00000000000000v=spf1 a/1107_86564func2contgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/b8d0e747da40b2501b1c2c39ed3bcd1e9c7c46d8-1000066400000000000000000000000201414622751200276530ustar00rootroot00000000000000v=spf1 redirect=golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ba4579a4b3ecf61155909dd7f561849c58cdc1b8-1000066400000000000000000000000261414622751200274760ustar00rootroot00000000000000v=spf1 mx:d1110/24~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/bc54f7f235fbe4eb55a7066dfe301b396bc1c634000066400000000000000000000000151414622751200274510ustar00rootroot00000000000000v=spf1 mx -algolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/bd34c53e2b4b044ca65993b5b21b5c1ab97e7a18-2000066400000000000000000000000131414622751200275130ustar00rootroot00000000000000v=spf1 ð—žµgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/bd74e6de533aa3f9d3a9ff0694639bac7cef1a02-3000066400000000000000000000000311414622751200277560ustar00rootroot00000000000000v=spf1 redirect=%{daAFAE}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/be6fc50d936510262252e2706edcacff891fe185-7000066400000000000000000000000361414622751200274670ustar00rootroot00000000000000v=spf1 include:domain   golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/bf8b39b3f7dc8b62718454e41a18b3fdf166b52a-14000066400000000000000000000000641414622751200276270ustar00rootroot00000000000000v=spf1 a:%{s}%{s}%{S}%{s}%{s}%{S}%{s} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c01b6f2672804a8b6abc85afa130f4db06ea1cb6-1000066400000000000000000000000301414622751200276350ustar00rootroot00000000000000v=spf1 include:domain ~agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c0eb81476da375b12c3dc6199325f6728fca8c25-6000066400000000000000000000000221414622751200274020ustar00rootroot00000000000000v=spf1 a/4 a/4 a/1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c1063b885395233902ccc891ececb6af2f1fb279-4000066400000000000000000000000251414622751200274620ustar00rootroot00000000000000v=spf1 ÕóÕóø‘‚Õógolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c1210ffd398a720b89fa9b2fd7d071c759848ccc-13000066400000000000000000000000501414622751200276310ustar00rootroot00000000000000v=spf1 a:%{I}%{I}%{I}%{I} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c19da7619ae805156926cde722e4753648e555b4-1000066400000000000000000000000211414622751200271720ustar00rootroot00000000000000v=spf1 ip6:e::0::golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c226841652a967c26fa9f1ca08bf90ea9df9bc4b000066400000000000000000000000211414622751200274620ustar00rootroot00000000000000v=spf1 a/-110723egolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c2672e5a51b373fa65f8edf478576d4cdbe5a09b-1000066400000000000000000000000251414622751200276310ustar00rootroot00000000000000v=spf1 ip6:CAFE:BABEEgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c34e8478439a802cd4aa682a54b865382a6e6b04-1000066400000000000000000000000121414622751200272340ustar00rootroot00000000000000v=spf1 mgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c37b8935a53aa115c6ba7677fbf413b039c635c8-3000066400000000000000000000000261414622751200273760ustar00rootroot00000000000000v=spf1 ÕóÕïïïïïïÕóÕïïgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c4b1bacbc00d582954dc53e6f6284236bf9fc64e000066400000000000000000000000271414622751200274600ustar00rootroot00000000000000v=spf1 include:domain ~golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c4d74e144b5811566925a3b84809485f5e6b5571-2000066400000000000000000000000471414622751200270430ustar00rootroot00000000000000v=spf1 a/-11071862645149230ÿ57031258::6golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c4f22db76ae464b5239fb7761091382756c3f3b6000066400000000000000000000000131414622751200271030ustar00rootroot00000000000000v=spf1 a:%}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c56287852954cfe96a89b3482b7afbb7a3a50f71-3000066400000000000000000000000221414622751200274160ustar00rootroot00000000000000v=spf1 Õóêïïïïïï4golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c566a989b153b7baf61decdf8580937596bef959-11000066400000000000000000000000421414622751200276030ustar00rootroot00000000000000v=spf1 mx:ÓØÐÞÐïï)½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c58d87a54c389bab92d1f4a209adc75523fc7574-2000066400000000000000000000000341414622751200274700ustar00rootroot00000000000000v=spf1 exists:%{i645149230r}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c642abd702594b1bef94016873d29be7c3426428000066400000000000000000000000161414622751200271000ustar00rootroot00000000000000v=spf1 ptr:aalgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c6e2ae81a2d096b2e9faf154beb78f8aaf715cff000066400000000000000000000000171414622751200277650ustar00rootroot00000000000000v=spf1 ip4:1.3 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c891ebdca240564cd6be85db7ec4f2419cca1560-1000066400000000000000000000000171414622751200276670ustar00rootroot00000000000000v=spf1 ip6:::E golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c8d66f4be86f0a428754e8150fae408f21421bb8-13000066400000000000000000000000501414622751200274610ustar00rootroot00000000000000v=spf1 a:%{s}%{s}%{s}%{s} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c8f75ab19304bff1037246dfbafe8e5903bb90cc-2000066400000000000000000000000271414622751200276740ustar00rootroot00000000000000v=spf1 mx:%{{{Šžõ¨ji} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c960d3112bff1a12d9bfe4f7e6ea1dd8c114e7d6000066400000000000000000000000321414622751200276060ustar00rootroot00000000000000v=spf1 redirect= redirect=golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c989438a20e09ca08d8d0a8bc3f3ff6e788aec7b-12000066400000000000000000000000441414622751200300000ustar00rootroot00000000000000v=spf1 a:%{I}%{I}%{I} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/c9fd32fb5a9d5c888423d58bcd6796c1b79c4933-8000066400000000000000000000000371414622751200275250ustar00rootroot00000000000000v=spf1 a:d1110/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ca425f5a4795eda3ba095d08f2fed2b9b56e294d000066400000000000000000000000261414622751200275440ustar00rootroot00000000000000v=spf1 a:ooo-%{o}-ooo golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cb2c25e688500463cbd57cccaf4651bd985b411e-14000066400000000000000000000000361414622751200276140ustar00rootroot00000000000000v=spf1 ip6:1::1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cb9c9d95ff6e8ad02f6dfa35614c56ee3ef8e70b000066400000000000000000000000231414622751200277220ustar00rootroot00000000000000v=spf1 exists:d1111golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cbd464ac586e17e09c93883119fae5001195bccf-9000066400000000000000000000000531414622751200274700ustar00rootroot00000000000000v=spf1 ó‚‚‚ó‚‚‚ó«žµó‚‚‚ó‚‚‚ó«žµó‚‚‚ó«¿½ó«¿½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cc183fa6e5f3eb5fa47e5b5207fe9a25cf68bcd6-5000066400000000000000000000000161414622751200300520ustar00rootroot00000000000000v=spf1 a/4 a/1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cc6bc932909f1589479e1129791402e99ffe2b98-11000066400000000000000000000000421414622751200273020ustar00rootroot00000000000000v=spf1 a:%{I=}%{I=} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cc9dc2f9d4124f385fb9589c57d26388ac1d584e-11000066400000000000000000000000341414622751200275730ustar00rootroot00000000000000v=spf1 a:%{s} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ccf0020a2b2da0b9440b8d6c98aac522f04e3f96-13000066400000000000000000000000551414622751200276520ustar00rootroot00000000000000v=spf1 mx:ó‚‚‚ó‚‚‚ó‚‚‚ó‚‚‚ó‚‚½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cd8b93cd61b30a1f045173bce142d6861bef88a2-5000066400000000000000000000000301414622751200275200ustar00rootroot00000000000000v=spf1 ptr:½ ptr:½ ptr6golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cdd335e7f0ca5359d324600ff443c5c8b2ad6b31-10000066400000000000000000000000631414622751200276000ustar00rootroot00000000000000v=spf1 a:d1110/1 a:d1110/1 a:d1110/1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cdd60476f4ef91a97ff0161196731409d8dc4187-15000066400000000000000000000000571414622751200273510ustar00rootroot00000000000000v=spf1 a:%{i0490116119384765625} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ce2c5d5257e32149064eb16f95ca854373d7bae3-12000066400000000000000000000000341414622751200274610ustar00rootroot00000000000000v=spf1 a:%-%- include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ce47ddf5b00c777dbf2214a2d8ac4579127464d0000066400000000000000000000000361414622751200273130ustar00rootroot00000000000000v=spf1 include:ipexamplecomallgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ce5296fce5bbc097e72fea0331519a92290a56be-13000066400000000000000000000000301414622751200276130ustar00rootroot00000000000000v=spf1 MX include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ce5b33baf137d522804df44ba49054ed0c99d86e000066400000000000000000000000311414622751200273730ustar00rootroot00000000000000v=spf1 ip6:CAFE:BABE:0:: golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ce91e7bf355c66eb7b54bd9eec6f9c3e1128abfa000066400000000000000000000000461414622751200277740ustar00rootroot00000000000000v=spf1 exists:%{l2r-}%{d2}%{l2r-}%{d2}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/cee815b2b87629959c5aaf8d9529de4302365eaf-11000066400000000000000000000000351414622751200275650ustar00rootroot00000000000000v=spf1 a:%{IR} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ceeaed584be8a2f84755b388bc2eca9d91e301dd-2000066400000000000000000000000151414622751200300440ustar00rootroot00000000000000v=spf1 mx:/ agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d010cd01f60d366a490939ba7e734ee0205bbf95-5000066400000000000000000000000311414622751200273600ustar00rootroot00000000000000v=spf1 aÊ1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d127e98987abe4687f4aac11b2405cf2028d9d7b-6000066400000000000000000000000501414622751200274670ustar00rootroot00000000000000v=spf1 exp= exp= exp= exp= redirect=%{D}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d1567d96b1c0e32073b56c363eb83d854bc2742f-12000066400000000000000000000000441414622751200273760ustar00rootroot00000000000000v=spf1 a/110718626451 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d1f256c13fc6d25a1ce60bee676bdc6dbf370b17-14000066400000000000000000000000541414622751200300270ustar00rootroot00000000000000v=spf1 a:%{I}%{I}%{I}%{I}%{I} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d3e99d5a3f89a6fec79bb8209d9584d55b99b650-6000066400000000000000000000000211414622751200275260ustar00rootroot00000000000000v=spf1  â  golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d48d9dfb5381fd1acaec2c9e7900a3fd86742674-3000066400000000000000000000000141414622751200276310ustar00rootroot00000000000000v=spf1 a a agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d4dc7ea8bce557418650da7fdc34e3f03877bdb9-3000066400000000000000000000000131414622751200277100ustar00rootroot00000000000000v=spf1 ÕÅgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d4f0fe1f081eee99d09ec18d0320e49421d796be-2000066400000000000000000000000241414622751200275450ustar00rootroot00000000000000v=spf1 redirect=%{h}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d5032b820a2b0b9e853b55878217fa9d262a314f-13000066400000000000000000000000401414622751200273030ustar00rootroot00000000000000v=spf1 a:%-%-%-%- include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d50ae4884ceef9773629d9dda6a742e631fd4b04-1000066400000000000000000000000131414622751200275510ustar00rootroot00000000000000v=spf1 ptr:golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d72da001152934c26ffdc5f09b8e6930a6029bf2000066400000000000000000000000261414622751200272270ustar00rootroot00000000000000v=spf1 a a a a a a a golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d7367455b7cc6e9d9e0a32d7e6ebf28c6c88aeae-6000066400000000000000000000000221414622751200300050ustar00rootroot00000000000000v=spf1 mx mx/ a mxgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d77c09dca3ad4265127e3cb9ab223a51af746e2f-3000066400000000000000000000000251414622751200276010ustar00rootroot00000000000000v=spf1 ip6:CAFE:BABEigolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d781c18c85da9ab3b4775e4db674a590ac73ef36-5000066400000000000000000000000261414622751200275550ustar00rootroot00000000000000v=spf1 mx mx/ a mx/ a/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d7f48fadee3af3b910ccc8cf04657a445cd4c9f4-3000066400000000000000000000000101414622751200300400ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d8c678392de65db470dae4b9f613ec42415ff864-5000066400000000000000000000000231414622751200275020ustar00rootroot00000000000000v=spf1 ó‚‚‚ó‚‚‚ó‚‚ïgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/d94e5b5d8b5854e3caba0444add40baaaba86996-1000066400000000000000000000000521414622751200277460ustar00rootroot00000000000000v=spf1 a:nothing/����pf1I��24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/da33d09eda59c78659696af049567c7ef68fb02f-8000066400000000000000000000000301414622751200275210ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/da39a3ee5e6b4b0d3255bfef95601890afd80709000066400000000000000000000000001414622751200273730ustar00rootroot00000000000000golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dae9a77a60e1491680c1d805118ac3751112909f-3000066400000000000000000000000271414622751200271500ustar00rootroot00000000000000v=spf1 a:¿½ï¿/½ï½ï¿)½½½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dbd0db742720740c10282518e4577cec3998e5cc-5000066400000000000000000000000201414622751200273140ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dbf895f600893e37727da6399b4285606db5f526-12000066400000000000000000000000441414622751200272750ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4/31 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dc0b19445201ed2c3996cdc6f3c244ee9f652f35-1000066400000000000000000000000161414622751200274600ustar00rootroot00000000000000v=spf1 mx:%{S}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dcc0a5de6197e7baf94c9bd0c312f3b3a8b5ffb8-6000066400000000000000000000000301414622751200301140ustar00rootroot00000000000000v=spf1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dda2d834936fe89fbd3f55adc62f793c19b5bb9c-1000066400000000000000000000000651414622751200300060ustar00rootroot00000000000000v=spf1 a/071862645a4B361qZ_usk_cs__685t____gWGu__k_y-golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/de07275958226e06cd1a914c7f9b9016b61c5b1f-12000066400000000000000000000000361414622751200274030ustar00rootroot00000000000000v=spf1 exists:‚ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/de4785b5ee386672dbf8e5db8273e0351ea1862b-14000066400000000000000000000000571414622751200275640ustar00rootroot00000000000000v=spf1 a:%{i1490116119384765625} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/de933a63454be499e4e9bed43e408d3d8e1ff567-18000066400000000000000000000000301414622751200276530ustar00rootroot00000000000000v=spf1 V= include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ded54786ddda6dc0f3ffaf5a73c619c3ff8e4b15-10000066400000000000000000000000341414622751200302110ustar00rootroot00000000000000v=spf1 a/1_7_8107_86564func2golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/dfe0b41c561174c2b49287ef075144ceef8da296-6000066400000000000000000000000341414622751200274660ustar00rootroot00000000000000v=spf1 a/0718626H51492305703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e02efe936c6ee8076f09724e5bb9e561c953300e-12000066400000000000000000000000311414622751200274720ustar00rootroot00000000000000v=spf1 mX: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e0fd54a63505541388b2f103523d8aa89bdb5bc6-11000066400000000000000000000002161414622751200274450ustar00rootroot00000000000000v=spf1 𨞵𫶵𫞵ð«µð«žµð«žµð«žµð«¶µð«žµð«žµð«Žµð«žµð«žµð«žµð«žµð«Žµð«žµð«žµð«žµð«žµð«žµð«¶µð«žµð«žµð«Žµð«žµð«žµð«žµð«žµð«Žµð«žµð«ž´ð«žµð«žµgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e10b4f7eaaad2300375a565a8dae9f2e85608a52-13000066400000000000000000000000141414622751200276010ustar00rootroot00000000000000v=spf1 mX: igolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e208097be0b0dc8618075d6583ce1f50568c15e2-1000066400000000000000000000000261414622751200272360ustar00rootroot00000000000000v=spf1 include:domain golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e28579d8a072e6615a51a0112bee851dc3a1f5fd-4000066400000000000000000000000301414622751200274410ustar00rootroot00000000000000v=spf1 redirect=%{l}%{o}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e2d874886a559a516efd5dc3a169334c7a963b30-12000066400000000000000000000000361414622751200274160ustar00rootroot00000000000000v=spf1 mx:d6660 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e3e07997d1dc92146f6984ff5720fa16894e7c53-9000066400000000000000000000000161414622751200273060ustar00rootroot00000000000000v=spf1 a//4 a/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e41fcf365302845c2340ccb398af2cfefb43f232-13000066400000000000000000000000641414622751200276100ustar00rootroot00000000000000v=spf1 a:%{I}%{i}%{i}%{i}%{i}%{i}%{i} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e54a3e98730496df3ea28dbfef487790c60708fb-11000066400000000000000000000000571414622751200275740ustar00rootroot00000000000000v=spf1 mx:ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚ó‚‚5 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e57744a0dd15293f65d65428a78b2ee3f130d009000066400000000000000000000000271414622751200271010ustar00rootroot00000000000000v=spf1 ip6:2001:db8::68golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e5880258d09616bbddf50349c7f55002c79b0022-3000066400000000000000000000000361414622751200271550ustar00rootroot00000000000000v=spf1 mx:%{{{Šžõ¨j{{Šžõ¨ji} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e60dbbdca9e3329fe3f1fb14b05d7f88a2c6ea63-14000066400000000000000000000000531414622751200301160ustar00rootroot00000000000000v=spf1 a/-107186261862645451 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e68c75a01a4dfa8bbba43e271e396726d72c2f5b000066400000000000000000000000151414622751200274510ustar00rootroot00000000000000v=spf1 exp= -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e69204559a621f21dc8f0e7002fd7fca9a7b8ae8-12000066400000000000000000000000511414622751200276220ustar00rootroot00000000000000v=spf1 ip6:1:: ip6:e:e:0:: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e73a0dbc0b873c3e1ddf99f0ac22927b1163e7c8-14000066400000000000000000000000431414622751200276730ustar00rootroot00000000000000v=spf1 mx:d6660//128 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e7914ed96774117a2015925f790c57fe8000c008-8000066400000000000000000000000521414622751200270320ustar00rootroot00000000000000v=spf1 a/4 a/4 a/4 a/4 a/4 a/4 a/4 a/4 a/1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e93a4f40a1901c685ac5a409a1f07ba714ef956c-2000066400000000000000000000000361414622751200274460ustar00rootroot00000000000000v=spf1 redirect=%{l29030}%{d2}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/e964873ffd42a21f02c1b2248873c0a901365005-1000066400000000000000000000000461414622751200270620ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4/31 ip4:1.2.3.4/32 2golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ea5be69cc8b6644519c5a167ca753a863b757097000066400000000000000000000000521414622751200272010ustar00rootroot00000000000000v=spf1 mx:%{l}.%{d}.%{i}.spf.example.net -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ec0f6eace689ed6111acd7ec285057da01a1eb21-18000066400000000000000000000000611414622751200300210ustar00rootroot00000000000000v=spf1 ip6::: ip6::: ip6::: ip6::: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ec41195137f57066d8f0d799ac8bb252dfdc93dc-2000066400000000000000000000000321414622751200275520ustar00rootroot00000000000000v=spf1 /ÕBó/ÕBó‚‚)`!44golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ec8282bd3e0bf237005a5a65e6bf5bffbf51e758-1000066400000000000000000000000161414622751200276740ustar00rootroot00000000000000v=spf1 ip6:e:Bgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ec93b5d52903ed882f9f6f24d6ec969012ed55ff-15000066400000000000000000000000471414622751200276630ustar00rootroot00000000000000v=spf1 ip6:::/6 ip6:::/4 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ed29237e59b78657edc357bf1fd4460a66268a5e-5000066400000000000000000000000361414622751200274320ustar00rootroot00000000000000v=spf1 exp= exp= redirect=%{D}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/eda8a35bd40b21a692a4995f705855c7312886c3-9000066400000000000000000000000401414622751200272470ustar00rootroot00000000000000v=spf1 mx mx a a mx mx a a mx mxgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ee703a3c97844bd923f94fcee3f4b1653c10fb6d-14000066400000000000000000000000411414622751200277050ustar00rootroot00000000000000v=spf1 ip6:::1:b:6 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ee79058d876696355d87d2126ad04f156ee520aa-2000066400000000000000000000000231414622751200272530ustar00rootroot00000000000000v=spf1 m0�110~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ee8656006a06959c1879616effb85a634b0aca13000066400000000000000000000000231414622751200271630ustar00rootroot00000000000000v=spf1 exists:d6660golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/eebf4b0d9b6cc26f1e7ee704bb832dcc7647ac8c-18000066400000000000000000000000511414622751200302060ustar00rootroot00000000000000v=spf1 ptr ptr ptr ptr ptr include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/efcb64bb622abb09cdf3c05e731cf05ab568f832-2000066400000000000000000000000161414622751200277400ustar00rootroot00000000000000v=spf1 �golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/efd13ba66006cb10e54fd5c8a2992aa935a8756e000066400000000000000000000000261414622751200273750ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1 allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f00d320792f2005cc22836f5dffde0be97502329-13000066400000000000000000000000511414622751200273650ustar00rootroot00000000000000v=spf1 ip6:1:b:6:1:b:6:1:1 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f00d61fecdc4f66b5c9d8327c224e31776d2ed0e-8000066400000000000000000000000351414622751200276250ustar00rootroot00000000000000v=spf1 include:domain ç ç ² ²golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f045bb4e8964c3e50f041d64f4af9d0183705b31-5000066400000000000000000000000341414622751200273120ustar00rootroot00000000000000v=spf1 a/0718626451492305703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f0790f92fc3c35ccf7e8a7fb6b48035edf0780a3000066400000000000000000000001341414622751200274710ustar00rootroot00000000000000v=spf1 mx=7_7MN3__a4B361qZ_usk_cs__685t____gWGu__k_y6__J____5Gb_NM30_uxX__/0xFA2467A2fFde5 ~golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f0edc684d8e8f6bab6d61c4219dbe9d58d39d326-17000066400000000000000000000000411414622751200300050ustar00rootroot00000000000000v=spf1 ptr ptr ptr include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f2ea57ec6f67baa4734129213423b9ebb4cde80b-1000066400000000000000000000000341414622751200276040ustar00rootroot00000000000000v=spf1 ip4:irect=eexamplecomgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f350da396279e5e30cf92a6d3204c5220a02ef0a-9000066400000000000000000000000341414622751200273560ustar00rootroot00000000000000v=spf1 a:%{I} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f37f1e713b1f67e3482d7e866517f016e1a13ce0-10000066400000000000000000000000351414622751200273770ustar00rootroot00000000000000v=spf1 a:%{I=} include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f3c307e9e0eaf6bd44a3ab6737ee11f342866326-15000066400000000000000000000000421414622751200275370ustar00rootroot00000000000000v=spf1 ip6:1::1:b:6 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f40589b11b7e03c9d880bd69b76e01e27c743df3-16000066400000000000000000000000431414622751200274730ustar00rootroot00000000000000v=spf1 ip6:CF:CAFE:: include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f4b8cedf44980c648c7e5e5fc44327c456156f57-12000066400000000000000000000000341414622751200275130ustar00rootroot00000000000000v=spf1 mxó‚05 include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f56d2e286b7ecc555ea356fe649fbf322ea02fc5-8000066400000000000000000000000611414622751200277150ustar00rootroot00000000000000v=spf1 mx:�������� include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f57ba6df08bfc3da035f8333e18bc446ba1f0e2d-1000066400000000000000000000000231414622751200277350ustar00rootroot00000000000000v=spf1 ip6:2001db8:golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f5bb1d1b02d908d9d249b8bc120e37abd12d94de-4000066400000000000000000000000221414622751200276550ustar00rootroot00000000000000v=spf1 ptr:½ ptr6golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f650013dbeb971d05740a25bcd8f6726a35cc47e000066400000000000000000000000101414622751200273000ustar00rootroot00000000000000v=spf1 agolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f70408cf87bef7015e9c01e21fe4d656bbe091f1-1000066400000000000000000000000151414622751200275340ustar00rootroot00000000000000v=spf1 ��golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f86d796e245a7f6baab8943e91639f3abe312654-3000066400000000000000000000000361414622751200274250ustar00rootroot00000000000000v=spf1 mx:ÞÐQ½¿¿ï½)½¿¿¿ïQ½¿¿ï½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f8a1991053a5a58d92e38049974f307b888d6124000066400000000000000000000000241414622751200267050ustar00rootroot00000000000000v=spf1 exists:%{l-}.golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f8e2610fa172fcf57c5a78abc250c624ea258abd-2000066400000000000000000000000321414622751200276610ustar00rootroot00000000000000v=spf1 ip6:1:8:1:b:6:1:8:8golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f97b07022630b9bb9d443021f67c6616a5e2499b-3000066400000000000000000000000411414622751200271560ustar00rootroot00000000000000v=spf1 ip6:1::1 ip6:1::1 ip6:1:::golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/f9f5579076d85ecffef2bc4201d38e2168c95486-6000066400000000000000000000000341414622751200274410ustar00rootroot00000000000000v=spf1 a/-110723451492305703golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fab1282ee7602b9bc7dd8814723a391dc902ad0d-12000066400000000000000000000000331414622751200276030ustar00rootroot00000000000000v=spf1 ip6:1::6/1 a:d1110/1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fb893e6d6923eb8bc63274ff5faad450b0c40abb-3000066400000000000000000000000271414622751200277530ustar00rootroot00000000000000v=spf1  include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fbfceed3f5d78a2c71b217856a3c8b12f6f22f5b-4000066400000000000000000000000171414622751200277620ustar00rootroot00000000000000v=spf1 ï¿/ï½ï¿)golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fc0a076254f8732cae001b698d036a858ca6dfb6-3000066400000000000000000000000111414622751200274450ustar00rootroot00000000000000v=spf1 \\golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fc7ec2e1564e22897591d02e3abc43245cd46ba1-6000066400000000000000000000000411414622751200274470ustar00rootroot00000000000000v=spf1 ptr:½ ptr:½ include:domaingolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fc9b2b87a881c97370779482229c8b6e56ff43f0-3000066400000000000000000000000631414622751200273020ustar00rootroot00000000000000v=spf1 mx:%{i}%{i}%{363797880709171295166015625i} -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fd8c9d87b2d24a6e2d677bc551b32e3fd26cc0a8-18000066400000000000000000000000301414622751200277630ustar00rootroot00000000000000v=spf1 mx:ó‚‚ó‚ó‚ó‚ó‚ó‚/golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fdb54165041061eb1bb177f83c824f7785124ee7-2000066400000000000000000000000141414622751200272340ustar00rootroot00000000000000v=spf1 Õ�golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fe0cfa994f142b9dbbcf323d29affdd09798c1ab000066400000000000000000000000141414622751200277620ustar00rootroot00000000000000v=spf1 mx/33golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fe1c45453c73861dfb5cf5ab1e032e90dc154572-4000066400000000000000000000000611414622751200274470ustar00rootroot00000000000000v=spf1 mx:ÞÐQ½¿¿ï½ÞÐQ½¿¿ï½)½¿¿¿ïQ½¿¿ï)½¿¿¿ïQ½¿¿ï½golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fe256c829f42896f75caaac59f3344d1657770a0-3000066400000000000000000000000241414622751200273370ustar00rootroot00000000000000v=spf1 redirect=%{D}golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/fe43d6d6a17b0d49226f25260bc5b76dc4d815da-7000066400000000000000000000000121414622751200275300ustar00rootroot00000000000000v=spf1 óóógolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/ff4c34829a3c7ad090d43175030a9e9ebb7b40af-3000066400000000000000000000000171414622751200275260ustar00rootroot00000000000000v=spf1 𫞵𫞵golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-000000066400000000000000000000000061414622751200224140ustar00rootroot00000000000000v=spf1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-001000066400000000000000000000000061414622751200224150ustar00rootroot00000000000000v=spf1golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-002000066400000000000000000000000101414622751200224110ustar00rootroot00000000000000v=spf1 -golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-003000066400000000000000000000000121414622751200224140ustar00rootroot00000000000000v=spf1 allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-004000066400000000000000000000000131414622751200224160ustar00rootroot00000000000000v=spf1 +allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-005000066400000000000000000000000131414622751200224170ustar00rootroot00000000000000v=spf1 -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-006000066400000000000000000000000131414622751200224200ustar00rootroot00000000000000v=spf1 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-007000066400000000000000000000000131414622751200224210ustar00rootroot00000000000000v=spf1 ?allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-008000066400000000000000000000000151414622751200224240ustar00rootroot00000000000000v=spf1 a ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-009000066400000000000000000000000131414622751200224230ustar00rootroot00000000000000v=spf1 a/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-010000066400000000000000000000000211414622751200224120ustar00rootroot00000000000000v=spf1 a:d1110/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-011000066400000000000000000000000161414622751200224170ustar00rootroot00000000000000v=spf1 a:d1110golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-012000066400000000000000000000000161414622751200224200ustar00rootroot00000000000000v=spf1 a:d1111golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-013000066400000000000000000000000231414622751200224170ustar00rootroot00000000000000v=spf1 a:nothing/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-014000066400000000000000000000000111414622751200224150ustar00rootroot00000000000000v=spf1 mxgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-015000066400000000000000000000000141414622751200224210ustar00rootroot00000000000000v=spf1 mx/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-016000066400000000000000000000000301414622751200224200ustar00rootroot00000000000000v=spf1 mx:a/montoto ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-017000066400000000000000000000000271414622751200224270ustar00rootroot00000000000000v=spf1 mx:d1110/24 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-018000066400000000000000000000000271414622751200224300ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-019000066400000000000000000000000221414622751200224240ustar00rootroot00000000000000v=spf1 ip6:12 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-020000066400000000000000000000000271414622751200224210ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1 -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-021000066400000000000000000000000171414622751200224210ustar00rootroot00000000000000v=spf1 ptr -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-022000066400000000000000000000000251414622751200224210ustar00rootroot00000000000000v=spf1 ptr:d1111 -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-023000066400000000000000000000000261414622751200224230ustar00rootroot00000000000000v=spf1 ptr:lalala -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-024000066400000000000000000000000131414622751200224200ustar00rootroot00000000000000v=spf1 blahgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-025000066400000000000000000000000121414622751200224200ustar00rootroot00000000000000v=spf1 allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-026000066400000000000000000000000151414622751200224240ustar00rootroot00000000000000v=spf1 a ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-027000066400000000000000000000000131414622751200224230ustar00rootroot00000000000000v=spf1 a/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-028000066400000000000000000000000211414622751200224230ustar00rootroot00000000000000v=spf1 a:d6660/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-029000066400000000000000000000000161414622751200224300ustar00rootroot00000000000000v=spf1 a:d6660golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-030000066400000000000000000000000161414622751200224200ustar00rootroot00000000000000v=spf1 a:d6666golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-031000066400000000000000000000000231414622751200224170ustar00rootroot00000000000000v=spf1 a:nothing/24golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-032000066400000000000000000000000271414622751200224240ustar00rootroot00000000000000v=spf1 mx:d6660/24 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-033000066400000000000000000000000341414622751200224230ustar00rootroot00000000000000v=spf1 ip6:2001:db8::68 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-034000066400000000000000000000000361414622751200224260ustar00rootroot00000000000000v=spf1 ip6:2001:db8::1/24 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-035000066400000000000000000000000371414622751200224300ustar00rootroot00000000000000v=spf1 ip6:2001:db8::1/100 ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-036000066400000000000000000000000171414622751200224270ustar00rootroot00000000000000v=spf1 ptr -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-037000066400000000000000000000000251414622751200224270ustar00rootroot00000000000000v=spf1 ptr:d6666 -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-038000066400000000000000000000000271414622751200224320ustar00rootroot00000000000000v=spf1 ptr:sonlas6 -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-039000066400000000000000000000000271414622751200224330ustar00rootroot00000000000000v=spf1 exists:blah -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-040000066400000000000000000000000241414622751200224200ustar00rootroot00000000000000v=spf1 exp=blah -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-041000066400000000000000000000000221414622751200224170ustar00rootroot00000000000000v=spf1 a:%{o} -allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-042000066400000000000000000000000321414622751200224210ustar00rootroot00000000000000v=spf1 include:domain ~allgolang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-043000066400000000000000000000000321414622751200224220ustar00rootroot00000000000000v=spf1 redirect=blah -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-044000066400000000000000000000000171414622751200224260ustar00rootroot00000000000000v=spf1 1up=foo golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-045000066400000000000000000000000121414622751200224220ustar00rootroot00000000000000v=spf1 a: golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-046000066400000000000000000000000211414622751200224230ustar00rootroot00000000000000v=spf1 a//0 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-047000066400000000000000000000000201414622751200224230ustar00rootroot00000000000000v=spf1 a/0 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-048000066400000000000000000000000271414622751200224330ustar00rootroot00000000000000v=spf1 a:111.222.33.44 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-049000066400000000000000000000000231414622751200224300ustar00rootroot00000000000000v=spf1 a//129 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-050000066400000000000000000000000251414622751200224220ustar00rootroot00000000000000v=spf1 a/24//64 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-051000066400000000000000000000000241414622751200224220ustar00rootroot00000000000000v=spf1 a/24/64 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-052000066400000000000000000000000211414622751200224200ustar00rootroot00000000000000v=spf1 a/24 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-053000066400000000000000000000000221414622751200224220ustar00rootroot00000000000000v=spf1 a//33 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-054000066400000000000000000000000211414622751200224220ustar00rootroot00000000000000v=spf1 a/33 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-055000066400000000000000000000000221414622751200224240ustar00rootroot00000000000000v=spf1 a//64 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-056000066400000000000000000000001331414622751200224300ustar00rootroot00000000000000v=spf1 a:a123456789012345678901234567890123456789012345678901234567890123.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-057000066400000000000000000000000271414622751200224330ustar00rootroot00000000000000v=spf1 a a a a a a a a golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-058000066400000000000000000000000211414622751200224260ustar00rootroot00000000000000v=spf1 a:abc.123 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-059000066400000000000000000000000371414622751200224360ustar00rootroot00000000000000v=spf1 a a:c1.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-060000066400000000000000000000000371414622751200224260ustar00rootroot00000000000000v=spf1 a:%{a}.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-061000066400000000000000000000000161414622751200224240ustar00rootroot00000000000000v=spf1 a -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-062000066400000000000000000000000161414622751200224250ustar00rootroot00000000000000v=spf1 a -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-063000066400000000000000000000000161414622751200224260ustar00rootroot00000000000000v=spf1 a -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-064000066400000000000000000000000461414622751200224320ustar00rootroot00000000000000v=spf1 a:ctrl.example.com\x0dptr -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-065000066400000000000000000000000231414622751200224260ustar00rootroot00000000000000v=spf1 a:d6660//24 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-066000066400000000000000000000000271414622751200224330ustar00rootroot00000000000000v=spf1 a:d6660/24//100 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-067000066400000000000000000000001001414622751200224240ustar00rootroot00000000000000v=spf1 a:erehwon.example.com a:foobar.com exp=nxdomain.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-068000066400000000000000000000001041414622751200224310ustar00rootroot00000000000000v=spf1 a:err.example.com a:err1.example.com a:err2.example.com ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-069000066400000000000000000000000611414622751200224340ustar00rootroot00000000000000v=spf1 a:err.example.com a:err1.example.com ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-070000066400000000000000000000000331414622751200224230ustar00rootroot00000000000000v=spf1 a:examplea.com:8080 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-071000066400000000000000000000000261414622751200224260ustar00rootroot00000000000000v=spf1 a:example.-com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-072000066400000000000000000000000321414622751200224240ustar00rootroot00000000000000v=spf1 a:example.com:8080 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-073000066400000000000000000000000321414622751200224250ustar00rootroot00000000000000v=spf1 a:example.net -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-074000066400000000000000000000000351414622751200224310ustar00rootroot00000000000000v=spf1 a:example.net \x96all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-075000066400000000000000000000000261414622751200224320ustar00rootroot00000000000000v=spf1 a:foo-bar -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-076000066400000000000000000000000411414622751200224300ustar00rootroot00000000000000v=spf1 a:foo:bar/baz.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-077000066400000000000000000000000331414622751200224320ustar00rootroot00000000000000v=spf1 a:foo.example.com\0 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-078000066400000000000000000000000341414622751200224340ustar00rootroot00000000000000v=spf1 a:foo.example.com/24 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-079000066400000000000000000000000451414622751200224370ustar00rootroot00000000000000v=spf1 a:foo.example.xn--zckzah -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-080000066400000000000000000000000231414622751200224230ustar00rootroot00000000000000v=spf1 a:%{H} -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-081000066400000000000000000000000241414622751200224250ustar00rootroot00000000000000v=spf1 -a:%{h} +all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-082000066400000000000000000000000271414622751200224310ustar00rootroot00000000000000v=spf1 a:%{H}.bar -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-083000066400000000000000000000000641414622751200224330ustar00rootroot00000000000000v=spf1 a include:inc.example.com a ip4:1.2.3.4 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-084000066400000000000000000000000651414622751200224350ustar00rootroot00000000000000v=spf1 a include:inc.example.com ip4:1.2.3.4 mx -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-085000066400000000000000000000000141414622751200224300ustar00rootroot00000000000000v=spf1 +all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-086000066400000000000000000000000141414622751200224310ustar00rootroot00000000000000v=spf1 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-087000066400000000000000000000000151414622751200224330ustar00rootroot00000000000000v=spf1 -all. golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-088000066400000000000000000000000141414622751200224330ustar00rootroot00000000000000v=spf1 =all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-089000066400000000000000000000000141414622751200224340ustar00rootroot00000000000000v=spf1 ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-090000066400000000000000000000000161414622751200224260ustar00rootroot00000000000000v=spf1 -all/8 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-091000066400000000000000000000000201414622751200224220ustar00rootroot00000000000000v=spf1 all -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-092000066400000000000000000000000431414622751200224300ustar00rootroot00000000000000v=spf1 -all exp=e11msg.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-093000066400000000000000000000000421414622751200224300ustar00rootroot00000000000000v=spf1 -all exp=e4msg.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-094000066400000000000000000000000421414622751200224310ustar00rootroot00000000000000v=spf1 -all exp=e6msg.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-095000066400000000000000000000000411414622751200224310ustar00rootroot00000000000000v=spf1 -all exp=exp2.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-096000066400000000000000000000000411414622751200224320ustar00rootroot00000000000000v=spf1 -all exp=exp4.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-097000066400000000000000000000000401414622751200224320ustar00rootroot00000000000000v=spf1 -all exp=exp.example.net golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-098000066400000000000000000000001131414622751200224340ustar00rootroot00000000000000v=spf1 -all exp=foobar.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-099000066400000000000000000000000421414622751200224360ustar00rootroot00000000000000v=spf1 -all exp=%{ir}.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-100000066400000000000000000000000331414622751200224150ustar00rootroot00000000000000v=spf1 -all exp=msg8.%{D2} golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-101000066400000000000000000000000411414622751200224150ustar00rootroot00000000000000v=spf1 -all exp=%{r}.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-102000066400000000000000000000000251414622751200224200ustar00rootroot00000000000000v=spf1 -all foo=%abc golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-103000066400000000000000000000000231414622751200224170ustar00rootroot00000000000000v=spf1 -all:foobar golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-104000066400000000000000000000000201414622751200224150ustar00rootroot00000000000000v=spf1 -all ip6 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-105000066400000000000000000000000261414622751200224240ustar00rootroot00000000000000v=spf1 ?all redirect= golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-106000066400000000000000000000000751414622751200224310ustar00rootroot00000000000000v=spf1 a:macro%%percent%_%_space%-url-space.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-107000066400000000000000000000000411414622751200224230ustar00rootroot00000000000000v=spf1 a:mail.example...com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-108000066400000000000000000000000201414622751200224210ustar00rootroot00000000000000v=spf1 a:museum golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-109000066400000000000000000000000211414622751200224230ustar00rootroot00000000000000v=spf1 a:museum. golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-110000066400000000000000000000000611414622751200224170ustar00rootroot00000000000000v=spf1 a:mx1.example.com mx:mx1.example.com ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-111000066400000000000000000000000641414622751200224230ustar00rootroot00000000000000v=spf1 a mx a mx a mx a mx a ptr a ip4:1.2.3.4 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-112000066400000000000000000000000621414622751200224220ustar00rootroot00000000000000v=spf1 a mx a mx a mx a mx a ptr ip4:1.2.3.4 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-113000066400000000000000000000000321414622751200224200ustar00rootroot00000000000000v=spf1 a mx include:a.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-114000066400000000000000000000000321414622751200224210ustar00rootroot00000000000000v=spf1 a mx include:b.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-115000066400000000000000000000000251414622751200224240ustar00rootroot00000000000000v=spf1 a:nothing//24 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-116000066400000000000000000000000171414622751200224260ustar00rootroot00000000000000v=spf1 a:%{o0} golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-117000066400000000000000000000000261414622751200224270ustar00rootroot00000000000000v=spf1 +a:o1-%{o1}-o1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-118000066400000000000000000000000311414622751200224240ustar00rootroot00000000000000v=spf1 +a:o1r-%{o1r}-o1r golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-119000066400000000000000000000000261414622751200224310ustar00rootroot00000000000000v=spf1 +a:o7-%{o7}-o7 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-120000066400000000000000000000000301414622751200224140ustar00rootroot00000000000000v=spf1 +a:ooo-%{o7}-ooo golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-121000066400000000000000000000000271414622751200224230ustar00rootroot00000000000000v=spf1 +a:ooo-%{o}-ooo golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-122000066400000000000000000000000271414622751200224240ustar00rootroot00000000000000v=spf1 +a:OOO-%{O}-OOO golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-123000066400000000000000000000000271414622751200224250ustar00rootroot00000000000000v=spf1 +a:ppp-%{p}-ppp golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-124000066400000000000000000000000311414622751200224210ustar00rootroot00000000000000v=spf1 +a:sra-%{sr.}-sra golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-125000066400000000000000000000000261414622751200224260ustar00rootroot00000000000000v=spf1 +a:sr-%{sr}-sr golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-126000066400000000000000000000000271414622751200224300ustar00rootroot00000000000000v=spf1 +a:sss-%{s}-sss golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-127000066400000000000000000000000271414622751200224310ustar00rootroot00000000000000v=spf1 +a:vvv-%{v}-vvv golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-128000066400000000000000000000000161414622751200224300ustar00rootroot00000000000000v=spf1 a:%{x} golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-129000066400000000000000000000000561414622751200224350ustar00rootroot00000000000000v=spf1 a:\xEF\xBB\xBFgarbage.example.net -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-130000066400000000000000000000000211414622751200224150ustar00rootroot00000000000000v=spf1 default=+ golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-131000066400000000000000000000000211414622751200224160ustar00rootroot00000000000000v=spf1 default=- golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-132000066400000000000000000000000241414622751200224220ustar00rootroot00000000000000v=spf1 default=pass golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-133000066400000000000000000000000161414622751200224240ustar00rootroot00000000000000v=spf1 exists golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-134000066400000000000000000000000171414622751200224260ustar00rootroot00000000000000v=spf1 exists: golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-135000066400000000000000000000000311414622751200224230ustar00rootroot00000000000000v=spf1 exists:d1111 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-136000066400000000000000000000000431414622751200224270ustar00rootroot00000000000000v=spf1 exists:err.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-137000066400000000000000000000000541414622751200224320ustar00rootroot00000000000000v=spf1 exists:foo%(ir).sbl.example.com ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-138000066400000000000000000000000501414622751200224270ustar00rootroot00000000000000v=spf1 exists:foo%.sbl.example.com ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-139000066400000000000000000000000461414622751200224350ustar00rootroot00000000000000v=spf1 exists:%{i}.%{l2r-}.user.%{d2} golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-140000066400000000000000000000000521414622751200224220ustar00rootroot00000000000000v=spf1 -exists:%(ir).sbl.example.com ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-141000066400000000000000000000000421414622751200224220ustar00rootroot00000000000000v=spf1 exists:%{l2r+-}.user.%{d2} golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-142000066400000000000000000000000451414622751200224260ustar00rootroot00000000000000v=spf1 exists:mail6.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-143000066400000000000000000000000371414622751200224300ustar00rootroot00000000000000v=spf1 exists:mail.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-144000066400000000000000000000000421414622751200224250ustar00rootroot00000000000000v=spf1 exists:mail.example.com/24 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-145000066400000000000000000000001021414622751200224230ustar00rootroot00000000000000v=spf1 exists:%{p}.should.example.com ~exists:%{p}.ok.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-146000066400000000000000000000000211414622751200224240ustar00rootroot00000000000000v=spf1 exp= -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-147000066400000000000000000000000201414622751200224240ustar00rootroot00000000000000v=spf1 exp=-all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-148000066400000000000000000000000431414622751200224320ustar00rootroot00000000000000v=spf1 exp=badexp.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-149000066400000000000000000000000251414622751200224330ustar00rootroot00000000000000v=spf1 exp=blah +all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-150000066400000000000000000000000431414622751200224230ustar00rootroot00000000000000v=spf1 exp=e13msg.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-151000066400000000000000000000000721414622751200224260ustar00rootroot00000000000000v=spf1 exp=e13msg.example.com -all exp=e11msg.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-152000066400000000000000000000000431414622751200224250ustar00rootroot00000000000000v=spf1 exp=e21msg.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-153000066400000000000000000000000641414622751200224310ustar00rootroot00000000000000v=spf1 exp=exp1.example.com redirect=e2.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-154000066400000000000000000000000641414622751200224320ustar00rootroot00000000000000v=spf1 exp=exp1.example.com redirect=e4.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-155000066400000000000000000000000411414622751200224260ustar00rootroot00000000000000v=spf1 exp=mail.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-156000066400000000000000000000000411414622751200224270ustar00rootroot00000000000000v=spf1 exp=msg.example.com. -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-157000066400000000000000000000000431414622751200224320ustar00rootroot00000000000000v=spf1 exp=twoexp.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-158000066400000000000000000000000241414622751200224320ustar00rootroot00000000000000v=spf1 include +all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-159000066400000000000000000000000251414622751200224340ustar00rootroot00000000000000v=spf1 include: -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-160000066400000000000000000000000431414622751200224240ustar00rootroot00000000000000v=spf1 include:domain2 ip4:1.1.1.1 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-161000066400000000000000000000000331414622751200224240ustar00rootroot00000000000000v=spf1 include:domain ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-162000066400000000000000000000000361414622751200224300ustar00rootroot00000000000000v=spf1 include:e2.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-163000066400000000000000000000000361414622751200224310ustar00rootroot00000000000000v=spf1 include:e3.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-164000066400000000000000000000000701414622751200224300ustar00rootroot00000000000000v=spf1 include:e3.example.com -all exp=exp3.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-165000066400000000000000000000000431414622751200224310ustar00rootroot00000000000000v=spf1 include:e6.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-166000066400000000000000000000000501414622751200224300ustar00rootroot00000000000000v=spf1 include:erehwon.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-167000066400000000000000000000000471414622751200224370ustar00rootroot00000000000000v=spf1 include:ip5.example.com/24 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-168000066400000000000000000000000441414622751200224350ustar00rootroot00000000000000v=spf1 include:ip5.example.com ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-169000066400000000000000000000000431414622751200224350ustar00rootroot00000000000000v=spf1 include:ip6.example.com all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-170000066400000000000000000000000441414622751200224260ustar00rootroot00000000000000v=spf1 include:ip7.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-171000066400000000000000000000000441414622751200224270ustar00rootroot00000000000000v=spf1 include:ip8.example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-172000066400000000000000000000000471414622751200224330ustar00rootroot00000000000000v=spf1 include:o.spf.example.com. ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-173000066400000000000000000000000601414622751200224270ustar00rootroot00000000000000v=spf1 -include:_spfh.%{d2} ip4:1.2.3.0/24 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-174000066400000000000000000000000131414622751200224260ustar00rootroot00000000000000v=spf1 ip4 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-175000066400000000000000000000000321414622751200224300ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1/0 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-176000066400000000000000000000000331414622751200224320ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1/33 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-177000066400000000000000000000000301414622751200224300ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-178000066400000000000000000000000531414622751200224360ustar00rootroot00000000000000v=spf1 ip4:1.1.1.1 redirect=e1.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-179000066400000000000000000000000211414622751200224320ustar00rootroot00000000000000v=spf1 ip4:1.2.3 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-180000066400000000000000000000000231414622751200224240ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-181000066400000000000000000000000341414622751200224270ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4/032 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-182000066400000000000000000000000271414622751200224320ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4//32 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-183000066400000000000000000000000331414622751200224300ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4/32 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-184000066400000000000000000000000331414622751200224310ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4/33 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-185000066400000000000000000000000301414622751200224270ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4:8080 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-186000066400000000000000000000000341414622751200224340ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 -all moo golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-187000066400000000000000000000000471414622751200224410ustar00rootroot00000000000000v=spf1 -ip4:1.2.3.4 ip6:::FFFF:1.2.3.4 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-188000066400000000000000000000000531414622751200224370ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 redirect:t2.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-189000066400000000000000000000000531414622751200224400ustar00rootroot00000000000000v=spf1 ip4:1.2.3.4 redirect=t2.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-190000066400000000000000000000000301414622751200224230ustar00rootroot00000000000000v=spf1 ip4:1.2.3.5 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-191000066400000000000000000000000301414622751200224240ustar00rootroot00000000000000v=spf1 ip4:1.2.3.6 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-192000066400000000000000000000000301414622751200224250ustar00rootroot00000000000000v=spf1 ip4:1.2.3.7 ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-193000066400000000000000000000000321414622751200224300ustar00rootroot00000000000000v=spf1 ip4:192.168.218.40 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-194000066400000000000000000000000271414622751200224350ustar00rootroot00000000000000v=spf1 ip6:::1.1.1.1/0 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-195000066400000000000000000000000311414622751200224310ustar00rootroot00000000000000v=spf1 ip6:::1.1.1.1/129 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-196000066400000000000000000000000311414622751200224320ustar00rootroot00000000000000v=spf1 ip6:::1.1.1.1//33 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-197000066400000000000000000000000271414622751200224400ustar00rootroot00000000000000v=spf1 ip6::CAFE::BABE golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-198000066400000000000000000000000371414622751200224420ustar00rootroot00000000000000v=spf1 ip6:Cafe:Babe:8000::/33 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-199000066400000000000000000000000371414622751200224430ustar00rootroot00000000000000v=spf1 ip6:CAFE:BABE:8000::/33 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-200000066400000000000000000000000641414622751200224220ustar00rootroot00000000000000v=spf1 moo.cow-far_out=man:dog/cat ip4:1.2.3.4 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-201000066400000000000000000000000641414622751200224230ustar00rootroot00000000000000v=spf1 moo.cow/far_out=man:dog/cat ip4:1.2.3.4 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-202000066400000000000000000000000641414622751200224240ustar00rootroot00000000000000v=spf1 moo.cow:far_out=man:dog/cat ip4:1.2.3.4 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-203000066400000000000000000000000121414622751200224160ustar00rootroot00000000000000v=spf1 mx golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-204000066400000000000000000000000221414622751200224200ustar00rootroot00000000000000v=spf1 mx//0 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-205000066400000000000000000000000211414622751200224200ustar00rootroot00000000000000v=spf1 mx/0 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-206000066400000000000000000000000241414622751200224240ustar00rootroot00000000000000v=spf1 mx//129 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-207000066400000000000000000000000701414622751200224260ustar00rootroot00000000000000v=spf1 mx/26 exists:%{l}.%{d}.%{i}.spf.example.net -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-208000066400000000000000000000000231414622751200224250ustar00rootroot00000000000000v=spf1 mx//33 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-209000066400000000000000000000000221414622751200224250ustar00rootroot00000000000000v=spf1 mx/33 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-210000066400000000000000000000000221414622751200224150ustar00rootroot00000000000000v=spf1 mx:abc.123 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-211000066400000000000000000000000201414622751200224140ustar00rootroot00000000000000v=spf1 mx: -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-212000066400000000000000000000000351414622751200224230ustar00rootroot00000000000000v=spf1 mx:d1110/24//100 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-213000066400000000000000000000000341414622751200224230ustar00rootroot00000000000000v=spf1 mx:d1110/24/100 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-214000066400000000000000000000000351414622751200224250ustar00rootroot00000000000000v=spf1 mx:d1110/24//129 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-215000066400000000000000000000000351414622751200224260ustar00rootroot00000000000000v=spf1 mx:d6660/24//100 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-216000066400000000000000000000000341414622751200224260ustar00rootroot00000000000000v=spf1 mx:d6660/24/100 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-217000066400000000000000000000000311414622751200224240ustar00rootroot00000000000000v=spf1 mx:d6660//24 ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-218000066400000000000000000000000271414622751200224320ustar00rootroot00000000000000v=spf1 mx:example.-com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-219000066400000000000000000000000331414622751200224300ustar00rootroot00000000000000v=spf1 mx:example.com:8080 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-220000066400000000000000000000000261414622751200224220ustar00rootroot00000000000000v=spf1 mx:%{fff} -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-221000066400000000000000000000000421414622751200224210ustar00rootroot00000000000000v=spf1 mx:foo:bar/baz.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-222000066400000000000000000000000341414622751200224230ustar00rootroot00000000000000v=spf1 mx:foo.example.com\0 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-223000066400000000000000000000000351414622751200224250ustar00rootroot00000000000000v=spf1 mx:foo.example.com/24 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-224000066400000000000000000000000441414622751200224260ustar00rootroot00000000000000v=spf1 mx redirect=_spf.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-225000066400000000000000000000000131414622751200224230ustar00rootroot00000000000000v=spf1 ptr golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-226000066400000000000000000000000141414622751200224250ustar00rootroot00000000000000v=spf1 ptr: golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-227000066400000000000000000000000221414622751200224250ustar00rootroot00000000000000v=spf1 ptr/0 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-228000066400000000000000000000000201414622751200224240ustar00rootroot00000000000000v=spf1 ptr -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-229000066400000000000000000000000341414622751200224320ustar00rootroot00000000000000v=spf1 ptr:example.com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-230000066400000000000000000000000341414622751200224220ustar00rootroot00000000000000v=spf1 ptr:example.Com -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-231000066400000000000000000000001131414622751200224210ustar00rootroot00000000000000v=spf1 ptr:fe.example.org ptr:sgp.example.com exp=_expspf.example.org -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-232000066400000000000000000000000271414622751200224260ustar00rootroot00000000000000v=spf1 ptr:%{fff} -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-233000066400000000000000000000000301414622751200224210ustar00rootroot00000000000000v=spf1 ptr:sonlas7 -all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-234000066400000000000000000000000211414622751200224220ustar00rootroot00000000000000v=spf1 redirect= golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-235000066400000000000000000000000321414622751200224250ustar00rootroot00000000000000v=spf1 redirect=-all ?all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-236000066400000000000000000000000421414622751200224270ustar00rootroot00000000000000v=spf1 redirect=a.spf.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-237000066400000000000000000000000501414622751200224270ustar00rootroot00000000000000v=spf1 redirect=%{d}.d.spf.example.com. golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-238000066400000000000000000000000351414622751200224330ustar00rootroot00000000000000v=spf1 redirect=doesnotexist golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-239000066400000000000000000000000301414622751200224270ustar00rootroot00000000000000v=spf1 redirect=domain2 golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-240000066400000000000000000000000761414622751200224310ustar00rootroot00000000000000v=spf1 redirect=e12.example.com -all redirect=e12.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-241000066400000000000000000000000441414622751200224250ustar00rootroot00000000000000v=spf1 redirect=erehwon.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-242000066400000000000000000000000301414622751200224210ustar00rootroot00000000000000v=spf1 redirect=faildom golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-243000066400000000000000000000000341414622751200224260ustar00rootroot00000000000000v=spf1 redirect=faildom all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-244000066400000000000000000000000271414622751200224310ustar00rootroot00000000000000v=spf1 redirect=%{fff} golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-245000066400000000000000000000000441414622751200224310ustar00rootroot00000000000000v=spf1 redirect=t5.example.com ~all golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-246000066400000000000000000000000511414622751200224300ustar00rootroot00000000000000v=spf1 redirect=testimplicit.example.com golang-blitiri-go-spf-1.3.0/testdata/fuzz/corpus/t-247000066400000000000000000000000361414622751200224340ustar00rootroot00000000000000v=spf1 \x80a:example.net -all golang-blitiri-go-spf-1.3.0/testdata/pyspf-tests.LICENSE000066400000000000000000000002021414622751200227230ustar00rootroot00000000000000The pyspf tests come from pyspf project as of commit de8d8fb150. pysf is licenced under the Python Software Foundation License. golang-blitiri-go-spf-1.3.0/testdata/pyspf-tests.yml000066400000000000000000000125431414622751200224550ustar00rootroot00000000000000# This is the test suite used during development of the pyspf library. # It is a collection of ad hoc tests based on bug reports. It is the # goal of the SPF test project to have an elegant and minimal test suite # that reflects RFC 4408. However, this should help get things started # by serving as a example of what tests look like. Also, any implementation # that flunks this, should flunk the minimal elegant suite as well. # # We extended the test attributes with 'receiver' and 'header' to test # our implementation of the Received-SPF header. This cannot easily # be part of the RFC test suite because of wide latitude in formatting. # --- comment: | check basic exists with macros tests: exists-pass: helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@example.co.uk result: pass receiver: receiver.com header: >- Pass (receiver.com: domain of example.co.uk designates 1.2.3.5 as permitted sender) client-ip=1.2.3.5; envelope-from="lyme.eater@example.co.uk"; helo=mail.example.net; receiver=receiver.com; mechanism="exists:%{l}.%{d}.%{i}.spf.example.net"; identity=mailfrom exists-fail: helo: mail.example.net host: 1.2.3.4 mailfrom: lyme.eater@example.co.uk result: fail zonedata: lyme.eater.example.co.uk.1.2.3.5.spf.example.net: - A: 127.0.0.1 example.co.uk: - SPF: v=spf1 mx/26 exists:%{l}.%{d}.%{i}.spf.example.net -all --- comment: | permerror detection tests: incloop: comment: | include loop helo: mail.example.com host: 66.150.186.79 mailfrom: chuckvsr@examplea.com result: permerror badall: helo: mail.example.com host: 66.150.186.79 mailfrom: chuckvsr@examplec.com result: permerror baddomain: helo: mail.example.com host: 66.150.186.79 mailfrom: chuckvsr@exampled.com result: permerror receiver: receiver.com header: >- PermError (receiver.com: permanent error in processing domain of exampled.com: Invalid domain found (use FQDN)) client-ip=66.150.186.79; envelope-from="chuckvsr@exampled.com"; helo=mail.example.com; receiver=receiver.com; problem="examplea.com:8080"; identity=mailfrom skip: Not worth the complexity of erroring on this. tworecs: helo: mail.example.com host: 66.150.186.79 mailfrom: chuckvsr@examplef.com result: permerror receiver: receiver.com header: >- PermError (receiver.com: permanent error in processing domain of examplef.com: Two or more type TXT spf records found.) client-ip=66.150.186.79; envelope-from="chuckvsr@examplef.com"; helo=mail.example.com; receiver=receiver.com; identity=mailfrom badip: helo: mail.example.com host: 66.150.186.79 mailfrom: chuckvsr@examplee.com result: permerror zonedata: examplea.com: - SPF: v=spf1 a mx include:b.com exampleb.com: - SPF: v=spf1 a mx include:a.com examplec.com: - SPF: v=spf1 -all:foobar exampled.com: - SPF: v=spf1 a:examplea.com:8080 examplee.com: - SPF: v=spf1 ip4:1.2.3.4:8080 examplef.com: - SPF: v=spf1 -all - SPF: v=spf1 +all --- tests: nospace1: comment: | test no space test multi-line comment helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example2.com result: none empty: comment: | test empty helo: mail1.example1.com host: 1.2.3.4 mailfrom: foo@example1.com result: neutral nospace2: helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example3.com result: pass zonedata: example3.com: - SPF: [ 'v=spf1','mx' ] - SPF: [ 'v=spf1 ', 'mx' ] - MX: [0, mail.example1.com] example1.com: - SPF: v=spf1 example2.com: - SPF: v=spf1mx mail.example1.com: - A: 1.2.3.4 --- comment: | corner cases tests: emptyMX: comment: | test empty MX helo: mail.example.com host: 1.2.3.4 mailfrom: "" result: neutral localhost: helo: mail.example.com host: 127.0.0.1 mailfrom: root@example.com result: fail default-modifier: comment: | default modifier implemented in lax mode for compatibility helo: mail.example.com host: 1.2.3.4 mailfrom: root@e1.example.com result: fail strict: 0 skip: It's not clear this is problematic. default-modifier-harsh: comment: | default modifier implemented in lax mode for compatibility helo: mail.example.com host: 1.2.3.4 mailfrom: root@e1.example.com result: ambiguous strict: 2 skip: It's not clear this is problematic. cname-chain: comment: | pyspf was duplicating TXT (and other) records while following CNAME helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass skip: Test runner doesn't handle CNAMEs yet. null-cname: comment: | pyspf was getting a type error for null CNAMEs Thanks to Kazuhiro Ogura helo: mail.example.com host: 1.2.3.4 mailfrom: bar@e3.example.com result: softfail zonedata: mail.example.com: - MX: [0, ''] - SPF: v=spf1 mx example.com: - SPF: v=spf1 -all e1.example.com: - SPF: v=spf1 default=- e2.example.com: - CNAME: c1.example.com. c1.example.com: - CNAME: c2.example.com. c2.example.com: - SPF: v=spf1 a a:c1.example.com -all - A: 1.2.3.4 mx1.example.com: - CNAME: '' e3.example.com: - SPF: v=spf1 a:mx1.example.com mx:mx1.example.com ~all golang-blitiri-go-spf-1.3.0/testdata/rfc-tests.README000066400000000000000000000003671414622751200222230ustar00rootroot00000000000000 The RFC tests were copied from the pyspf repository at https://github.com/sdgathman/pyspf. They are licensed separately, and only used for testing purposes. See the open-spf test suite page for more details: http://www.open-spf.org/Test_Suite/ golang-blitiri-go-spf-1.3.0/testdata/rfc4408-tests.LICENSE000066400000000000000000000027431414622751200226700ustar00rootroot00000000000000The RFC 4408 test-suite (rfc4408-tests.yml) is (C) 2006-2007 Stuart D Gathman 2007 Julian Mehnle All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. golang-blitiri-go-spf-1.3.0/testdata/rfc4408-tests.yml000066400000000000000000002224501414622751200224060ustar00rootroot00000000000000# This is the openspf.org test suite (release 2009.10) based on RFC 4408. # http://www.openspf.org/Test_Suite # # $Id$ # vim:sw=2 sts=2 et # # See rfc4408-tests.CHANGES for a changelog. # # Contributors: # Stuart D Gathman 90% of the tests # Julian Mehnle proofread YAML syntax, spelling, formal schema # Informal contributors (suggestions but no code): # Craig Whitmore # Frank Ellermann # Scott Kitterman # Wayne Schlitt # Craig Whitmore # Norman Maurer # Mark Shewmaker # Philip Gladstone # # While the test suite is designed for all types of implementations, it only # needs to explicitly concern itself with SPF-only (type 99) and TXT-only # implementations. This is because while an implementation may support both, # it must use only one record type for a given query - see 4.5/5. If an # implementation finds SPF (type 99) records and decides to use them, they # override TXT, and it must ignore any TXT records. Note that an # implementation may decide whether to use SPF records on a case by case basis. # Maybe it looks TXT and SPF up in parallel and goes with the first result to # come back. Or maybe one is cached already. Or maybe it chooses at random. # Think of dual SPF/TXT implementations as a quantum superposition of SPF-only # and TXT-only. It must collapse to one or the other on each observation to be # compliant. # # The "Selecting records" test section is the only one concerned with weeding # out (incorrect) mixed behaviour and checking for proper response to duplicate # or conflicting records. Other sections rely on auto-magic duplication # of SPF to TXT records (by test suite drivers) to test all implementation # types with one specification. # --- description: Initial processing tests: toolonglabel: description: >- DNS labels limited to 63 chars. comment: >- For initial processing, a long label results in None, not TempError spec: 4.3/1 helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@A123456789012345678901234567890123456789012345678901234567890123.example.com result: none longlabel: description: >- DNS labels limited to 63 chars. spec: 4.3/1 helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@A12345678901234567890123456789012345678901234567890123456789012.example.com result: fail emptylabel: spec: 4.3/1 helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@A...example.com result: none helo-not-fqdn: spec: 4.3/1 helo: A2345678 host: 1.2.3.5 mailfrom: "" result: none helo-domain-literal: spec: 4.3/1 helo: "[1.2.3.5]" host: 1.2.3.5 mailfrom: "" result: none nolocalpart: spec: 4.3/2 helo: mail.example.net host: 1.2.3.4 mailfrom: '@example.net' result: fail explanation: postmaster domain-literal: spec: 4.3/1 helo: OEMCOMPUTER host: 1.2.3.5 mailfrom: "foo@[1.2.3.5]" result: none non-ascii-policy: description: >- SPF policies are restricted to 7-bit ascii. spec: 3.1.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@hosed.example.com" result: permerror skip: We don't enforce 7-bit ascii. non-ascii-mech: description: >- SPF policies are restricted to 7-bit ascii. comment: >- Checking a possibly different code path for non-ascii chars. spec: 3.1.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@hosed2.example.com" result: permerror skip: We don't enforce 7-bit ascii. non-ascii-result: description: >- SPF policies are restricted to 7-bit ascii. comment: >- Checking yet another code path for non-ascii chars. spec: 3.1.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@hosed3.example.com" result: permerror non-ascii-non-spf: description: >- Non-ascii content in non-SPF related records. comment: >- Non-SPF related TXT records are none of our business. (But what about SPF records?) spec: 3.1.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@nothosed.example.com" result: fail explanation: DEFAULT two-spaces: description: >- ABNF for term separation is one or more spaces, not just one. spec: 4.6.1 helo: hosed host: 1.2.3.4 mailfrom: "actually@fine.example.com" result: fail zonedata: example.com: - TIMEOUT: true example.net: - SPF: v=spf1 -all exp=exp.example.net a.example.net: - SPF: v=spf1 -all exp=exp.example.net exp.example.net: - TXT: '%{l}' a12345678901234567890123456789012345678901234567890123456789012.example.com: - SPF: v=spf1 -all hosed.example.com: - SPF: "v=spf1 a:\xEF\xBB\xBFgarbage.example.net -all" hosed2.example.com: - SPF: "v=spf1 \x80a:example.net -all" hosed3.example.com: - SPF: "v=spf1 a:example.net \x96all" nothosed.example.com: - SPF: "v=spf1 a:example.net -all" - SPF: "\x96" fine.example.com: - TXT: "v=spf1 a -all" --- description: Record lookup tests: both: spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@both.example.net result: fail txtonly: description: Result is none if checking SPF records only. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@txtonly.example.net result: [fail, none] spfonly: description: Result is none if checking TXT records only. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@spfonly.example.net result: [fail, none] spftimeout: description: >- TXT record present, but SPF lookup times out. Result is temperror if checking SPF records only. comment: >- This actually happens for a popular braindead DNS server. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@spftimeout.example.net result: [fail, temperror] txttimeout: description: >- SPF record present, but TXT lookup times out. If only TXT records are checked, result is temperror. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@txttimeout.example.net result: [fail, temperror] nospftxttimeout: description: >- No SPF record present, and TXT lookup times out. If only TXT records are checked, result is temperror. comment: >- Because TXT records is where v=spf1 records will likely be, returning temperror will try again later. A timeout due to a braindead server is unlikely in the case of TXT, as opposed to the newer SPF RR. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@nospftxttimeout.example.net result: [temperror, none] alltimeout: description: Both TXT and SPF queries time out spec: 4.4/2 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@alltimeout.example.net result: temperror zonedata: both.example.net: - TXT: v=spf1 -all - SPF: v=spf1 -all txtonly.example.net: - TXT: v=spf1 -all spfonly.example.net: - SPF: v=spf1 -all - TXT: NONE spftimeout.example.net: - TXT: v=spf1 -all - TIMEOUT: true txttimeout.example.net: - SPF: v=spf1 -all - TXT: NONE - TIMEOUT: true nospftxttimeout.example.net: - SPF: "v=spf3 !a:yahoo.com -all" - TXT: NONE - TIMEOUT: true alltimeout.example.net: - TIMEOUT: true --- description: Selecting records tests: nospace1: description: >- Version must be terminated by space or end of record. TXT pieces are joined without intervening spaces. spec: 4.5/4 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example2.com result: none empty: description: Empty SPF record. spec: 4.5/4 helo: mail1.example1.com host: 1.2.3.4 mailfrom: foo@example1.com result: neutral nospace2: spec: 4.5/4 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example3.com result: pass spfoverride: description: >- SPF records override TXT records. Older implementation may check TXT records only. spec: 4.5/5 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example4.com result: [pass, fail] multitxt1: description: >- Older implementations will give permerror/unknown because of the conflicting TXT records. However, RFC 4408 says the SPF records overrides them. spec: 4.5/5 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example5.com result: [pass, permerror] multitxt2: description: >- Multiple records is a permerror, v=spf1 is case insensitive spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example6.com result: permerror multispf1: description: >- Multiple records is a permerror, even when they are identical. However, this situation cannot be reliably reproduced with live DNS since cache and resolvers are allowed to combine identical records. spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example7.com result: [permerror, fail] multispf2: description: >- Older implementations ignoring SPF-type records will give pass because there is a (single) TXT record. But RFC 4408 requires permerror because the SPF records override and there are more than one. spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example8.com result: [permerror, pass] nospf: spec: 4.5/7 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@mail.example1.com result: none case-insensitive: description: >- v=spf1 is case insensitive spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example9.com result: softfail zonedata: example3.com: - SPF: v=spf10 - SPF: v=spf1 mx - MX: [0, mail.example1.com] example1.com: - SPF: v=spf1 example2.com: - SPF: ['v=spf1', 'mx'] mail.example1.com: - A: 1.2.3.4 example4.com: - SPF: v=spf1 +all - TXT: v=spf1 -all example5.com: - SPF: v=spf1 +all - TXT: v=spf1 -all - TXT: v=spf1 +all example6.com: - SPF: v=spf1 -all - SPF: V=sPf1 +all example7.com: - SPF: v=spf1 -all - SPF: v=spf1 -all example8.com: - SPF: V=spf1 -all - SPF: v=spf1 -all - TXT: v=spf1 +all example9.com: - SPF: v=SpF1 ~all --- description: Record evaluation tests: detect-errors-anywhere: description: Any syntax errors anywhere in the record MUST be detected. spec: 4.6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t1.example.com result: permerror skip: We don't catch errors after a match. modifier-charset-good: description: name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) spec: 4.6.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t2.example.com result: pass skip: We don't enforce the domain charset. modifier-charset-bad1: description: >- '=' character immediately after the name and before any ":" or "/" spec: 4.6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t3.example.com result: permerror modifier-charset-bad2: description: >- '=' character immediately after the name and before any ":" or "/" spec: 4.6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t4.example.com result: permerror redirect-after-mechanisms1: description: >- The "redirect" modifier has an effect after all the mechanisms. comment: >- The redirect in this example would violate processing limits, except that it is never used because of the all mechanism. spec: 4.6.3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t5.example.com result: softfail redirect-after-mechanisms2: description: >- The "redirect" modifier has an effect after all the mechanisms. spec: 4.6.3 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@t6.example.com result: fail skip: Not worth the complexity of erroring on this. default-result: description: Default result is neutral. spec: 4.7/1 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@t7.example.com result: neutral redirect-is-modifier: description: |- Invalid mechanism. Redirect is a modifier. spec: 4.6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t8.example.com result: permerror skip: We don't catch errors after a match. invalid-domain: description: >- Domain-spec must end in macro-expand or valid toplabel. spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t9.example.com result: permerror skip: We don't enforce TLD structure. invalid-domain-empty-label: description: >- target-name that is a valid domain-spec per RFC 4408 but an invalid domain name per RFC 1035 (empty label) must be treated as non-existent. comment: >- An empty domain label, i.e. two successive dots, in a mechanism target-name is valid domain-spec syntax, even though a DNS query cannot be composed from it. The spec being unclear about it, this could either be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the mechanism chould be treated as a no-match. spec: [4.3/1, 5/10/3] helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t10.example.com result: [permerror, fail] invalid-domain-long: description: >- target-name that is a valid domain-spec per RFC 4408 but an invalid domain name per RFC 1035 (long label) must be treated as non-existent. comment: >- A domain label longer than 63 characters in a mechanism target-name is valid domain-spec syntax, even though a DNS query cannot be composed from it. The spec being unclear about it, this could either be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the mechanism chould be treated as a no-match. spec: [4.3/1, 5/10/3] helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t11.example.com result: [permerror,fail] invalid-domain-long-via-macro: description: >- target-name that is a valid domain-spec per RFC 4408 but an invalid domain name per RFC 1035 (long label) must be treated as non-existent. comment: >- A domain label longer than 63 characters that results from macro expansion in a mechanism target-name is valid domain-spec syntax (and is not even subject to syntax checking after macro expansion), even though a DNS query cannot be composed from it. The spec being unclear about it, this could either be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the mechanism chould be treated as a no-match. spec: [4.3/1, 5/10/3] helo: "%%%%%%%%%%%%%%%%%%%%%%" host: 1.2.3.4 mailfrom: foo@t12.example.com result: [permerror,fail] zonedata: mail.example.com: - A: 1.2.3.4 t1.example.com: - SPF: v=spf1 ip4:1.2.3.4 -all moo t2.example.com: - SPF: v=spf1 moo.cow-far_out=man:dog/cat ip4:1.2.3.4 -all t3.example.com: - SPF: v=spf1 moo.cow/far_out=man:dog/cat ip4:1.2.3.4 -all t4.example.com: - SPF: v=spf1 moo.cow:far_out=man:dog/cat ip4:1.2.3.4 -all t5.example.com: - SPF: v=spf1 redirect=t5.example.com ~all t6.example.com: - SPF: v=spf1 ip4:1.2.3.4 redirect=t2.example.com t7.example.com: - SPF: v=spf1 ip4:1.2.3.4 t8.example.com: - SPF: v=spf1 ip4:1.2.3.4 redirect:t2.example.com t9.example.com: - SPF: v=spf1 a:foo-bar -all t10.example.com: - SPF: v=spf1 a:mail.example...com -all t11.example.com: - SPF: v=spf1 a:a123456789012345678901234567890123456789012345678901234567890123.example.com -all t12.example.com: - SPF: v=spf1 a:%{H}.bar -all --- description: ALL mechanism syntax tests: all-dot: description: | all = "all" comment: |- At least one implementation got this wrong spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror all-arg: description: | all = "all" comment: |- At least one implementation got this wrong spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: permerror all-cidr: description: | all = "all" spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror all-neutral: description: | all = "all" spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: neutral all-double: description: | all = "all" spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: pass zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 -all. e2.example.com: - SPF: v=spf1 -all:foobar e3.example.com: - SPF: v=spf1 -all/8 e4.example.com: - SPF: v=spf1 ?all e5.example.com: - SPF: v=spf1 all -all --- description: PTR mechanism syntax tests: ptr-cidr: description: |- PTR = "ptr" [ ":" domain-spec ] spec: 5.5/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror ptr-match-target: description: >- Check all validated domain names to see if they end in the domain. spec: 5.5/5 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass ptr-match-implicit: description: >- Check all validated domain names to see if they end in the domain. spec: 5.5/5 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: pass ptr-nomatch-invalid: description: >- Check all validated domain names to see if they end in the domain. comment: >- This PTR record does not validate spec: 5.5/5 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: fail ptr-match-ip6: description: >- Check all validated domain names to see if they end in the domain. spec: 5.5/5 helo: mail.example.com host: CAFE:BABE::1 mailfrom: foo@e3.example.com result: pass ptr-empty-domain: description: >- domain-spec cannot be empty. spec: 5.5/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 ptr/0 -all e2.example.com: - SPF: v=spf1 ptr:example.com -all 4.3.2.1.in-addr.arpa: - PTR: e3.example.com - PTR: e4.example.com - PTR: mail.example.com 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa: - PTR: e3.example.com e3.example.com: - SPF: v=spf1 ptr -all - A: 1.2.3.4 - AAAA: CAFE:BABE::1 e4.example.com: - SPF: v=spf1 ptr -all e5.example.com: - SPF: "v=spf1 ptr:" --- description: A mechanism syntax tests: a-cidr6: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: fail a-bad-cidr4: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6a.example.com result: permerror a-bad-cidr6: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror a-dual-cidr-ip4-match: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: pass a-dual-cidr-ip4-err: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8e.example.com result: permerror a-dual-cidr-ip6-match: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 2001:db8:1234::cafe:babe mailfrom: foo@e8.example.com result: pass a-dual-cidr-ip4-default: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8b.example.com result: fail a-dual-cidr-ip6-default: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 2001:db8:1234::cafe:babe mailfrom: foo@e8a.example.com result: fail a-multi-ip1: description: >- A matches any returned IP. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass a-multi-ip2: description: >- A matches any returned IP. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass a-bad-domain: description: >- domain-spec must pass basic syntax checks; a ':' may appear in domain-spec, but not in top-label spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror skip: We don't enforce domain charset. a-nxdomain: description: >- If no ips are returned, A mechanism does not match, even with /0. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: fail a-cidr4-0: description: >- Matches if any A records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass a-cidr4-0-ip6: description: >- Matches if any A records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2.example.com result: fail a-cidr6-0-ip4: description: >- Would match if any AAAA records are present in DNS, but not for an IP4 connection. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2a.example.com result: fail a-cidr6-0-ip4mapped: description: >- Would match if any AAAA records are present in DNS, but not for an IP4 connection. spec: 5.3/3 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e2a.example.com result: fail a-cidr6-0-ip6: description: >- Matches if any AAAA records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2a.example.com result: pass a-ip6-dualstack: description: >- Simple IP6 Address match with dual stack. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@ipv6.example.com result: pass a-cidr6-0-nxdomain: description: >- No match if no AAAA records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2b.example.com result: fail a-null: description: >- Null octets not allowed in toplabel spec: 8.1/2 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e3.example.com result: permerror skip: We don't enforce charset. a-numeric: description: >- toplabel may not be all numeric comment: >- A common publishing mistake is using ip4 addresses with A mechanism. This should receive special diagnostic attention in the permerror. spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: permerror skip: We don't enforce domain structure. a-numeric-toplabel: description: >- toplabel may not be all numeric spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror skip: We don't enforce TLD structure. a-dash-in-toplabel: description: >- toplabel may contain dashes comment: >- Going from the "toplabel" grammar definition, an implementation using regular expressions in incrementally parsing SPF records might erroneously try to match a TLD such as ".xn--zckzah" (cf. IDN TLDs!) to '( *alphanum ALPHA *alphanum )' first before trying the alternative '( 1*alphanum "-" *( alphanum / "-" ) alphanum )', essentially causing a non-greedy, and thus, incomplete match. Make sure a greedy match is performed! spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e14.example.com result: pass a-bad-toplabel: description: >- toplabel may not begin with a dash spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: permerror skip: We don't enforce TLD structure. a-only-toplabel: description: >- domain-spec may not consist of only a toplabel. spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5a.example.com result: permerror skip: We don't enforce TLD structure. a-only-toplabel-trailing-dot: description: >- domain-spec may not consist of only a toplabel. comment: >- "A trailing dot doesn't help." spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5b.example.com result: permerror skip: We don't enforce TLD structure. a-colon-domain: description: >- domain-spec may contain any visible char except % spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity a-colon-domain-ip4mapped: description: >- domain-spec may contain any visible char except % spec: 8.1/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity a-empty-domain: description: >- domain-spec cannot be empty. spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e13.example.com result: permerror skip: Not worth the complexity of erroring on this. zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 a/0 -all e2.example.com: - A: 1.1.1.1 - AAAA: 1234::2 - SPF: v=spf1 a/0 -all e2a.example.com: - AAAA: 1234::1 - SPF: v=spf1 a//0 -all e2b.example.com: - A: 1.1.1.1 - SPF: v=spf1 a//0 -all ipv6.example.com: - AAAA: 1234::1 - A: 1.1.1.1 - SPF: v=spf1 a -all e3.example.com: - SPF: "v=spf1 a:foo.example.com\0" e4.example.com: - SPF: v=spf1 a:111.222.33.44 e5.example.com: - SPF: v=spf1 a:abc.123 e5a.example.com: - SPF: v=spf1 a:museum e5b.example.com: - SPF: v=spf1 a:museum. e6.example.com: - SPF: v=spf1 a//33 -all e6a.example.com: - SPF: v=spf1 a/33 -all e7.example.com: - SPF: v=spf1 a//129 -all e8.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a/24//64 -all e8e.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a/24/64 -all e8a.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a/24 -all e8b.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a//64 -all e9.example.com: - SPF: v=spf1 a:example.com:8080 e10.example.com: - SPF: v=spf1 a:foo.example.com/24 foo.example.com: - A: 1.1.1.1 - A: 1.2.3.5 e11.example.com: - SPF: v=spf1 a:foo:bar/baz.example.com foo:bar/baz.example.com: - A: 1.2.3.4 e12.example.com: - SPF: v=spf1 a:example.-com e13.example.com: - SPF: "v=spf1 a:" e14.example.com: - SPF: "v=spf1 a:foo.example.xn--zckzah -all" foo.example.xn--zckzah: - A: 1.2.3.4 --- description: Include mechanism semantics and syntax tests: include-fail: description: >- recursive check_host() result of fail causes include to not match. spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: softfail include-softfail: description: >- recursive check_host() result of softfail causes include to not match. spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass include-neutral: description: >- recursive check_host() result of neutral causes include to not match. spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: fail include-temperror: description: >- recursive check_host() result of temperror causes include to temperror spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: temperror include-permerror: description: >- recursive check_host() result of permerror causes include to permerror spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror include-syntax-error: description: >- include = "include" ":" domain-spec spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror include-cidr: description: >- include = "include" ":" domain-spec spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror include-none: description: >- recursive check_host() result of none causes include to permerror spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror include-empty-domain: description: >- domain-spec cannot be empty. spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: permerror zonedata: mail.example.com: - A: 1.2.3.4 ip5.example.com: - SPF: v=spf1 ip4:1.2.3.5 -all ip6.example.com: - SPF: v=spf1 ip4:1.2.3.6 ~all ip7.example.com: - SPF: v=spf1 ip4:1.2.3.7 ?all ip8.example.com: - TIMEOUT: true erehwon.example.com: - TXT: v=spfl am not an SPF record e1.example.com: - SPF: v=spf1 include:ip5.example.com ~all e2.example.com: - SPF: v=spf1 include:ip6.example.com all e3.example.com: - SPF: v=spf1 include:ip7.example.com -all e4.example.com: - SPF: v=spf1 include:ip8.example.com -all e5.example.com: - SPF: v=spf1 include:e6.example.com -all e6.example.com: - SPF: v=spf1 include +all e7.example.com: - SPF: v=spf1 include:erehwon.example.com -all e8.example.com: - SPF: "v=spf1 include: -all" e9.example.com: - SPF: "v=spf1 include:ip5.example.com/24 -all" --- description: MX mechanism syntax tests: mx-cidr6: description: | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.4/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: fail mx-bad-cidr4: description: | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.4/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6a.example.com result: permerror mx-bad-cidr6: description: | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.4/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror mx-multi-ip1: description: >- MX matches any returned IP. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass mx-multi-ip2: description: >- MX matches any returned IP. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass mx-bad-domain: description: >- domain-spec must pass basic syntax checks comment: >- A ':' may appear in domain-spec, but not in top-label. spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror skip: We don't enforce domain syntax. mx-nxdomain: description: >- If no ips are returned, MX mechanism does not match, even with /0. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: fail mx-cidr4-0: description: >- Matches if any A records for any MX records are present in DNS. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass mx-cidr4-0-ip6: description: >- cidr4 doesn't apply to IP6 connections. spec: 5.4/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2.example.com result: fail mx-cidr6-0-ip4: description: >- Would match if any AAAA records for MX records are present in DNS, but not for an IP4 connection. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2a.example.com result: fail mx-cidr6-0-ip4mapped: description: >- Would match if any AAAA records for MX records are present in DNS, but not for an IP4 connection. spec: 5.4/3 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e2a.example.com result: fail mx-cidr6-0-ip6: description: >- Matches if any AAAA records for any MX records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2a.example.com result: pass mx-cidr6-0-nxdomain: description: >- No match if no AAAA records for any MX records are present in DNS. spec: 5.4/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2b.example.com result: fail mx-null: description: >- Null not allowed in top-label. spec: 8.1/2 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e3.example.com result: permerror skip: We don't enforce charset. mx-numeric-top-label: description: >- Top-label may not be all numeric spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror skip: We don't validate top-level domains. mx-colon-domain: description: >- Domain-spec may contain any visible char except % spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity mx-colon-domain-ip4mapped: description: >- Domain-spec may contain any visible char except % spec: 8.1/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity mx-bad-toplab: description: >- Toplabel may not begin with - spec: 8.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: permerror skip: We don't enforce TLD structure. mx-empty: description: >- test null MX comment: >- Some implementations have had trouble with null MX spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: "" result: neutral mx-implicit: description: >- If the target name has no MX records, check_host() MUST NOT pretend the target is its single MX, and MUST NOT default to an A lookup on the target-name directly. spec: 5.4/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: neutral mx-empty-domain: description: >- domain-spec cannot be empty. spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e13.example.com result: permerror skip: Not worth the complexity of erroring on this. zonedata: mail.example.com: - A: 1.2.3.4 - MX: [0, ""] - SPF: v=spf1 mx e1.example.com: - SPF: v=spf1 mx/0 -all - MX: [0, e1.example.com] e2.example.com: - A: 1.1.1.1 - AAAA: 1234::2 - MX: [0, e2.example.com] - SPF: v=spf1 mx/0 -all e2a.example.com: - AAAA: 1234::1 - MX: [0, e2a.example.com] - SPF: v=spf1 mx//0 -all e2b.example.com: - A: 1.1.1.1 - MX: [0, e2b.example.com] - SPF: v=spf1 mx//0 -all e3.example.com: - SPF: "v=spf1 mx:foo.example.com\0" e4.example.com: - SPF: v=spf1 mx - A: 1.2.3.4 e5.example.com: - SPF: v=spf1 mx:abc.123 e6.example.com: - SPF: v=spf1 mx//33 -all e6a.example.com: - SPF: v=spf1 mx/33 -all e7.example.com: - SPF: v=spf1 mx//129 -all e9.example.com: - SPF: v=spf1 mx:example.com:8080 e10.example.com: - SPF: v=spf1 mx:foo.example.com/24 foo.example.com: - MX: [0, foo1.example.com] foo1.example.com: - A: 1.1.1.1 - A: 1.2.3.5 e11.example.com: - SPF: v=spf1 mx:foo:bar/baz.example.com foo:bar/baz.example.com: - MX: [0, "foo:bar/baz.example.com"] - A: 1.2.3.4 e12.example.com: - SPF: v=spf1 mx:example.-com e13.example.com: - SPF: "v=spf1 mx: -all" --- description: EXISTS mechanism syntax tests: exists-empty-domain: description: >- domain-spec cannot be empty. spec: 5.7/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror exists-implicit: description: >- exists = "exists" ":" domain-spec spec: 5.7/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: permerror exists-cidr: description: >- exists = "exists" ":" domain-spec spec: 5.7/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror exists-ip4: description: >- mechanism matches if any DNS A RR exists spec: 5.7/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: pass exists-ip6: description: >- The lookup type is A even when the connection is ip6 spec: 5.7/3 helo: mail.example.com host: CAFE:BABE::3 mailfrom: foo@e4.example.com result: pass exists-ip6only: description: >- The lookup type is A even when the connection is ip6 spec: 5.7/3 helo: mail.example.com host: CAFE:BABE::3 mailfrom: foo@e5.example.com result: fail exists-dnserr: description: >- Result for DNS error is being clarified in spfbis spec: 5.7/3 helo: mail.example.com host: CAFE:BABE::3 mailfrom: foo@e6.example.com result: [fail, temperror] zonedata: mail.example.com: - A: 1.2.3.4 mail6.example.com: - AAAA: CAFE:BABE::4 err.example.com: - TIMEOUT: true e1.example.com: - SPF: "v=spf1 exists:" e2.example.com: - SPF: "v=spf1 exists" e3.example.com: - SPF: "v=spf1 exists:mail.example.com/24" e4.example.com: - SPF: "v=spf1 exists:mail.example.com" e5.example.com: - SPF: "v=spf1 exists:mail6.example.com -all" e6.example.com: - SPF: "v=spf1 exists:err.example.com -all" --- description: IP4 mechanism syntax tests: cidr4-0: description: >- ip4-cidr-length = "/" 1*DIGIT spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: pass cidr4-32: description: >- ip4-cidr-length = "/" 1*DIGIT spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass cidr4-33: description: >- Invalid CIDR should get permerror. comment: >- The RFC is silent on ip4 CIDR > 32 or ip6 CIDR > 128. However, since there is no reasonable interpretation (except a noop), we have read between the lines to see a prohibition on invalid CIDR. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror cidr4-032: description: >- Invalid CIDR should get permerror. comment: >- Leading zeros are not explicitly prohibited by the RFC. However, since the RFC explicity prohibits leading zeros in ip4-network, our interpretation is that CIDR should be also. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: permerror skip: It's not clear this is problematic. bare-ip4: description: >- IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror bad-ip4-port: description: >- IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] comment: >- This has actually been published in SPF records. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: permerror bad-ip4-short: description: >- It is not permitted to omit parts of the IP address instead of using CIDR notations. spec: 5.6/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror ip4-dual-cidr: description: >- dual-cidr-length not permitted on ip4 spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror ip4-mapped-ip6: description: >- IP4 mapped IP6 connections MUST be treated as IP4 spec: 5/9/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e7.example.com result: fail zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 ip4:1.1.1.1/0 -all e2.example.com: - SPF: v=spf1 ip4:1.2.3.4/32 -all e3.example.com: - SPF: v=spf1 ip4:1.2.3.4/33 -all e4.example.com: - SPF: v=spf1 ip4:1.2.3.4/032 -all e5.example.com: - SPF: v=spf1 ip4 e6.example.com: - SPF: v=spf1 ip4:1.2.3.4//32 e7.example.com: - SPF: v=spf1 -ip4:1.2.3.4 ip6:::FFFF:1.2.3.4 e8.example.com: - SPF: v=spf1 ip4:1.2.3.4:8080 e9.example.com: - SPF: v=spf1 ip4:1.2.3 --- description: IP6 mechanism syntax comment: >- IP4 only implementations may skip tests where host is not IP4 tests: bare-ip6: description: >- IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ] spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror skip: There's an early match. cidr6-0-ip4: description: >- IP4 connections do not match ip6. comment: >- There is controversy over ip4 mapped connections. RFC4408 clearly requires such connections to be considered as ip4. However, some interpret the RFC to mean that such connections should *also* match appropriate ip6 mechanisms (but not, inexplicably, A or MX mechanisms). Until there is consensus, both results are acceptable. spec: 5/9/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: [neutral, pass] cidr6-ip4: description: >- Even if the SMTP connection is via IPv6, an IPv4-mapped IPv6 IP address (see RFC 3513, Section 2.5.5) MUST still be considered an IPv4 address. comment: >- There is controversy over ip4 mapped connections. RFC4408 clearly requires such connections to be considered as ip4. However, some interpret the RFC to mean that such connections should *also* match appropriate ip6 mechanisms (but not, inexplicably, A or MX mechanisms). Until there is consensus, both results are acceptable. spec: 5/9/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e2.example.com result: [neutral, pass] cidr6-0: description: >- Match any IP6 spec: 5/8 helo: mail.example.com host: DEAF:BABE::CAB:FEE mailfrom: foo@e2.example.com result: pass cidr6-129: description: >- Invalid CIDR comment: >- IP4 only implementations MUST fully syntax check all mechanisms, even if they otherwise ignore them. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror cidr6-bad: description: >- dual-cidr syntax not used for ip6 comment: >- IP4 only implementations MUST fully syntax check all mechanisms, even if they otherwise ignore them. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: permerror cidr6-33: description: >- make sure ip4 cidr restriction are not used for ip6 spec: 5.6/2 helo: mail.example.com host: "CAFE:BABE:8000::" mailfrom: foo@e5.example.com result: pass cidr6-33-ip4: description: >- make sure ip4 cidr restriction are not used for ip6 spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: neutral ip6-bad1: description: >- spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 -all ip6 e2.example.com: - SPF: v=spf1 ip6:::1.1.1.1/0 e3.example.com: - SPF: v=spf1 ip6:::1.1.1.1/129 e4.example.com: - SPF: v=spf1 ip6:::1.1.1.1//33 e5.example.com: - SPF: v=spf1 ip6:CAFE:BABE:8000::/33 e6.example.com: - SPF: v=spf1 ip6::CAFE::BABE --- description: Semantics of exp and other modifiers comment: >- Implementing exp= is optional. If not implemented, the test driver should not check the explanation field. tests: redirect-none: description: >- If no SPF record is found, or if the target-name is malformed, the result is a "PermError" rather than "None". spec: 6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: permerror redirect-cancels-exp: description: >- when executing "redirect", exp= from the original domain MUST NOT be used. spec: 6.2/13 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: fail explanation: DEFAULT redirect-syntax-error: description: | redirect = "redirect" "=" domain-spec comment: >- A literal application of the grammar causes modifier syntax errors (except for macro syntax) to become unknown-modifier. modifier = explanation | redirect | unknown-modifier However, it is generally agreed, with precedent in other RFCs, that unknown-modifier should not be "greedy", and should not match known modifier names. There should have been explicit prose to this effect, and some has been proposed as an erratum. spec: 6.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e17.example.com result: permerror skip: We don't enforce charset within the redirect. include-ignores-exp: description: >- when executing "include", exp= from the target domain MUST NOT be used. spec: 6.2/13 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: fail explanation: Correct! redirect-cancels-prior-exp: description: >- when executing "redirect", exp= from the original domain MUST NOT be used. spec: 6.2/13 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: fail explanation: See me. invalid-modifier: description: | unknown-modifier = name "=" macro-string name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) comment: >- Unknown modifier name must begin with alpha. spec: A/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror empty-modifier-name: description: | name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) comment: >- Unknown modifier name must not be empty. spec: A/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror dorky-sentinel: description: >- An implementation that uses a legal expansion as a sentinel. We cannot check them all, but we can check this one. comment: >- Spaces are allowed in local-part. spec: 8.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: "Macro Error@e8.example.com" result: fail explanation: Macro Error in implementation exp-multiple-txt: description: | Ignore exp if multiple TXT records. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: fail explanation: DEFAULT exp-no-txt: description: | Ignore exp if no TXT records. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e22.example.com result: fail explanation: DEFAULT exp-dns-error: description: | Ignore exp if DNS error. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e21.example.com result: fail explanation: DEFAULT exp-empty-domain: description: | PermError if exp= domain-spec is empty. comment: >- Section 6.2/4 says, "If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given." However, "if domain-spec is empty" conflicts with the grammar given for the exp modifier. This was reported as an erratum, and the solution chosen was to report explicit "exp=" as PermError, but ignore problems due to macro expansion, DNS, or invalid explanation string. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: permerror skip: We ignore exp, and is harmless. explanation-syntax-error: description: | Ignore exp if the explanation string has a syntax error. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e13.example.com result: fail explanation: DEFAULT exp-syntax-error: description: | explanation = "exp" "=" domain-spec comment: >- A literal application of the grammar causes modifier syntax errors (except for macro syntax) to become unknown-modifier. modifier = explanation | redirect | unknown-modifier However, it is generally agreed, with precedent in other RFCs, that unknown-modifier should not be "greedy", and should not match known modifier names. There should have been explicit prose to this effect, and some has been proposed as an erratum. spec: 6.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e16.example.com result: permerror skip: We don't enforce exp values. exp-twice: description: | exp= appears twice. comment: >- These two modifiers (exp,redirect) MUST NOT appear in a record more than once each. If they do, then check_host() exits with a result of "PermError". spec: 6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e14.example.com result: permerror skip: We ignore exp, and is harmless. redirect-empty-domain: description: | redirect = "redirect" "=" domain-spec comment: >- Unlike for exp, there is no instruction to override the permerror for an empty domain-spec (which is invalid syntax). spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e18.example.com result: permerror skip: There's an early match. redirect-twice: description: | redirect= appears twice. comment: >- These two modifiers (exp,redirect) MUST NOT appear in a record more than once each. If they do, then check_host() exits with a result of "PermError". spec: 6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e15.example.com result: permerror unknown-modifier-syntax: description: | unknown-modifier = name "=" macro-string comment: >- Unknown modifiers must have valid macro syntax. spec: A/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror skip: There's an early match. default-modifier-obsolete: description: | Unknown modifiers do not modify the RFC SPF result. comment: >- Some implementations may have a leftover default= modifier from earlier drafts. spec: 6/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e19.example.com result: neutral skip: Not worth the complexity of erroring on this. default-modifier-obsolete2: description: | Unknown modifiers do not modify the RFC SPF result. comment: >- Some implementations may have a leftover default= modifier from earlier drafts. spec: 6/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e20.example.com result: neutral skip: Not worth the complexity of erroring on this. non-ascii-exp: description: >- SPF explanation text is restricted to 7-bit ascii. comment: >- Checking a possibly different code path for non-ascii chars. spec: 6.2/5 helo: hosed host: 1.2.3.4 mailfrom: "foobar@nonascii.example.com" result: fail explanation: DEFAULT two-exp-records: description: >- Must ignore exp= if DNS returns more than one TXT record. spec: 6.2/4 helo: hosed host: 1.2.3.4 mailfrom: "foobar@tworecs.example.com" result: fail explanation: DEFAULT zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 exp=exp1.example.com redirect=e2.example.com e2.example.com: - SPF: v=spf1 -all e3.example.com: - SPF: v=spf1 exp=exp1.example.com redirect=e4.example.com e4.example.com: - SPF: v=spf1 -all exp=exp2.example.com exp1.example.com: - TXT: No-see-um exp2.example.com: - TXT: See me. exp3.example.com: - TXT: Correct! exp4.example.com: - TXT: "%{l} in implementation" e5.example.com: - SPF: v=spf1 1up=foo e6.example.com: - SPF: v=spf1 =all e7.example.com: - SPF: v=spf1 include:e3.example.com -all exp=exp3.example.com e8.example.com: - SPF: v=spf1 -all exp=exp4.example.com e9.example.com: - SPF: v=spf1 -all foo=%abc e10.example.com: - SPF: v=spf1 redirect=erehwon.example.com e11.example.com: - SPF: v=spf1 -all exp=e11msg.example.com e11msg.example.com: - TXT: Answer a fool according to his folly. - TXT: Do not answer a fool according to his folly. e12.example.com: - SPF: v=spf1 exp= -all e13.example.com: - SPF: v=spf1 exp=e13msg.example.com -all e13msg.example.com: - TXT: The %{x}-files. e14.example.com: - SPF: v=spf1 exp=e13msg.example.com -all exp=e11msg.example.com e15.example.com: - SPF: v=spf1 redirect=e12.example.com -all redirect=e12.example.com e16.example.com: - SPF: v=spf1 exp=-all e17.example.com: - SPF: v=spf1 redirect=-all ?all e18.example.com: - SPF: v=spf1 ?all redirect= e19.example.com: - SPF: v=spf1 default=pass e20.example.com: - SPF: "v=spf1 default=+" e21.example.com: - SPF: v=spf1 exp=e21msg.example.com -all e21msg.example.com: - TIMEOUT: true e22.example.com: - SPF: v=spf1 exp=mail.example.com -all nonascii.example.com: - SPF: v=spf1 exp=badexp.example.com -all badexp.example.com: - TXT: "\xEF\xBB\xBFExplanation" tworecs.example.com: - SPF: v=spf1 exp=twoexp.example.com -all twoexp.example.com: - TXT: "one" - TXT: "two" --- description: Macro expansion rules tests: trailing-dot-domain: spec: 8.1/16 description: >- trailing dot is ignored for domains helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@example.com result: pass trailing-dot-exp: spec: 8.1 description: >- trailing dot is not removed from explanation comment: >- A simple way for an implementation to ignore trailing dots on domains is to remove it when present. But be careful not to remove it for explanation text. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@exp.example.com result: fail explanation: This is a test. exp-only-macro-char: spec: 8.1/8 description: >- The following macro letters are allowed only in "exp" text: c, r, t helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e2.example.com result: permerror skip: We ignore exp, and is harmless. invalid-macro-char: spec: 8.1/9 description: >- A '%' character not followed by a '{', '%', '-', or '_' character is a syntax error. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e1.example.com result: permerror invalid-embedded-macro-char: spec: 8.1/9 description: >- A '%' character not followed by a '{', '%', '-', or '_' character is a syntax error. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e1e.example.com result: permerror invalid-trailing-macro-char: spec: 8.1/9 description: >- A '%' character not followed by a '{', '%', '-', or '_' character is a syntax error. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e1t.example.com result: permerror macro-mania-in-domain: description: >- macro-encoded percents (%%), spaces (%_), and URL-percent-encoded spaces (%-) spec: 8.1/3, 8.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: test@e1a.example.com result: pass exp-txt-macro-char: spec: 8.1/20 description: >- For IPv4 addresses, both the "i" and "c" macros expand to the standard dotted-quad format. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e3.example.com result: fail explanation: Connections from 192.168.218.40 not authorized. domain-name-truncation: spec: 8.1/25 description: >- When the result of macro expansion is used in a domain name query, if the expanded domain name exceeds 253 characters, the left side is truncated to fit, by removing successive domain labels until the total length does not exceed 253 characters. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@somewhat.long.exp.example.com result: fail explanation: Congratulations! That was tricky. v-macro-ip4: spec: 8.1/6 description: |- v = the string "in-addr" if is ipv4, or "ip6" if is ipv6 helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e4.example.com result: fail explanation: 192.168.218.40 is queried as 40.218.168.192.in-addr.arpa v-macro-ip6: spec: 8.1/6 description: |- v = the string "in-addr" if is ipv4, or "ip6" if is ipv6 helo: msgbas2x.cos.example.com host: CAFE:BABE::1 mailfrom: test@e4.example.com result: fail explanation: cafe:babe::1 is queried as 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa undef-macro: spec: 8.1/6 description: >- Allowed macros chars are 'slodipvh' plus 'crt' in explanation. helo: msgbas2x.cos.example.com host: CAFE:BABE::192.168.218.40 mailfrom: test@e5.example.com result: permerror p-macro-ip4-novalid: spec: 8.1/22 description: |- p = the validated domain name of comment: >- The PTR in this example does not validate. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e6.example.com result: fail explanation: connect from unknown p-macro-ip4-valid: spec: 8.1/22 description: |- p = the validated domain name of comment: >- If a subdomain of the is present, it SHOULD be used. helo: msgbas2x.cos.example.com host: 192.168.218.41 mailfrom: test@e6.example.com result: fail explanation: connect from mx.example.com p-macro-ip6-novalid: spec: 8.1/22 description: |- p = the validated domain name of comment: >- The PTR in this example does not validate. helo: msgbas2x.cos.example.com host: CAFE:BABE::1 mailfrom: test@e6.example.com result: fail explanation: connect from unknown p-macro-ip6-valid: spec: 8.1/22 description: |- p = the validated domain name of comment: >- If a subdomain of the is present, it SHOULD be used. helo: msgbas2x.cos.example.com host: CAFE:BABE::3 mailfrom: test@e6.example.com result: fail explanation: connect from mx.example.com p-macro-multiple: spec: 8.1/22 description: |- p = the validated domain name of comment: >- If a subdomain of the is present, it SHOULD be used. helo: msgbas2x.cos.example.com host: 192.168.218.42 mailfrom: test@e7.example.com result: [pass, softfail] skip: p macro is not supported upper-macro: spec: 8.1/26 description: >- Uppercased macros expand exactly as their lowercased equivalents, and are then URL escaped. helo: msgbas2x.cos.example.com host: 192.168.218.42 mailfrom: jack&jill=up@e8.example.com result: fail explanation: http://example.com/why.html?l=jack%26jill%3Dup hello-macro: spec: 8.1/6 description: |- h = HELO/EHLO domain helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e9.example.com result: pass skip: We don't have a HELO-explicit mode. invalid-hello-macro: spec: 8.1/2 description: |- h = HELO/EHLO domain, but HELO is invalid comment: >- Domain-spec must end in either a macro, or a valid toplabel. It is not correct to check syntax after macro expansion. helo: "JUMPIN' JUPITER" host: 192.168.218.40 mailfrom: test@e9.example.com result: fail hello-domain-literal: spec: 8.1/2 description: |- h = HELO/EHLO domain, but HELO is a domain literal comment: >- Domain-spec must end in either a macro, or a valid toplabel. It is not correct to check syntax after macro expansion. helo: "[192.168.218.40]" host: 192.168.218.40 mailfrom: test@e9.example.com result: fail require-valid-helo: spec: 8.1/6 description: >- Example of requiring valid helo in sender policy. This is a complex policy testing several points at once. helo: OEMCOMPUTER host: 1.2.3.4 mailfrom: test@e10.example.com result: fail macro-reverse-split-on-dash: spec: [8.1/15, 8.1/16, 8.1/17, 8.1/18] description: >- Macro value transformation (splitting on arbitrary characters, reversal, number of right-hand parts to use) helo: mail.example.com host: 1.2.3.4 mailfrom: philip-gladstone-test@e11.example.com result: pass macro-multiple-delimiters: spec: [8.1/15, 8.1/16] description: |- Multiple delimiters may be specified in a macro expression. macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) / "%%" / "%_" / "%-" helo: mail.example.com host: 1.2.3.4 mailfrom: foo-bar+zip+quux@e12.example.com result: pass zonedata: example.com.d.spf.example.com: - SPF: v=spf1 redirect=a.spf.example.com a.spf.example.com: - SPF: v=spf1 include:o.spf.example.com. ~all o.spf.example.com: - SPF: v=spf1 ip4:192.168.218.40 msgbas2x.cos.example.com: - A: 192.168.218.40 example.com: - A: 192.168.90.76 - SPF: v=spf1 redirect=%{d}.d.spf.example.com. exp.example.com: - SPF: v=spf1 exp=msg.example.com. -all msg.example.com: - TXT: This is a test. e1.example.com: - SPF: v=spf1 -exists:%(ir).sbl.example.com ?all e1e.example.com: - SPF: v=spf1 exists:foo%(ir).sbl.example.com ?all e1t.example.com: - SPF: v=spf1 exists:foo%.sbl.example.com ?all e1a.example.com: - SPF: "v=spf1 a:macro%%percent%_%_space%-url-space.example.com -all" "macro%percent space%20url-space.example.com": - A: 1.2.3.4 e2.example.com: - SPF: v=spf1 -all exp=%{r}.example.com e3.example.com: - SPF: v=spf1 -all exp=%{ir}.example.com 40.218.168.192.example.com: - TXT: Connections from %{c} not authorized. somewhat.long.exp.example.com: - SPF: v=spf1 -all exp=foobar.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.example.com somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.example.com: - TXT: Congratulations! That was tricky. e4.example.com: - SPF: v=spf1 -all exp=e4msg.example.com e4msg.example.com: - TXT: "%{c} is queried as %{ir}.%{v}.arpa" e5.example.com: - SPF: v=spf1 a:%{a}.example.com -all e6.example.com: - SPF: v=spf1 -all exp=e6msg.example.com e6msg.example.com: - TXT: "connect from %{p}" mx.example.com: - A: 192.168.218.41 - A: 192.168.218.42 - AAAA: CAFE:BABE::2 - AAAA: CAFE:BABE::3 40.218.168.192.in-addr.arpa: - PTR: mx.example.com 41.218.168.192.in-addr.arpa: - PTR: mx.example.com 42.218.168.192.in-addr.arpa: - PTR: mx.example.com - PTR: mx.e7.example.com 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa: - PTR: mx.example.com 3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa: - PTR: mx.example.com mx.e7.example.com: - A: 192.168.218.42 mx.e7.example.com.should.example.com: - A: 127.0.0.2 mx.example.com.ok.example.com: - A: 127.0.0.2 e7.example.com: - SPF: v=spf1 exists:%{p}.should.example.com ~exists:%{p}.ok.example.com e8.example.com: - SPF: v=spf1 -all exp=msg8.%{D2} msg8.example.com: - TXT: "http://example.com/why.html?l=%{L}" e9.example.com: - SPF: v=spf1 a:%{H} -all e10.example.com: - SPF: v=spf1 -include:_spfh.%{d2} ip4:1.2.3.0/24 -all _spfh.example.com: - SPF: v=spf1 -a:%{h} +all e11.example.com: - SPF: v=spf1 exists:%{i}.%{l2r-}.user.%{d2} 1.2.3.4.gladstone.philip.user.example.com: - A: 127.0.0.2 e12.example.com: - SPF: v=spf1 exists:%{l2r+-}.user.%{d2} bar.foo.user.example.com: - A: 127.0.0.2 --- description: Processing limits tests: redirect-loop: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 10.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror include-loop: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 10.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: permerror mx-limit: description: >- there MUST be a limit of no more than 10 MX looked up and checked. comment: >- The required result for this test was the subject of much controversy. Many felt that the RFC *should* have specified permerror, but the consensus was that it failed to actually do so. The preferred result reflects evaluating the 10 allowed MX records in the order returned by the test data - or sorted via priority. If testing with live DNS, the MX order may be random, and a pass result would still be compliant. The SPF result is effectively random. spec: 10.1/7 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e4.example.com result: [neutral, pass, permerror] ptr-limit: description: >- there MUST be a limit of no more than 10 PTR looked up and checked. comment: >- The result of this test cannot be permerror not only because the RFC does not specify it, but because the sender has no control over the PTR records of spammers. The preferred result reflects evaluating the 10 allowed PTR records in the order returned by the test data. If testing with live DNS, the PTR order may be random, and a pass result would still be compliant. The SPF result is effectively randomized. spec: 10.1/7 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e5.example.com result: [neutral, pass] false-a-limit: description: >- unlike MX, PTR, there is no RR limit for A comment: >- There seems to be a tendency for developers to want to limit A RRs in addition to MX and PTR. These are IPs, not usable for 3rd party DoS attacks, and hence need no low limit. spec: 10.1/7 helo: mail.example.com host: 1.2.3.12 mailfrom: foo@e10.example.com result: pass mech-at-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 10.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: pass skip: This is a legitimate fail because we don't do caching. mech-over-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. comment: >- We do not check whether an implementation counts mechanisms before or after evaluation. The RFC is not clear on this. spec: 10.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror include-at-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. comment: >- The part of the RFC that talks about MAY parse the entire record first (4.6) is specific to syntax errors. Processing limits is a different, non-syntax issue. Processing limits (10.1) specifically talks about limits during a check. spec: 10.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: pass include-over-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 10.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 ip4:1.1.1.1 redirect=e1.example.com - A: 1.2.3.6 e2.example.com: - SPF: v=spf1 include:e3.example.com - A: 1.2.3.7 e3.example.com: - SPF: v=spf1 include:e2.example.com - A: 1.2.3.8 e4.example.com: - SPF: v=spf1 mx - MX: [0, mail.example.com] - MX: [1, mail.example.com] - MX: [2, mail.example.com] - MX: [3, mail.example.com] - MX: [4, mail.example.com] - MX: [5, mail.example.com] - MX: [6, mail.example.com] - MX: [7, mail.example.com] - MX: [8, mail.example.com] - MX: [9, mail.example.com] - MX: [10, e4.example.com] - A: 1.2.3.5 e5.example.com: - SPF: v=spf1 ptr - A: 1.2.3.5 5.3.2.1.in-addr.arpa: - PTR: e1.example.com. - PTR: e2.example.com. - PTR: e3.example.com. - PTR: e4.example.com. - PTR: example.com. - PTR: e6.example.com. - PTR: e7.example.com. - PTR: e8.example.com. - PTR: e9.example.com. - PTR: e10.example.com. - PTR: e5.example.com. e6.example.com: - SPF: v=spf1 a mx a mx a mx a mx a ptr ip4:1.2.3.4 -all - A: 1.2.3.8 - MX: [10, e6.example.com] e7.example.com: - SPF: v=spf1 a mx a mx a mx a mx a ptr a ip4:1.2.3.4 -all - A: 1.2.3.20 e8.example.com: - SPF: v=spf1 a include:inc.example.com ip4:1.2.3.4 mx -all - A: 1.2.3.4 inc.example.com: - SPF: v=spf1 a a a a a a a a - A: 1.2.3.10 e9.example.com: - SPF: v=spf1 a include:inc.example.com a ip4:1.2.3.4 -all - A: 1.2.3.21 e10.example.com: - SPF: v=spf1 a -all - A: 1.2.3.1 - A: 1.2.3.2 - A: 1.2.3.3 - A: 1.2.3.4 - A: 1.2.3.5 - A: 1.2.3.6 - A: 1.2.3.7 - A: 1.2.3.8 - A: 1.2.3.9 - A: 1.2.3.10 - A: 1.2.3.11 - A: 1.2.3.12 golang-blitiri-go-spf-1.3.0/testdata/rfc7208-tests.CHANGES000066400000000000000000000145261414622751200226610ustar00rootroot00000000000000# Legend: # --- = A new release # ! = Added a test case or otherwise tightened a requirement, possibly # causing implementations to become incompliant with the current # test-suite release # - = Removed a test case or otherwise relaxed a requirement # * = Fixed a bug, or made a minor improvement --- 2014.04 (UNRELEASED) ! Updates for RFC 7208 (4408bis) ! Updated multiple tests not to consider type SPF records under mixed conditions - Note: due to the way the test suite is structured, many records are still labled SPF internally, but for test functions, it doesn't matter externally. - Removed "invalid-domain-empty-label", "invalid-domain-long", and "invalid-domain-long-via-macro". Since RFC 7208 explicitly describes the results for these conditions as undefined, there's no point in testing for a particular result. ! Modified multiple tests to remove ambiguous results for cases that were ambiguous in RFC 4408, but have been clarified in RFC 7208. ! Changed "mx-limit" test to produce permerror result per changes in RFC 7208 ! Added "invalid-trailing-macro-char" and "invalid-embedded-macro-char" tests from Stuart on pyspf trunk --- 2009.10 (2009-10-31 20:00) ! Added test case: ! "macro-multiple-delimiters": Multiple delimiters in a macro expression must be supported. * Fixed "multitxt2" test case failing with SPF-type-only implementations. Tolerate a "None" result to accomodate those. --- 2008.08 (2008-08-17 16:00) ! "invalid-domain-empty-label", "invalid-domain-long", "invalid-domain-long-via-macro" test cases: A that is a valid domain-spec per RFC 4408 but an invalid domain name per RFC 1035 (two successive dots or labels longer than 63 characters) must be treated either as a "PermError" or as non-existent and thus a no-match. (In particular, those cases can never cause a TempError because the error is guaranteed to reoccur given the same input data. This applies likewise to RFC-1035-invalid s that are the result of macro expansion.) Refined descriptions and comments to that end. The no-match behavior can be inferred by analogy from 4.3/1 and 5/10/3. The spec reference to 8.1/2 is bogus because the formal grammar does not preclude such invalid domain names. ! The "exp= without domain-spec" controversy has been resolved; it must be a syntax error. Tightened "exp-empty-domain" test case accordingly. ! Added test cases: ! "a-dash-in-toplabel": may contain dashes. Implementations matching non-greedily may get that wrong. ! "a-only-toplabel", "a-only-toplabel-trailing-dot": Both "a:museum" and "a:museum." are invalid syntax. A bare top-label is insufficient, with or without a trailing dot. ! "exp-no-txt", "exp-dns-error": Clearly, "exp=" referring to a non-existent TXT RR, or the look-up resulting in a DNS error, must cause the "exp=" modifier to be ignored per 6.2/4. ! "macro-mania-in-domain": Test macro-encoded percents (%%), spaces (%_), and URL-percent-encoded spaces (%20) in . ! "macro-reverse-split-on-dash": Test transformation of macro expansion results: splitting on non-dot separator characters, reversal, number of right-hand parts to use. - Removed "a-valid-syntax-but-unqueryable" test case. It is redundant to the "invalid-domain-empty-label" test case. - Relaxed "multispf1" test case: If performed via live DNS (yes, some people do that!), this test may be ineffective as DNS resolvers may combine multiple identical RRs. Thus, tolerate the test failing in this manner. * Adjusted "multispf2" test case: Avoid combination of multiple identical RRs by using different capitalization in intentionally duplicate RRs. * Renamed test cases: a-numeric-top-label -> a-numeric-toplabel a-bad-toplab -> a-bad-toplabel --- 2007.05 (2007-05-30 21:00) - "exp-empty-domain" test case is subject to controversy. "exp=" with an empty domain-spec may be considered a syntax error or not, thus both "Fail" and "PermError" results are acceptable for now. * Renamed the old "exp-syntax-error" test case to "explanation-syntax-error" to indicate that it refers to syntax errors in the explanation string, not in the "exp=" modifier. ! Added test cases: ! "exp-syntax-error", "redirect-syntax-error": Syntax errors in "exp=" and "redirect=" must be treated as such. ! "a-empty-domain", "mx-empty-domain", "ptr-empty-domain", "include-empty-domain", "redirect-empty-domain": "a:", "mx:", "ptr:", "include:", and "redirect=" with an empty domain-spec are syntax errors. ! "include-cidr": "include:/" is a syntax error. ! "helo-not-fqdn", "helo-domain-literal", "domain-literal": A non-FQDN HELO or MAIL FROM must result in a "None" result. ! "hello-domain-literal": Macro expansion results must not be checked for syntax errors, but must rather be treated as non-matches if nonsensical. ! "false-a-limit": There is no limit for the number of A records resulting from an "a:"-induced lookup, and no such limit must be imposed. ! "default-modifier-obsolete(2)": The "default=" modifier used in very old spec drafts must be ignored by RFC 4408 implementations. --- 2007.01 (2007-01-14 05:19) ! Added test cases: ! "nospftxttimeout": If no SPF-type record is present and the TXT lookup times out, the result must either be "None" (preferred) or "TempError". ! "exp-multiple-txt", "exp-syntax-error": Multiple explanation string TXT records and syntax errors in explanation strings must be ignored (i.e., specifically "PermError" must NOT be returned). ! "exp-empty-domain": "exp=" with an empty domain-spec is to be tolerated, i.e., ignored, too. (This is under debate.) ! "exp-twice", "redirect-twice": Added. Multiple "exp=" or "redirect=" modifiers are prohibited. * "Macro expansion rules" scenario: Fixed a bug that caused TXT-only implementations to fail several tests incorrectly due to a real TXT record blocking the automatic synthesis of TXT records from the corresponding SPF-type records. --- 2006.11 (initial release) (2006-11-27 21:27) # $Id$ # vim:tw=79 sts=2 sw=2 golang-blitiri-go-spf-1.3.0/testdata/rfc7208-tests.LICENSE000066400000000000000000000030271414622751200226650ustar00rootroot00000000000000The RFC 7208 test-suite (rfc7208-tests.yml) is (C) 2006-2008 Stuart D Gathman 2007-2008 Julian Mehnle 2014 Scott Kitterman All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. golang-blitiri-go-spf-1.3.0/testdata/rfc7208-tests.yml000066400000000000000000002336661414622751200224220ustar00rootroot00000000000000# This is the openspf.org test suite (release 2014.04) based on RFC 7208. # http://www.openspf.org/Test_Suite # # $Id$ # vim:sw=2 sts=2 et # # See rfc7208-tests.CHANGES for a changelog. # # Contributors: # Stuart D Gathman 90% of the tests # Julian Mehnle some tests, proofread YAML syntax, formal schema # Frank Ellermann # Scott Kitterman # Wayne Schlitt # Craig Whitmore # Norman Maurer # Mark Shewmaker # Philip Gladstone # # For RFC 4408, the test suite was designed for use with SPF (type 99) and TXT # implementations. In RFC 7208, use of type SPF has been removed. # # The "Selecting records" test section is the only one concerned with weeding # out (incorrect) queries for type SPF of any kind or proper response to # duplicate or conflicting records. Other sections rely on auto-magic # duplication of SPF to TXT records (by test suite drivers) to test all # implementation types with one specification. # # All new tests should use Documentation IPs for both IP4 and IP6. I was # stupid to use 1.2.3.4 - that is a real global IP (although it doesn't ping). # --- description: Initial processing tests: toolonglabel: description: >- DNS labels limited to 63 chars. comment: >- For initial processing, a long label results in None, not TempError spec: 4.3/1 helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@A123456789012345678901234567890123456789012345678901234567890123.example.com result: none longlabel: description: >- DNS labels limited to 63 chars. spec: 4.3/1 helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@A12345678901234567890123456789012345678901234567890123456789012.example.com result: fail emptylabel: spec: 4.3/1 helo: mail.example.net host: 1.2.3.5 mailfrom: lyme.eater@A...example.com result: none helo-not-fqdn: spec: 4.3/1 helo: A2345678 host: 1.2.3.5 mailfrom: "" result: none helo-domain-literal: spec: 4.3/1 helo: "[1.2.3.5]" host: 1.2.3.5 mailfrom: "" result: none nolocalpart: spec: 4.3/2 helo: mail.example.net host: 1.2.3.4 mailfrom: '@example.net' result: fail explanation: postmaster domain-literal: spec: 4.3/1 helo: OEMCOMPUTER host: 1.2.3.5 mailfrom: "foo@[1.2.3.5]" result: none non-ascii-policy: description: >- SPF policies are restricted to 7-bit ascii. spec: 3.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@hosed.example.com" result: permerror skip: We don't enforce 7-bit ascii. non-ascii-mech: description: >- SPF policies are restricted to 7-bit ascii. comment: >- Checking a possibly different code path for non-ascii chars. spec: 3.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@hosed2.example.com" result: permerror skip: We don't enforce 7-bit ascii. non-ascii-result: description: >- SPF policies are restricted to 7-bit ascii. comment: >- Checking yet another code path for non-ascii chars. spec: 3.1/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@hosed3.example.com" result: permerror non-ascii-non-spf: description: >- Non-ascii content in non-SPF related records. comment: >- Non-SPF related TXT records are none of our business. spec: 4.5/1 helo: hosed host: 1.2.3.4 mailfrom: "foobar@nothosed.example.com" result: fail explanation: DEFAULT control-char-policy: description: >- Mechanisms are separated by spaces only, not any control char. spec: 4.6.1/2 helo: hosed host: 192.0.2.3 mailfrom: "foobar@ctrl.example.com" result: permerror skip: We fail instead of permerror because we don't enforce the charset. two-spaces: description: >- ABNF for term separation is one or more spaces, not just one. spec: 4.6.1 helo: hosed host: 1.2.3.4 mailfrom: "actually@fine.example.com" result: fail trailing-space: description: >- ABNF for record does allow trailing spaces. comment: >- record = version terms *SP spec: 4.5/2 helo: hosed host: 192.0.2.5 mailfrom: "silly@trail.example.com" result: fail null-text: description: >- Multiple strings are glued together with no separator. comment: >- Note that null text (no strings) is illegal, but SPF should not crash. spec: 3.3 helo: hosed host: 192.0.2.5 mailfrom: "silly@null.example.com" result: pass zonedata: example.com: - TIMEOUT: true example.net: - SPF: v=spf1 -all exp=exp.example.net a.example.net: - SPF: v=spf1 -all exp=exp.example.net exp.example.net: - TXT: '%{l}' a12345678901234567890123456789012345678901234567890123456789012.example.com: - SPF: v=spf1 -all hosed.example.com: - SPF: "v=spf1 a:\xEF\xBB\xBFgarbage.example.net -all" hosed2.example.com: - SPF: "v=spf1 \x80a:example.net -all" hosed3.example.com: - SPF: "v=spf1 a:example.net \x96all" nothosed.example.com: - SPF: "v=spf1 a:example.net -all" - SPF: "\x96" ctrl.example.com: - SPF: "v=spf1 a:ctrl.example.com\x0dptr -all" - A: 192.0.2.3 fine.example.com: - SPF: "v=spf1 a -all" trail.example.com: - SPF: "v=spf1 a -all " null.example.com: - SPF: [ "v=spf1 ip4:", "192.0.2.5 -all" ] - SPF: [ ] --- description: Record lookup tests: both: spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@both.example.net result: fail txtonly: description: Result is none if checking SPF records only (which you should not be doing). spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@txtonly.example.net result: fail spfonly: description: Result is none if checking TXT records only. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@spfonly.example.net result: none spftimeout: description: >- TXT record present, but SPF lookup times out. Result is temperror if checking SPF records only. Fortunately, we don't do type SPF anymore. comment: >- This actually happens for a popular braindead DNS server. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@spftimeout.example.net result: fail skip: We don't use SPF records, it's ok to temperror here. txttimeout: description: >- SPF record present, but TXT lookup times out. If only TXT records are checked, result is temperror. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@txttimeout.example.net result: temperror nospftxttimeout: description: >- No SPF record present, and TXT lookup times out. If only TXT records are checked, result is temperror. comment: >- Because TXT records is where v=spf1 records will likely be, returning temperror will try again later. A timeout due to a braindead server is unlikely in the case of TXT, as opposed to the newer SPF RR. spec: 4.4/1 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@nospftxttimeout.example.net result: temperror alltimeout: description: Both TXT and SPF queries time out spec: 4.4/2 helo: mail.example.net host: 1.2.3.4 mailfrom: foo@alltimeout.example.net result: temperror zonedata: both.example.net: - TXT: v=spf1 -all - SPF: v=spf1 -all txtonly.example.net: - TXT: v=spf1 -all spfonly.example.net: - SPF: v=spf1 -all - TXT: NONE spftimeout.example.net: - TXT: v=spf1 -all - TIMEOUT: true txttimeout.example.net: - SPF: v=spf1 -all - TXT: NONE - TIMEOUT: true nospftxttimeout.example.net: - SPF: "v=spf3 !a:yahoo.com -all" - TXT: NONE - TIMEOUT: true alltimeout.example.net: - TIMEOUT: true --- description: Selecting records tests: nospace1: description: >- Version must be terminated by space or end of record. TXT pieces are joined without intervening spaces. spec: 4.5/4 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example2.com result: none empty: description: Empty SPF record. spec: 4.5/4 helo: mail1.example1.com host: 1.2.3.4 mailfrom: foo@example1.com result: neutral nospace2: spec: 4.5/4 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example3.com result: pass spfoverride: description: >- SPF records no longer used. spec: 4.5/5 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example4.com result: fail multitxt1: description: >- Implementations should give permerror/unknown because of the conflicting TXT records. spec: 4.5/5 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example5.com result: permerror multitxt2: description: >- Multiple records is a permerror, v=spf1 is case insensitive spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example6.com result: permerror multispf1: description: >- Multiple records is a permerror, even when they are identical. However, this situation cannot be reliably reproduced with live DNS since cache and resolvers are allowed to combine identical records. spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example7.com result: [permerror, fail] multispf2: description: >- Ignoring SPF-type records will give pass because there is a (single) TXT record. spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example8.com result: pass nospf: spec: 4.5/7 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@mail.example1.com result: none case-insensitive: description: >- v=spf1 is case insensitive spec: 4.5/6 helo: mail.example1.com host: 1.2.3.4 mailfrom: foo@example9.com result: softfail zonedata: example3.com: - SPF: v=spf10 - SPF: v=spf1 mx - MX: [0, mail.example1.com] example1.com: - SPF: v=spf1 example2.com: - SPF: ['v=spf1', 'mx'] mail.example1.com: - A: 1.2.3.4 example4.com: - SPF: v=spf1 +all - TXT: v=spf1 -all example5.com: - SPF: v=spf1 +all - TXT: v=spf1 -all - TXT: v=spf1 +all example6.com: - SPF: v=spf1 -all - SPF: V=sPf1 +all example7.com: - SPF: v=spf1 -all - SPF: v=spf1 -all example8.com: - SPF: V=spf1 -all - SPF: v=spf1 -all - TXT: v=spf1 +all example9.com: - SPF: v=SpF1 ~all --- description: Record evaluation tests: detect-errors-anywhere: description: Any syntax errors anywhere in the record MUST be detected. spec: 4.6 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t1.example.com result: permerror skip: We don't catch errors after a match. modifier-charset-good: description: name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) spec: 4.6.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t2.example.com result: pass skip: We don't enforce the domain charset. modifier-charset-bad1: description: >- '=' character immediately after the name and before any ":" or "/" spec: 4.6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t3.example.com result: permerror modifier-charset-bad2: description: >- '=' character immediately after the name and before any ":" or "/" spec: 4.6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t4.example.com result: permerror redirect-after-mechanisms1: description: >- The "redirect" modifier has an effect after all the mechanisms. comment: >- The redirect in this example would violate processing limits, except that it is never used because of the all mechanism. spec: 4.6.3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t5.example.com result: softfail redirect-after-mechanisms2: description: >- The "redirect" modifier has an effect after all the mechanisms. spec: 4.6.3 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@t6.example.com result: fail skip: Not worth the complexity of erroring on this. default-result: description: Default result is neutral. spec: 4.7/1 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@t7.example.com result: neutral redirect-is-modifier: description: |- Invalid mechanism. Redirect is a modifier. spec: 4.6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t8.example.com result: permerror skip: We don't catch errors after a match. invalid-domain: description: >- Domain-spec must end in macro-expand or valid toplabel. spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t9.example.com result: permerror skip: We don't enforce TLD structure. invalid-domain-empty-label: description: >- target-name that is a valid domain-spec per RFC 4408 and RFC 7208 but an invalid domain name per RFC 1035 (empty label) should be treated as non-existent. comment: >- An empty domain label, i.e. two successive dots, in a mechanism target-name is valid domain-spec syntax (perhaps formed from a macro expansion), even though a DNS query cannot be composed from it. The spec being unclear about it, this could either be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the mechanism could be treated as a no-match. RFC 7208 failed to agree on which result to use, and declares the situation undefined. The preferred test result is therefore a matter of opinion. spec: 4.3/1, 4.8/5, 5/10/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t10.example.com result: [fail, permerror] invalid-domain-long: description: >- target-name that is a valid domain-spec per RFC 4408 and RFC 7208 but an invalid domain name per RFC 1035 (long label) must be treated as non-existent. comment: >- A domain label longer than 63 characters in a mechanism target-name is valid domain-spec syntax (perhaps formed from a macro expansion), even though a DNS query cannot be composed from it. The spec being unclear about it, this could either be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the mechanism could be treated as a no-match. RFC 7208 failed to agree on which result to use, and declares the situation undefined. The preferred test result is therefore a matter of opinion. spec: 4.3/1, 4.8/5, 5/10/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@t11.example.com result: [fail,permerror] invalid-domain-long-via-macro: description: >- target-name that is a valid domain-spec per RFC 4408 and RFC 7208 but an invalid domain name per RFC 1035 (long label) must be treated as non-existent. comment: >- A domain label longer than 63 characters that results from macro expansion in a mechanism target-name is valid domain-spec syntax (and is not even subject to syntax checking after macro expansion), even though a DNS query cannot be composed from it. The spec being unclear about it, this could either be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the mechanism could be treated as a no-match. RFC 7208 failed to agree on which result to use, and declares the situation undefined. The preferred test result is therefore a matter of opinion. spec: 4.3/1, 4.8/5, 5/10/3 helo: "%%%%%%%%%%%%%%%%%%%%%%" host: 1.2.3.4 mailfrom: foo@t12.example.com result: [fail,permerror] zonedata: mail.example.com: - A: 1.2.3.4 t1.example.com: - SPF: v=spf1 ip4:1.2.3.4 -all moo t2.example.com: - SPF: v=spf1 moo.cow-far_out=man:dog/cat ip4:1.2.3.4 -all t3.example.com: - SPF: v=spf1 moo.cow/far_out=man:dog/cat ip4:1.2.3.4 -all t4.example.com: - SPF: v=spf1 moo.cow:far_out=man:dog/cat ip4:1.2.3.4 -all t5.example.com: - SPF: v=spf1 redirect=t5.example.com ~all t6.example.com: - SPF: v=spf1 ip4:1.2.3.4 redirect=t2.example.com t7.example.com: - SPF: v=spf1 ip4:1.2.3.4 t8.example.com: - SPF: v=spf1 ip4:1.2.3.4 redirect:t2.example.com t9.example.com: - SPF: v=spf1 a:foo-bar -all t10.example.com: - SPF: v=spf1 a:mail.example...com -all t11.example.com: - SPF: v=spf1 a:a123456789012345678901234567890123456789012345678901234567890123.example.com -all t12.example.com: - SPF: v=spf1 a:%{H}.bar -all --- description: ALL mechanism syntax tests: all-dot: description: | all = "all" comment: |- At least one implementation got this wrong spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror all-arg: description: | all = "all" comment: |- At least one implementation got this wrong spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: permerror all-cidr: description: | all = "all" spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror all-neutral: description: | all = "all" spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: neutral all-double: description: | all = "all" spec: 5.1/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: pass zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 -all. e2.example.com: - SPF: v=spf1 -all:foobar e3.example.com: - SPF: v=spf1 -all/8 e4.example.com: - SPF: v=spf1 ?all e5.example.com: - SPF: v=spf1 all -all --- description: PTR mechanism syntax tests: ptr-cidr: description: |- PTR = "ptr" [ ":" domain-spec ] spec: 5.5/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror ptr-match-target: description: >- Check all validated domain names to see if they end in the domain. spec: 5.5/5 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass ptr-match-implicit: description: >- Check all validated domain names to see if they end in the domain. spec: 5.5/5 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: pass ptr-nomatch-invalid: description: >- Check all validated domain names to see if they end in the domain. comment: >- This PTR record does not validate spec: 5.5/5 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: fail ptr-match-ip6: description: >- Check all validated domain names to see if they end in the domain. spec: 5.5/5 helo: mail.example.com host: CAFE:BABE::1 mailfrom: foo@e3.example.com result: pass ptr-empty-domain: description: >- domain-spec cannot be empty. spec: 5.5/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror ptr-case-change: description: >- arpa domain is case insensitive. comment: >- Some DNS servers have random case in the domain part of returned answers, especially for PTR records. For example, a query for 1.2.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.F.0.0.4.F.1.1.1.0.1.0.A.2.ip6.arpa may return 1.2.6.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.F.0.0.4.F.1.1.1.0.1.0.a.2.ip6.arpa spec: 5.5/2 helo: mail.example.com host: 2001:db8::1 mailfrom: bar@e6.example.com result: pass ptr-cname-loop: description: >- a PTR with CNAME loop and inconsistent case in domain. comment: >- RFC 1034 3.6.2/11 says, CNAME chains should be followed and CNAME loops signalled as an error. RFC 7208 5.5/7 says, If a DNS error occurs while doing an A RR lookup, then that domain name is skipped and the search continues. spec: 5.5/7 helo: loop.example.com host: 192.0.2.4 mailfrom: postmaster@loop.example.com result: neutral zonedata: mail.example.com: - A: 1.2.3.4 - AAAA: 2001:db8::1 e1.example.com: - SPF: v=spf1 ptr/0 -all e2.example.com: - SPF: v=spf1 ptr:example.com -all 4.3.2.1.in-addr.arpa: - PTR: e3.example.com - PTR: e4.example.com - PTR: mail.example.com 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa: - PTR: e3.example.com 1.0.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.ip6.arpa: - PTR: mail.Example.com e3.example.com: - SPF: v=spf1 ptr -all - A: 1.2.3.4 - AAAA: CAFE:BABE::1 e4.example.com: - SPF: v=spf1 ptr -all e5.example.com: - SPF: "v=spf1 ptr:" e6.example.com: - SPF: "v=spf1 ptr:example.Com -all" loop.example.com: - SPF: "v=spf1 ptr" 4.2.0.192.in-addr.arpa: - PTR: "loop4.example.com." loop4.example.com: - CNAME: "CNAME.example.com." cname.example.com: - CNAME: "CNAME.example.com." --- description: A mechanism syntax tests: a-cidr6: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: fail a-bad-cidr4: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6a.example.com result: permerror a-bad-cidr6: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror a-dual-cidr-ip4-match: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: pass a-dual-cidr-ip4-err: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8e.example.com result: permerror a-dual-cidr-ip6-match: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 2001:db8:1234::cafe:babe mailfrom: foo@e8.example.com result: pass a-dual-cidr-ip4-default: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8b.example.com result: fail a-dual-cidr-ip6-default: description: | A = "a" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.3/2 helo: mail.example.com host: 2001:db8:1234::cafe:babe mailfrom: foo@e8a.example.com result: fail a-multi-ip1: description: >- A matches any returned IP. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass a-multi-ip2: description: >- A matches any returned IP. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass a-bad-domain: description: >- domain-spec must pass basic syntax checks; a ':' may appear in domain-spec, but not in top-label spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror skip: We don't enforce domain charset. a-nxdomain: description: >- If no ips are returned, A mechanism does not match, even with /0. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: fail a-cidr4-0: description: >- Matches if any A records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass a-cidr4-0-ip6: description: >- Matches if any A records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2.example.com result: fail a-cidr6-0-ip4: description: >- Would match if any AAAA records are present in DNS, but not for an IP4 connection. spec: 5.3/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2a.example.com result: fail a-cidr6-0-ip4mapped: description: >- Would match if any AAAA records are present in DNS, but not for an IP4 connection. spec: 5.3/3 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e2a.example.com result: fail a-cidr6-0-ip6: description: >- Matches if any AAAA records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2a.example.com result: pass a-ip6-dualstack: description: >- Simple IP6 Address match with dual stack. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@ipv6.example.com result: pass a-cidr6-0-nxdomain: description: >- No match if no AAAA records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2b.example.com result: fail a-null: description: >- Null octets not allowed in toplabel spec: 7.1/2 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e3.example.com result: permerror skip: We don't enforce charset. a-numeric: description: >- toplabel may not be all numeric comment: >- A common publishing mistake is using ip4 addresses with A mechanism. This should receive special diagnostic attention in the permerror. spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: permerror skip: We don't enforce domain structure. a-numeric-toplabel: description: >- toplabel may not be all numeric spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror skip: We don't enforce TLD structure. a-dash-in-toplabel: description: >- toplabel may contain dashes comment: >- Going from the "toplabel" grammar definition, an implementation using regular expressions in incrementally parsing SPF records might erroneously try to match a TLD such as ".xn--zckzah" (cf. IDN TLDs!) to '( *alphanum ALPHA *alphanum )' first before trying the alternative '( 1*alphanum "-" *( alphanum / "-" ) alphanum )', essentially causing a non-greedy, and thus, incomplete match. Make sure a greedy match is performed! spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e14.example.com result: pass a-bad-toplabel: description: >- toplabel may not begin with a dash spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: permerror skip: We don't enforce TLD structure. a-only-toplabel: description: >- domain-spec may not consist of only a toplabel. spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5a.example.com result: permerror skip: We don't enforce TLD structure. a-only-toplabel-trailing-dot: description: >- domain-spec may not consist of only a toplabel. comment: >- "A trailing dot doesn't help." spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5b.example.com result: permerror skip: We don't enforce TLD structure. a-colon-domain: description: >- domain-spec may contain any visible char except % spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity a-colon-domain-ip4mapped: description: >- domain-spec may contain any visible char except % spec: 7.1/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity a-empty-domain: description: >- domain-spec cannot be empty. spec: 5.3/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e13.example.com result: permerror skip: Not worth the complexity of erroring on this. zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 a/0 -all e2.example.com: - A: 1.1.1.1 - AAAA: 1234::2 - SPF: v=spf1 a/0 -all e2a.example.com: - AAAA: 1234::1 - SPF: v=spf1 a//0 -all e2b.example.com: - A: 1.1.1.1 - SPF: v=spf1 a//0 -all ipv6.example.com: - AAAA: 1234::1 - A: 1.1.1.1 - SPF: v=spf1 a -all e3.example.com: - SPF: "v=spf1 a:foo.example.com\0" e4.example.com: - SPF: v=spf1 a:111.222.33.44 e5.example.com: - SPF: v=spf1 a:abc.123 e5a.example.com: - SPF: v=spf1 a:museum e5b.example.com: - SPF: v=spf1 a:museum. e6.example.com: - SPF: v=spf1 a//33 -all e6a.example.com: - SPF: v=spf1 a/33 -all e7.example.com: - SPF: v=spf1 a//129 -all e8.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a/24//64 -all e8e.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a/24/64 -all e8a.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a/24 -all e8b.example.com: - A: 1.2.3.5 - AAAA: 2001:db8:1234::dead:beef - SPF: v=spf1 a//64 -all e9.example.com: - SPF: v=spf1 a:example.com:8080 e10.example.com: - SPF: v=spf1 a:foo.example.com/24 foo.example.com: - A: 1.1.1.1 - A: 1.2.3.5 e11.example.com: - SPF: v=spf1 a:foo:bar/baz.example.com foo:bar/baz.example.com: - A: 1.2.3.4 e12.example.com: - SPF: v=spf1 a:example.-com e13.example.com: - SPF: "v=spf1 a:" e14.example.com: - SPF: "v=spf1 a:foo.example.xn--zckzah -all" foo.example.xn--zckzah: - A: 1.2.3.4 --- description: Include mechanism semantics and syntax tests: include-fail: description: >- recursive check_host() result of fail causes include to not match. spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: softfail include-softfail: description: >- recursive check_host() result of softfail causes include to not match. spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass include-neutral: description: >- recursive check_host() result of neutral causes include to not match. spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: fail include-temperror: description: >- recursive check_host() result of temperror causes include to temperror spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: temperror include-permerror: description: >- recursive check_host() result of permerror causes include to permerror spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror include-syntax-error: description: >- include = "include" ":" domain-spec spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror include-cidr: description: >- include = "include" ":" domain-spec spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror include-none: description: >- recursive check_host() result of none causes include to permerror spec: 5.2/9 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror include-empty-domain: description: >- domain-spec cannot be empty. spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: permerror zonedata: mail.example.com: - A: 1.2.3.4 ip5.example.com: - SPF: v=spf1 ip4:1.2.3.5 -all ip6.example.com: - SPF: v=spf1 ip4:1.2.3.6 ~all ip7.example.com: - SPF: v=spf1 ip4:1.2.3.7 ?all ip8.example.com: - TIMEOUT: true erehwon.example.com: - TXT: v=spfl am not an SPF record e1.example.com: - SPF: v=spf1 include:ip5.example.com ~all e2.example.com: - SPF: v=spf1 include:ip6.example.com all e3.example.com: - SPF: v=spf1 include:ip7.example.com -all e4.example.com: - SPF: v=spf1 include:ip8.example.com -all e5.example.com: - SPF: v=spf1 include:e6.example.com -all e6.example.com: - SPF: v=spf1 include +all e7.example.com: - SPF: v=spf1 include:erehwon.example.com -all e8.example.com: - SPF: "v=spf1 include: -all" e9.example.com: - SPF: "v=spf1 include:ip5.example.com/24 -all" --- description: MX mechanism syntax tests: mx-cidr6: description: | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.4/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: fail mx-bad-cidr4: description: | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.4/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6a.example.com result: permerror mx-bad-cidr6: description: | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] spec: 5.4/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror mx-multi-ip1: description: >- MX matches any returned IP. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass mx-multi-ip2: description: >- MX matches any returned IP. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: pass mx-bad-domain: description: >- domain-spec must pass basic syntax checks comment: >- A ':' may appear in domain-spec, but not in top-label. spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror skip: We don't enforce domain syntax. mx-nxdomain: description: >- If no ips are returned, MX mechanism does not match, even with /0. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: fail mx-cidr4-0: description: >- Matches if any A records for any MX records are present in DNS. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass mx-cidr4-0-ip6: description: >- cidr4 doesn't apply to IP6 connections. comment: >- The IP6 CIDR starts with a double slash. spec: 5.4/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2.example.com result: fail mx-cidr6-0-ip4: description: >- Would match if any AAAA records for MX records are present in DNS, but not for an IP4 connection. spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2a.example.com result: fail mx-cidr6-0-ip4mapped: description: >- Would match if any AAAA records for MX records are present in DNS, but not for an IP4 connection. spec: 5.4/3 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e2a.example.com result: fail mx-cidr6-0-ip6: description: >- Matches if any AAAA records for any MX records are present in DNS. spec: 5.3/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2a.example.com result: pass mx-cidr6-0-nxdomain: description: >- No match if no AAAA records for any MX records are present in DNS. spec: 5.4/3 helo: mail.example.com host: 1234::1 mailfrom: foo@e2b.example.com result: fail mx-null: description: >- Null not allowed in top-label. spec: 7.1/2 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e3.example.com result: permerror skip: We don't enforce charset. mx-numeric-top-label: description: >- Top-label may not be all numeric spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror skip: We don't validate top-level domains. mx-colon-domain: description: >- Domain-spec may contain any visible char except % spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity mx-colon-domain-ip4mapped: description: >- Domain-spec may contain any visible char except % spec: 7.1/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e11.example.com result: pass skip: Allowing / in domain names is not worth the complexity mx-bad-toplab: description: >- Toplabel may not begin with - spec: 7.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: permerror skip: We don't enforce TLD structure. mx-empty: description: >- test null MX comment: >- Some implementations have had trouble with null MX spec: 5.4/3 helo: mail.example.com host: 1.2.3.4 mailfrom: "" result: neutral mx-implicit: description: >- If the target name has no MX records, check_host() MUST NOT pretend the target is its single MX, and MUST NOT default to an A lookup on the target-name directly. spec: 5.4/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: neutral mx-empty-domain: description: >- domain-spec cannot be empty. spec: 5.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e13.example.com result: permerror skip: Not worth the complexity of erroring on this. zonedata: mail.example.com: - A: 1.2.3.4 - MX: [0, ""] - SPF: v=spf1 mx e1.example.com: - SPF: v=spf1 mx/0 -all - MX: [0, e1.example.com] e2.example.com: - A: 1.1.1.1 - AAAA: 1234::2 - MX: [0, e2.example.com] - SPF: v=spf1 mx/0 -all e2a.example.com: - AAAA: 1234::1 - MX: [0, e2a.example.com] - SPF: v=spf1 mx//0 -all e2b.example.com: - A: 1.1.1.1 - MX: [0, e2b.example.com] - SPF: v=spf1 mx//0 -all e3.example.com: - SPF: "v=spf1 mx:foo.example.com\0" e4.example.com: - SPF: v=spf1 mx - A: 1.2.3.4 e5.example.com: - SPF: v=spf1 mx:abc.123 e6.example.com: - SPF: v=spf1 mx//33 -all e6a.example.com: - SPF: v=spf1 mx/33 -all e7.example.com: - SPF: v=spf1 mx//129 -all e9.example.com: - SPF: v=spf1 mx:example.com:8080 e10.example.com: - SPF: v=spf1 mx:foo.example.com/24 foo.example.com: - MX: [0, foo1.example.com] foo1.example.com: - A: 1.1.1.1 - A: 1.2.3.5 e11.example.com: - SPF: v=spf1 mx:foo:bar/baz.example.com foo:bar/baz.example.com: - MX: [0, "foo:bar/baz.example.com"] - A: 1.2.3.4 e12.example.com: - SPF: v=spf1 mx:example.-com e13.example.com: - SPF: "v=spf1 mx: -all" --- description: EXISTS mechanism syntax tests: exists-empty-domain: description: >- domain-spec cannot be empty. spec: 5.7/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror exists-implicit: description: >- exists = "exists" ":" domain-spec spec: 5.7/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: permerror exists-cidr: description: >- exists = "exists" ":" domain-spec spec: 5.7/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror exists-ip4: description: >- mechanism matches if any DNS A RR exists spec: 5.7/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: pass exists-ip6: description: >- The lookup type is A even when the connection is ip6 spec: 5.7/3 helo: mail.example.com host: CAFE:BABE::3 mailfrom: foo@e4.example.com result: pass exists-ip6only: description: >- The lookup type is A even when the connection is ip6 spec: 5.7/3 helo: mail.example.com host: CAFE:BABE::3 mailfrom: foo@e5.example.com result: fail exists-dnserr: description: >- Result for DNS error clarified in RFC7208: MTAs or other processors SHOULD impose a limit on the maximum amount of elapsed time to evaluate check_host(). Such a limit SHOULD allow at least 20 seconds. If such a limit is exceeded, the result of authorization SHOULD be "temperror". spec: 5/8 helo: mail.example.com host: CAFE:BABE::3 mailfrom: foo@e6.example.com result: temperror zonedata: mail.example.com: - A: 1.2.3.4 mail6.example.com: - AAAA: CAFE:BABE::4 err.example.com: - TIMEOUT: true e1.example.com: - SPF: "v=spf1 exists:" e2.example.com: - SPF: "v=spf1 exists" e3.example.com: - SPF: "v=spf1 exists:mail.example.com/24" e4.example.com: - SPF: "v=spf1 exists:mail.example.com" e5.example.com: - SPF: "v=spf1 exists:mail6.example.com -all" e6.example.com: - SPF: "v=spf1 exists:err.example.com -all" --- description: IP4 mechanism syntax tests: cidr4-0: description: >- ip4-cidr-length = "/" 1*DIGIT spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: pass cidr4-32: description: >- ip4-cidr-length = "/" 1*DIGIT spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: pass cidr4-33: description: >- Invalid CIDR should get permerror. comment: >- The RFC4408 was silent on ip4 CIDR > 32 or ip6 CIDR > 128, but RFC7208 is explicit. Invalid CIDR is prohibited. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror cidr4-032: description: >- Invalid CIDR should get permerror. comment: >- Leading zeros are not explicitly prohibited by the RFC. However, since the RFC explicity prohibits leading zeros in ip4-network, our interpretation is that CIDR should be also. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: permerror skip: It's not clear this is problematic. bare-ip4: description: >- IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror bad-ip4-port: description: >- IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] comment: >- This has actually been published in SPF records. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: permerror bad-ip4-short: description: >- It is not permitted to omit parts of the IP address instead of using CIDR notations. spec: 5.6/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror ip4-dual-cidr: description: >- dual-cidr-length not permitted on ip4 spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror ip4-mapped-ip6: description: >- IP4 mapped IP6 connections MUST be treated as IP4 spec: 5/9/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e7.example.com result: fail zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 ip4:1.1.1.1/0 -all e2.example.com: - SPF: v=spf1 ip4:1.2.3.4/32 -all e3.example.com: - SPF: v=spf1 ip4:1.2.3.4/33 -all e4.example.com: - SPF: v=spf1 ip4:1.2.3.4/032 -all e5.example.com: - SPF: v=spf1 ip4 e6.example.com: - SPF: v=spf1 ip4:1.2.3.4//32 e7.example.com: - SPF: v=spf1 -ip4:1.2.3.4 ip6:::FFFF:1.2.3.4 e8.example.com: - SPF: v=spf1 ip4:1.2.3.4:8080 e9.example.com: - SPF: v=spf1 ip4:1.2.3 --- description: IP6 mechanism syntax comment: >- IP4 only implementations may skip tests where host is not IP4 tests: bare-ip6: description: >- IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ] spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror skip: There's an early match. cidr6-0-ip4: description: >- IP4 connections do not match ip6. comment: >- There was controversy over IPv4 mapped connections. RFC7208 clearly states IPv4 mapped addresses only match ip4: mechanisms. spec: 5/9/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: neutral cidr6-ip4: description: >- Even if the SMTP connection is via IPv6, an IPv4-mapped IPv6 IP address (see RFC 3513, Section 2.5.5) MUST still be considered an IPv4 address. comment: >- There was controversy over ip4 mapped connections. RFC7208 clearly requires such connections to be considered as ip4 only. spec: 5/9/2 helo: mail.example.com host: ::FFFF:1.2.3.4 mailfrom: foo@e2.example.com result: neutral cidr6-0: description: >- Match any IP6 spec: 5/8 helo: mail.example.com host: DEAF:BABE::CAB:FEE mailfrom: foo@e2.example.com result: pass cidr6-129: description: >- Invalid CIDR comment: >- IP4 only implementations MUST fully syntax check all mechanisms, even if they otherwise ignore them. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: permerror cidr6-bad: description: >- dual-cidr syntax not used for ip6 comment: >- IP4 only implementations MUST fully syntax check all mechanisms, even if they otherwise ignore them. spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e4.example.com result: permerror cidr6-33: description: >- make sure ip4 cidr restriction are not used for ip6 spec: 5.6/2 helo: mail.example.com host: "CAFE:BABE:8000::" mailfrom: foo@e5.example.com result: pass cidr6-33-ip4: description: >- make sure ip4 cidr restriction are not used for ip6 spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: neutral ip6-bad1: description: >- spec: 5.6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 -all ip6 e2.example.com: - SPF: v=spf1 ip6:::1.1.1.1/0 e3.example.com: - SPF: v=spf1 ip6:::1.1.1.1/129 e4.example.com: - SPF: v=spf1 ip6:::1.1.1.1//33 e5.example.com: - SPF: v=spf1 ip6:Cafe:Babe:8000::/33 e6.example.com: - SPF: v=spf1 ip6::CAFE::BABE --- description: Semantics of exp and other modifiers comment: >- Implementing exp= is optional. If not implemented, the test driver should not check the explanation field. tests: redirect-none: description: >- If no SPF record is found, or if the target-name is malformed, the result is a "PermError" rather than "None". spec: 6.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e10.example.com result: permerror redirect-cancels-exp: description: >- when executing "redirect", exp= from the original domain MUST NOT be used. spec: 6.2/13 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: fail explanation: DEFAULT redirect-syntax-error: description: | redirect = "redirect" "=" domain-spec comment: >- A literal application of the grammar causes modifier syntax errors (except for macro syntax) to become unknown-modifier. modifier = explanation | redirect | unknown-modifier However, it is generally agreed, with precedent in other RFCs, that unknown-modifier should not be "greedy", and should not match known modifier names. There should have been explicit prose to this effect, and some has been proposed as an erratum. spec: 6.1/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e17.example.com result: permerror skip: We don't enforce charset within the redirect. include-ignores-exp: description: >- when executing "include", exp= from the target domain MUST NOT be used. spec: 6.2/13 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: fail explanation: Correct! redirect-cancels-prior-exp: description: >- when executing "redirect", exp= from the original domain MUST NOT be used. spec: 6.2/13 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e3.example.com result: fail explanation: See me. invalid-modifier: description: | unknown-modifier = name "=" macro-string name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) comment: >- Unknown modifier name must begin with alpha. spec: A/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e5.example.com result: permerror empty-modifier-name: description: | name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) comment: >- Unknown modifier name must not be empty. spec: A/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: permerror dorky-sentinel: description: >- An implementation that uses a legal expansion as a sentinel. We cannot check them all, but we can check this one. comment: >- Spaces are allowed in local-part. spec: 7.1/6 helo: mail.example.com host: 1.2.3.4 mailfrom: "Macro Error@e8.example.com" result: fail explanation: Macro Error in implementation exp-multiple-txt: description: | Ignore exp if multiple TXT records. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: fail explanation: DEFAULT exp-no-txt: description: | Ignore exp if no TXT records. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e22.example.com result: fail explanation: DEFAULT exp-dns-error: description: | Ignore exp if DNS error. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e21.example.com result: fail explanation: DEFAULT exp-empty-domain: description: | PermError if exp= domain-spec is empty. comment: >- Section 6.2/4 says, "If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given." However, "if domain-spec is empty" conflicts with the grammar given for the exp modifier. This was reported as an erratum, and the solution chosen was to report explicit "exp=" as PermError, but ignore problems due to macro expansion, DNS, or invalid explanation string. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: permerror skip: We ignore exp, and is harmless. explanation-syntax-error: description: | Ignore exp if the explanation string has a syntax error. comment: >- If domain-spec is empty, or there are any DNS processing errors (any RCODE other than 0), or if no records are returned, or if more than one record is returned, or if there are syntax errors in the explanation string, then proceed as if no exp modifier was given. spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e13.example.com result: fail explanation: DEFAULT exp-syntax-error: description: | explanation = "exp" "=" domain-spec comment: >- A literal application of the grammar causes modifier syntax errors (except for macro syntax) to become unknown-modifier. modifier = explanation | redirect | unknown-modifier However, it is generally agreed, with precedent in other RFCs, that unknown-modifier should not be "greedy", and should not match known modifier names. There should have been explicit prose to this effect, and some has been proposed as an erratum. spec: 6.2/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e16.example.com result: permerror skip: We don't enforce exp values. exp-twice: description: | exp= appears twice. comment: >- These two modifiers (exp,redirect) MUST NOT appear in a record more than once each. If they do, then check_host() exits with a result of "PermError". spec: 6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e14.example.com result: permerror skip: We ignore exp, and is harmless. redirect-empty-domain: description: | redirect = "redirect" "=" domain-spec comment: >- Unlike for exp, there is no instruction to override the permerror for an empty domain-spec (which is invalid syntax). spec: 6.2/4 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e18.example.com result: permerror skip: There's an early match. redirect-twice: description: | redirect= appears twice. comment: >- These two modifiers (exp,redirect) MUST NOT appear in a record more than once each. If they do, then check_host() exits with a result of "PermError". spec: 6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e15.example.com result: permerror unknown-modifier-syntax: description: | unknown-modifier = name "=" macro-string comment: >- Unknown modifiers must have valid macro syntax. spec: A/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror skip: There's an early match. default-modifier-obsolete: description: | Unknown modifiers do not modify the RFC SPF result. comment: >- Some implementations may have a leftover default= modifier from earlier drafts. spec: 6/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e19.example.com result: neutral skip: Not worth the complexity of erroring on this. default-modifier-obsolete2: description: | Unknown modifiers do not modify the RFC SPF result. comment: >- Some implementations may have a leftover default= modifier from earlier drafts. spec: 6/3 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e20.example.com result: neutral skip: Not worth the complexity of erroring on this. non-ascii-exp: description: >- SPF explanation text is restricted to 7-bit ascii. comment: >- Checking a possibly different code path for non-ascii chars. spec: 6.2/5 helo: hosed host: 1.2.3.4 mailfrom: "foobar@nonascii.example.com" result: fail explanation: DEFAULT two-exp-records: description: >- Must ignore exp= if DNS returns more than one TXT record. spec: 6.2/4 helo: hosed host: 1.2.3.4 mailfrom: "foobar@tworecs.example.com" result: fail explanation: DEFAULT exp-void: description: | exp=nxdomain.tld comment: >- Non-existent exp= domains MUST NOT count against the void lookup limit. Implementations should lookup any exp record at most once after computing the result. spec: 4.6.4/1, 6/2 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e23.example.com result: fail redirect-implicit: description: | redirect changes implicit domain spec: 6.1/4 helo: e24.example.com host: 192.0.2.2 mailfrom: bar@e24.example.com result: pass zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 exp=exp1.example.com redirect=e2.example.com e2.example.com: - SPF: v=spf1 -all e3.example.com: - SPF: v=spf1 exp=exp1.example.com redirect=e4.example.com e4.example.com: - SPF: v=spf1 -all exp=exp2.example.com exp1.example.com: - TXT: No-see-um exp2.example.com: - TXT: See me. exp3.example.com: - TXT: Correct! exp4.example.com: - TXT: "%{l} in implementation" e5.example.com: - SPF: v=spf1 1up=foo e6.example.com: - SPF: v=spf1 =all e7.example.com: - SPF: v=spf1 include:e3.example.com -all exp=exp3.example.com e8.example.com: - SPF: v=spf1 -all exp=exp4.example.com e9.example.com: - SPF: v=spf1 -all foo=%abc e10.example.com: - SPF: v=spf1 redirect=erehwon.example.com e11.example.com: - SPF: v=spf1 -all exp=e11msg.example.com e11msg.example.com: - TXT: Answer a fool according to his folly. - TXT: Do not answer a fool according to his folly. e12.example.com: - SPF: v=spf1 exp= -all e13.example.com: - SPF: v=spf1 exp=e13msg.example.com -all e13msg.example.com: - TXT: The %{x}-files. e14.example.com: - SPF: v=spf1 exp=e13msg.example.com -all exp=e11msg.example.com e15.example.com: - SPF: v=spf1 redirect=e12.example.com -all redirect=e12.example.com e16.example.com: - SPF: v=spf1 exp=-all e17.example.com: - SPF: v=spf1 redirect=-all ?all e18.example.com: - SPF: v=spf1 ?all redirect= e19.example.com: - SPF: v=spf1 default=pass e20.example.com: - SPF: "v=spf1 default=+" e21.example.com: - SPF: v=spf1 exp=e21msg.example.com -all e21msg.example.com: - TIMEOUT: true e22.example.com: - SPF: v=spf1 exp=mail.example.com -all nonascii.example.com: - SPF: v=spf1 exp=badexp.example.com -all badexp.example.com: - TXT: "\xEF\xBB\xBFExplanation" tworecs.example.com: - SPF: v=spf1 exp=twoexp.example.com -all twoexp.example.com: - TXT: "one" - TXT: "two" e23.example.com: - SPF: v=spf1 a:erehwon.example.com a:foobar.com exp=nxdomain.com -all e24.example.com: - SPF: v=spf1 redirect=testimplicit.example.com - A: 192.0.2.1 testimplicit.example.com: - SPF: v=spf1 a -all - A: 192.0.2.2 --- description: Macro expansion rules tests: trailing-dot-domain: spec: 7.1/16 description: >- trailing dot is ignored for domains helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@example.com result: pass trailing-dot-exp: spec: 7.1 description: >- trailing dot is not removed from explanation comment: >- A simple way for an implementation to ignore trailing dots on domains is to remove it when present. But be careful not to remove it for explanation text. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@exp.example.com result: fail explanation: This is a test. exp-only-macro-char: spec: 7.1/8 description: >- The following macro letters are allowed only in "exp" text: c, r, t helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e2.example.com result: permerror skip: We ignore exp, and is harmless. invalid-macro-char: spec: 7.1/9 description: >- A '%' character not followed by a '{', '%', '-', or '_' character is a syntax error. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e1.example.com result: permerror invalid-embedded-macro-char: spec: 7.1/9 description: >- A '%' character not followed by a '{', '%', '-', or '_' character is a syntax error. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e1e.example.com result: permerror invalid-trailing-macro-char: spec: 7.1/9 description: >- A '%' character not followed by a '{', '%', '-', or '_' character is a syntax error. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e1t.example.com result: permerror macro-mania-in-domain: description: >- macro-encoded percents (%%), spaces (%_), and URL-percent-encoded spaces (%-) spec: 7.1/3, 7.1/4 helo: mail.example.com host: 1.2.3.4 mailfrom: test@e1a.example.com result: pass exp-txt-macro-char: spec: 7.1/20 description: >- For IPv4 addresses, both the "i" and "c" macros expand to the standard dotted-quad format. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e3.example.com result: fail explanation: Connections from 192.168.218.40 not authorized. domain-name-truncation: spec: 7.1/25 description: >- When the result of macro expansion is used in a domain name query, if the expanded domain name exceeds 253 characters, the left side is truncated to fit, by removing successive domain labels until the total length does not exceed 253 characters. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@somewhat.long.exp.example.com result: fail explanation: Congratulations! That was tricky. v-macro-ip4: spec: 7.1/6 description: |- v = the string "in-addr" if is ipv4, or "ip6" if is ipv6 helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e4.example.com result: fail explanation: 192.168.218.40 is queried as 40.218.168.192.in-addr.arpa v-macro-ip6: spec: 7.1/6 description: |- v = the string "in-addr" if is ipv4, or "ip6" if is ipv6 helo: msgbas2x.cos.example.com host: CAFE:BABE::1 mailfrom: test@e4.example.com result: fail explanation: cafe:babe::1 is queried as 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa undef-macro: spec: 7.1/6 description: >- Allowed macros chars are 'slodipvh' plus 'crt' in explanation. helo: msgbas2x.cos.example.com host: CAFE:BABE::192.168.218.40 mailfrom: test@e5.example.com result: permerror p-macro-ip4-novalid: spec: 7.1/22 description: |- p = the validated domain name of comment: >- The PTR in this example does not validate. helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e6.example.com result: fail explanation: connect from unknown p-macro-ip4-valid: spec: 7.1/22 description: |- p = the validated domain name of comment: >- If a subdomain of the is present, it SHOULD be used. helo: msgbas2x.cos.example.com host: 192.168.218.41 mailfrom: test@e6.example.com result: fail explanation: connect from mx.example.com p-macro-ip6-novalid: spec: 7.1/22 description: |- p = the validated domain name of comment: >- The PTR in this example does not validate. helo: msgbas2x.cos.example.com host: CAFE:BABE::1 mailfrom: test@e6.example.com result: fail explanation: connect from unknown p-macro-ip6-valid: spec: 7.1/22 description: |- p = the validated domain name of comment: >- If a subdomain of the is present, it SHOULD be used. helo: msgbas2x.cos.example.com host: CAFE:BABE::3 mailfrom: test@e6.example.com result: fail explanation: connect from mx.example.com p-macro-multiple: spec: 7.1/22 description: |- p = the validated domain name of comment: >- If a subdomain of the is present, it SHOULD be used. helo: msgbas2x.cos.example.com host: 192.168.218.42 mailfrom: test@e7.example.com result: [pass, softfail] skip: p macro is not supported upper-macro: spec: 7.1/26 description: >- Uppercased macros expand exactly as their lowercased equivalents, and are then URL escaped. All chars not in the unreserved set MUST be escaped. comment: | unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" helo: msgbas2x.cos.example.com host: 192.168.218.42 mailfrom: ~jack&jill=up-a_b3.c@e8.example.com result: fail explanation: http://example.com/why.html?l=~jack%26jill%3Dup-a_b3.c hello-macro: spec: 7.1/6 description: |- h = HELO/EHLO domain helo: msgbas2x.cos.example.com host: 192.168.218.40 mailfrom: test@e9.example.com result: pass skip: We don't have a HELO-explicit mode. invalid-hello-macro: spec: 7.1/2 description: |- h = HELO/EHLO domain, but HELO is invalid comment: >- Domain-spec must end in either a macro, or a valid toplabel. It is not correct to check syntax after macro expansion. helo: "JUMPIN' JUPITER" host: 192.168.218.40 mailfrom: test@e9.example.com result: fail hello-domain-literal: spec: 7.1/2 description: |- h = HELO/EHLO domain, but HELO is a domain literal comment: >- Domain-spec must end in either a macro, or a valid toplabel. It is not correct to check syntax after macro expansion. helo: "[192.168.218.40]" host: 192.168.218.40 mailfrom: test@e9.example.com result: fail require-valid-helo: spec: 7.1/6 description: >- Example of requiring valid helo in sender policy. This is a complex policy testing several points at once. helo: OEMCOMPUTER host: 1.2.3.4 mailfrom: test@e10.example.com result: fail macro-reverse-split-on-dash: spec: 7.1/15, 7.1/16, 7.1/17, 7.1/18 description: >- Macro value transformation (splitting on arbitrary characters, reversal, number of right-hand parts to use) helo: mail.example.com host: 1.2.3.4 mailfrom: philip-gladstone-test@e11.example.com result: pass macro-multiple-delimiters: spec: 7.1/15, 7.1/16 description: |- Multiple delimiters may be specified in a macro expression. macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) / "%%" / "%_" / "%-" helo: mail.example.com host: 1.2.3.4 mailfrom: foo-bar+zip+quux@e12.example.com result: pass zonedata: example.com.d.spf.example.com: - SPF: v=spf1 redirect=a.spf.example.com a.spf.example.com: - SPF: v=spf1 include:o.spf.example.com. ~all o.spf.example.com: - SPF: v=spf1 ip4:192.168.218.40 msgbas2x.cos.example.com: - A: 192.168.218.40 example.com: - A: 192.168.90.76 - SPF: v=spf1 redirect=%{d}.d.spf.example.com. exp.example.com: - SPF: v=spf1 exp=msg.example.com. -all msg.example.com: - TXT: This is a test. e1.example.com: - SPF: v=spf1 -exists:%(ir).sbl.example.com ?all e1e.example.com: - SPF: v=spf1 exists:foo%(ir).sbl.example.com ?all e1t.example.com: - SPF: v=spf1 exists:foo%.sbl.example.com ?all e1a.example.com: - SPF: "v=spf1 a:macro%%percent%_%_space%-url-space.example.com -all" "macro%percent space%20url-space.example.com": - A: 1.2.3.4 e2.example.com: - SPF: v=spf1 -all exp=%{r}.example.com e3.example.com: - SPF: v=spf1 -all exp=%{ir}.example.com 40.218.168.192.example.com: - TXT: Connections from %{c} not authorized. somewhat.long.exp.example.com: - SPF: v=spf1 -all exp=foobar.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.example.com somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.example.com: - TXT: Congratulations! That was tricky. e4.example.com: - SPF: v=spf1 -all exp=e4msg.example.com e4msg.example.com: - TXT: "%{c} is queried as %{ir}.%{v}.arpa" e5.example.com: - SPF: v=spf1 a:%{a}.example.com -all e6.example.com: - SPF: v=spf1 -all exp=e6msg.example.com e6msg.example.com: - TXT: "connect from %{p}" mx.example.com: - A: 192.168.218.41 - A: 192.168.218.42 - AAAA: CAFE:BABE::2 - AAAA: CAFE:BABE::3 40.218.168.192.in-addr.arpa: - PTR: mx.example.com 41.218.168.192.in-addr.arpa: - PTR: mx.example.com 42.218.168.192.in-addr.arpa: - PTR: mx.example.com - PTR: mx.e7.example.com 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa: - PTR: mx.example.com 3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa: - PTR: mx.example.com mx.e7.example.com: - A: 192.168.218.42 mx.e7.example.com.should.example.com: - A: 127.0.0.2 mx.example.com.ok.example.com: - A: 127.0.0.2 e7.example.com: - SPF: v=spf1 exists:%{p}.should.example.com ~exists:%{p}.ok.example.com e8.example.com: - SPF: v=spf1 -all exp=msg8.%{D2} msg8.example.com: - TXT: "http://example.com/why.html?l=%{L}" e9.example.com: - SPF: v=spf1 a:%{H} -all e10.example.com: - SPF: v=spf1 -include:_spfh.%{d2} ip4:1.2.3.0/24 -all _spfh.example.com: - SPF: v=spf1 -a:%{h} +all e11.example.com: - SPF: v=spf1 exists:%{i}.%{l2r-}.user.%{d2} 1.2.3.4.gladstone.philip.user.example.com: - A: 127.0.0.2 e12.example.com: - SPF: v=spf1 exists:%{l2r+-}.user.%{d2} bar.foo.user.example.com: - A: 127.0.0.2 --- description: Processing limits tests: redirect-loop: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 4.6.4/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e1.example.com result: permerror include-loop: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 4.6.4/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e2.example.com result: permerror mx-limit: description: >- there MUST be a limit of no more than 10 MX looked up and checked. comment: >- The required result for this test was the subject of much controversy with RFC4408. For RFC7208 the ambiguity was resolved in favor of producing a permerror result. spec: 4.6.4/2 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e4.example.com result: permerror ptr-limit: description: >- there MUST be a limit of no more than 10 PTR looked up and checked. comment: >- The result of this test cannot be permerror not only because the RFC does not specify it, but because the sender has no control over the PTR records of spammers. The preferred result reflects evaluating the 10 allowed PTR records in the order returned by the test data. If testing with live DNS, the PTR order may be random, and a pass result would still be compliant. The SPF result is effectively randomized. spec: 4.6.4/3 helo: mail.example.com host: 1.2.3.5 mailfrom: foo@e5.example.com result: [neutral, pass] false-a-limit: description: >- unlike MX, PTR, there is no RR limit for A comment: >- There seems to be a tendency for developers to want to limit A RRs in addition to MX and PTR. These are IPs, not usable for 3rd party DoS attacks, and hence need no low limit. spec: 4.6.4 helo: mail.example.com host: 1.2.3.12 mailfrom: foo@e10.example.com result: pass mech-at-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 4.6.4/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e6.example.com result: pass skip: This is a legitimate fail because we don't do caching. mech-over-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. comment: >- We do not check whether an implementation counts mechanisms before or after evaluation. The RFC is not clear on this. spec: 4.6.4/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e7.example.com result: permerror include-at-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. comment: >- The part of the RFC that talks about MAY parse the entire record first (4.6) is specific to syntax errors. In RFC7208, processing limits are part of syntax checking (4.6). spec: 4.6.4/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e8.example.com result: pass include-over-limit: description: >- SPF implementations MUST limit the number of mechanisms and modifiers that do DNS lookups to at most 10 per SPF check. spec: 4.6.4/1 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e9.example.com result: permerror void-at-limit: description: >- SPF implementations SHOULD limit "void lookups" to two. An implementation MAY choose to make such a limit configurable. In this case, a default of two is RECOMMENDED. comment: >- This is a new check in RFC7208, but it's been implemented in Mail::SPF for years with no issues. spec: 4.6.4/7 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e12.example.com result: neutral void-over-limit: description: >- SPF implementations SHOULD limit "void lookups" to two. An implementation MAY choose to make such a limit configurable. In this case, a default of two is RECOMMENDED. spec: 4.6.4/7 helo: mail.example.com host: 1.2.3.4 mailfrom: foo@e11.example.com result: permerror skip: We don't limit this separately from the total 10 limit. zonedata: mail.example.com: - A: 1.2.3.4 e1.example.com: - SPF: v=spf1 ip4:1.1.1.1 redirect=e1.example.com - A: 1.2.3.6 e2.example.com: - SPF: v=spf1 include:e3.example.com - A: 1.2.3.7 e3.example.com: - SPF: v=spf1 include:e2.example.com - A: 1.2.3.8 e4.example.com: - SPF: v=spf1 mx - MX: [0, mail.example.com] - MX: [1, mail.example.com] - MX: [2, mail.example.com] - MX: [3, mail.example.com] - MX: [4, mail.example.com] - MX: [5, mail.example.com] - MX: [6, mail.example.com] - MX: [7, mail.example.com] - MX: [8, mail.example.com] - MX: [9, mail.example.com] - MX: [10, e4.example.com] - A: 1.2.3.5 e5.example.com: - SPF: v=spf1 ptr - A: 1.2.3.5 5.3.2.1.in-addr.arpa: - PTR: e1.example.com. - PTR: e2.example.com. - PTR: e3.example.com. - PTR: e4.example.com. - PTR: example.com. - PTR: e6.example.com. - PTR: e7.example.com. - PTR: e8.example.com. - PTR: e9.example.com. - PTR: e10.example.com. - PTR: e5.example.com. e6.example.com: - SPF: v=spf1 a mx a mx a mx a mx a ptr ip4:1.2.3.4 -all - A: 1.2.3.8 - MX: [10, e6.example.com] e7.example.com: - SPF: v=spf1 a mx a mx a mx a mx a ptr a ip4:1.2.3.4 -all - A: 1.2.3.20 e8.example.com: - SPF: v=spf1 a include:inc.example.com ip4:1.2.3.4 mx -all - A: 1.2.3.4 inc.example.com: - SPF: v=spf1 a a a a a a a a - A: 1.2.3.10 e9.example.com: - SPF: v=spf1 a include:inc.example.com a ip4:1.2.3.4 -all - A: 1.2.3.21 e10.example.com: - SPF: v=spf1 a -all - A: 1.2.3.1 - A: 1.2.3.2 - A: 1.2.3.3 - A: 1.2.3.4 - A: 1.2.3.5 - A: 1.2.3.6 - A: 1.2.3.7 - A: 1.2.3.8 - A: 1.2.3.9 - A: 1.2.3.10 - A: 1.2.3.11 - A: 1.2.3.12 e11.example.com: - TXT: v=spf1 a:err.example.com a:err1.example.com a:err2.example.com ?all e12.example.com: - TXT: v=spf1 a:err.example.com a:err1.example.com ?all --- description: Test cases from implementation bugs tests: bytes-bug: description: >- Bytes vs str bug from pyspf. comment: >- Pyspf failed with strict=2 only. Other implementations may ignore the strict parameter. spec: 5.4/4 helo: example.org host: 2001:db8:ff0:100::2 mailfrom: test@example.org result: pass strict: 2 zonedata: example.org: - SPF: "v=spf1 mx redirect=_spf.example.com" - MX: [10,smtp.example.org] - MX: [10,smtp1.example.com] smtp.example.org: - A: 198.51.100.2 - AAAA: 2001:db8:ff0:100::3 smtp1.example.com: - A: 192.0.2.26 - AAAA: 2001:db8:ff0:200::2 2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.F.F.0.8.B.D.0.1.0.0.2.ip6.arpa: - PTR: smtp6-v.fe.example.org smtp6-v.fe.example.org: - AAAA: 2001:db8:ff0:100::2 _spf.example.com: - SPF: "v=spf1 ptr:fe.example.org ptr:sgp.example.com exp=_expspf.example.org -all" _expspf.example.org: - TXT: "Sender domain not allowed from this host. Please see http://www.openspf.org/Why?s=mfrom&id=%{S}&ip=%{C}&r=%{R}" golang-blitiri-go-spf-1.3.0/yml_test.go000066400000000000000000000165241414622751200200120ustar00rootroot00000000000000package spf import ( "flag" "fmt" "io" "net" "os" "strings" "testing" "gopkg.in/yaml.v2" ) var ( ymlSingle = flag.String("yml_single", "", "run only the test with this name") ymlSkipMarked = flag.Bool("yml_skip_marked", true, "skip tests marked with the 'skip' value") ) ////////////////////////////////////////////////////// // YAML test suite parsing. // type Suite struct { Description string Tests map[string]Test ZoneData map[string][]Record `yaml:"zonedata"` } type Test struct { Description string Comment string Spec stringSlice Helo string Host string MailFrom string `yaml:"mailfrom"` Result stringSlice Explanation string Skip string } // Only one of these will be set. type Record struct { A stringSlice `yaml:"A"` AAAA stringSlice `yaml:"AAAA"` MX *MX `yaml:"MX"` SPF stringSlice `yaml:"SPF"` TXT stringSlice `yaml:"TXT"` PTR stringSlice `yaml:"PTR"` CNAME stringSlice `yaml:"CNAME"` TIMEOUT bool `yaml:"TIMEOUT"` SERVFAIL bool `yaml:"SERVFAIL"` } func (r Record) String() string { if len(r.A) > 0 { return fmt.Sprintf("A: %v", r.A) } if len(r.AAAA) > 0 { return fmt.Sprintf("AAAA: %v", r.AAAA) } if r.MX != nil { return fmt.Sprintf("MX: %v", *r.MX) } if len(r.SPF) > 0 { return fmt.Sprintf("SPF: %v", r.SPF) } if len(r.TXT) > 0 { return fmt.Sprintf("TXT: %v", r.TXT) } if len(r.PTR) > 0 { return fmt.Sprintf("PTR: %v", r.PTR) } if len(r.CNAME) > 0 { return fmt.Sprintf("CNAME: %v", r.CNAME) } if r.TIMEOUT { return "TIMEOUT" } if r.SERVFAIL { return "SERVFAIL" } return "" } // String slice with a custom yaml unmarshaller, because the yaml parser can't // handle single-element entries. // https://github.com/go-yaml/yaml/issues/100 type stringSlice []string func (sl *stringSlice) UnmarshalYAML(unmarshal func(interface{}) error) error { // Try a slice first, and if it works, return it. slice := []string{} if err := unmarshal(&slice); err == nil { *sl = slice return nil } // Get a single string, and append it. single := "" if err := unmarshal(&single); err != nil { return err } *sl = []string{single} return nil } // MX is encoded as: // MX: [0, mail.example.com] // so we have a custom decoder to handle the multi-typed list. type MX struct { Prio uint16 Host string } func (mx *MX) UnmarshalYAML(unmarshal func(interface{}) error) error { seq := []interface{}{} if err := unmarshal(&seq); err != nil { return err } mx.Prio = uint16(seq[0].(int)) mx.Host = seq[1].(string) return nil } ////////////////////////////////////////////////////// // Test runners. // func testRFC(t *testing.T, fname string) { input, err := os.Open(fname) if err != nil { t.Fatal(err) } suites := []Suite{} dec := yaml.NewDecoder(input) for { s := Suite{} err = dec.Decode(&s) if err == io.EOF { break } if err != nil { t.Fatal(err) } suites = append(suites, s) } defaultTrace = t.Logf for _, suite := range suites { t.Logf("suite: %v", suite.Description) // Set up zone for the suite based on zonedata. dns := NewDefaultResolver() for domain, records := range suite.ZoneData { t.Logf(" domain %v", domain) for _, record := range records { t.Logf(" %v", record) if record.TIMEOUT { err := &net.DNSError{ Err: "test timeout error", IsTimeout: true, } dns.Errors[domain] = err } if record.SERVFAIL { err := &net.DNSError{ Err: "test servfail error", IsTimeout: false, IsTemporary: false, } dns.Errors[domain] = err } for _, s := range record.A { dns.Ip[domain] = append(dns.Ip[domain], net.ParseIP(s)) } for _, s := range record.AAAA { dns.Ip[domain] = append(dns.Ip[domain], net.ParseIP(s)) } for _, s := range record.TXT { dns.Txt[domain] = append(dns.Txt[domain], s) } if record.MX != nil { dns.Mx[domain] = append(dns.Mx[domain], mx(record.MX.Host, record.MX.Prio)) } for _, s := range record.PTR { // domain in this case is of the form: // 4.3.2.1.in-addr.arpa // 1.0.0.0.0.[...].0.0.E.B.A.B.E.F.A.C.ip6.arpa // We need to extract the normal string representation for // them, and add the record to dns.addr[ip.String()]. // Enforce that the record is fully qualified, that's what // we expect to see in practice. if !strings.HasSuffix(s, ".") { s += "." } ip := reverseDNS(t, domain).String() dns.Addr[ip] = append(dns.Addr[ip], s) } // TODO: CNAME } // The test suite is not well done: some tests use SPF instead of // TXT because they are old, and others expect the lookup to try // TXT first and SPF later, even though that's forbidden by the // standard. // To try to minimize changes to the suite, we work around this by // only adding records from SPF if there is no TXT already. // We need to do this in a separate step because order of // appearance is not guaranteed. if len(dns.Txt[domain]) == 0 { for _, record := range records { if len(record.SPF) > 0 { // The test suite expect a single-line SPF record to be // concatenated without spaces. dns.Txt[domain] = append(dns.Txt[domain], strings.Join(record.SPF, "")) } } } } // Run each test. for name, test := range suite.Tests { if *ymlSingle != "" && *ymlSingle != name { continue } if test.Skip != "" && *ymlSkipMarked { continue } t.Logf(" test %s", name) ip := net.ParseIP(test.Host) t.Logf(" checkhost %v %v", ip, test.MailFrom) res, err := CheckHostWithSender( net.ParseIP(test.Host), test.Helo, test.MailFrom) if !resultIn(res, test.Result) { t.Errorf(" failed: expected %v, got %v (%v) [%v]", test.Result, res, err, name) } else { t.Logf(" success: %v, %v [%v]", res, err, name) } } } } func resultIn(got Result, exp []string) bool { for _, e := range exp { if e == string(got) { return true } } return false } // Take a reverse-dns host name of the form: // 4.3.2.1.in-addr.arpa // 1.0.0.0.0.[...].0.0.E.B.A.B.E.F.A.C.ip6.arpa // and returns the corresponding ip. func reverseDNS(t *testing.T, r string) net.IP { s := "" if strings.HasSuffix(r, ".in-addr.arpa") { // Strip suffix. r := r[:len(r)-len(".in-addr.arpa")] // Break down in pieces, and construct the ipv4 string backwards. pieces := strings.Split(r, ".") for i := 0; i < len(pieces); i++ { s += pieces[len(pieces)-1-i] + "." } s = s[:len(s)-1] } else if strings.HasSuffix(r, ".ip6.arpa") { // Strip suffix. r := r[:len(r)-len(".ip6.arpa")] // Break down in pieces, and construct the ipv6 string backwards. pieces := strings.Split(r, ".") for i := 0; i < len(pieces); i++ { s += pieces[len(pieces)-1-i] if i%4 == 3 { s += ":" } } s = s[:len(s)-1] } else { t.Fatalf("invalid reverse dns %q: invalid suffix", r) } ip := net.ParseIP(s) if ip == nil { t.Fatalf("invalid reverse dns %q: bad ip %q", r, s) } return ip } func TestOurs(t *testing.T) { testRFC(t, "testdata/blitirispf-tests.yml") } func TestRFC4408(t *testing.T) { testRFC(t, "testdata/rfc4408-tests.yml") } func TestRFC7208(t *testing.T) { testRFC(t, "testdata/rfc7208-tests.yml") } func TestPySPF(t *testing.T) { testRFC(t, "testdata/pyspf-tests.yml") }