Remote Timeline: add Streaming support
[akkoma] / lib / pleroma / plugs / http_signature.ex
index d2d4bdd635c31e2adc4ae4ab75724f41956bda93..036e2a7739e0ca16fb05412d15249fa6594c2ab3 100644 (file)
@@ -1,22 +1,43 @@
+# 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
   import Plug.Conn
+  import Phoenix.Controller, only: [get_format: 1, text: 2]
   require Logger
 
   def init(options) do
     options
   end
 
-  def call(%{assigns: %{valid_signature: true}} = conn, opts) do
+  def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
     conn
   end
 
-  def call(conn, opts) do
-    user = conn.params["actor"]
-    Logger.debug("Checking sig for #{user}")
-    if get_req_header(conn, "signature") do
-      conn = conn
-      |> put_req_header("(request-target)", String.downcase("#{conn.method}") <> " #{conn.request_path}")
+  def call(conn, _opts) do
+    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
@@ -24,4 +45,21 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
       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