federation: fake success on Deletes signed with an unknown gone key

This commit is contained in:
Oneric 2025-02-02 15:40:31 +01:00
parent a11c862ad7
commit 6cb6e3886c
2 changed files with 56 additions and 5 deletions

View file

@ -61,6 +61,23 @@ defp maybe_log_error(conn, verification_error) do
conn
end
defp maybe_halt(conn, :gone) do
# If the key was deleted the error is basically unrecoverable.
# Most likely it was the Delete activity for the key actor and we never knew about this actor before.
# Older Mastodon is very insistent about resending those Deletes until it receives a success.
# see: https://github.com/mastodon/mastodon/pull/33617
with "POST" <- conn.method,
%{"type" => "Delete"} <- conn.body_params do
conn
|> resp(202, "Accepted")
|> halt()
else
_ -> conn
end
end
defp maybe_halt(conn, _), do: conn
defp assign_valid_signature(%{assigns: %{valid_signature: true}} = conn, _),
do: conn
@ -76,6 +93,7 @@ defp assign_valid_signature(conn, request_targets) do
|> assign(:valid_signature, false)
|> assign(:signature_user, nil)
|> maybe_log_error(e)
|> maybe_halt(e)
end
end

View file

@ -27,11 +27,16 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do
{HTTPSignatures, [],
[
validate_conn: fn conn, _ ->
if Map.get(conn.assigns, :valid_signature, true) do
{:ok, user} = Pleroma.User.get_or_fetch_by_ap_id(@user_ap_id)
{:ok, %HTTPSignatures.HTTPKey{key: "aaa", user_data: %{"key_user" => user}}}
else
{:error, :wrong_signature}
cond do
Map.get(conn.assigns, :gone_signature_key, false) ->
{:error, :gone}
Map.get(conn.assigns, :valid_signature, true) ->
{:ok, user} = Pleroma.User.get_or_fetch_by_ap_id(@user_ap_id)
{:ok, %HTTPSignatures.HTTPKey{key: "aaa", user_data: %{"key_user" => user}}}
true ->
{:error, :wrong_signature}
end
end
]}
@ -111,4 +116,32 @@ test "aliases redirected /object endpoints", _ do
assert ["/notice/#{act.id}", "/notice/#{act.id}?actor=someparam"] ==
HTTPSignaturePlug.route_aliases(conn)
end
test "fakes success on gone key when receiving Delete" do
build_conn(:post, "/inbox", %{"type" => "Delete"})
|> put_format("activity+json")
|> assign(:gone_signature_key, true)
|> put_req_header(
"signature",
"keyId=\"http://somewhere.example.org/users/deleted#main-key\""
)
|> HTTPSignaturePlug.call(%{})
|> response(202)
end
test "fails on gone key for non-Delete" do
conn =
build_conn(:post, "/inbox", %{"type" => "Note"})
|> put_format("activity+json")
|> assign(:gone_signature_key, true)
|> put_req_header(
"signature",
"keyId=\"http://somewhere.example.org/users/deleted#main-key\""
)
|> HTTPSignaturePlug.call(%{})
refute conn.halted
assert conn.assigns.valid_signature == false
assert conn.assigns.signature_user == nil
end
end