Use the proper encoding function in the relay server when constructing the URL. In the pool server, parse and re-encode the query values to sanitize whatever the client sent.
This commit is contained in:
@@ -368,6 +368,11 @@ func handlePostRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Canonicalize the URL. In particular, parse and re-encode the query
|
||||||
|
// string so that it's guaranteed to be valid.
|
||||||
|
uri.RawQuery = uri.Query().Encode()
|
||||||
|
newRelay.URL = uri.String()
|
||||||
|
|
||||||
if relayCert != nil {
|
if relayCert != nil {
|
||||||
advertisedId := uri.Query().Get("id")
|
advertisedId := uri.Query().Get("id")
|
||||||
idFromCert := protocol.NewDeviceID(relayCert.Raw).String()
|
idFromCert := protocol.NewDeviceID(relayCert.Raw).String()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -65,3 +66,29 @@ func TestHandleGetRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCanonicalizeQueryValues(t *testing.T) {
|
||||||
|
// This just demonstrates and validates the uri.Parse/String stuff in
|
||||||
|
// regards to query strings.
|
||||||
|
|
||||||
|
in := "http://example.com/?some weird= query^value"
|
||||||
|
exp := "http://example.com/?some+weird=+query%5Evalue"
|
||||||
|
|
||||||
|
uri, err := url.Parse(in)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
str := uri.String()
|
||||||
|
if str != in {
|
||||||
|
// Just re-encoding the URL doesn't sanitize the query string.
|
||||||
|
t.Errorf("expected %q, got %q", in, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
uri.RawQuery = uri.Query().Encode()
|
||||||
|
str = uri.String()
|
||||||
|
if str != exp {
|
||||||
|
// The query string is now in correct format.
|
||||||
|
t.Errorf("expected %q, got %q", exp, str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+20
-1
@@ -230,12 +230,31 @@ func main() {
|
|||||||
go statusService(statusAddr)
|
go statusService(statusAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
uri, err := url.Parse(fmt.Sprintf("relay://%s/?id=%s&pingInterval=%s&networkTimeout=%s&sessionLimitBps=%d&globalLimitBps=%d&statusAddr=%s&providedBy=%s", mapping.Address(), id, pingInterval, networkTimeout, sessionLimitBps, globalLimitBps, statusAddr, providedBy))
|
uri, err := url.Parse(fmt.Sprintf("relay://%s/", mapping.Address()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Failed to construct URI", err)
|
log.Fatalln("Failed to construct URI", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add properly encoded query string parameters to URL.
|
||||||
|
query := make(url.Values)
|
||||||
|
query.Set("id", id.String())
|
||||||
|
query.Set("pingInterval", pingInterval.String())
|
||||||
|
query.Set("networkTimeout", networkTimeout.String())
|
||||||
|
if sessionLimitBps > 0 {
|
||||||
|
query.Set("sessionLimitBps", fmt.Sprint(sessionLimitBps))
|
||||||
|
}
|
||||||
|
if globalLimitBps > 0 {
|
||||||
|
query.Set("globalLimitBps", fmt.Sprint(globalLimitBps))
|
||||||
|
}
|
||||||
|
if statusAddr != "" {
|
||||||
|
query.Set("statusAddr", statusAddr)
|
||||||
|
}
|
||||||
|
if providedBy != "" {
|
||||||
|
query.Set("providedBy", providedBy)
|
||||||
|
}
|
||||||
|
uri.RawQuery = query.Encode()
|
||||||
|
|
||||||
log.Println("URI:", uri.String())
|
log.Println("URI:", uri.String())
|
||||||
|
|
||||||
if poolAddrs == defaultPoolAddrs {
|
if poolAddrs == defaultPoolAddrs {
|
||||||
|
|||||||
Reference in New Issue
Block a user