/notice signing checks on redirect (#150)
authorfloatingghost <hannah@coffee-and-dreams.uk>
Fri, 5 Aug 2022 19:31:32 +0000 (19:31 +0000)
committerfloatingghost <hannah@coffee-and-dreams.uk>
Fri, 5 Aug 2022 19:31:32 +0000 (19:31 +0000)
Reviewed-on: https://akkoma.dev/AkkomaGang/akkoma/pulls/150

lib/pleroma/web/plugs/http_signature_plug.ex
test/pleroma/web/plugs/http_signature_plug_test.exs

index 0f7550516365467a6a569d219bde0c9294819b75..79030be5f1f5b25697e8697d2a981c818f449dec 100644 (file)
@@ -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 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug 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
index 56ef6b06f86f4ec82dcf313d5f8ccbd38aa53699..02e8b309202524bfca150e318b9877d4e0423ce5 100644 (file)
@@ -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 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlugTest do
       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