changeset 3884:cea52400623d

component AP gateway: work around encoding bug in Mastodon: Mastodon in wrongly unquoting URL path in `(request-target)`, and thus Libervia was doing the same to check signature. However that doesn't work with Pleroma which is using the path value used in the request (percent-encoded), and thus Pleroma signature were rejected. To work around that, signature is first checked without unquoting, and if this fails a new check is done with unquoting. Bug has been reported at https://github.com/mastodon/mastodon/issues/18871 rel 371
author Goffi <goffi@goffi.org>
date Wed, 31 Aug 2022 17:07:03 +0200
parents 6da749bbf320
children 18ff4f75f0e6
files sat/plugins/plugin_comp_ap_gateway/http_server.py
diffstat 1 files changed, 19 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/sat/plugins/plugin_comp_ap_gateway/http_server.py	Wed Aug 31 17:07:03 2022 +0200
+++ b/sat/plugins/plugin_comp_ap_gateway/http_server.py	Wed Aug 31 17:07:03 2022 +0200
@@ -980,7 +980,7 @@
         for to_sign in signed_headers:
             if to_sign == "(request-target)":
                 method = request.method.decode().lower()
-                uri = parse.unquote(request.uri.decode())
+                uri = request.uri.decode()
                 headers[to_sign] = f"{method} /{uri.lstrip('/')}"
             elif to_sign in ("(created)", "(expires)"):
                 if algorithm != HS2019:
@@ -1070,11 +1070,24 @@
         if created > limit_ts:
             raise exceptions.EncryptionError("Signature has expired")
 
-        return await self.apg.checkSignature(
-            sign_data["signature"],
-            key_id,
-            headers
-        )
+        try:
+            return await self.apg.checkSignature(
+                sign_data["signature"],
+                key_id,
+                headers
+            )
+        except exceptions.EncryptionError:
+            method, url = headers["(request-target)"].rsplit(' ', 1)
+            headers["(request-target)"] = f"{method} {parse.unquote(url)}"
+            log.debug(
+                "Using workaround for (request-target) encoding bug in signature, "
+                "see https://github.com/mastodon/mastodon/issues/18871"
+            )
+            return await self.apg.checkSignature(
+                sign_data["signature"],
+                key_id,
+                headers
+            )
 
     def render(self, request):
         request.setHeader("server", VERSION)