diff --git a/go.mod b/go.mod index 7d3fdd11353..a46282bb35a 100644 --- a/go.mod +++ b/go.mod @@ -16,10 +16,10 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 github.com/jmhodges/clock v1.2.0 github.com/letsencrypt/borp v0.0.0-20251118150929-89c6927051ae - github.com/letsencrypt/challtestsrv v1.3.3 + github.com/letsencrypt/challtestsrv v1.4.2 github.com/letsencrypt/pkcs11key/v4 v4.0.0 github.com/letsencrypt/validator/v10 v10.0.0-20230215210743-a0c7dfc17158 - github.com/miekg/dns v1.1.61 + github.com/miekg/dns v1.1.62 github.com/miekg/pkcs11 v1.1.1 github.com/nxadm/tail v1.4.11 github.com/prometheus/client_golang v1.22.0 diff --git a/go.sum b/go.sum index f93a47907e6..7e0d8bb6d91 100644 --- a/go.sum +++ b/go.sum @@ -153,8 +153,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/letsencrypt/borp v0.0.0-20251118150929-89c6927051ae h1:yFuF5yRIwaandcuNMi1A4he4FMWJsGRv38rsizIaxJA= github.com/letsencrypt/borp v0.0.0-20251118150929-89c6927051ae/go.mod h1:gMSMCNKhxox/ccR923EJsIvHeVVYfCABGbirqa0EwuM= -github.com/letsencrypt/challtestsrv v1.3.3 h1:ki02PH84fo6IOe/A+zt1/kfRBp2JrtauEaa5xwjg4/Q= -github.com/letsencrypt/challtestsrv v1.3.3/go.mod h1:Ur4e4FvELUXLGhkMztHOsPIsvGxD/kzSJninOrkM+zc= +github.com/letsencrypt/challtestsrv v1.4.2 h1:0ON3ldMhZyWlfVNYYpFuWRTmZNnyfiL9Hh5YzC3JVwU= +github.com/letsencrypt/challtestsrv v1.4.2/go.mod h1:GhqMqcSoeGpYd5zX5TgwA6er/1MbWzx/o7yuuVya+Wk= github.com/letsencrypt/pkcs11key/v4 v4.0.0 h1:qLc/OznH7xMr5ARJgkZCCWk+EomQkiNTOoOF5LAgagc= github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/letsencrypt/validator/v10 v10.0.0-20230215210743-a0c7dfc17158 h1:HGFsIltYMUiB5eoFSowFzSoXkocM2k9ctmJ57QMGjys= @@ -168,9 +168,8 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-sqlite3 v1.14.26 h1:h72fc7d3zXGhHpwjWw+fPOBxYUupuKlbhUAQi5n6t58= github.com/mattn/go-sqlite3 v1.14.26/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= -github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= +github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= +github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -355,7 +354,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -375,7 +373,6 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/test/chall-test-srv/dnsone.go b/test/chall-test-srv/dnsone.go index fa077cbb2ba..24b1469b89b 100644 --- a/test/chall-test-srv/dnsone.go +++ b/test/chall-test-srv/dnsone.go @@ -28,7 +28,7 @@ func (srv *managementServer) addDNS01(w http.ResponseWriter, r *http.Request) { } // Add the DNS-01 challenge response TXT to the challenge server - srv.challSrv.AddDNSOneChallenge(request.Host, request.Value) + srv.challSrv.AddDNSTXTRecord(request.Host, request.Value) srv.log.Printf("Added DNS-01 TXT challenge for Host %q - Value %q\n", request.Host, request.Value) w.WriteHeader(http.StatusOK) @@ -59,7 +59,7 @@ func (srv *managementServer) delDNS01(w http.ResponseWriter, r *http.Request) { // Delete the DNS-01 challenge response TXT for the given host from the // challenge server - srv.challSrv.DeleteDNSOneChallenge(request.Host) + srv.challSrv.DeleteDNSTXTRecord(request.Host) srv.log.Printf("Removed DNS-01 TXT challenge for Host %q\n", request.Host) w.WriteHeader(http.StatusOK) } diff --git a/test/chall-test-srv/main.go b/test/chall-test-srv/main.go index 41241be523e..dd57d665c17 100644 --- a/test/chall-test-srv/main.go +++ b/test/chall-test-srv/main.go @@ -84,7 +84,7 @@ func main() { httpOneAddresses := filterEmpty(strings.Split(*httpOneBind, ",")) httpsOneAddresses := filterEmpty(strings.Split(*httpsOneBind, ",")) dohAddresses := filterEmpty(strings.Split(*dohBind, ",")) - dnsOneAddresses := filterEmpty(strings.Split(*dnsOneBind, ",")) + dnsAddresses := filterEmpty(strings.Split(*dnsOneBind, ",")) tlsAlpnOneAddresses := filterEmpty(strings.Split(*tlsAlpnOneBind, ",")) logger := log.New(os.Stdout, "chall-test-srv - ", log.Ldate|log.Ltime) @@ -96,7 +96,7 @@ func main() { DOHAddrs: dohAddresses, DOHCert: *dohCert, DOHCertKey: *dohCertKey, - DNSOneAddrs: dnsOneAddresses, + DNSAddrs: dnsAddresses, TLSALPNOneAddrs: tlsAlpnOneAddresses, Log: logger, }) diff --git a/test/chall-test-srv/mockdns.go b/test/chall-test-srv/mockdns.go index 5b3151f1bf6..d4070ccee0d 100644 --- a/test/chall-test-srv/mockdns.go +++ b/test/chall-test-srv/mockdns.go @@ -194,7 +194,7 @@ func (srv *managementServer) delDNSAAAARecord(w http.ResponseWriter, r *http.Req func (srv *managementServer) addDNSCAARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string - Policies []challtestsrv.MockCAAPolicy + Policies []challtestsrv.CAAPolicy } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) diff --git a/test/load-generator/boulder-calls.go b/test/load-generator/boulder-calls.go index 74db6d8e43c..78ab698e203 100644 --- a/test/load-generator/boulder-calls.go +++ b/test/load-generator/boulder-calls.go @@ -296,8 +296,8 @@ func completeAuthorization(authz *core.Authorization, s *State, c *acmeCache) er h.Write([]byte(authStr)) authorizedKeysDigest := base64.RawURLEncoding.EncodeToString(h.Sum(nil)) domain := "_acme-challenge." + authz.Identifier.Value + "." - s.challSrv.AddDNSOneChallenge(domain, authorizedKeysDigest) - defer s.challSrv.DeleteDNSOneChallenge(domain) + s.challSrv.AddDNSTXTRecord(domain, authorizedKeysDigest) + defer s.challSrv.DeleteDNSTXTRecord(domain) case core.ChallengeTypeTLSALPN01: s.challSrv.AddTLSALPNChallenge(authz.Identifier.Value, authStr) defer s.challSrv.DeleteTLSALPNChallenge(authz.Identifier.Value) diff --git a/test/load-generator/state.go b/test/load-generator/state.go index 8c377965adf..bba11e58330 100644 --- a/test/load-generator/state.go +++ b/test/load-generator/state.go @@ -355,7 +355,7 @@ func (s *State) Run( challSrv, err := challtestsrv.New(challtestsrv.Config{ HTTPOneAddrs: httpOneAddrs, TLSALPNOneAddrs: tlsALPNOneAddrs, - DNSOneAddrs: dnsAddrs, + DNSAddrs: dnsAddrs, // Use a logger that has a load-generator prefix Log: log.New(os.Stdout, "load-generator challsrv - ", log.LstdFlags), }) diff --git a/vendor/github.com/letsencrypt/challtestsrv/.golangci.yaml b/vendor/github.com/letsencrypt/challtestsrv/.golangci.yaml index 5aac6ddb8be..d1aa48a6791 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/.golangci.yaml +++ b/vendor/github.com/letsencrypt/challtestsrv/.golangci.yaml @@ -1,35 +1,75 @@ -linters-settings: - gocyclo: - min-complexity: 25 - govet: - check-shadowing: false - misspell: - locale: "US" - +version: "2" linters: - enable-all: true - disable: - - stylecheck - - gosec - - dupl - - maligned - - depguard - - lll - - prealloc - - scopelint - - gocritic - - gochecknoinits - - gochecknoglobals - - gomnd - - wsl - - goerr113 - - godot - + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - containedctx + - copyloopvar + - decorder + - dogsled + - dupword + - durationcheck + - errchkjson + - errorlint + - forcetypeassert + - ginkgolinter + - gocheckcompilerdirectives + - gocognit + - goconst + - gocyclo + - goheader + - gomoddirectives + - gomodguard + - goprintffuncname + - importas + - inamedparam + - ireturn + - loggercheck + - makezero + - mirror + - misspell + - nakedret + - nolintlint + - nonamedreturns + - nosprintfhostport + - perfsprint + - predeclared + - reassign + - revive + - tagalign + - testableexamples + - testifylint + - thelper + - unconvert + - unparam + - usestdlibvars + - usetesting + - wastedassign + settings: + gocyclo: + min-complexity: 25 + misspell: + locale: US + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling issues: - exclude-use-default: true - max-per-linter: 0 + max-issues-per-linter: 0 max-same-issues: 0 - # The following excludes are considered false-positives/known-OK. - exclude-rules: - - path: tlsalpnone.go - text: '`marshalling` is a misspelling of `marshaling`' +formatters: + enable: + - gofmt + - gofumpt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/vendor/github.com/letsencrypt/challtestsrv/README.md b/vendor/github.com/letsencrypt/challtestsrv/README.md index 404831bd10b..5e7277d02c8 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/README.md +++ b/vendor/github.com/letsencrypt/challtestsrv/README.md @@ -7,9 +7,9 @@ The `challtestsrv` package offers a library that can be used by test code to respond to HTTP-01, DNS-01, and TLS-ALPN-01 ACME challenges. The -`challtestsrv` package can also be used as a mock DNS server letting -developers mock `A`, `AAAA`, `CNAME`, and `CAA` DNS data for specific hostnames. -The mock server will resolve up to one level of `CNAME` aliasing for accepted +`challtestsrv` package can also be used as a DNS server letting +developers configure `A`, `AAAA`, `CNAME`, and `CAA` DNS data for specific hostnames. +The DNS server will resolve up to one level of `CNAME` aliasing for accepted DNS request types. **Important note: The `challtestsrv` library is for TEST USAGE @@ -26,11 +26,11 @@ Create a challenge server responding to HTTP-01 challenges on ":8888" and DNS-01 challenges on ":9999" and "10.0.0.1:9998": ``` - import "github.com/letsencrypt/pebble/challtestsrv" + import "github.com/letsencrypt/challtestsrv" - challSrv, err := challtestsrv.New(challsrv.Config{ - HTTPOneAddr: []string{":8888"}, - DNSOneAddr: []string{":9999", "10.0.0.1:9998"}, + challSrv, err := challtestsrv.New(challtestsrv.Config{ + HTTPOneAddrs: []string{":8888"}, + DNSAddrs: []string{":9999", "10.0.0.1:9998"}, }) if err != nil { panic(err) @@ -50,11 +50,11 @@ cleaning it up again: defer challSrv.DeleteHTTPOneChallenge("aaa") ``` -Add a DNS-01 TXT response for the host `"_acme-challenge.example.com."` and the +Add a DNS TXT response for the host `"_acme-challenge.example.com."` and the value `"bbb"`, defer cleaning it up again: ``` - challSrv.AddDNSOneChallenge("_acme-challenge.example.com.", "bbb") - defer challSrv.DeleteHTTPOneChallenge("_acme-challenge.example.com.") + challSrv.AddDNSTXTRecord("_acme-challenge.example.com.", "bbb") + defer challSrv.DeleteDNSTXTRecord("_acme-challenge.example.com.") ``` Get the history of HTTP requests processed by the challenge server for the host diff --git a/vendor/github.com/letsencrypt/challtestsrv/challenge-servers.go b/vendor/github.com/letsencrypt/challtestsrv/challenge-servers.go index 85bb38fa206..9e7f7e56688 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/challenge-servers.go +++ b/vendor/github.com/letsencrypt/challtestsrv/challenge-servers.go @@ -3,7 +3,7 @@ package challtestsrv import ( - "fmt" + "errors" "log" "net/http" "os" @@ -13,7 +13,7 @@ import ( const ( // Default to using localhost for both A and AAAA queries that don't match - // more specific mock host data. + // a host in the dnsData maps. defaultIPv4 = "127.0.0.1" defaultIPv6 = "::1" ) @@ -45,13 +45,8 @@ type ChallSrv struct { // responses. httpOne map[string]string - // dnsOne is a map of DNS host values to key authorizations used for DNS-01 - // responses. - dnsOne map[string][]string - - // dnsMocks holds mock DNS data used to respond to DNS queries other than - // DNS-01 TXT challenge lookups. - dnsMocks mockDNSData + // dnsData is the data used to respond to all DNS queries. + dnsData dnsData // tlsALPNOne is a map of token values to key authorizations used for TLS-ALPN-01 // responses. @@ -62,8 +57,8 @@ type ChallSrv struct { redirects map[string]string } -// mockDNSData holds mock responses for DNS A, AAAA, and CAA lookups. -type mockDNSData struct { +// dnsData holds the data used to respond to all DNS queries. +type dnsData struct { // The IPv4 address used for all A record responses that don't match a host in // aRecords. defaultIPv4 string @@ -74,21 +69,16 @@ type mockDNSData struct { aRecords map[string][]string // A map of host to IPv6 addresses in string form for AAAA record responses. aaaaRecords map[string][]string + // A map of host to TXT records. + txtRecords map[string][]string // A map of host to CAA policies for CAA responses. - caaRecords map[string][]MockCAAPolicy + caaRecords map[string][]CAAPolicy // A map of host to CNAME records. cnameRecords map[string]string // A map of hostnames that should receive a SERVFAIL response for all queries. servFailRecords map[string]bool } -// MockCAAPolicy holds a tag and a value for a CAA record. See -// https://tools.ietf.org/html/rfc6844 -type MockCAAPolicy struct { - Tag string - Value string -} - // Config holds challenge server configuration type Config struct { Log *log.Logger @@ -96,10 +86,10 @@ type Config struct { HTTPOneAddrs []string // HTTPSOneAddrs are the HTTPS HTTP-01 challenge server bind addresses/ports HTTPSOneAddrs []string - // DOHAddrs are the DOH challenge server bind addresses/ports + // DOHAddrs are the DNS over HTTPS (DoH) server bind addresses/ports DOHAddrs []string - // DNSOneAddrs are the DNS-01 challenge server bind addresses/ports - DNSOneAddrs []string + // DNSAddrs are the DNS over UDP/TCP server bind addresses/ports + DNSAddrs []string // TLSALPNOneAddrs are the TLS-ALPN-01 challenge server bind addresses/ports TLSALPNOneAddrs []string @@ -116,11 +106,12 @@ func (c *Config) validate() error { // There needs to be at least one challenge type with a bind address if len(c.HTTPOneAddrs) < 1 && len(c.HTTPSOneAddrs) < 1 && - len(c.DNSOneAddrs) < 1 && + len(c.DNSAddrs) < 1 && + len(c.DOHAddrs) < 1 && len(c.TLSALPNOneAddrs) < 1 { - return fmt.Errorf( + return errors.New( "config must specify at least one HTTPOneAddrs entry, one HTTPSOneAddr " + - "entry, one DOHAddrs, one DNSOneAddrs entry, or one TLSALPNOneAddrs entry") + "entry, one DOHAddrs, one DNSAddrs entry, or one TLSALPNOneAddrs entry") } // If there is no configured log make a default with a prefix if c.Log == nil { @@ -140,15 +131,15 @@ func New(config Config) (*ChallSrv, error) { log: config.Log, requestHistory: make(map[string]map[RequestEventType][]RequestEvent), httpOne: make(map[string]string), - dnsOne: make(map[string][]string), tlsALPNOne: make(map[string]string), redirects: make(map[string]string), - dnsMocks: mockDNSData{ + dnsData: dnsData{ defaultIPv4: defaultIPv4, defaultIPv6: defaultIPv6, aRecords: make(map[string][]string), aaaaRecords: make(map[string][]string), - caaRecords: make(map[string][]MockCAAPolicy), + txtRecords: make(map[string][]string), + caaRecords: make(map[string][]CAAPolicy), cnameRecords: make(map[string]string), servFailRecords: make(map[string]bool), }, @@ -168,19 +159,16 @@ func New(config Config) (*ChallSrv, error) { challSrv.servers = append(challSrv.servers, httpOneServer(address, challSrv, true)) } - // If there are DNS-01 addresses configured, create DNS-01 servers - for _, address := range config.DNSOneAddrs { - challSrv.log.Printf("Creating TCP and UDP DNS-01 challenge server on %s\n", address) + // If there are DNS addresses configured, create DNS servers + for _, address := range config.DNSAddrs { + challSrv.log.Printf("Creating TCP and UDP DNS server on %s\n", address) challSrv.servers = append(challSrv.servers, - dnsOneServer(address, challSrv.dnsHandler)...) + dnsServer(address, challSrv.dnsHandler)...) } for _, address := range config.DOHAddrs { challSrv.log.Printf("Creating DoH server on %s\n", address) - s, err := dohServer(address, config.DOHCert, config.DOHCertKey, http.HandlerFunc(challSrv.dohHandler)) - if err != nil { - return nil, err - } + s := dohServer(address, config.DOHCert, config.DOHCertKey, http.HandlerFunc(challSrv.dohHandler)) challSrv.servers = append(challSrv.servers, s) } diff --git a/vendor/github.com/letsencrypt/challtestsrv/dns.go b/vendor/github.com/letsencrypt/challtestsrv/dns.go index 7c16fd048b9..40c806ec69e 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/dns.go +++ b/vendor/github.com/letsencrypt/challtestsrv/dns.go @@ -1,30 +1,213 @@ package challtestsrv import ( + "context" "fmt" "io" "net" "net/http" + "time" "github.com/miekg/dns" ) -// mockSOA returns a mock DNS SOA record with fake data. -func mockSOA() *dns.SOA { - return &dns.SOA{ - Hdr: dns.RR_Header{ - Name: "challtestsrv.invalid.", - Rrtype: dns.TypeSOA, - Class: dns.ClassINET, - }, - Ns: "ns.challtestsrv.invalid.", - Mbox: "master.challtestsrv.invalid.", - Serial: 1, - Refresh: 1, - Retry: 1, - Expire: 1, - Minttl: 1, - } +// SetDefaultDNSIPv4 sets the default IPv4 address used for A query responses +// that don't match hosts added with AddDNSARecord. Use "" to disable default +// A query responses. +func (s *ChallSrv) SetDefaultDNSIPv4(addr string) { + s.challMu.Lock() + defer s.challMu.Unlock() + s.dnsData.defaultIPv4 = addr +} + +// SetDefaultDNSIPv6 sets the default IPv6 address used for AAAA query responses +// that don't match hosts added with AddDNSAAAARecord. Use "" to disable default +// AAAA query responses. +func (s *ChallSrv) SetDefaultDNSIPv6(addr string) { + s.challMu.Lock() + defer s.challMu.Unlock() + s.dnsData.defaultIPv6 = addr +} + +// GetDefaultDNSIPv4 gets the default IPv4 address used for A query responses +// (in string form), or an empty string if no default is being used. +func (s *ChallSrv) GetDefaultDNSIPv4() string { + s.challMu.RLock() + defer s.challMu.RUnlock() + return s.dnsData.defaultIPv4 +} + +// GetDefaultDNSIPv6 gets the default IPv6 address used for AAAA query responses +// (in string form), or an empty string if no default is being used. +func (s *ChallSrv) GetDefaultDNSIPv6() string { + s.challMu.RLock() + defer s.challMu.RUnlock() + return s.dnsData.defaultIPv6 +} + +// AddDNSCNAMERecord sets a CNAME record that will be used like an alias when +// querying for other DNS records for the given host. +func (s *ChallSrv) AddDNSCNAMERecord(host string, value string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + value = dns.Fqdn(value) + s.dnsData.cnameRecords[host] = value +} + +// GetDNSCNAMERecord returns a target host if a CNAME is set for the querying +// host and an empty string otherwise. +func (s *ChallSrv) GetDNSCNAMERecord(host string) string { + s.challMu.RLock() + host = dns.Fqdn(host) + defer s.challMu.RUnlock() + return s.dnsData.cnameRecords[host] +} + +// DeleteDNSCAMERecord deletes any CNAME alias set for the given host. +func (s *ChallSrv) DeleteDNSCNAMERecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + delete(s.dnsData.cnameRecords, host) +} + +// AddDNSTXTRecord adds a TXT record for the given host with the given content. +func (s *ChallSrv) AddDNSTXTRecord(host, content string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + s.dnsData.txtRecords[host] = append(s.dnsData.txtRecords[host], content) +} + +// GetDNSTXTRecords returns a slice of TXT record values for the given host. If +// the host does not exist in the TXT record data then nil is returned. +func (s *ChallSrv) GetDNSTXTRecords(host string) []string { + s.challMu.RLock() + defer s.challMu.RUnlock() + return s.dnsData.txtRecords[dns.Fqdn(host)] +} + +// DeleteDNSTXTRecord deletes all TXT records for the given host. +func (s *ChallSrv) DeleteDNSTXTRecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + delete(s.dnsData.txtRecords, dns.Fqdn(host)) +} + +// AddDNSARecord adds IPv4 addresses that will be returned when querying for +// A records for the given host. +func (s *ChallSrv) AddDNSARecord(host string, addresses []string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + s.dnsData.aRecords[host] = append(s.dnsData.aRecords[host], addresses...) +} + +// DeleteDNSARecord deletes any IPv4 addresses that will be returned when +// querying for A records for the given host.record for the given host. +func (s *ChallSrv) DeleteDNSARecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + delete(s.dnsData.aRecords, host) +} + +// GetDNSARecord returns a slice of IPv4 addresses (in string form) that will be +// returned when querying for A records for the given host. +func (s *ChallSrv) GetDNSARecord(host string) []string { + s.challMu.RLock() + host = dns.Fqdn(host) + defer s.challMu.RUnlock() + return s.dnsData.aRecords[host] +} + +// AddDNSAAAARecord adds IPv6 addresses that will be returned when querying for +// AAAA records for the given host. +func (s *ChallSrv) AddDNSAAAARecord(host string, addresses []string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + s.dnsData.aaaaRecords[host] = append(s.dnsData.aaaaRecords[host], addresses...) +} + +// DeleteDNSAAAARecord deletes any IPv6 addresses that will be returned when +// querying for A records for the given host. +func (s *ChallSrv) DeleteDNSAAAARecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + delete(s.dnsData.aaaaRecords, host) +} + +// GetDNSAAAARecord returns a slice of IPv6 addresses (in string form) that will +// be returned when querying for A records for the given host. +func (s *ChallSrv) GetDNSAAAARecord(host string) []string { + s.challMu.RLock() + defer s.challMu.RUnlock() + host = dns.Fqdn(host) + return s.dnsData.aaaaRecords[host] +} + +// CAAPolicy holds a tag and a value for a CAA policy record. See +// https://tools.ietf.org/html/rfc6844 +type CAAPolicy struct { + Tag string + Value string +} + +// AddDNSCAARecord adds CAA records that will be returned when querying +// CAA for the given host. +func (s *ChallSrv) AddDNSCAARecord(host string, policies []CAAPolicy) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + s.dnsData.caaRecords[host] = append(s.dnsData.caaRecords[host], policies...) +} + +// DeleteDNSCAARecord deletes any CAA policies that will be returned when +// querying CAA for the given host. +func (s *ChallSrv) DeleteDNSCAARecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + delete(s.dnsData.caaRecords, host) +} + +// GetDNSCAARecord returns a slice of CAA policy records that will +// be returned when querying CAA for the given host. +func (s *ChallSrv) GetDNSCAARecord(host string) []CAAPolicy { + s.challMu.RLock() + defer s.challMu.RUnlock() + host = dns.Fqdn(host) + return s.dnsData.caaRecords[host] +} + +// AddDNSServFailRecord configures the chall srv to return SERVFAIL responses +// for all queries for the given host. +func (s *ChallSrv) AddDNSServFailRecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + s.dnsData.servFailRecords[host] = true +} + +// DeleteDNSServFailRecord configures the chall srv to no longer return SERVFAIL +// responses for all queries for the given host. +func (s *ChallSrv) DeleteDNSServFailRecord(host string) { + s.challMu.Lock() + defer s.challMu.Unlock() + host = dns.Fqdn(host) + delete(s.dnsData.servFailRecords, host) +} + +// GetDNSServFailRecord returns true when the chall srv has been configured with +// AddDNSServFailRecord to return SERVFAIL for all queries to the given host. +func (s *ChallSrv) GetDNSServFailRecord(host string) bool { + s.challMu.RLock() + defer s.challMu.RUnlock() + host = dns.Fqdn(host) + return s.dnsData.servFailRecords[host] } // dnsAnswerFunc is a function that accepts a DNS question and returns one or @@ -32,7 +215,7 @@ func mockSOA() *dns.SOA { type dnsAnswerFunc func(question dns.Question) []dns.RR // cnameAnswers is a dnsAnswerFunc that creates CNAME RR's for the given question -// using the ChallSrv's dns mock data. If there is no mock CNAME data for the +// using the ChallSrv's DNS records. If there is no CNAME record for the // given hostname in the question no RR's will be returned. func (s *ChallSrv) cnameAnswers(q dns.Question) []dns.RR { var records []dns.RR @@ -54,11 +237,11 @@ func (s *ChallSrv) cnameAnswers(q dns.Question) []dns.RR { } // txtAnswers is a dnsAnswerFunc that creates TXT RR's for the given question -// using the ChallSrv's dns mock data. If there is no mock TXT data for the +// using the ChallSrv's DNS records. If there is no TXT record for the // given hostname in the question no RR's will be returned. func (s *ChallSrv) txtAnswers(q dns.Question) []dns.RR { var records []dns.RR - values := s.GetDNSOneChallenge(q.Name) + values := s.GetDNSTXTRecords(q.Name) for _, resp := range values { record := &dns.TXT{ Hdr: dns.RR_Header{ @@ -66,15 +249,35 @@ func (s *ChallSrv) txtAnswers(q dns.Question) []dns.RR { Rrtype: dns.TypeTXT, Class: dns.ClassINET, }, - Txt: []string{resp}, + Txt: splitTXTRecordValue(resp), } records = append(records, record) } return records } +// splitTXTRecordValue splits a TXT value into RFC 1035 +// chunks of at most 255 octets so long TXT values can be represented as +// multiple strings in one RR. +func splitTXTRecordValue(value string) []string { + const maxTXTStringOctets = 255 + if len(value) <= maxTXTStringOctets { + return []string{value} + } + + var chunks []string + for len(value) > maxTXTStringOctets { + chunks = append(chunks, value[:maxTXTStringOctets]) + value = value[maxTXTStringOctets:] + } + if len(value) > 0 { + chunks = append(chunks, value) + } + return chunks +} + // aAnswers is a dnsAnswerFunc that creates A RR's for the given question using -// the ChallSrv's dns mock data. If there is not a mock ipv4 A response added +// the ChallSrv's DNS records. If there is not a IPv4 A record added // for the given hostname in the question the default IPv4 address will be used // for the response. func (s *ChallSrv) aAnswers(q dns.Question) []dns.RR { @@ -91,7 +294,7 @@ func (s *ChallSrv) aAnswers(q dns.Question) []dns.RR { for _, resp := range values { ipAddr := net.ParseIP(resp) if ipAddr == nil || ipAddr.To4() == nil { - // If the mock data isn't a valid IPv4 address, don't use it. + // If the DNS records aren't a valid IPv4 address, don't use them. continue } record := &dns.A{ @@ -108,7 +311,7 @@ func (s *ChallSrv) aAnswers(q dns.Question) []dns.RR { } // aaaaAnswers is a dnsAnswerFunc that creates AAAA RR's for the given question -// using the ChallSrv's dns mock data. If there is not a mock IPv6 AAAA response +// using the ChallSrv's DNS records. If there is not an IPv6 AAAA record // added for the given hostname in the question the default IPv6 address will be // used for the response. func (s *ChallSrv) aaaaAnswers(q dns.Question) []dns.RR { @@ -120,7 +323,7 @@ func (s *ChallSrv) aaaaAnswers(q dns.Question) []dns.RR { for _, resp := range values { ipAddr := net.ParseIP(resp) if ipAddr == nil || ipAddr.To4() != nil { - // If the mock data isn't a valid IPv6 address, don't use it. + // If the DNS records aren't a valid IPv6 address, don't use them. continue } record := &dns.AAAA{ @@ -137,7 +340,7 @@ func (s *ChallSrv) aaaaAnswers(q dns.Question) []dns.RR { } // caaAnswers is a dnsAnswerFunc that creates CAA RR's for the given question -// using the ChallSrv's dns mock data. If there is not a mock CAA response +// using the ChallSrv's DNS records. If there is not a CAA record // added for the given hostname in the question no RRs will be returned. func (s *ChallSrv) caaAnswers(q dns.Question) []dns.RR { var records []dns.RR @@ -158,7 +361,7 @@ func (s *ChallSrv) caaAnswers(q dns.Question) []dns.RR { } type writeMsg interface { - WriteMsg(*dns.Msg) error + WriteMsg(m *dns.Msg) error } type dnsToHTTPWriter struct { @@ -200,13 +403,31 @@ func (s *ChallSrv) dohHandler(w http.ResponseWriter, r *http.Request) { // dnsHandler is a miekg/dns handler that can process a dns.Msg request and // write a response to the provided dns.ResponseWriter. TXT, A, AAAA, CNAME, -// and CAA queries types are supported and answered using the ChallSrv's mock -// DNS data. A host that is aliased by a CNAME record will follow that alias +// and CAA queries types are supported and answered using the ChallSrv's DNS +// records. A host that is aliased by a CNAME record will follow that alias // one level and return the requested record types for that alias' target func (s *ChallSrv) dnsHandler(w dns.ResponseWriter, r *dns.Msg) { s.dnsHandlerInner(w, r, "") } +// newDefaultSOA returns a DNS SOA record with sensible default values. +func newDefaultSOA() *dns.SOA { + return &dns.SOA{ + Hdr: dns.RR_Header{ + Name: "challtestsrv.invalid.", + Rrtype: dns.TypeSOA, + Class: dns.ClassINET, + }, + Ns: "ns.challtestsrv.invalid.", + Mbox: "master.challtestsrv.invalid.", + Serial: 1, + Refresh: 1, + Retry: 1, + Expire: 1, + Minttl: 1, + } +} + func (s *ChallSrv) dnsHandlerInner(w writeMsg, r *dns.Msg, userAgent string) { m := new(dns.Msg) m.SetReply(r) @@ -219,7 +440,7 @@ func (s *ChallSrv) dnsHandlerInner(w writeMsg, r *dns.Msg, userAgent string) { UserAgent: userAgent, }) - // If there is a ServFail mock set then ignore the question and set the + // If there is a ServFail record set then ignore the question and set the // SERVFAIL rcode and continue. if s.GetDNSServFailRecord(q.Name) { m.SetRcode(r, dns.RcodeServerFailure) @@ -260,6 +481,58 @@ func (s *ChallSrv) dnsHandlerInner(w writeMsg, r *dns.Msg, userAgent string) { } } - m.Ns = append(m.Ns, mockSOA()) + m.Ns = append(m.Ns, newDefaultSOA()) _ = w.WriteMsg(m) } + +type dnsHandler func(dns.ResponseWriter, *dns.Msg) + +// dnsServer creates a DNS server that registers the provided handler with the +// `miekg/dns` package. Because the DNS server runs both a UDP and a TCP +// listener, two `server` objects are returned. +func dnsServer(address string, handler dnsHandler) []challengeServer { + // Register the dnsHandler + dns.HandleFunc(".", handler) + // Create a UDP DNS server + udpServer := &dns.Server{ + Addr: address, + Net: "udp", + ReadTimeout: time.Second, + WriteTimeout: time.Second, + } + // Create a TCP DNS server + tcpServer := &dns.Server{ + Addr: address, + Net: "tcp", + ReadTimeout: time.Second, + WriteTimeout: time.Second, + } + return []challengeServer{udpServer, tcpServer} +} + +type doh struct { + *http.Server + tlsCert, tlsCertKey string +} + +func (s *doh) Shutdown() error { + return s.Server.Shutdown(context.Background()) +} + +func (s *doh) ListenAndServe() error { + return s.ListenAndServeTLS(s.tlsCert, s.tlsCertKey) +} + +// dohServer creates a DNS-over-HTTPS server backed by the provided handler. +func dohServer(address string, tlsCert, tlsCertKey string, handler http.Handler) *doh { + return &doh{ + &http.Server{ + Handler: handler, + Addr: address, + ReadTimeout: time.Second, + WriteTimeout: time.Second, + }, + tlsCert, + tlsCertKey, + } +} diff --git a/vendor/github.com/letsencrypt/challtestsrv/dnsone.go b/vendor/github.com/letsencrypt/challtestsrv/dnsone.go deleted file mode 100644 index 228e86f2688..00000000000 --- a/vendor/github.com/letsencrypt/challtestsrv/dnsone.go +++ /dev/null @@ -1,86 +0,0 @@ -package challtestsrv - -import ( - "context" - "net/http" - "time" - - "github.com/miekg/dns" -) - -// AddDNSOneChallenge adds a TXT record for the given host with the given -// content. -func (s *ChallSrv) AddDNSOneChallenge(host, content string) { - s.challMu.Lock() - defer s.challMu.Unlock() - s.dnsOne[host] = append(s.dnsOne[host], content) -} - -// DeleteDNSOneChallenge deletes a TXT record for the given host. -func (s *ChallSrv) DeleteDNSOneChallenge(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - delete(s.dnsOne, host) -} - -// GetDNSOneChallenge returns a slice of TXT record values for the given host. -// If the host does not exist in the challenge response data then nil is -// returned. -func (s *ChallSrv) GetDNSOneChallenge(host string) []string { - s.challMu.RLock() - defer s.challMu.RUnlock() - return s.dnsOne[host] -} - -type dnsHandler func(dns.ResponseWriter, *dns.Msg) - -// dnsOneServer creates an ACME DNS-01 challenge server. The provided dns -// handler will be registered with the `miekg/dns` package to -// handle DNS requests. Because the DNS server runs both a UDP and a TCP -// listener two `server` objects are returned. -func dnsOneServer(address string, handler dnsHandler) []challengeServer { - // Register the dnsHandler - dns.HandleFunc(".", handler) - // Create a UDP DNS server - udpServer := &dns.Server{ - Addr: address, - Net: "udp", - ReadTimeout: time.Second, - WriteTimeout: time.Second, - } - // Create a TCP DNS server - tcpServer := &dns.Server{ - Addr: address, - Net: "tcp", - ReadTimeout: time.Second, - WriteTimeout: time.Second, - } - return []challengeServer{udpServer, tcpServer} -} - -type doh struct { - *http.Server - tlsCert, tlsCertKey string -} - -func (s *doh) Shutdown() error { - return s.Server.Shutdown(context.Background()) -} - -func (s *doh) ListenAndServe() error { - return s.Server.ListenAndServeTLS(s.tlsCert, s.tlsCertKey) -} - -// dohServer creates a DoH server. -func dohServer(address string, tlsCert, tlsCertKey string, handler http.Handler) (challengeServer, error) { - return &doh{ - &http.Server{ - Handler: handler, - Addr: address, - ReadTimeout: time.Second, - WriteTimeout: time.Second, - }, - tlsCert, - tlsCertKey, - }, nil -} diff --git a/vendor/github.com/letsencrypt/challtestsrv/event.go b/vendor/github.com/letsencrypt/challtestsrv/event.go index 671d766c72c..a97f647decb 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/event.go +++ b/vendor/github.com/letsencrypt/challtestsrv/event.go @@ -56,7 +56,7 @@ func (e HTTPRequestEvent) Key() string { return e.Host } -// DNSRequestEvent corresponds to a DNS request received by a dnsOneServer. It +// DNSRequestEvent corresponds to a DNS request received by a dnsServer. It // implements the RequestEvent interface. type DNSRequestEvent struct { // The DNS question received. @@ -74,11 +74,7 @@ func (e DNSRequestEvent) Type() RequestEventType { // DNSRequestEvents use the Question Name as the storage key. Any trailing `.` // in the question name is removed. func (e DNSRequestEvent) Key() string { - key := e.Question.Name - if strings.HasSuffix(key, ".") { - key = strings.TrimSuffix(key, ".") - } - return key + return strings.TrimSuffix(e.Question.Name, ".") } // TLSALPNRequestEvent corresponds to a TLS request received by diff --git a/vendor/github.com/letsencrypt/challtestsrv/httpone.go b/vendor/github.com/letsencrypt/challtestsrv/httpone.go index abdce72e1e2..e73edc30d25 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/httpone.go +++ b/vendor/github.com/letsencrypt/challtestsrv/httpone.go @@ -164,9 +164,9 @@ type challHTTPServer struct { // challenge response server useful for redirect targets in another // configuration. func (c challHTTPServer) ListenAndServe() error { - if c.Server.TLSConfig != nil { + if c.TLSConfig != nil { // This will use the certificate and key from TLSConfig. - return c.Server.ListenAndServeTLS("", "") + return c.ListenAndServeTLS("", "") } // Otherwise use HTTP return c.Server.ListenAndServe() @@ -182,7 +182,7 @@ func (c challHTTPServer) Shutdown() error { // resulting challengeServer will run a HTTPS server with a self-signed // certificate useful for HTTP-01 -> HTTPS HTTP-01 redirect responses. If HTTPS // is false the resulting challengeServer will run an HTTP server. -func httpOneServer(address string, handler http.Handler, https bool) challengeServer { +func httpOneServer(address string, handler http.Handler, https bool) challHTTPServer { // If HTTPS is requested build a TLS Config that uses the self-signed // certificate generated at startup. var tlsConfig *tls.Config diff --git a/vendor/github.com/letsencrypt/challtestsrv/mockdns.go b/vendor/github.com/letsencrypt/challtestsrv/mockdns.go deleted file mode 100644 index b192c47831b..00000000000 --- a/vendor/github.com/letsencrypt/challtestsrv/mockdns.go +++ /dev/null @@ -1,174 +0,0 @@ -package challtestsrv - -import ( - "github.com/miekg/dns" -) - -// SetDefaultDNSIPv4 sets the default IPv4 address used for A query responses -// that don't match hosts added with AddDNSARecord. Use "" to disable default -// A query responses. -func (s *ChallSrv) SetDefaultDNSIPv4(addr string) { - s.challMu.Lock() - defer s.challMu.Unlock() - s.dnsMocks.defaultIPv4 = addr -} - -// SetDefaultDNSIPv6 sets the default IPv6 address used for AAAA query responses -// that don't match hosts added with AddDNSAAAARecord. Use "" to disable default -// AAAA query responses. -func (s *ChallSrv) SetDefaultDNSIPv6(addr string) { - s.challMu.Lock() - defer s.challMu.Unlock() - s.dnsMocks.defaultIPv6 = addr -} - -// GetDefaultDNSIPv4 gets the default IPv4 address used for A query responses -// (in string form), or an empty string if no default is being used. -func (s *ChallSrv) GetDefaultDNSIPv4() string { - s.challMu.RLock() - defer s.challMu.RUnlock() - return s.dnsMocks.defaultIPv4 -} - -// GetDefaultDNSIPv6 gets the default IPv6 address used for AAAA query responses -// (in string form), or an empty string if no default is being used. -func (s *ChallSrv) GetDefaultDNSIPv6() string { - s.challMu.RLock() - defer s.challMu.RUnlock() - return s.dnsMocks.defaultIPv6 -} - -// AddDNSCNAMERecord sets a CNAME record that will be used like an alias when -// querying for other DNS records for the given host. -func (s *ChallSrv) AddDNSCNAMERecord(host string, value string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - value = dns.Fqdn(value) - s.dnsMocks.cnameRecords[host] = value -} - -// GetDNSCNAMERecord returns a target host if a CNAME is set for the querying -// host and an empty string otherwise. -func (s *ChallSrv) GetDNSCNAMERecord(host string) string { - s.challMu.RLock() - host = dns.Fqdn(host) - defer s.challMu.RUnlock() - return s.dnsMocks.cnameRecords[host] -} - -// DeleteDNSCAMERecord deletes any CNAME alias set for the given host. -func (s *ChallSrv) DeleteDNSCNAMERecord(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - delete(s.dnsMocks.cnameRecords, host) -} - -// AddDNSARecord adds IPv4 addresses that will be returned when querying for -// A records for the given host. -func (s *ChallSrv) AddDNSARecord(host string, addresses []string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - s.dnsMocks.aRecords[host] = append(s.dnsMocks.aRecords[host], addresses...) -} - -// DeleteDNSARecord deletes any IPv4 addresses that will be returned when -// querying for A records for the given host.record for the given host. -func (s *ChallSrv) DeleteDNSARecord(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - delete(s.dnsMocks.aRecords, host) -} - -// GetDNSARecord returns a slice of IPv4 addresses (in string form) that will be -// returned when querying for A records for the given host. -func (s *ChallSrv) GetDNSARecord(host string) []string { - s.challMu.RLock() - host = dns.Fqdn(host) - defer s.challMu.RUnlock() - return s.dnsMocks.aRecords[host] -} - -// AddDNSAAAARecord adds IPv6 addresses that will be returned when querying for -// AAAA records for the given host. -func (s *ChallSrv) AddDNSAAAARecord(host string, addresses []string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - s.dnsMocks.aaaaRecords[host] = append(s.dnsMocks.aaaaRecords[host], addresses...) -} - -// DeleteDNSAAAARecord deletes any IPv6 addresses that will be returned when -// querying for A records for the given host. -func (s *ChallSrv) DeleteDNSAAAARecord(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - delete(s.dnsMocks.aaaaRecords, host) -} - -// GetDNSAAAARecord returns a slice of IPv6 addresses (in string form) that will -// be returned when querying for A records for the given host. -func (s *ChallSrv) GetDNSAAAARecord(host string) []string { - s.challMu.RLock() - defer s.challMu.RUnlock() - host = dns.Fqdn(host) - return s.dnsMocks.aaaaRecords[host] -} - -// AddDNSCAARecord adds mock CAA records that will be returned when querying -// CAA for the given host. -func (s *ChallSrv) AddDNSCAARecord(host string, policies []MockCAAPolicy) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - s.dnsMocks.caaRecords[host] = append(s.dnsMocks.caaRecords[host], policies...) -} - -// DeleteDNSCAARecord deletes any CAA policies that will be returned when -// querying CAA for the given host. -func (s *ChallSrv) DeleteDNSCAARecord(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - delete(s.dnsMocks.caaRecords, host) -} - -// GetDNSCAARecord returns a slice of mock CAA policies that will -// be returned when querying CAA for the given host. -func (s *ChallSrv) GetDNSCAARecord(host string) []MockCAAPolicy { - s.challMu.RLock() - defer s.challMu.RUnlock() - host = dns.Fqdn(host) - return s.dnsMocks.caaRecords[host] -} - -// AddDNSServFailRecord configures the chall srv to return SERVFAIL responses -// for all queries for the given host. -func (s *ChallSrv) AddDNSServFailRecord(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - s.dnsMocks.servFailRecords[host] = true -} - -// DeleteDNSServFailRecord configures the chall srv to no longer return SERVFAIL -// responses for all queries for the given host. -func (s *ChallSrv) DeleteDNSServFailRecord(host string) { - s.challMu.Lock() - defer s.challMu.Unlock() - host = dns.Fqdn(host) - delete(s.dnsMocks.servFailRecords, host) -} - -// GetDNSServFailRecord returns true when the chall srv has been configured with -// AddDNSServFailRecord to return SERVFAIL for all queries to the given host. -func (s *ChallSrv) GetDNSServFailRecord(host string) bool { - s.challMu.RLock() - defer s.challMu.RUnlock() - host = dns.Fqdn(host) - return s.dnsMocks.servFailRecords[host] -} diff --git a/vendor/github.com/letsencrypt/challtestsrv/tlsalpnone.go b/vendor/github.com/letsencrypt/challtestsrv/tlsalpnone.go index 22b1fc3a7c7..d322da93ff3 100644 --- a/vendor/github.com/letsencrypt/challtestsrv/tlsalpnone.go +++ b/vendor/github.com/letsencrypt/challtestsrv/tlsalpnone.go @@ -69,7 +69,7 @@ func (s *ChallSrv) ServeChallengeCertFunc(k *ecdsa.PrivateKey) func(*tls.ClientH kaHash := sha256.Sum256([]byte(ka)) extValue, err := asn1.Marshal(kaHash[:]) if err != nil { - return nil, fmt.Errorf("failed marshalling hash OCTET STRING: %s", err) + return nil, fmt.Errorf("failed marshaling hash OCTET STRING: %w", err) } certTmpl := x509.Certificate{ SerialNumber: big.NewInt(1729), @@ -84,7 +84,7 @@ func (s *ChallSrv) ServeChallengeCertFunc(k *ecdsa.PrivateKey) func(*tls.ClientH } certBytes, err := x509.CreateCertificate(rand.Reader, &certTmpl, &certTmpl, k.Public(), k) if err != nil { - return nil, fmt.Errorf("failed creating challenge certificate: %s", err) + return nil, fmt.Errorf("failed creating challenge certificate: %w", err) } return &tls.Certificate{ Certificate: [][]byte{certBytes}, @@ -104,10 +104,10 @@ func (c challTLSServer) Shutdown() error { func (c challTLSServer) ListenAndServe() error { // Since we set TLSConfig.GetCertificate, the certfile and keyFile arguments // are ignored and we leave them blank. - return c.Server.ListenAndServeTLS("", "") + return c.ListenAndServeTLS("", "") } -func tlsALPNOneServer(address string, challSrv *ChallSrv) challengeServer { +func tlsALPNOneServer(address string, challSrv *ChallSrv) challTLSServer { key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { panic(err) diff --git a/vendor/github.com/miekg/dns/README.md b/vendor/github.com/miekg/dns/README.md index 10ddda14273..8d5a2a47893 100644 --- a/vendor/github.com/miekg/dns/README.md +++ b/vendor/github.com/miekg/dns/README.md @@ -148,6 +148,7 @@ Example programs can be found in the `github.com/miekg/exdns` repository. * 3225 - DO bit (DNSSEC OK) * 340{1,2,3} - NAPTR record * 3445 - Limiting the scope of (DNS)KEY +* 3596 - AAAA record * 3597 - Unknown RRs * 4025 - A Method for Storing IPsec Keying Material in DNS * 403{3,4,5} - DNSSEC + validation functions diff --git a/vendor/github.com/miekg/dns/edns.go b/vendor/github.com/miekg/dns/edns.go index 1b58e8f0aa9..c1bbdaae2e9 100644 --- a/vendor/github.com/miekg/dns/edns.go +++ b/vendor/github.com/miekg/dns/edns.go @@ -756,36 +756,48 @@ const ( ExtendedErrorCodeNoReachableAuthority ExtendedErrorCodeNetworkError ExtendedErrorCodeInvalidData + ExtendedErrorCodeSignatureExpiredBeforeValid + ExtendedErrorCodeTooEarly + ExtendedErrorCodeUnsupportedNSEC3IterValue + ExtendedErrorCodeUnableToConformToPolicy + ExtendedErrorCodeSynthesized + ExtendedErrorCodeInvalidQueryType ) // ExtendedErrorCodeToString maps extended error info codes to a human readable // description. var ExtendedErrorCodeToString = map[uint16]string{ - ExtendedErrorCodeOther: "Other", - ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm", - ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type", - ExtendedErrorCodeStaleAnswer: "Stale Answer", - ExtendedErrorCodeForgedAnswer: "Forged Answer", - ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate", - ExtendedErrorCodeDNSBogus: "DNSSEC Bogus", - ExtendedErrorCodeSignatureExpired: "Signature Expired", - ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid", - ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing", - ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing", - ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set", - ExtendedErrorCodeNSECMissing: "NSEC Missing", - ExtendedErrorCodeCachedError: "Cached Error", - ExtendedErrorCodeNotReady: "Not Ready", - ExtendedErrorCodeBlocked: "Blocked", - ExtendedErrorCodeCensored: "Censored", - ExtendedErrorCodeFiltered: "Filtered", - ExtendedErrorCodeProhibited: "Prohibited", - ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer", - ExtendedErrorCodeNotAuthoritative: "Not Authoritative", - ExtendedErrorCodeNotSupported: "Not Supported", - ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority", - ExtendedErrorCodeNetworkError: "Network Error", - ExtendedErrorCodeInvalidData: "Invalid Data", + ExtendedErrorCodeOther: "Other", + ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm", + ExtendedErrorCodeUnsupportedDSDigestType: "Unsupported DS Digest Type", + ExtendedErrorCodeStaleAnswer: "Stale Answer", + ExtendedErrorCodeForgedAnswer: "Forged Answer", + ExtendedErrorCodeDNSSECIndeterminate: "DNSSEC Indeterminate", + ExtendedErrorCodeDNSBogus: "DNSSEC Bogus", + ExtendedErrorCodeSignatureExpired: "Signature Expired", + ExtendedErrorCodeSignatureNotYetValid: "Signature Not Yet Valid", + ExtendedErrorCodeDNSKEYMissing: "DNSKEY Missing", + ExtendedErrorCodeRRSIGsMissing: "RRSIGs Missing", + ExtendedErrorCodeNoZoneKeyBitSet: "No Zone Key Bit Set", + ExtendedErrorCodeNSECMissing: "NSEC Missing", + ExtendedErrorCodeCachedError: "Cached Error", + ExtendedErrorCodeNotReady: "Not Ready", + ExtendedErrorCodeBlocked: "Blocked", + ExtendedErrorCodeCensored: "Censored", + ExtendedErrorCodeFiltered: "Filtered", + ExtendedErrorCodeProhibited: "Prohibited", + ExtendedErrorCodeStaleNXDOMAINAnswer: "Stale NXDOMAIN Answer", + ExtendedErrorCodeNotAuthoritative: "Not Authoritative", + ExtendedErrorCodeNotSupported: "Not Supported", + ExtendedErrorCodeNoReachableAuthority: "No Reachable Authority", + ExtendedErrorCodeNetworkError: "Network Error", + ExtendedErrorCodeInvalidData: "Invalid Data", + ExtendedErrorCodeSignatureExpiredBeforeValid: "Signature Expired Before Valid", + ExtendedErrorCodeTooEarly: "Too Early", + ExtendedErrorCodeUnsupportedNSEC3IterValue: "Unsupported NSEC3 Iterations Value", + ExtendedErrorCodeUnableToConformToPolicy: "Unable To Conform To Policy", + ExtendedErrorCodeSynthesized: "Synthesized", + ExtendedErrorCodeInvalidQueryType: "Invalid Query Type", } // StringToExtendedErrorCode is a map from human readable descriptions to diff --git a/vendor/github.com/miekg/dns/types.go b/vendor/github.com/miekg/dns/types.go index 8e3129cbd25..7a34c14ca0a 100644 --- a/vendor/github.com/miekg/dns/types.go +++ b/vendor/github.com/miekg/dns/types.go @@ -96,6 +96,7 @@ const ( TypeLP uint16 = 107 TypeEUI48 uint16 = 108 TypeEUI64 uint16 = 109 + TypeNXNAME uint16 = 128 TypeURI uint16 = 256 TypeCAA uint16 = 257 TypeAVC uint16 = 258 @@ -294,6 +295,19 @@ func (*NULL) parse(c *zlexer, origin string) *ParseError { return &ParseError{err: "NULL records do not have a presentation format"} } +// NXNAME is a meta record. See https://www.iana.org/go/draft-ietf-dnsop-compact-denial-of-existence-04 +// Reference: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml +type NXNAME struct { + Hdr RR_Header + // Does not have any rdata +} + +func (rr *NXNAME) String() string { return rr.Hdr.String() } + +func (*NXNAME) parse(c *zlexer, origin string) *ParseError { + return &ParseError{err: "NXNAME records do not have a presentation format"} +} + // CNAME RR. See RFC 1034. type CNAME struct { Hdr RR_Header diff --git a/vendor/github.com/miekg/dns/version.go b/vendor/github.com/miekg/dns/version.go index dc34e5902be..00c8629f278 100644 --- a/vendor/github.com/miekg/dns/version.go +++ b/vendor/github.com/miekg/dns/version.go @@ -3,7 +3,7 @@ package dns import "fmt" // Version is current version of this library. -var Version = v{1, 1, 58} +var Version = v{1, 1, 62} // v holds the version of this library. type v struct { diff --git a/vendor/github.com/miekg/dns/zduplicate.go b/vendor/github.com/miekg/dns/zduplicate.go index 03029fb3ebb..330c05395f3 100644 --- a/vendor/github.com/miekg/dns/zduplicate.go +++ b/vendor/github.com/miekg/dns/zduplicate.go @@ -886,6 +886,15 @@ func (r1 *NULL) isDuplicate(_r2 RR) bool { return true } +func (r1 *NXNAME) isDuplicate(_r2 RR) bool { + r2, ok := _r2.(*NXNAME) + if !ok { + return false + } + _ = r2 + return true +} + func (r1 *NXT) isDuplicate(_r2 RR) bool { r2, ok := _r2.(*NXT) if !ok { diff --git a/vendor/github.com/miekg/dns/zmsg.go b/vendor/github.com/miekg/dns/zmsg.go index 39b3bc8102e..5a6cf4c6ad5 100644 --- a/vendor/github.com/miekg/dns/zmsg.go +++ b/vendor/github.com/miekg/dns/zmsg.go @@ -706,6 +706,10 @@ func (rr *NULL) pack(msg []byte, off int, compression compressionMap, compress b return off, nil } +func (rr *NXNAME) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { + return off, nil +} + func (rr *NXT) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { off, err = packDomainName(rr.NextDomain, msg, off, compression, false) if err != nil { @@ -2266,6 +2270,13 @@ func (rr *NULL) unpack(msg []byte, off int) (off1 int, err error) { return off, nil } +func (rr *NXNAME) unpack(msg []byte, off int) (off1 int, err error) { + rdStart := off + _ = rdStart + + return off, nil +} + func (rr *NXT) unpack(msg []byte, off int) (off1 int, err error) { rdStart := off _ = rdStart diff --git a/vendor/github.com/miekg/dns/ztypes.go b/vendor/github.com/miekg/dns/ztypes.go index 2c70fc44d6f..11f13ecf9c2 100644 --- a/vendor/github.com/miekg/dns/ztypes.go +++ b/vendor/github.com/miekg/dns/ztypes.go @@ -60,6 +60,7 @@ var TypeToRR = map[uint16]func() RR{ TypeNSEC3: func() RR { return new(NSEC3) }, TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) }, TypeNULL: func() RR { return new(NULL) }, + TypeNXNAME: func() RR { return new(NXNAME) }, TypeNXT: func() RR { return new(NXT) }, TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) }, TypeOPT: func() RR { return new(OPT) }, @@ -146,6 +147,7 @@ var TypeToString = map[uint16]string{ TypeNSEC3: "NSEC3", TypeNSEC3PARAM: "NSEC3PARAM", TypeNULL: "NULL", + TypeNXNAME: "NXNAME", TypeNXT: "NXT", TypeNone: "None", TypeOPENPGPKEY: "OPENPGPKEY", @@ -230,6 +232,7 @@ func (rr *NSEC) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3) Header() *RR_Header { return &rr.Hdr } func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr } func (rr *NULL) Header() *RR_Header { return &rr.Hdr } +func (rr *NXNAME) Header() *RR_Header { return &rr.Hdr } func (rr *NXT) Header() *RR_Header { return &rr.Hdr } func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr } func (rr *OPT) Header() *RR_Header { return &rr.Hdr } @@ -594,6 +597,11 @@ func (rr *NULL) len(off int, compression map[string]struct{}) int { return l } +func (rr *NXNAME) len(off int, compression map[string]struct{}) int { + l := rr.Hdr.len(off, compression) + return l +} + func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int { l := rr.Hdr.len(off, compression) l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) @@ -1107,6 +1115,10 @@ func (rr *NULL) copy() RR { return &NULL{rr.Hdr, rr.Data} } +func (rr *NXNAME) copy() RR { + return &NXNAME{rr.Hdr} +} + func (rr *NXT) copy() RR { return &NXT{*rr.NSEC.copy().(*NSEC)} } diff --git a/vendor/modules.txt b/vendor/modules.txt index 9f736884f39..af06ba86b47 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -214,8 +214,8 @@ github.com/jmhodges/clock # github.com/letsencrypt/borp v0.0.0-20251118150929-89c6927051ae ## explicit; go 1.20 github.com/letsencrypt/borp -# github.com/letsencrypt/challtestsrv v1.3.3 -## explicit; go 1.13 +# github.com/letsencrypt/challtestsrv v1.4.2 +## explicit; go 1.24 github.com/letsencrypt/challtestsrv # github.com/letsencrypt/pkcs11key/v4 v4.0.0 ## explicit; go 1.12 @@ -223,7 +223,7 @@ github.com/letsencrypt/pkcs11key/v4 # github.com/letsencrypt/validator/v10 v10.0.0-20230215210743-a0c7dfc17158 ## explicit; go 1.18 github.com/letsencrypt/validator/v10 -# github.com/miekg/dns v1.1.61 +# github.com/miekg/dns v1.1.62 ## explicit; go 1.19 github.com/miekg/dns # github.com/miekg/pkcs11 v1.1.1