Merge branch 'relay-list-change' into 'develop'
[akkoma] / lib / pleroma / plugs / http_signature.ex
index 9e53371b74664baa54a8bede27db3079fa1e406d..036e2a7739e0ca16fb05412d15249fa6594c2ab3 100644 (file)
@@ -1,7 +1,10 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
 defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
-  alias Pleroma.Web.HTTPSignatures
-  alias Pleroma.Web.ActivityPub.Utils
   import Plug.Conn
+  import Phoenix.Controller, only: [get_format: 1, text: 2]
   require Logger
 
   def init(options) do
@@ -13,38 +16,50 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
   end
 
   def call(conn, _opts) do
-    user = Utils.get_ap_id(conn.params["actor"])
-    Logger.debug("Checking sig for #{user}")
-    [signature | _] = get_req_header(conn, "signature")
-
-    cond do
-      signature && String.contains?(signature, user) ->
-        # set (request-target) header to the appropriate value
-        # we also replace the digest header with the one we computed
-        conn =
-          conn
-          |> put_req_header(
-            "(request-target)",
-            String.downcase("#{conn.method}") <> " #{conn.request_path}"
-          )
-
-        conn =
-          if conn.assigns[:digest] do
-            conn
-            |> put_req_header("digest", conn.assigns[:digest])
-          else
-            conn
-          end
-
-        assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn))
-
-      signature ->
-        Logger.debug("Signature not from actor")
-        assign(conn, :valid_signature, false)
-
-      true ->
-        Logger.debug("No signature header!")
+    if get_format(conn) == "activity+json" do
+      conn
+      |> maybe_assign_valid_signature()
+      |> maybe_require_signature()
+    else
+      conn
+    end
+  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))
+    else
+      Logger.debug("No signature header!")
+      conn
+    end
+  end
+
+  defp has_signature_header?(conn) do
+    conn |> get_req_header("signature") |> Enum.at(0, false)
+  end
+
+  defp maybe_require_signature(%{assigns: %{valid_signature: true}} = conn), do: conn
+
+  defp maybe_require_signature(conn) do
+    if Pleroma.Config.get([:activitypub, :authorized_fetch_mode], false) do
+      conn
+      |> put_status(:unauthorized)
+      |> text("Request not signed")
+      |> halt()
+    else
+      conn
     end
   end
 end