Mercurial > libervia-backend
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)