Skip to content

Commit

Permalink
verify the :authority pseudo-header when parsing request (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann authored Sep 20, 2024
1 parent e270820 commit d7d7865
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
16 changes: 15 additions & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package masque
import (
"fmt"
"net/http"
"net/url"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -46,6 +47,14 @@ func (e *RequestParseError) Unwrap() error { return e.Err }
// ParseRequest parses a CONNECT-UDP request.
// The template is the URI template that clients will use to configure this UDP proxy.
func ParseRequest(r *http.Request, template *uritemplate.Template) (*Request, error) {
u, err := url.Parse(template.Raw())
if err != nil {
return nil, &RequestParseError{
HTTPStatus: http.StatusInternalServerError,
Err: fmt.Errorf("failed to parse template: %w", err),
}
}

if r.Method != http.MethodConnect {
return nil, &RequestParseError{
HTTPStatus: http.StatusMethodNotAllowed,
Expand All @@ -58,7 +67,12 @@ func ParseRequest(r *http.Request, template *uritemplate.Template) (*Request, er
Err: fmt.Errorf("unexpected protocol: %s", r.Proto),
}
}
// TODO: check :authority
if r.Host != u.Host {
return nil, &RequestParseError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("host in :authority (%s) does not match template host (%s)", r.Host, u.Host),
}
}
capsuleHeaderValues, ok := r.Header[capsuleHeader]
if !ok {
return nil, &RequestParseError{
Expand Down
7 changes: 7 additions & 0 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ func TestRequestParsing(t *testing.T) {
require.Equal(t, http.StatusNotImplemented, err.(*RequestParseError).HTTPStatus)
})

t.Run("wrong :authority", func(t *testing.T) {
req := newRequest("https://quic-go.net:1234/masque")
_, err := ParseRequest(req, template)
require.EqualError(t, err, "host in :authority (quic-go.net:1234) does not match template host (localhost:1234)")
require.Equal(t, http.StatusBadRequest, err.(*RequestParseError).HTTPStatus)
})

t.Run("missing Capsule-Protocol header", func(t *testing.T) {
req := newRequest("https://localhost:1234/masque")
req.Header.Del("Capsule-Protocol")
Expand Down

0 comments on commit d7d7865

Please sign in to comment.