Fix WebFinger for split-domain set ups

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk 2025-12-15 16:52:45 +01:00
commit 3e2573f1c4
3 changed files with 52 additions and 21 deletions

View file

@ -194,8 +194,8 @@ defmodule Pleroma.Web.WebFinger do
defp get_address_from_domain(_, _), do: {:error, :webfinger_no_domain}
@spec finger(String.t()) :: {:ok, map()} | {:error, any()}
def finger(account) do
@spec finger(String.t(), boolean()) :: {:ok, map()} | {:error, any()}
def finger(account, follow_redirects \\ true) do
account = String.trim_leading(account, "@")
domain =
@ -229,8 +229,15 @@ defmodule Pleroma.Web.WebFinger do
{:error, {:content_type, nil}}
end
|> case do
{:ok, data} -> validate_webfinger(address, data)
error -> error
{:ok, data} ->
if follow_redirects do
validate_webfinger(address, data)
else
{:ok, data}
end
error ->
error
end
else
error ->
@ -241,10 +248,8 @@ defmodule Pleroma.Web.WebFinger do
defp validate_webfinger(request_url, %{"subject" => "acct:" <> acct = subject} = data) do
with [_name, acct_host] <- String.split(acct, "@"),
{_, url} <- {:address, get_address_from_domain(acct_host, subject)},
%URI{host: request_host} <- URI.parse(request_url),
%URI{host: acct_host} <- URI.parse(url),
{_, true} <- {:hosts_match, acct_host == request_host} do
{_, resolved_url} <- {:address, get_address_from_domain(acct_host, subject)},
{_, true} <- {:url_match, resolved_webfinger_matches?(request_url, resolved_url, data)} do
{:ok, data}
else
_ -> {:error, {:webfinger_invalid, request_url, data}}
@ -252,4 +257,17 @@ defmodule Pleroma.Web.WebFinger do
end
defp validate_webfinger(url, data), do: {:error, {:webfinger_invalid, url, data}}
defp resolved_webfinger_matches?(request_url, resolved_url, _data)
when request_url == resolved_url do
true
end
defp resolved_webfinger_matches?(_request_url, _resolved_url, %{"subject" => "acct:" <> acct}) do
with {:ok, %{"subject" => "acct:" <> new_acct}} <- finger(acct, false) do
acct == new_acct
else
_ -> false
end
end
end

View file

@ -93,7 +93,7 @@ defmodule Pleroma.Web.WebFingerTest do
{:ok, _data} = WebFinger.finger(user)
end
test "it work for AP-only user" do
test "it works for AP-only user" do
user = "kpherox@mstdn.jp"
{:ok, data} = WebFinger.finger(user)
@ -224,24 +224,36 @@ defmodule Pleroma.Web.WebFingerTest do
status: 200,
body: File.read!("test/fixtures/tesla_mock/gleasonator.com_host_meta")
}}
%{url: "https://whitehouse.gov/.well-known/webfinger?resource=acct:trump@whitehouse.gov"} ->
{:ok, %Tesla.Env{status: 404}}
end)
{:error, _data} = WebFinger.finger("alex@gleasonator.com")
end
end
test "prevents forgeries" do
Tesla.Mock.mock(fn
%{url: "https://fba.ryona.agency/.well-known/webfinger?resource=acct:graf@fba.ryona.agency"} ->
fake_webfinger =
File.read!("test/fixtures/webfinger/graf-imposter-webfinger.json") |> Jason.decode!()
test "prevents forgeries" do
Tesla.Mock.mock(fn
%{url: "https://fba.ryona.agency/.well-known/webfinger?resource=acct:graf@fba.ryona.agency"} ->
fake_webfinger =
File.read!("test/fixtures/webfinger/graf-imposter-webfinger.json") |> Jason.decode!()
Tesla.Mock.json(fake_webfinger)
Tesla.Mock.json(fake_webfinger)
%{url: "https://fba.ryona.agency/.well-known/host-meta"} ->
{:ok, %Tesla.Env{status: 404}}
end)
%{url: url}
when url in [
"https://poa.st/.well-known/webfinger?resource=acct:graf@poa.st",
"https://fba.ryona.agency/.well-known/host-meta"
] ->
{:ok, %Tesla.Env{status: 404}}
end)
assert {:error, _} = WebFinger.finger("graf@fba.ryona.agency")
assert {:error, _} = WebFinger.finger("graf@fba.ryona.agency")
end
test "works for correctly set up split-domain instances" do
{:ok, _data} = WebFinger.finger("a@mastodon.example")
{:ok, _data} = WebFinger.finger("a@sub.mastodon.example")
end
end
end

View file

@ -1229,7 +1229,8 @@ defmodule HttpRequestMock do
{:ok, %Tesla.Env{status: 404, body: ""}}
end
def get("https://mstdn.jp/.well-known/webfinger?resource=acct:kpherox@mstdn.jp", _, _, _) do
def get("https://mstdn.jp/.well-known/webfinger?resource=acct:" <> acct, _, _, _)
when acct in ["kpherox@mstdn.jp", "kPherox@mstdn.jp"] do
{:ok,
%Tesla.Env{
status: 200,