From ec162b496b1012ebac328885695b6e25645fd71a Mon Sep 17 00:00:00 2001 From: floatingghost Date: Fri, 5 Aug 2022 19:31:32 +0000 Subject: [PATCH] /notice signing checks on redirect (#150) Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/150 --- lib/pleroma/web/plugs/http_signature_plug.ex | 48 ++++++++++++++----- .../web/plugs/http_signature_plug_test.exs | 10 ++++ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/lib/pleroma/web/plugs/http_signature_plug.ex b/lib/pleroma/web/plugs/http_signature_plug.ex index 0f7550516..79030be5f 100644 --- a/lib/pleroma/web/plugs/http_signature_plug.ex +++ b/lib/pleroma/web/plugs/http_signature_plug.ex @@ -5,6 +5,8 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do import Plug.Conn import Phoenix.Controller, only: [get_format: 1, text: 2] + alias Pleroma.Activity + alias Pleroma.Web.Router require Logger def init(options) do @@ -25,21 +27,45 @@ def call(conn, _opts) do end end + def route_aliases(%{path_info: ["objects", id]} = conn) do + ap_id = Router.Helpers.o_status_url(Pleroma.Web.Endpoint, :object, id) + + with %Activity{} = activity <- Activity.get_by_object_ap_id_with_object(ap_id) do + ["/notice/#{activity.id}"] + else + _ -> [] + end + end + + def route_aliases(_), do: [] + + defp assign_valid_signature_on_route_aliases(conn, []), do: conn + + defp assign_valid_signature_on_route_aliases(%{assigns: %{valid_signature: true}} = conn, _), + do: conn + + defp assign_valid_signature_on_route_aliases(conn, [path | rest]) do + request_target = String.downcase("#{conn.method}") <> " #{path}" + + conn = + conn + |> put_req_header("(request-target)", request_target) + |> case do + %{assigns: %{digest: digest}} = conn -> put_req_header(conn, "digest", digest) + conn -> conn + end + + conn + |> assign(:valid_signature, HTTPSignatures.validate_conn(conn)) + |> assign_valid_signature_on_route_aliases(rest) + 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 - request_target = String.downcase("#{conn.method}") <> " #{conn.request_path}" - - conn = - conn - |> put_req_header("(request-target)", request_target) - |> case do - %{assigns: %{digest: digest}} = conn -> put_req_header(conn, "digest", digest) - conn -> conn - end - - assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn)) + possible_paths = route_aliases(conn) ++ [conn.request_path] + assign_valid_signature_on_route_aliases(conn, possible_paths) else Logger.debug("No signature header!") conn diff --git a/test/pleroma/web/plugs/http_signature_plug_test.exs b/test/pleroma/web/plugs/http_signature_plug_test.exs index 56ef6b06f..02e8b3092 100644 --- a/test/pleroma/web/plugs/http_signature_plug_test.exs +++ b/test/pleroma/web/plugs/http_signature_plug_test.exs @@ -4,6 +4,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do use Pleroma.Web.ConnCase + import Pleroma.Factory alias Pleroma.Web.Plugs.HTTPSignaturePlug import Plug.Conn @@ -81,5 +82,14 @@ test "halts the connection when `signature` header is not present", %{conn: conn assert conn.state == :sent assert conn.resp_body == "Request not signed" end + + test "aliases redirected /object endpoints", _ do + obj = insert(:note) + act = insert(:note_activity, note: obj) + params = %{"actor" => "http://mastodon.example.org/users/admin"} + path = URI.parse(obj.data["id"]).path + conn = build_conn(:get, path, params) + assert ["/notice/#{act.id}"] == HTTPSignaturePlug.route_aliases(conn) + end end end