diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 36 | ||||
| -rw-r--r-- | lib/pleroma/web/activity_pub/transmogrifier.ex | 24 | ||||
| -rw-r--r-- | lib/pleroma/web/federator/federator.ex | 8 | 
3 files changed, 51 insertions, 17 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 51b787272..ed579e336 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -628,9 +628,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do    end    def fetch_and_prepare_user_from_ap_id(ap_id) do -    with {:ok, %{status_code: 200, body: body}} <- -           @httpoison.get(ap_id, [Accept: "application/activity+json"], follow_redirect: true), -         {:ok, data} <- Jason.decode(body) do +    with {:ok, data} <- fetch_and_contain_remote_object_from_id(ap_id) do        user_data_from_user_object(data)      else        e -> Logger.error("Could not decode user at fetch #{ap_id}, #{inspect(e)}") @@ -732,16 +730,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      else        Logger.info("Fetching #{id} via AP") -      with true <- String.starts_with?(id, "http"), -           {:ok, %{body: body, status_code: code}} when code in 200..299 <- -             @httpoison.get( -               id, -               [Accept: "application/activity+json"], -               follow_redirect: true, -               timeout: 10000, -               recv_timeout: 20000 -             ), -           {:ok, data} <- Jason.decode(body), +      with {:ok, data} <- fetch_and_contain_remote_object_from_id(id),             nil <- Object.normalize(data),             params <- %{               "type" => "Create", @@ -771,6 +760,27 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do      end    end +  def fetch_and_contain_remote_object_from_id(id) do +    Logger.info("Fetching #{id} via AP") + +    with true <- String.starts_with?(id, "http"), +         {:ok, %{body: body, status_code: code}} when code in 200..299 <- +           @httpoison.get( +             id, +             [Accept: "application/activity+json"], +             follow_redirect: true, +             timeout: 10000, +             recv_timeout: 20000 +           ), +         {:ok, data} <- Jason.decode(body), +         :ok <- Transmogrifier.contain_origin_from_id(id, data) do +      {:ok, data} +    else +      e -> +        {:error, e} +    end +  end +    def is_public?(activity) do      "https://www.w3.org/ns/activitystreams#Public" in (activity.data["to"] ++                                                           (activity.data["cc"] || [])) diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index d51d8626b..5864855b0 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -50,6 +50,19 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      end    end +  def contain_origin_from_id(id, %{"id" => nil}), do: :error + +  def contain_origin_from_id(id, %{"id" => other_id} = params) do +    id_uri = URI.parse(id) +    other_uri = URI.parse(other_id) + +    if id_uri.host == other_uri.host do +      :ok +    else +      :error +    end +  end +    @doc """    Modifies an incoming AP object (mastodon format) to our internal format.    """ @@ -454,15 +467,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do      end    end -  # TODO: Make secure. +  # TODO: We presently assume that any actor on the same origin domain as the object being +  # deleted has the rights to delete that object.  A better way to validate whether or not +  # the object should be deleted is to refetch the object URI, which should return either +  # an error or a tombstone.  This would allow us to verify that a deletion actually took +  # place.    def handle_incoming( -        %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = data +        %{"type" => "Delete", "object" => object_id, "actor" => _actor, "id" => _id} = data        ) do      object_id = Utils.get_ap_id(object_id)      with actor <- get_actor(data), -         %User{} = _actor <- User.get_or_fetch_by_ap_id(actor), +         %User{} = actor <- User.get_or_fetch_by_ap_id(actor),           {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id), +         :ok <- contain_origin(actor.ap_id, object.data),           {:ok, activity} <- ActivityPub.delete(object, false) do        {:ok, activity}      else diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex index 962cacfa3..6554fd2ef 100644 --- a/lib/pleroma/web/federator/federator.ex +++ b/lib/pleroma/web/federator/federator.ex @@ -101,17 +101,23 @@ defmodule Pleroma.Web.Federator do      params = Utils.normalize_params(params) +    # NOTE: we use the actor ID to do the containment, this is fine because an +    # actor shouldn't be acting on objects outside their own AP server.      with {:ok, _user} <- ap_enabled_actor(params["actor"]),           nil <- Activity.normalize(params["id"]), -         {:ok, _activity} <- Transmogrifier.handle_incoming(params) do +         :ok <- Transmogrifier.contain_origin_from_id(params["actor"], params), +         {:ok, activity} <- Transmogrifier.handle_incoming(params) do +      {:ok, activity}      else        %Activity{} ->          Logger.info("Already had #{params["id"]}") +        :error        _e ->          # Just drop those for now          Logger.info("Unhandled activity")          Logger.info(Poison.encode!(params, pretty: 2)) +        :error      end    end  | 
