summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/http_signatures_api.ex4
-rw-r--r--lib/pleroma/signature.ex16
-rw-r--r--lib/pleroma/web/mastodon_api/views/instance_view.ex7
-rw-r--r--lib/pleroma/web/plugs/http_signature_plug.ex53
4 files changed, 73 insertions, 7 deletions
diff --git a/lib/pleroma/http_signatures_api.ex b/lib/pleroma/http_signatures_api.ex
new file mode 100644
index 000000000..8e73dc98e
--- /dev/null
+++ b/lib/pleroma/http_signatures_api.ex
@@ -0,0 +1,4 @@
+defmodule Pleroma.HTTPSignaturesAPI do
+ @callback validate_conn(conn :: Plug.Conn.t()) :: boolean
+ @callback signature_for_conn(conn :: Plug.Conn.t()) :: map
+end
diff --git a/lib/pleroma/signature.ex b/lib/pleroma/signature.ex
index 8fd422a6e..900d40c4b 100644
--- a/lib/pleroma/signature.ex
+++ b/lib/pleroma/signature.ex
@@ -44,8 +44,7 @@ defmodule Pleroma.Signature do
defp remove_suffix(uri, []), do: uri
def fetch_public_key(conn) do
- with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
- {:ok, actor_id} <- key_id_to_actor_id(kid),
+ with {:ok, actor_id} <- get_actor_id(conn),
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
{:ok, public_key}
else
@@ -55,8 +54,7 @@ defmodule Pleroma.Signature do
end
def refetch_public_key(conn) do
- with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
- {:ok, actor_id} <- key_id_to_actor_id(kid),
+ with {:ok, actor_id} <- get_actor_id(conn),
{:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
{:ok, public_key}
@@ -66,6 +64,16 @@ defmodule Pleroma.Signature do
end
end
+ def get_actor_id(conn) do
+ with %{"keyId" => kid} <- HTTPSignatures.signature_for_conn(conn),
+ {:ok, actor_id} <- key_id_to_actor_id(kid) do
+ {:ok, actor_id}
+ else
+ e ->
+ {:error, e}
+ end
+ end
+
def sign(%User{keys: keys} = user, headers) do
with {:ok, private_key, _} <- Keys.keys_from_pem(keys) do
HTTPSignatures.sign(private_key, user.ap_id <> "#main-key", headers)
diff --git a/lib/pleroma/web/mastodon_api/views/instance_view.ex b/lib/pleroma/web/mastodon_api/views/instance_view.ex
index 99fc6d0c3..913684928 100644
--- a/lib/pleroma/web/mastodon_api/views/instance_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/instance_view.ex
@@ -152,6 +152,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
def federation do
quarantined = Config.get([:instance, :quarantined_instances], [])
+ rejected = Config.get([:instance, :rejected_instances], [])
if Config.get([:mrf, :transparency]) do
{:ok, data} = MRF.describe()
@@ -171,6 +172,12 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|> Enum.map(fn {instance, reason} -> {instance, %{"reason" => reason}} end)
|> Map.new()
})
+ |> Map.put(
+ :rejected_instances,
+ rejected
+ |> Enum.map(fn {instance, reason} -> {instance, %{"reason" => reason}} end)
+ |> Map.new()
+ )
else
%{}
end
diff --git a/lib/pleroma/web/plugs/http_signature_plug.ex b/lib/pleroma/web/plugs/http_signature_plug.ex
index 7ec202662..6bf2dd432 100644
--- a/lib/pleroma/web/plugs/http_signature_plug.ex
+++ b/lib/pleroma/web/plugs/http_signature_plug.ex
@@ -7,8 +7,18 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
import Plug.Conn
import Phoenix.Controller, only: [get_format: 1, text: 2]
+
+ alias Pleroma.Web.ActivityPub.MRF
+
require Logger
+ @config_impl Application.compile_env(:pleroma, [__MODULE__, :config_impl], Pleroma.Config)
+ @http_signatures_impl Application.compile_env(
+ :pleroma,
+ [__MODULE__, :http_signatures_impl],
+ HTTPSignatures
+ )
+
def init(options) do
options
end
@@ -21,7 +31,9 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
if get_format(conn) in ["json", "activity+json"] do
conn
|> maybe_assign_valid_signature()
+ |> maybe_assign_actor_id()
|> maybe_require_signature()
+ |> maybe_filter_requests()
else
conn
end
@@ -35,7 +47,7 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|> put_req_header("(request-target)", request_target)
|> put_req_header("@request-target", request_target)
- HTTPSignatures.validate_conn(conn)
+ @http_signatures_impl.validate_conn(conn)
end
defp validate_signature(conn) do
@@ -85,6 +97,16 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
end
end
+ defp maybe_assign_actor_id(%{assigns: %{valid_signature: true}} = conn) do
+ adapter = Application.get_env(:http_signatures, :adapter)
+
+ {:ok, actor_id} = adapter.get_actor_id(conn)
+
+ assign(conn, :actor_id, actor_id)
+ end
+
+ defp maybe_assign_actor_id(conn), do: conn
+
defp has_signature_header?(conn) do
conn |> get_req_header("signature") |> Enum.at(0, false)
end
@@ -92,9 +114,9 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
defp maybe_require_signature(%{assigns: %{valid_signature: true}} = conn), do: conn
defp maybe_require_signature(%{remote_ip: remote_ip} = conn) do
- if Pleroma.Config.get([:activitypub, :authorized_fetch_mode], false) do
+ if @config_impl.get([:activitypub, :authorized_fetch_mode], false) do
exceptions =
- Pleroma.Config.get([:activitypub, :authorized_fetch_mode_exceptions], [])
+ @config_impl.get([:activitypub, :authorized_fetch_mode_exceptions], [])
|> Enum.map(&InetHelper.parse_cidr/1)
if Enum.any?(exceptions, fn x -> InetCidr.contains?(x, remote_ip) end) do
@@ -109,4 +131,29 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
conn
end
end
+
+ defp maybe_filter_requests(%{halted: true} = conn), do: conn
+
+ defp maybe_filter_requests(conn) do
+ if @config_impl.get([:activitypub, :authorized_fetch_mode], false) and
+ conn.assigns[:actor_id] do
+ %{host: host} = URI.parse(conn.assigns.actor_id)
+
+ if MRF.subdomain_match?(rejected_domains(), host) do
+ conn
+ |> put_status(:unauthorized)
+ |> halt()
+ else
+ conn
+ end
+ else
+ conn
+ end
+ end
+
+ defp rejected_domains do
+ @config_impl.get([:instance, :rejected_instances])
+ |> Pleroma.Web.ActivityPub.MRF.instance_list_from_tuples()
+ |> Pleroma.Web.ActivityPub.MRF.subdomains_regex()
+ end
end