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