From ecfea10e359b9c9e7c0e6b5fd092e3caa5587df6 Mon Sep 17 00:00:00 2001 From: tobi <31960611+tsmethurst@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:11:07 +0200 Subject: [bugfix] Use punycode for `host` part of `resource` query param when doing webfinger requests (#3133) * [bugfix] use punycode when webfingering * account for punycode when checking if final URI matches expected * hmm * fix test --- internal/transport/finger.go | 18 +++++++++++++----- internal/transport/finger_test.go | 12 ++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'internal/transport') diff --git a/internal/transport/finger.go b/internal/transport/finger.go index f550769af..f82719245 100644 --- a/internal/transport/finger.go +++ b/internal/transport/finger.go @@ -28,6 +28,7 @@ import ( apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/util" ) // webfingerURLFor returns the URL to try a webfinger request against, as @@ -73,9 +74,16 @@ func prepWebfingerReq(ctx context.Context, loc, domain, username string) (*http. } func (t *transport) Finger(ctx context.Context, targetUsername string, targetDomain string) ([]byte, error) { + // Remotes seem to prefer having their punycode + // domain used in webfinger requests, so let's oblige. + punyDomain, err := util.Punify(targetDomain) + if err != nil { + return nil, gtserror.Newf("error punifying %s: %w", targetDomain, err) + } + // Generate new GET request - url, cached := t.webfingerURLFor(targetDomain) - req, err := prepWebfingerReq(ctx, url, targetDomain, targetUsername) + url, cached := t.webfingerURLFor(punyDomain) + req, err := prepWebfingerReq(ctx, url, punyDomain, targetUsername) if err != nil { return nil, err } @@ -95,7 +103,7 @@ func (t *transport) Finger(ctx context.Context, targetUsername string, targetDom // If we got a response we consider successful on a cached URL, i.e one set // by us later on when a host-meta based webfinger request succeeded, set it // again here to renew the TTL - t.controller.state.Caches.Webfinger.Set(targetDomain, url) + t.controller.state.Caches.Webfinger.Set(punyDomain, url) } if rsp.StatusCode == http.StatusGone { @@ -128,7 +136,7 @@ func (t *transport) Finger(ctx context.Context, targetUsername string, targetDom // So far we've failed to get a successful response from the expected // webfinger endpoint. Lets try and discover the webfinger endpoint // through /.well-known/host-meta - host, err := t.webfingerFromHostMeta(ctx, targetDomain) + host, err := t.webfingerFromHostMeta(ctx, punyDomain) if err != nil { return nil, fmt.Errorf("failed to discover webfinger URL fallback for: %s through host-meta: %w", targetDomain, err) } @@ -142,7 +150,7 @@ func (t *transport) Finger(ctx context.Context, targetUsername string, targetDom // Now that we have a different URL for the webfinger // endpoint, try the request against that endpoint instead - req, err = prepWebfingerReq(ctx, host, targetDomain, targetUsername) + req, err = prepWebfingerReq(ctx, host, punyDomain, targetUsername) if err != nil { return nil, err } diff --git a/internal/transport/finger_test.go b/internal/transport/finger_test.go index db2369799..dd3449b73 100644 --- a/internal/transport/finger_test.go +++ b/internal/transport/finger_test.go @@ -42,6 +42,18 @@ func (suite *FingerTestSuite) TestFinger() { suite.Equal(0, wc.Len(), "expect webfinger cache to be empty for normal webfinger request") } +func (suite *FingerTestSuite) TestFingerPunycode() { + wc := suite.state.Caches.Webfinger + suite.Equal(0, wc.Len(), "expect webfinger cache to be empty") + + _, err := suite.transport.Finger(context.TODO(), "brand_new_person", "pünycöde.example.org") + if err != nil { + suite.FailNow(err.Error()) + } + + suite.Equal(0, wc.Len(), "expect webfinger cache to be empty for normal webfinger request") +} + func (suite *FingerTestSuite) TestFingerWithHostMeta() { wc := suite.state.Caches.Webfinger suite.Equal(0, wc.Len(), "expect webfinger cache to be empty") -- cgit v1.3