Include port in host for signatures
authorMaksim Pechnikov <parallel588@gmail.com>
Tue, 14 Jul 2020 18:44:08 +0000 (21:44 +0300)
committerMaksim Pechnikov <parallel588@gmail.com>
Tue, 14 Jul 2020 18:44:08 +0000 (21:44 +0300)
lib/pleroma/web/activity_pub/publisher.ex
test/web/activity_pub/publisher_test.exs

index b70cbd04343b4d40ca899a6e63c331d861f3d3d4..d88f7f3ee57d40614d3c574293aad7423805773d 100644 (file)
@@ -49,7 +49,8 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
   """
   def publish_one(%{inbox: inbox, json: json, actor: %User{} = actor, id: id} = params) do
     Logger.debug("Federating #{id} to #{inbox}")
-    %{host: host, path: path} = URI.parse(inbox)
+
+    uri = URI.parse(inbox)
 
     digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
 
@@ -57,8 +58,8 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
 
     signature =
       Pleroma.Signature.sign(actor, %{
-        "(request-target)": "post #{path}",
-        host: host,
+        "(request-target)": "post #{uri.path}",
+        host: signature_host(uri),
         "content-length": byte_size(json),
         digest: digest,
         date: date
@@ -76,8 +77,9 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
                  {"digest", digest}
                ]
              ) do
-      if !Map.has_key?(params, :unreachable_since) || params[:unreachable_since],
-        do: Instances.set_reachable(inbox)
+      if not Map.has_key?(params, :unreachable_since) || params[:unreachable_since] do
+        Instances.set_reachable(inbox)
+      end
 
       result
     else
@@ -96,6 +98,14 @@ defmodule Pleroma.Web.ActivityPub.Publisher do
     |> publish_one()
   end
 
+  defp signature_host(%URI{port: port, scheme: scheme, host: host}) do
+    if port == URI.default_port(scheme) do
+      host
+    else
+      "#{host}:#{port}"
+    end
+  end
+
   defp should_federate?(inbox, public) do
     if public do
       true
index c2bc38d52508fdf896d2781484dfe742080d4919..b9388b966d5d3e067df18c325a54b8c146728a35 100644 (file)
@@ -123,6 +123,39 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
   end
 
   describe "publish_one/1" do
+    test "publish to url with with different ports" do
+      inbox80 = "http://42.site/users/nick1/inbox"
+      inbox42 = "http://42.site:42/users/nick1/inbox"
+
+      mock(fn
+        %{method: :post, url: "http://42.site:42/users/nick1/inbox"} ->
+          {:ok, %Tesla.Env{status: 200, body: "port 42"}}
+
+        %{method: :post, url: "http://42.site/users/nick1/inbox"} ->
+          {:ok, %Tesla.Env{status: 200, body: "port 80"}}
+      end)
+
+      actor = insert(:user)
+
+      assert {:ok, %{body: "port 42"}} =
+               Publisher.publish_one(%{
+                 inbox: inbox42,
+                 json: "{}",
+                 actor: actor,
+                 id: 1,
+                 unreachable_since: true
+               })
+
+      assert {:ok, %{body: "port 80"}} =
+               Publisher.publish_one(%{
+                 inbox: inbox80,
+                 json: "{}",
+                 actor: actor,
+                 id: 1,
+                 unreachable_since: true
+               })
+    end
+
     test_with_mock "calls `Instances.set_reachable` on successful federation if `unreachable_since` is not specified",
                    Instances,
                    [:passthrough],
@@ -131,7 +164,6 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do
       inbox = "http://200.site/users/nick1/inbox"
 
       assert {:ok, _} = Publisher.publish_one(%{inbox: inbox, json: "{}", actor: actor, id: 1})
-
       assert called(Instances.set_reachable(inbox))
     end