// addDNS01 handles an HTTP POST request to add a new DNS-01 challenge TXT package main import ( "net/http" "strings" "github.com/letsencrypt/challtestsrv" ) // setDefaultDNSIPv4 handles an HTTP POST request to set the default IPv4 // address used for all A query responses that do not match more-specific mocked // responses. // // The POST body is expected to have one parameter: // "ip" - the string representation of an IPv4 address to use for all A queries // that do not match more specific mocks. // // Providing an empty string as the IP value will disable the default // A responses. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) setDefaultDNSIPv4(w http.ResponseWriter, r *http.Request) { var request struct { IP string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Set the challenge server's default IPv4 address - we allow request.IP to be // the empty string so that the default can be cleared using the same // method. srv.challSrv.SetDefaultDNSIPv4(request.IP) srv.log.Printf("Set default IPv4 address for DNS A queries to %q\n", request.IP) w.WriteHeader(http.StatusOK) } // setDefaultDNSIPv6 handles an HTTP POST request to set the default IPv6 // address used for all AAAA query responses that do not match more-specific // mocked responses. // // The POST body is expected to have one parameter: // "ip" - the string representation of an IPv6 address to use for all AAAA // queries that do not match more specific mocks. // // Providing an empty string as the IP value will disable the default // A responses. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) setDefaultDNSIPv6(w http.ResponseWriter, r *http.Request) { var request struct { IP string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // Set the challenge server's default IPv6 address - we allow request.IP to be // the empty string so that the default can be cleared using the same // method. srv.challSrv.SetDefaultDNSIPv6(request.IP) srv.log.Printf("Set default IPv6 address for DNS AAAA queries to %q\n", request.IP) w.WriteHeader(http.StatusOK) } // addDNSARecord handles an HTTP POST request to add a mock A query response record // for a host. // // The POST body is expected to have two non-empty parameters: // "host" - the hostname that when queried should return the mocked A record. // "addresses" - an array of IPv4 addresses in string representation that should // be used for the A records returned for the query. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) addDNSARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string Addresses []string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has no addresses or an empty host it's a bad request if len(request.Addresses) == 0 || request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.AddDNSARecord(request.Host, request.Addresses) srv.log.Printf("Added response for DNS A queries to %q : %s\n", request.Host, strings.Join(request.Addresses, ", ")) w.WriteHeader(http.StatusOK) } // delDNSARecord handles an HTTP POST request to delete an existing mock A // policy record for a host. // // The POST body is expected to have one non-empty parameter: // "host" - the hostname to remove the mock A record for. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) delDNSARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has an empty host it's a bad request if request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.DeleteDNSARecord(request.Host) srv.log.Printf("Removed response for DNS A queries to %q", request.Host) w.WriteHeader(http.StatusOK) } // addDNSAAAARecord handles an HTTP POST request to add a mock AAAA query // response record for a host. // // The POST body is expected to have two non-empty parameters: // "host" - the hostname that when queried should return the mocked A record. // "addresses" - an array of IPv6 addresses in string representation that should // be used for the AAAA records returned for the query. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) addDNSAAAARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string Addresses []string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has no addresses or an empty host it's a bad request if len(request.Addresses) == 0 || request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.AddDNSAAAARecord(request.Host, request.Addresses) srv.log.Printf("Added response for DNS AAAA queries to %q : %s\n", request.Host, strings.Join(request.Addresses, ", ")) w.WriteHeader(http.StatusOK) } // delDNSAAAARecord handles an HTTP POST request to delete an existing mock AAAA // policy record for a host. // // The POST body is expected to have one non-empty parameter: // "host" - the hostname to remove the mock AAAA record for. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) delDNSAAAARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has an empty host it's a bad request if request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.DeleteDNSAAAARecord(request.Host) srv.log.Printf("Removed response for DNS AAAA queries to %q", request.Host) w.WriteHeader(http.StatusOK) } // addDNSCAARecord handles an HTTP POST request to add a mock CAA query // response record for a host. // // The POST body is expected to have two non-empty parameters: // "host" - the hostname that when queried should return the mocked CAA record. // "policies" - an array of CAA policy objects. Each policy object is expected // to have two non-empty keys, "tag" and "value". // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) addDNSCAARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string Policies []challtestsrv.MockCAAPolicy } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has no host or no caa policies it's a bad request if request.Host == "" || len(request.Policies) == 0 { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.AddDNSCAARecord(request.Host, request.Policies) srv.log.Printf("Added response for DNS CAA queries to %q", request.Host) w.WriteHeader(http.StatusOK) } // delDNSCAARecord handles an HTTP POST request to delete an existing mock CAA // policy record for a host. // // The POST body is expected to have one non-empty parameter: // "host" - the hostname to remove the mock CAA policy for. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) delDNSCAARecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has an empty host it's a bad request if request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.DeleteDNSCAARecord(request.Host) srv.log.Printf("Removed response for DNS CAA queries to %q", request.Host) w.WriteHeader(http.StatusOK) } // addDNSCNAMERecord handles an HTTP POST request to add a mock CNAME query // response record and alias for a host. // // The POST body is expected to have two non-empty parameters: // "host" - the hostname that should be treated as an alias to the target // "target" - the hostname whose mocked DNS records should be returned // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) addDNSCNAMERecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string Target string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has no host or no caa policies it's a bad request if request.Host == "" || request.Target == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.AddDNSCNAMERecord(request.Host, request.Target) srv.log.Printf("Added response for DNS CNAME queries to %q targeting %q", request.Host, request.Target) w.WriteHeader(http.StatusOK) } // delDNSCNAMERecord handles an HTTP POST request to delete an existing mock // CNAME record for a host. // // The POST body is expected to have one non-empty parameters: // "host" - the hostname to remove the mock CNAME alias for. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) delDNSCNAMERecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has an empty host it's a bad request if request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.DeleteDNSCNAMERecord(request.Host) srv.log.Printf("Removed response for DNS CNAME queries to %q", request.Host) w.WriteHeader(http.StatusOK) } // addDNSServFailRecord handles an HTTP POST request to add a mock SERVFAIL // response record for a host. All queries for that host will subsequently // result in SERVFAIL responses, overriding any other mocks. // // The POST body is expected to have one non-empty parameter: // "host" - the hostname that should return SERVFAIL responses. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) addDNSServFailRecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has no host it's a bad request if request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.AddDNSServFailRecord(request.Host) srv.log.Printf("Added SERVFAIL response for DNS queries to %q", request.Host) w.WriteHeader(http.StatusOK) } // delDNSServFailRecord handles an HTTP POST request to delete an existing mock // SERVFAIL record for a host. // // The POST body is expected to have one non-empty parameters: // "host" - the hostname to remove the mock SERVFAIL response from. // // A successful POST will write http.StatusOK to the client. func (srv *managementServer) delDNSServFailRecord(w http.ResponseWriter, r *http.Request) { var request struct { Host string } if err := mustParsePOST(&request, r); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // If the request has an empty host it's a bad request if request.Host == "" { w.WriteHeader(http.StatusBadRequest) return } srv.challSrv.DeleteDNSServFailRecord(request.Host) srv.log.Printf("Removed SERVFAIL response for DNS queries to %q", request.Host) w.WriteHeader(http.StatusOK) }