akkoma/lib/pleroma/web/plugs/http_signature_plug.ex
Oneric 8dad70e8e7 instances: drop has_request_signatures
This property was introduced as a way to gauge whether and
how much enabling authfetch might break passive federation in
https://akkoma.dev/AkkomaGang/akkoma/pulls/312.

However, with the db field defaulting to false, there’s no distinction
between instances without valid signatures and those which just never
attempted to fetch anything from the local instance.
Furthermore, this was never exposed anywhere and required manually
checking the database or cachex state via a remote shell.

Given the above it appears this doesn't actually
provide anything useful, thus drop it.
2025-06-07 20:27:58 +02:00

110 lines
3.2 KiB
Elixir
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Pleroma: A lightweight social networking server
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
import Plug.Conn
import Phoenix.Controller, only: [get_format: 1]
alias HTTPSignatures.HTTPKey
use Pleroma.Web, :verified_routes
alias Pleroma.Activity
require Logger
def init(options) do
options
end
def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
conn
end
def call(conn, _opts) do
if get_format(conn) in ["json", "activity+json"] do
conn
|> maybe_assign_valid_signature()
else
conn
end
end
def route_aliases(%{path_info: ["objects", id], query_string: query_string}) do
ap_id = url(~p[/objects/#{id}])
with %Activity{} = activity <- Activity.get_by_object_ap_id_with_object(ap_id) do
[~p"/notice/#{activity.id}", "/notice/#{activity.id}?#{query_string}"]
else
_ -> []
end
end
def route_aliases(_), do: []
defp maybe_log_error_and_try_aliases(conn, verification_error, remaining_aliases) do
case verification_error do
{:gone, key_id} ->
# We can't verify the data since the actor was deleted and not previously known.
# Likely we just received the actors Delete activity, so just silently drop.
Logger.debug("Unable to verify request signature of deleted actor; dropping (#{key_id})")
conn
:wrong_signature ->
assign_valid_signature_on_route_aliases(conn, remaining_aliases)
error ->
Logger.error("Failed to verify request signature due to fatal error: #{inspect(error)}")
conn
end
end
defp assign_valid_signature_on_route_aliases(%{assigns: %{valid_signature: true}} = conn, _),
do: conn
defp assign_valid_signature_on_route_aliases(conn, []) do
Logger.warning("Received request with invalid signature!\n#{inspect(conn)}")
conn
end
defp assign_valid_signature_on_route_aliases(conn, [path | rest]) do
request_target = String.downcase("#{conn.method}") <> " #{path}"
case HTTPSignatures.validate_conn(conn, request_target) do
{:ok, %HTTPKey{user_data: ud}} ->
conn
|> assign(:valid_signature, true)
|> assign(:signature_user, ud["key_user"])
{:error, e} ->
conn
|> assign(:valid_signature, false)
|> assign(:signature_user, nil)
|> maybe_log_error_and_try_aliases(e, rest)
end
end
defp maybe_assign_valid_signature(conn) do
if has_signature_header?(conn) do
# set (request-target) header to the appropriate value
# we also replace the digest header with the one we computed
possible_paths =
[conn.request_path, conn.request_path <> "?#{conn.query_string}" | route_aliases(conn)]
conn =
case conn do
%{assigns: %{digest: digest}} = conn -> put_req_header(conn, "digest", digest)
conn -> conn
end
assign_valid_signature_on_route_aliases(conn, possible_paths)
else
Logger.debug("No signature header!")
conn
end
end
defp has_signature_header?(conn) do
conn |> get_req_header("signature") |> Enum.at(0, false)
end
end