ReceiverWorker: Check that signature matches actor
This commit is contained in:
parent
da28a4c441
commit
42683e79df
2 changed files with 16 additions and 2 deletions
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
||||||
alias Pleroma.Signature
|
alias Pleroma.Signature
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.Federator
|
alias Pleroma.Web.Federator
|
||||||
|
alias Pleroma.Web.Plugs.MappedSignatureToIdentityPlug
|
||||||
|
|
||||||
use Oban.Worker, queue: :federator_incoming, max_attempts: 5, unique: [period: :infinity]
|
use Oban.Worker, queue: :federator_incoming, max_attempts: 5, unique: [period: :infinity]
|
||||||
|
|
||||||
|
|
@ -27,6 +28,7 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
||||||
req_headers = Enum.into(req_headers, [], &List.to_tuple(&1))
|
req_headers = Enum.into(req_headers, [], &List.to_tuple(&1))
|
||||||
|
|
||||||
conn_data = %Plug.Conn{
|
conn_data = %Plug.Conn{
|
||||||
|
assigns: %{valid_signature: true},
|
||||||
method: method,
|
method: method,
|
||||||
params: params,
|
params: params,
|
||||||
req_headers: req_headers,
|
req_headers: req_headers,
|
||||||
|
|
@ -37,6 +39,7 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
||||||
with {:ok, %User{}} <- User.get_or_fetch_by_ap_id(conn_data.params["actor"]),
|
with {:ok, %User{}} <- User.get_or_fetch_by_ap_id(conn_data.params["actor"]),
|
||||||
{:ok, _public_key} <- Signature.refetch_public_key(conn_data),
|
{:ok, _public_key} <- Signature.refetch_public_key(conn_data),
|
||||||
{:signature, true} <- {:signature, Signature.validate_signature(conn_data)},
|
{:signature, true} <- {:signature, Signature.validate_signature(conn_data)},
|
||||||
|
{:same_actor, true} <- {:same_actor, validate_same_actor(conn_data)},
|
||||||
{:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
|
{:ok, res} <- Federator.perform(:incoming_ap_doc, params) do
|
||||||
unless Instances.reachable?(params["actor"]) do
|
unless Instances.reachable?(params["actor"]) do
|
||||||
domain = URI.parse(params["actor"]).host
|
domain = URI.parse(params["actor"]).host
|
||||||
|
|
@ -67,6 +70,16 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
||||||
|
|
||||||
def timeout(_job), do: :timer.seconds(5)
|
def timeout(_job), do: :timer.seconds(5)
|
||||||
|
|
||||||
|
defp validate_same_actor(conn_data) do
|
||||||
|
case MappedSignatureToIdentityPlug.call(conn_data, []) do
|
||||||
|
%Plug.Conn{assigns: %{valid_signature: true}} ->
|
||||||
|
true
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp process_errors({:error, {:error, _} = error}), do: process_errors(error)
|
defp process_errors({:error, {:error, _} = error}), do: process_errors(error)
|
||||||
|
|
||||||
defp process_errors(errors) do
|
defp process_errors(errors) do
|
||||||
|
|
@ -85,6 +98,7 @@ defmodule Pleroma.Workers.ReceiverWorker do
|
||||||
{:error, {:reject, _} = reason} -> {:cancel, reason}
|
{:error, {:reject, _} = reason} -> {:cancel, reason}
|
||||||
# HTTP Sigs
|
# HTTP Sigs
|
||||||
{:signature, false} -> {:cancel, :invalid_signature}
|
{:signature, false} -> {:cancel, :invalid_signature}
|
||||||
|
{:same_actor, false} -> {:cancel, :actor_signature_mismatch}
|
||||||
# Origin / URL validation failed somewhere possibly due to spoofing
|
# Origin / URL validation failed somewhere possibly due to spoofing
|
||||||
{:error, :origin_containment_failed} -> {:cancel, :origin_containment_failed}
|
{:error, :origin_containment_failed} -> {:cancel, :origin_containment_failed}
|
||||||
# Unclear if this can be reached
|
# Unclear if this can be reached
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
test "cancels when signature actor does not match payload actor" do
|
test "cancels when signature actor does not match payload actor" do
|
||||||
alice = insert(:user, local: false, ap_id: "https://example.com/users/alice")
|
_alice = insert(:user, local: false, ap_id: "https://example.com/users/alice")
|
||||||
bob = insert(:user, local: false, ap_id: "https://example.com/users/bob")
|
bob = insert(:user, local: false, ap_id: "https://example.com/users/bob")
|
||||||
|
|
||||||
note = insert(:note, user: bob, object_local: false)
|
note = insert(:note, user: bob, object_local: false)
|
||||||
|
|
@ -343,7 +343,7 @@ defmodule Pleroma.Workers.ReceiverWorkerTest do
|
||||||
with_mock Pleroma.Signature, [:passthrough],
|
with_mock Pleroma.Signature, [:passthrough],
|
||||||
refetch_public_key: fn _conn -> {:ok, :fake_public_key} end,
|
refetch_public_key: fn _conn -> {:ok, :fake_public_key} end,
|
||||||
validate_signature: fn _conn -> true end do
|
validate_signature: fn _conn -> true end do
|
||||||
assert {:cancel, :invalid_signature} = ReceiverWorker.perform(oban_job)
|
assert {:cancel, :actor_signature_mismatch} = ReceiverWorker.perform(oban_job)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue