logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma

http_signature.ex (1747B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
  5. import Plug.Conn
  6. import Phoenix.Controller, only: [get_format: 1, text: 2]
  7. require Logger
  8. def init(options) do
  9. options
  10. end
  11. def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
  12. conn
  13. end
  14. def call(conn, _opts) do
  15. if get_format(conn) == "activity+json" do
  16. conn
  17. |> maybe_assign_valid_signature()
  18. |> maybe_require_signature()
  19. else
  20. conn
  21. end
  22. end
  23. defp maybe_assign_valid_signature(conn) do
  24. if has_signature_header?(conn) do
  25. # set (request-target) header to the appropriate value
  26. # we also replace the digest header with the one we computed
  27. request_target = String.downcase("#{conn.method}") <> " #{conn.request_path}"
  28. conn =
  29. conn
  30. |> put_req_header("(request-target)", request_target)
  31. |> case do
  32. %{assigns: %{digest: digest}} = conn -> put_req_header(conn, "digest", digest)
  33. conn -> conn
  34. end
  35. assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn))
  36. else
  37. Logger.debug("No signature header!")
  38. conn
  39. end
  40. end
  41. defp has_signature_header?(conn) do
  42. conn |> get_req_header("signature") |> Enum.at(0, false)
  43. end
  44. defp maybe_require_signature(%{assigns: %{valid_signature: true}} = conn), do: conn
  45. defp maybe_require_signature(conn) do
  46. if Pleroma.Config.get([:activitypub, :authorized_fetch_mode], false) do
  47. conn
  48. |> put_status(:unauthorized)
  49. |> text("Request not signed")
  50. |> halt()
  51. else
  52. conn
  53. end
  54. end
  55. end