From 2a645b1502702af5ff98c5e51f9b0367f335bf58 Mon Sep 17 00:00:00 2001 From: Gijs Key Date: Tue, 16 Feb 2021 13:27:31 +0100 Subject: [PATCH 1/2] DNS update with FQDN in domain field, main.go This pull requests removes the "ZONE" string from the "hostname" or "domain" fields of the request, as this is used by AVM fritz!box routers to check if the update is actually executed, but would recursively lead to updates in the form of: ZONE=example.com request url: https://ddns.example.com/v3/update?hostname=hostname.example.com&myip=&password= Resulting entry in the zone file: hostname.example.com.example.com Solves #63 --- rest-api/main.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/rest-api/main.go b/rest-api/main.go index d556ad4..3a8de89 100644 --- a/rest-api/main.go +++ b/rest-api/main.go @@ -42,7 +42,12 @@ func DynUpdate(w http.ResponseWriter, r *http.Request) { return sharedSecret }, - Domain: func(r *http.Request) string { return r.URL.Query().Get("hostname") }, + Domain: func(r *http.Request) string { + confDomain := "." + appConfig.Domain + srcDomain := r.URL.Query().Get("hostname") + srcDomain = strings.Replace(srcDomain, confDomain, "", -1) + return srcDomain + }, } response := BuildWebserviceResponseFromRequest(r, appConfig, extractor) @@ -77,7 +82,12 @@ func Update(w http.ResponseWriter, r *http.Request) { extractor := RequestDataExtractor{ Address: func(r *http.Request) string { return r.URL.Query().Get("addr") }, Secret: func(r *http.Request) string { return r.URL.Query().Get("secret") }, - Domain: func(r *http.Request) string { return r.URL.Query().Get("domain") }, + Domain: func(r *http.Request) string { + confDomain := "." + appConfig.Domain + srcDomain := r.URL.Query().Get("domain") + srcDomain = strings.Replace(srcDomain, confDomain, "", -1) + return srcDomain + }, } response := BuildWebserviceResponseFromRequest(r, appConfig, extractor) From 53e6ad0142a419ed4bde116abaa08ea9514659d1 Mon Sep 17 00:00:00 2001 From: Gijs Key Date: Tue, 16 Feb 2021 13:46:40 +0100 Subject: [PATCH 2/2] Update request_handler_test.go --- rest-api/request_handler_test.go | 64 +++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/rest-api/request_handler_test.go b/rest-api/request_handler_test.go index ba6681a..47b9e29 100644 --- a/rest-api/request_handler_test.go +++ b/rest-api/request_handler_test.go @@ -3,12 +3,18 @@ package main import ( "net/http" "testing" + "strings" ) var defaultExtractor = RequestDataExtractor{ Address: func(r *http.Request) string { return r.URL.Query().Get("addr") }, Secret: func(r *http.Request) string { return r.URL.Query().Get("secret") }, - Domain: func(r *http.Request) string { return r.URL.Query().Get("domain") }, + Domain: func(r *http.Request) string { + confDomain := "." + appConfig.Domain + srcDomain := r.URL.Query().Get("domain") + srcDomain = strings.Replace(srcDomain, confDomain, "", -1) + return srcDomain + }, } var dynExtractor = RequestDataExtractor{ @@ -21,7 +27,12 @@ var dynExtractor = RequestDataExtractor{ return sharedSecret }, - Domain: func(r *http.Request) string { return r.URL.Query().Get("hostname") }, + Domain: func(r *http.Request) string { + confDomain := "." + appConfig.Domain + srcDomain := r.URL.Query().Get("hostname") + srcDomain = strings.Replace(srcDomain, confDomain, "", -1) + return srcDomain + }, } func TestBuildWebserviceResponseFromRequestToReturnValidObject(t *testing.T) { @@ -48,6 +59,31 @@ func TestBuildWebserviceResponseFromRequestToReturnValidObject(t *testing.T) { } } +func TestBuildWebserviceResponseFromRequestToReturnValidObjectLongDom(t *testing.T) { + var appConfig = &Config{} + appConfig.SharedSecret = "changeme" + + req, _ := http.NewRequest("GET", "/update?secret=changeme&domain=foo.example.org&addr=1.2.3.4", nil) + result := BuildWebserviceResponseFromRequest(req, appConfig, defaultExtractor) + + if result.Success != true { + t.Fatalf("Expected WebserviceResponse.Success to be true") + } + + if result.Domain != "foo" { + t.Fatalf("Expected WebserviceResponse.Domain to be foo") + } + + if result.Address != "1.2.3.4" { + t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4") + } + + if result.AddrType != "A" { + t.Fatalf("Expected WebserviceResponse.AddrType to be A") + } +} + + func TestBuildWebserviceResponseFromRequestWithXRealIPHeaderToReturnValidObject(t *testing.T) { var appConfig = &Config{} appConfig.SharedSecret = "changeme" @@ -73,6 +109,30 @@ func TestBuildWebserviceResponseFromRequestWithXRealIPHeaderToReturnValidObject( } } +func TestBuildWebserviceResponseFromRequestWithXRealIPHeaderToReturnValidObjectLongDom(t *testing.T) { + var appConfig = &Config{} + appConfig.SharedSecret = "changeme" + + req, _ := http.NewRequest("GET", "/update?secret=changeme&domain=foo.example.org", nil) + req.Header.Add("X-Real-Ip", "1.2.3.4") + result := BuildWebserviceResponseFromRequest(req, appConfig, defaultExtractor) + + if result.Success != true { + t.Fatalf("Expected WebserviceResponse.Success to be true") + } + + if result.Domain != "foo" { + t.Fatalf("Expected WebserviceResponse.Domain to be foo") + } + + if result.Address != "1.2.3.4" { + t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4") + } + + if result.AddrType != "A" { + t.Fatalf("Expected WebserviceResponse.AddrType to be A") + } +} func TestBuildWebserviceResponseFromRequestWithXForwardedForHeaderToReturnValidObject(t *testing.T) { var appConfig = &Config{} appConfig.SharedSecret = "changeme"