Report DNS errors properly.
Previously we would return a detailed errorString, which ProblemDetailsFromDNSError would turn into a generic, uninformative "Server failure at resolver". Now we return a new internal dnsError type, which ProblemDetailsFromDNSError can turn into a more informative message to be shown to the user.
This commit is contained in:
		
							parent
							
								
									2b15b6cc33
								
							
						
					
					
						commit
						df4ba7aaa8
					
				
							
								
								
									
										38
									
								
								bdns/dns.go
								
								
								
								
							
							
						
						
									
										38
									
								
								bdns/dns.go
								
								
								
								
							| 
						 | 
				
			
			@ -201,24 +201,24 @@ func (dnsResolver *DNSResolverImpl) exchangeOne(hostname string, qtype uint16, m
 | 
			
		|||
// the provided hostname.
 | 
			
		||||
func (dnsResolver *DNSResolverImpl) LookupTXT(hostname string) ([]string, error) {
 | 
			
		||||
	var txt []string
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dns.TypeTXT, dnsResolver.txtStats)
 | 
			
		||||
	dnsType := dns.TypeTXT
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.txtStats)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return nil, &dnsError{dnsType, hostname, err, -1}
 | 
			
		||||
	}
 | 
			
		||||
	if r.Rcode != dns.RcodeSuccess {
 | 
			
		||||
		err = fmt.Errorf("DNS failure: %d-%s for TXT query", r.Rcode, dns.RcodeToString[r.Rcode])
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return nil, &dnsError{dnsType, hostname, nil, r.Rcode}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, answer := range r.Answer {
 | 
			
		||||
		if answer.Header().Rrtype == dns.TypeTXT {
 | 
			
		||||
		if answer.Header().Rrtype == dnsType {
 | 
			
		||||
			if txtRec, ok := answer.(*dns.TXT); ok {
 | 
			
		||||
				txt = append(txt, strings.Join(txtRec.Txt, ""))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return txt, err
 | 
			
		||||
	return txt, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isPrivateV4(ip net.IP) bool {
 | 
			
		||||
| 
						 | 
				
			
			@ -235,18 +235,17 @@ func isPrivateV4(ip net.IP) bool {
 | 
			
		|||
// aliases and return relevant A records.
 | 
			
		||||
func (dnsResolver *DNSResolverImpl) LookupHost(hostname string) ([]net.IP, error) {
 | 
			
		||||
	var addrs []net.IP
 | 
			
		||||
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dns.TypeA, dnsResolver.aStats)
 | 
			
		||||
	dnsType := dns.TypeA
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.aStats)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return addrs, err
 | 
			
		||||
		return addrs, &dnsError{dnsType, hostname, err, -1}
 | 
			
		||||
	}
 | 
			
		||||
	if r.Rcode != dns.RcodeSuccess {
 | 
			
		||||
		err = fmt.Errorf("DNS failure: %d-%s for A query", r.Rcode, dns.RcodeToString[r.Rcode])
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return nil, &dnsError{dnsType, hostname, nil, r.Rcode}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, answer := range r.Answer {
 | 
			
		||||
		if answer.Header().Rrtype == dns.TypeA {
 | 
			
		||||
		if answer.Header().Rrtype == dnsType {
 | 
			
		||||
			if a, ok := answer.(*dns.A); ok && a.A.To4() != nil && (!isPrivateV4(a.A) || dnsResolver.allowRestrictedAddresses) {
 | 
			
		||||
				addrs = append(addrs, a.A)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -260,9 +259,10 @@ func (dnsResolver *DNSResolverImpl) LookupHost(hostname string) ([]net.IP, error
 | 
			
		|||
// the provided hostname. If the response code from the resolver is
 | 
			
		||||
// SERVFAIL an empty slice of CAA records is returned.
 | 
			
		||||
func (dnsResolver *DNSResolverImpl) LookupCAA(hostname string) ([]*dns.CAA, error) {
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dns.TypeCAA, dnsResolver.caaStats)
 | 
			
		||||
	dnsType := dns.TypeCAA
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.caaStats)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return nil, &dnsError{dnsType, hostname, err, -1}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// On resolver validation failure, or other server failures, return empty an
 | 
			
		||||
| 
						 | 
				
			
			@ -273,7 +273,7 @@ func (dnsResolver *DNSResolverImpl) LookupCAA(hostname string) ([]*dns.CAA, erro
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	for _, answer := range r.Answer {
 | 
			
		||||
		if answer.Header().Rrtype == dns.TypeCAA {
 | 
			
		||||
		if answer.Header().Rrtype == dnsType {
 | 
			
		||||
			if caaR, ok := answer.(*dns.CAA); ok {
 | 
			
		||||
				CAAs = append(CAAs, caaR)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -285,13 +285,13 @@ func (dnsResolver *DNSResolverImpl) LookupCAA(hostname string) ([]*dns.CAA, erro
 | 
			
		|||
// LookupMX sends a DNS query to find a MX record associated hostname and returns the
 | 
			
		||||
// record target.
 | 
			
		||||
func (dnsResolver *DNSResolverImpl) LookupMX(hostname string) ([]string, error) {
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dns.TypeMX, dnsResolver.mxStats)
 | 
			
		||||
	dnsType := dns.TypeMX
 | 
			
		||||
	r, err := dnsResolver.exchangeOne(hostname, dnsType, dnsResolver.mxStats)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return nil, &dnsError{dnsType, hostname, err, -1}
 | 
			
		||||
	}
 | 
			
		||||
	if r.Rcode != dns.RcodeSuccess {
 | 
			
		||||
		err = fmt.Errorf("DNS failure: %d-%s for MX query", r.Rcode, dns.RcodeToString[r.Rcode])
 | 
			
		||||
		return nil, err
 | 
			
		||||
		return nil, &dnsError{dnsType, hostname, nil, r.Rcode}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var results []string
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,6 +61,9 @@ func mockDNSQuery(w dns.ResponseWriter, r *dns.Msg) {
 | 
			
		|||
				record.A = net.ParseIP("127.0.0.1")
 | 
			
		||||
				appendAnswer(record)
 | 
			
		||||
			}
 | 
			
		||||
			if q.Name == "nxdomain.letsencrypt.org." {
 | 
			
		||||
				m.SetRcode(r, dns.RcodeNameError)
 | 
			
		||||
			}
 | 
			
		||||
		case dns.TypeCNAME:
 | 
			
		||||
			if q.Name == "cname.letsencrypt.org." {
 | 
			
		||||
				record := new(dns.CNAME)
 | 
			
		||||
| 
						 | 
				
			
			@ -105,6 +108,9 @@ func mockDNSQuery(w dns.ResponseWriter, r *dns.Msg) {
 | 
			
		|||
				record.Txt = []string{"a", "b", "c"}
 | 
			
		||||
				appendAnswer(record)
 | 
			
		||||
			}
 | 
			
		||||
			if q.Name == "nxdomain.letsencrypt.org." {
 | 
			
		||||
				m.SetRcode(r, dns.RcodeNameError)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -248,6 +254,23 @@ func TestDNSLookupHost(t *testing.T) {
 | 
			
		|||
	test.Assert(t, len(ip) == 0, "Should not have IPs")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDNSNXDOMAIN(t *testing.T) {
 | 
			
		||||
	obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats)
 | 
			
		||||
 | 
			
		||||
	hostname := "nxdomain.letsencrypt.org"
 | 
			
		||||
	_, err := obj.LookupHost(hostname)
 | 
			
		||||
	expected := dnsError{dns.TypeA, hostname, nil, dns.RcodeNameError}
 | 
			
		||||
	if err, ok := err.(*dnsError); !ok || *err != expected {
 | 
			
		||||
		t.Errorf("Looking up %s, got %#v, expected %#v", hostname, err, expected)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err = obj.LookupTXT(hostname)
 | 
			
		||||
	expected.recordType = dns.TypeTXT
 | 
			
		||||
	if err, ok := err.(*dnsError); !ok || *err != expected {
 | 
			
		||||
		t.Errorf("Looking up %s, got %#v, expected %#v", hostname, err, expected)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDNSLookupCAA(t *testing.T) {
 | 
			
		||||
	obj := NewTestDNSResolverImpl(time.Second*10, []string{dnsLoopbackAddr}, testStats)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,116 @@
 | 
			
		|||
package bdns
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MockDNSResolver is a mock
 | 
			
		||||
type MockDNSResolver struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupTXT is a mock
 | 
			
		||||
func (mock *MockDNSResolver) LookupTXT(hostname string) ([]string, error) {
 | 
			
		||||
	if hostname == "_acme-challenge.servfail.com" {
 | 
			
		||||
		return nil, fmt.Errorf("SERVFAIL")
 | 
			
		||||
	}
 | 
			
		||||
	if hostname == "_acme-challenge.good-dns01.com" {
 | 
			
		||||
		// base64(sha256("LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0"
 | 
			
		||||
		//               + "." + "9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI"))
 | 
			
		||||
		// expected token + test account jwk thumbprint
 | 
			
		||||
		return []string{"LPsIwTo7o8BoG0-vjCyGQGBWSVIPxI-i_X336eUOQZo"}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return []string{"hostname"}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MockTimeoutError returns a a net.OpError for which Timeout() returns true.
 | 
			
		||||
func MockTimeoutError() *net.OpError {
 | 
			
		||||
	return &net.OpError{
 | 
			
		||||
		Err: os.NewSyscallError("ugh timeout", timeoutError{}),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type timeoutError struct{}
 | 
			
		||||
 | 
			
		||||
func (t timeoutError) Error() string {
 | 
			
		||||
	return "so sloooow"
 | 
			
		||||
}
 | 
			
		||||
func (t timeoutError) Timeout() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupHost is a mock
 | 
			
		||||
//
 | 
			
		||||
// Note: see comments on LookupMX regarding email.only
 | 
			
		||||
//
 | 
			
		||||
func (mock *MockDNSResolver) LookupHost(hostname string) ([]net.IP, error) {
 | 
			
		||||
	if hostname == "always.invalid" ||
 | 
			
		||||
		hostname == "invalid.invalid" ||
 | 
			
		||||
		hostname == "email.only" {
 | 
			
		||||
		return []net.IP{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	if hostname == "always.timeout" {
 | 
			
		||||
		return []net.IP{}, &dnsError{dns.TypeA, "always.timeout", MockTimeoutError(), -1}
 | 
			
		||||
	}
 | 
			
		||||
	if hostname == "always.error" {
 | 
			
		||||
		return []net.IP{}, &dnsError{dns.TypeA, "always.error", &net.OpError{
 | 
			
		||||
			Err: errors.New("some net error"),
 | 
			
		||||
		}, -1}
 | 
			
		||||
	}
 | 
			
		||||
	ip := net.ParseIP("127.0.0.1")
 | 
			
		||||
	return []net.IP{ip}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupCAA is a mock
 | 
			
		||||
func (mock *MockDNSResolver) LookupCAA(domain string) ([]*dns.CAA, error) {
 | 
			
		||||
	var results []*dns.CAA
 | 
			
		||||
	var record dns.CAA
 | 
			
		||||
	switch strings.TrimRight(domain, ".") {
 | 
			
		||||
	case "caa-timeout.com":
 | 
			
		||||
		return nil, &dnsError{dns.TypeCAA, "always.timeout", MockTimeoutError(), -1}
 | 
			
		||||
	case "reserved.com":
 | 
			
		||||
		record.Tag = "issue"
 | 
			
		||||
		record.Value = "symantec.com"
 | 
			
		||||
		results = append(results, &record)
 | 
			
		||||
	case "critical.com":
 | 
			
		||||
		record.Flag = 1
 | 
			
		||||
		record.Tag = "issue"
 | 
			
		||||
		record.Value = "symantec.com"
 | 
			
		||||
		results = append(results, &record)
 | 
			
		||||
	case "present.com":
 | 
			
		||||
		record.Tag = "issue"
 | 
			
		||||
		record.Value = "letsencrypt.org"
 | 
			
		||||
		results = append(results, &record)
 | 
			
		||||
	case "com":
 | 
			
		||||
		// Nothing should ever call this, since CAA checking should stop when it
 | 
			
		||||
		// reaches a public suffix.
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case "servfail.com":
 | 
			
		||||
		return results, fmt.Errorf("SERVFAIL")
 | 
			
		||||
	}
 | 
			
		||||
	return results, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupMX is a mock
 | 
			
		||||
//
 | 
			
		||||
// Note: the email.only domain must have an MX but no A or AAAA
 | 
			
		||||
// records. The mock LookupHost returns an address of 127.0.0.1 for
 | 
			
		||||
// all domains except for special cases, so MX-only domains must be
 | 
			
		||||
// handled in both LookupHost and LookupMX.
 | 
			
		||||
//
 | 
			
		||||
func (mock *MockDNSResolver) LookupMX(domain string) ([]string, error) {
 | 
			
		||||
	switch strings.TrimRight(domain, ".") {
 | 
			
		||||
	case "letsencrypt.org":
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case "email.only":
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case "email.com":
 | 
			
		||||
		return []string{"mail.email.com"}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,30 +9,55 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
 | 
			
		||||
	"github.com/letsencrypt/boulder/probs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const detailDNSTimeout = "DNS query timed out"
 | 
			
		||||
const detailDNSNetFailure = "DNS networking error"
 | 
			
		||||
const detailServerFailure = "Server failure at resolver"
 | 
			
		||||
type dnsError struct {
 | 
			
		||||
	recordType uint16
 | 
			
		||||
	hostname   string
 | 
			
		||||
	// Exactly one of rCode or underlying should be set.
 | 
			
		||||
	underlying error
 | 
			
		||||
	rCode      int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d dnsError) Error() string {
 | 
			
		||||
	var detail string
 | 
			
		||||
	if d.underlying != nil {
 | 
			
		||||
		if netErr, ok := d.underlying.(*net.OpError); ok {
 | 
			
		||||
			if netErr.Timeout() {
 | 
			
		||||
				detail = detailDNSTimeout
 | 
			
		||||
			} else {
 | 
			
		||||
				detail = detailDNSNetFailure
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else if d.rCode != dns.RcodeSuccess {
 | 
			
		||||
		detail = dns.RcodeToString[d.rCode]
 | 
			
		||||
	} else {
 | 
			
		||||
		detail = detailServerFailure
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("DNS problem: %s looking up %s for %s", detail,
 | 
			
		||||
		dns.TypeToString[d.recordType], d.hostname)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const detailDNSTimeout = "query timed out"
 | 
			
		||||
const detailDNSNetFailure = "networking error"
 | 
			
		||||
const detailServerFailure = "server failure at resolver"
 | 
			
		||||
 | 
			
		||||
// ProblemDetailsFromDNSError checks the error returned from Lookup...  methods
 | 
			
		||||
// and tests if the error was an underlying net.OpError or an error caused by
 | 
			
		||||
// resolver returning SERVFAIL or other invalid Rcodes and returns the relevant
 | 
			
		||||
// core.ProblemDetails. The detail string will contain a mention of the DNS
 | 
			
		||||
// record type and domain given.
 | 
			
		||||
func ProblemDetailsFromDNSError(recordType, domain string, err error) *probs.ProblemDetails {
 | 
			
		||||
	detail := detailServerFailure
 | 
			
		||||
	if netErr, ok := err.(*net.OpError); ok {
 | 
			
		||||
		if netErr.Timeout() {
 | 
			
		||||
			detail = detailDNSTimeout
 | 
			
		||||
		} else {
 | 
			
		||||
			detail = detailDNSNetFailure
 | 
			
		||||
func ProblemDetailsFromDNSError(err error) *probs.ProblemDetails {
 | 
			
		||||
	if dnsErr, ok := err.(*dnsError); ok {
 | 
			
		||||
		return &probs.ProblemDetails{
 | 
			
		||||
			Type:   probs.ConnectionProblem,
 | 
			
		||||
			Detail: dnsErr.Error(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	detail = fmt.Sprintf("%s during %s-record lookup of %s", detail, recordType, domain)
 | 
			
		||||
	return &probs.ProblemDetails{
 | 
			
		||||
		Type:   probs.ConnectionProblem,
 | 
			
		||||
		Detail: detail,
 | 
			
		||||
		Detail: detailServerFailure,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,8 @@ import (
 | 
			
		|||
	"net"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/letsencrypt/boulder/mocks"
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
 | 
			
		||||
 | 
			
		||||
	"github.com/letsencrypt/boulder/probs"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,23 +21,25 @@ func TestProblemDetailsFromDNSError(t *testing.T) {
 | 
			
		|||
		expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			mocks.TimeoutError(),
 | 
			
		||||
			detailDNSTimeout,
 | 
			
		||||
			&dnsError{dns.TypeA, "hostname", MockTimeoutError(), -1},
 | 
			
		||||
			"DNS problem: query timed out looking up A for hostname",
 | 
			
		||||
		}, {
 | 
			
		||||
			errors.New("other failure"),
 | 
			
		||||
			detailServerFailure,
 | 
			
		||||
		}, {
 | 
			
		||||
			&net.OpError{Err: errors.New("some net error")},
 | 
			
		||||
			detailDNSNetFailure,
 | 
			
		||||
			&dnsError{dns.TypeMX, "hostname", &net.OpError{Err: errors.New("some net error")}, -1},
 | 
			
		||||
			"DNS problem: networking error looking up MX for hostname",
 | 
			
		||||
		}, {
 | 
			
		||||
			&dnsError{dns.TypeTXT, "hostname", nil, dns.RcodeNameError},
 | 
			
		||||
			"DNS problem: NXDOMAIN looking up TXT for hostname",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		err := ProblemDetailsFromDNSError("TXT", "example.com", tc.err)
 | 
			
		||||
		err := ProblemDetailsFromDNSError(tc.err)
 | 
			
		||||
		if err.Type != probs.ConnectionProblem {
 | 
			
		||||
			t.Errorf("ProblemDetailsFromDNSError(%q).Type = %q, expected %q", tc.err, err.Type, probs.ConnectionProblem)
 | 
			
		||||
		}
 | 
			
		||||
		exp := tc.expected + " during TXT-record lookup of example.com"
 | 
			
		||||
		if err.Detail != exp {
 | 
			
		||||
		if err.Detail != tc.expected {
 | 
			
		||||
			t.Errorf("ProblemDetailsFromDNSError(%q).Detail = %q, expected %q", tc.err, err.Detail, tc.expected)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										108
									
								
								mocks/mocks.go
								
								
								
								
							
							
						
						
									
										108
									
								
								mocks/mocks.go
								
								
								
								
							| 
						 | 
				
			
			@ -12,8 +12,6 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
 | 
			
		||||
| 
						 | 
				
			
			@ -23,116 +21,10 @@ import (
 | 
			
		|||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/signer"
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose"
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/miekg/dns"
 | 
			
		||||
 | 
			
		||||
	"github.com/letsencrypt/boulder/core"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DNSResolver is a mock
 | 
			
		||||
type DNSResolver struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupTXT is a mock
 | 
			
		||||
func (mock *DNSResolver) LookupTXT(hostname string) ([]string, error) {
 | 
			
		||||
	if hostname == "_acme-challenge.servfail.com" {
 | 
			
		||||
		return nil, fmt.Errorf("SERVFAIL")
 | 
			
		||||
	}
 | 
			
		||||
	if hostname == "_acme-challenge.good-dns01.com" {
 | 
			
		||||
		// base64(sha256("LoqXcYV8q5ONbJQxbmR7SCTNo3tiAXDfowyjxAjEuX0"
 | 
			
		||||
		//               + "." + "9jg46WB3rR_AHD-EBXdN7cBkH1WOu0tA3M9fm21mqTI"))
 | 
			
		||||
		// expected token + test account jwk thumbprint
 | 
			
		||||
		return []string{"LPsIwTo7o8BoG0-vjCyGQGBWSVIPxI-i_X336eUOQZo"}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return []string{"hostname"}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TimeoutError returns a a net.OpError for which Timeout() returns true.
 | 
			
		||||
func TimeoutError() *net.OpError {
 | 
			
		||||
	return &net.OpError{
 | 
			
		||||
		Err: os.NewSyscallError("ugh timeout", timeoutError{}),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type timeoutError struct{}
 | 
			
		||||
 | 
			
		||||
func (t timeoutError) Error() string {
 | 
			
		||||
	return "so sloooow"
 | 
			
		||||
}
 | 
			
		||||
func (t timeoutError) Timeout() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupHost is a mock
 | 
			
		||||
//
 | 
			
		||||
// Note: see comments on LookupMX regarding email.only
 | 
			
		||||
//
 | 
			
		||||
func (mock *DNSResolver) LookupHost(hostname string) ([]net.IP, error) {
 | 
			
		||||
	if hostname == "always.invalid" ||
 | 
			
		||||
		hostname == "invalid.invalid" ||
 | 
			
		||||
		hostname == "email.only" {
 | 
			
		||||
		return []net.IP{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	if hostname == "always.timeout" {
 | 
			
		||||
		return []net.IP{}, TimeoutError()
 | 
			
		||||
	}
 | 
			
		||||
	if hostname == "always.error" {
 | 
			
		||||
		return []net.IP{}, &net.OpError{
 | 
			
		||||
			Err: errors.New("some net error"),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ip := net.ParseIP("127.0.0.1")
 | 
			
		||||
	return []net.IP{ip}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupCAA is a mock
 | 
			
		||||
func (mock *DNSResolver) LookupCAA(domain string) ([]*dns.CAA, error) {
 | 
			
		||||
	var results []*dns.CAA
 | 
			
		||||
	var record dns.CAA
 | 
			
		||||
	switch strings.TrimRight(domain, ".") {
 | 
			
		||||
	case "caa-timeout.com":
 | 
			
		||||
		return nil, TimeoutError()
 | 
			
		||||
	case "reserved.com":
 | 
			
		||||
		record.Tag = "issue"
 | 
			
		||||
		record.Value = "symantec.com"
 | 
			
		||||
		results = append(results, &record)
 | 
			
		||||
	case "critical.com":
 | 
			
		||||
		record.Flag = 1
 | 
			
		||||
		record.Tag = "issue"
 | 
			
		||||
		record.Value = "symantec.com"
 | 
			
		||||
		results = append(results, &record)
 | 
			
		||||
	case "present.com":
 | 
			
		||||
		record.Tag = "issue"
 | 
			
		||||
		record.Value = "letsencrypt.org"
 | 
			
		||||
		results = append(results, &record)
 | 
			
		||||
	case "com":
 | 
			
		||||
		// Nothing should ever call this, since CAA checking should stop when it
 | 
			
		||||
		// reaches a public suffix.
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case "servfail.com":
 | 
			
		||||
		return results, fmt.Errorf("SERVFAIL")
 | 
			
		||||
	}
 | 
			
		||||
	return results, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LookupMX is a mock
 | 
			
		||||
//
 | 
			
		||||
// Note: the email.only domain must have an MX but no A or AAAA
 | 
			
		||||
// records. The mock LookupHost returns an address of 127.0.0.1 for
 | 
			
		||||
// all domains except for special cases, so MX-only domains must be
 | 
			
		||||
// handled in both LookupHost and LookupMX.
 | 
			
		||||
//
 | 
			
		||||
func (mock *DNSResolver) LookupMX(domain string) ([]string, error) {
 | 
			
		||||
	switch strings.TrimRight(domain, ".") {
 | 
			
		||||
	case "letsencrypt.org":
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case "email.only":
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case "email.com":
 | 
			
		||||
		return []string{"mail.email.com"}, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StorageAuthority is a mock
 | 
			
		||||
type StorageAuthority struct {
 | 
			
		||||
	clk               clock.Clock
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,10 +97,8 @@ func validateEmail(address string, resolver bdns.DNSResolver) (prob *probs.Probl
 | 
			
		|||
	var resultMX []string
 | 
			
		||||
	var resultA []net.IP
 | 
			
		||||
	resultMX, err = resolver.LookupMX(domain)
 | 
			
		||||
	recQ := "MX"
 | 
			
		||||
	if err == nil && len(resultMX) == 0 {
 | 
			
		||||
		resultA, err = resolver.LookupHost(domain)
 | 
			
		||||
		recQ = "A"
 | 
			
		||||
		if err == nil && len(resultA) == 0 {
 | 
			
		||||
			return &probs.ProblemDetails{
 | 
			
		||||
				Type:   probs.InvalidEmailProblem,
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +107,7 @@ func validateEmail(address string, resolver bdns.DNSResolver) (prob *probs.Probl
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		prob := bdns.ProblemDetailsFromDNSError(recQ, domain, err)
 | 
			
		||||
		prob := bdns.ProblemDetailsFromDNSError(err)
 | 
			
		||||
		prob.Type = probs.InvalidEmailProblem
 | 
			
		||||
		return prob
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ import (
 | 
			
		|||
	cfsslConfig "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
 | 
			
		||||
	"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/jmhodges/clock"
 | 
			
		||||
	jose "github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/letsencrypt/go-jose"
 | 
			
		||||
	"github.com/letsencrypt/boulder/bdns"
 | 
			
		||||
	"github.com/letsencrypt/boulder/ca"
 | 
			
		||||
	"github.com/letsencrypt/boulder/cmd"
 | 
			
		||||
	"github.com/letsencrypt/boulder/core"
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +247,7 @@ func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAut
 | 
			
		|||
	ra.VA = va
 | 
			
		||||
	ra.CA = ca
 | 
			
		||||
	ra.PA = pa
 | 
			
		||||
	ra.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	ra.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	AuthzInitial.RegistrationID = Registration.ID
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -317,15 +318,15 @@ func TestValidateEmail(t *testing.T) {
 | 
			
		|||
	}{
 | 
			
		||||
		{"an email`", unparseableEmailDetail},
 | 
			
		||||
		{"a@always.invalid", emptyDNSResponseDetail},
 | 
			
		||||
		{"a@always.timeout", "DNS query timed out during A-record lookup of always.timeout"},
 | 
			
		||||
		{"a@always.error", "DNS networking error during A-record lookup of always.error"},
 | 
			
		||||
		{"a@always.timeout", "DNS problem: query timed out looking up A for always.timeout"},
 | 
			
		||||
		{"a@always.error", "DNS problem: networking error looking up A for always.error"},
 | 
			
		||||
	}
 | 
			
		||||
	testSuccesses := []string{
 | 
			
		||||
		"a@email.com",
 | 
			
		||||
		"b@email.only",
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testFailures {
 | 
			
		||||
		problem := validateEmail(tc.input, &mocks.DNSResolver{})
 | 
			
		||||
		problem := validateEmail(tc.input, &bdns.MockDNSResolver{})
 | 
			
		||||
		if problem.Type != probs.InvalidEmailProblem {
 | 
			
		||||
			t.Errorf("validateEmail(%q): got problem type %#v, expected %#v", tc.input, problem.Type, probs.InvalidEmailProblem)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +337,7 @@ func TestValidateEmail(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	for _, addr := range testSuccesses {
 | 
			
		||||
		if prob := validateEmail(addr, &mocks.DNSResolver{}); prob != nil {
 | 
			
		||||
		if prob := validateEmail(addr, &bdns.MockDNSResolver{}); prob != nil {
 | 
			
		||||
			t.Errorf("validateEmail(%q): expected success, but it failed: %s",
 | 
			
		||||
				addr, prob)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ func (va ValidationAuthorityImpl) getAddr(hostname string) (net.IP, []net.IP, *p
 | 
			
		|||
	addrs, err := va.DNSResolver.LookupHost(hostname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		va.log.Debug(fmt.Sprintf("%s DNS failure: %s", hostname, err))
 | 
			
		||||
		problem := bdns.ProblemDetailsFromDNSError("A", hostname, err)
 | 
			
		||||
		problem := bdns.ProblemDetailsFromDNSError(err)
 | 
			
		||||
		return net.IP{}, nil, problem
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -435,7 +435,7 @@ func (va *ValidationAuthorityImpl) validateDNS01(identifier core.AcmeIdentifier,
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		va.log.Debug(fmt.Sprintf("%s [%s] DNS failure: %s", challenge.Type, identifier, err))
 | 
			
		||||
 | 
			
		||||
		return nil, bdns.ProblemDetailsFromDNSError("TXT", challengeSubdomain, err)
 | 
			
		||||
		return nil, bdns.ProblemDetailsFromDNSError(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, element := range txts {
 | 
			
		||||
| 
						 | 
				
			
			@ -456,7 +456,7 @@ func (va *ValidationAuthorityImpl) checkCAA(identifier core.AcmeIdentifier, regI
 | 
			
		|||
	present, valid, err := va.CheckCAARecords(identifier)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		va.log.Warning(fmt.Sprintf("Problem checking CAA: %s", err))
 | 
			
		||||
		return bdns.ProblemDetailsFromDNSError("CAA", identifier.Value, err)
 | 
			
		||||
		return bdns.ProblemDetailsFromDNSError(err)
 | 
			
		||||
	}
 | 
			
		||||
	// AUDIT[ Certificate Requests ] 11917fa4-10ef-4e0d-9105-bacbe7836a3c
 | 
			
		||||
	va.log.Audit(fmt.Sprintf("Checked CAA records for %s, registration ID %d [Present: %t, Valid for issuance: %t]", identifier.Value, regID, present, valid))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -221,7 +221,7 @@ func TestHTTP(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: badPort}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	_, prob := va.validateHTTP01(ident, chall)
 | 
			
		||||
	if prob == nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +230,7 @@ func TestHTTP(t *testing.T) {
 | 
			
		|||
	test.AssertEquals(t, prob.Type, probs.ConnectionProblem)
 | 
			
		||||
 | 
			
		||||
	va = NewValidationAuthorityImpl(&PortConfig{HTTPPort: goodPort}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	log.Clear()
 | 
			
		||||
	t.Logf("Trying to validate: %+v\n", chall)
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +314,7 @@ func TestHTTPRedirectLookup(t *testing.T) {
 | 
			
		|||
	test.AssertNotError(t, err, "failed to get test server port")
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	log.Clear()
 | 
			
		||||
	setChallengeToken(&chall, pathMoved)
 | 
			
		||||
| 
						 | 
				
			
			@ -372,7 +372,7 @@ func TestHTTPRedirectLoop(t *testing.T) {
 | 
			
		|||
	test.AssertNotError(t, err, "failed to get test server port")
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	log.Clear()
 | 
			
		||||
	_, prob := va.validateHTTP01(ident, chall)
 | 
			
		||||
| 
						 | 
				
			
			@ -392,7 +392,7 @@ func TestHTTPRedirectUserAgent(t *testing.T) {
 | 
			
		|||
	test.AssertNotError(t, err, "failed to get test server port")
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	va.UserAgent = rejectUserAgent
 | 
			
		||||
 | 
			
		||||
	setChallengeToken(&chall, pathMoved)
 | 
			
		||||
| 
						 | 
				
			
			@ -434,7 +434,7 @@ func TestTLSSNI(t *testing.T) {
 | 
			
		|||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
 | 
			
		||||
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	log.Clear()
 | 
			
		||||
	_, prob := va.validateTLSSNI01(ident, chall)
 | 
			
		||||
| 
						 | 
				
			
			@ -506,7 +506,7 @@ func TestTLSError(t *testing.T) {
 | 
			
		|||
	test.AssertNotError(t, err, "failed to get test server port")
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
 | 
			
		||||
	_, prob := va.validateTLSSNI01(ident, chall)
 | 
			
		||||
	if prob == nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -525,7 +525,7 @@ func TestValidateHTTP(t *testing.T) {
 | 
			
		|||
	test.AssertNotError(t, err, "failed to get test server port")
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{HTTPPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -582,7 +582,7 @@ func TestValidateTLSSNI01(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -600,7 +600,7 @@ func TestValidateTLSSNI01(t *testing.T) {
 | 
			
		|||
func TestValidateTLSSNINotSane(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default()) // no calls made
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -622,7 +622,7 @@ func TestValidateTLSSNINotSane(t *testing.T) {
 | 
			
		|||
func TestUpdateValidations(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -649,13 +649,13 @@ func TestUpdateValidations(t *testing.T) {
 | 
			
		|||
func TestCAATimeout(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	va.IssuerDomain = "letsencrypt.org"
 | 
			
		||||
	err := va.checkCAA(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "caa-timeout.com"}, 101)
 | 
			
		||||
	if err.Type != probs.ConnectionProblem {
 | 
			
		||||
		t.Errorf("Expected timeout error type %s, got %s", probs.ConnectionProblem, err.Type)
 | 
			
		||||
	}
 | 
			
		||||
	expected := "DNS query timed out during CAA-record lookup of caa-timeout.com"
 | 
			
		||||
	expected := "DNS problem: query timed out looking up CAA for always.timeout"
 | 
			
		||||
	if err.Detail != expected {
 | 
			
		||||
		t.Errorf("checkCAA: got %#v, expected %#v", err.Detail, expected)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -682,7 +682,7 @@ func TestCAAChecking(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	va.IssuerDomain = "letsencrypt.org"
 | 
			
		||||
	for _, caaTest := range tests {
 | 
			
		||||
		present, valid, err := va.CheckCAARecords(core.AcmeIdentifier{Type: "dns", Value: caaTest.Domain})
 | 
			
		||||
| 
						 | 
				
			
			@ -712,7 +712,7 @@ func TestCAAChecking(t *testing.T) {
 | 
			
		|||
func TestDNSValidationFailure(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -749,7 +749,7 @@ func TestDNSValidationInvalid(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -763,7 +763,7 @@ func TestDNSValidationInvalid(t *testing.T) {
 | 
			
		|||
func TestDNSValidationNotSane(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -790,7 +790,7 @@ func TestDNSValidationNotSane(t *testing.T) {
 | 
			
		|||
func TestDNSValidationServFail(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -839,7 +839,7 @@ func TestDNSValidationNoServer(t *testing.T) {
 | 
			
		|||
func TestDNSValidationOK(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -873,7 +873,7 @@ func TestDNSValidationOK(t *testing.T) {
 | 
			
		|||
func TestDNSValidationLive(t *testing.T) {
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -932,7 +932,7 @@ func TestCAAFailure(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	stats, _ := statsd.NewNoopClient()
 | 
			
		||||
	va := NewValidationAuthorityImpl(&PortConfig{TLSPort: port}, nil, stats, clock.Default())
 | 
			
		||||
	va.DNSResolver = &mocks.DNSResolver{}
 | 
			
		||||
	va.DNSResolver = &bdns.MockDNSResolver{}
 | 
			
		||||
	mockRA := &MockRegistrationAuthority{}
 | 
			
		||||
	va.RA = mockRA
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue