commit: 16a9b34876f3a9289c02253e802bffdac4901ac0
parent 06deacd58e6aa676847530f24c6799162ed06777
Author: Mark Felder <feld@feld.me>
Date: Thu, 29 Aug 2024 14:16:59 -0400
Convert to an Plug called InboxGuard
Diffstat:
5 files changed, 91 insertions(+), 28 deletions(-)
diff --git a/lib/pleroma/constants.ex b/lib/pleroma/constants.ex
@@ -85,6 +85,18 @@ defmodule Pleroma.Constants do
]
)
+ const(allowed_activity_types_from_strangers,
+ do: [
+ "Block",
+ "Create",
+ "Flag",
+ "Follow",
+ "Like",
+ "Move",
+ "React"
+ ]
+ )
+
# basic regex, just there to weed out potential mistakes
# https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
const(mime_regex,
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -294,19 +294,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
end
def inbox(%{assigns: %{valid_signature: false}} = conn, params) do
- case unknown_delete?(params) do
- true ->
- :ok
-
- false ->
- Federator.incoming_ap_doc(%{
- method: conn.method,
- req_headers: conn.req_headers,
- request_path: conn.request_path,
- params: params,
- query_string: conn.query_string
- })
- end
+ Federator.incoming_ap_doc(%{
+ method: conn.method,
+ req_headers: conn.req_headers,
+ request_path: conn.request_path,
+ params: params,
+ query_string: conn.query_string
+ })
json(conn, "ok")
end
@@ -564,17 +558,4 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
|> json(UserView.render("featured.json", %{user: user}))
end
end
-
- defp unknown_delete?(
- %{
- "type" => "Delete"
- } = data
- ) do
- case data |> Pleroma.Object.Containment.get_actor() |> User.get_cached_by_ap_id() do
- %User{} -> false
- _ -> true
- end
- end
-
- defp unknown_delete?(_), do: false
end
diff --git a/lib/pleroma/web/plugs/inbox_guard_plug.ex b/lib/pleroma/web/plugs/inbox_guard_plug.ex
@@ -0,0 +1,66 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Plugs.InboxGuardPlug do
+ import Plug.Conn
+ import Pleroma.Constants, only: [allowed_activity_types_from_strangers: 0]
+
+ alias Pleroma.Config
+ alias Pleroma.User
+
+ def init(options) do
+ options
+ end
+
+ def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
+ conn
+ end
+
+ def call(conn, _opts) do
+ with {_, true} <- {:federating, Config.get!([:instance, :federating])},
+ true <- known_actor?(conn) do
+ conn
+ else
+ {:federating, false} ->
+ conn
+ |> json(403, "Not federating")
+
+ _ ->
+ conn
+ |> filter_from_strangers()
+ end
+ end
+
+ # If signature failed but we know this actor we should
+ # accept it as we may only need to refetch their public key
+ # during processing
+ defp known_actor?(%{body_params: data}) do
+ case Pleroma.Object.Containment.get_actor(data) |> User.get_cached_by_ap_id() do
+ %User{} -> true
+ _ -> false
+ end
+ end
+
+ # Only permit a subset of activity types from strangers
+ # or else it will add actors you've never interacted with
+ # to the database
+ defp filter_from_strangers(%{body_params: %{"type" => type}} = conn) do
+ with true <- type in allowed_activity_types_from_strangers() do
+ conn
+ else
+ _ ->
+ conn
+ |> json(400, "Invalid activity type for an unknown actor")
+ end
+ end
+
+ defp json(conn, status, resp) do
+ json_resp = Jason.encode!(resp)
+
+ conn
+ |> put_resp_content_type("application/json")
+ |> resp(status, json_resp)
+ |> halt()
+ end
+end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
@@ -217,6 +217,10 @@ defmodule Pleroma.Web.Router do
plug(Pleroma.Web.Plugs.MappedSignatureToIdentityPlug)
end
+ pipeline :inbox_guard do
+ plug(Pleroma.Web.Plugs.InboxGuardPlug)
+ end
+
pipeline :static_fe do
plug(Pleroma.Web.Plugs.StaticFEPlug)
end
@@ -920,7 +924,7 @@ defmodule Pleroma.Web.Router do
end
scope "/", Pleroma.Web.ActivityPub do
- pipe_through(:activitypub)
+ pipe_through([:activitypub, :inbox_guard])
post("/inbox", ActivityPubController, :inbox)
post("/users/:nickname/inbox", ActivityPubController, :inbox)
end
diff --git a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs
@@ -700,7 +700,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
|> assign(:valid_signature, false)
|> put_req_header("content-type", "application/activity+json")
|> post("/inbox", params)
- |> json_response(200)
+ |> json_response(400)
assert all_enqueued() == []
end