comparison sat/plugins/plugin_comp_ap_gateway/http_server.py @ 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 1bd44367337d
children aa7197b67c26
comparison
equal deleted inserted replaced
3883:6da749bbf320 3884:cea52400623d
978 request.content.seek(0) 978 request.content.seek(0)
979 headers = {} 979 headers = {}
980 for to_sign in signed_headers: 980 for to_sign in signed_headers:
981 if to_sign == "(request-target)": 981 if to_sign == "(request-target)":
982 method = request.method.decode().lower() 982 method = request.method.decode().lower()
983 uri = parse.unquote(request.uri.decode()) 983 uri = request.uri.decode()
984 headers[to_sign] = f"{method} /{uri.lstrip('/')}" 984 headers[to_sign] = f"{method} /{uri.lstrip('/')}"
985 elif to_sign in ("(created)", "(expires)"): 985 elif to_sign in ("(created)", "(expires)"):
986 if algorithm != HS2019: 986 if algorithm != HS2019:
987 raise exceptions.EncryptionError( 987 raise exceptions.EncryptionError(
988 f"{to_sign!r} pseudo-header can only be used with {HS2019} " 988 f"{to_sign!r} pseudo-header can only be used with {HS2019} "
1068 limit_ts = min(limit_ts, expires) 1068 limit_ts = min(limit_ts, expires)
1069 1069
1070 if created > limit_ts: 1070 if created > limit_ts:
1071 raise exceptions.EncryptionError("Signature has expired") 1071 raise exceptions.EncryptionError("Signature has expired")
1072 1072
1073 return await self.apg.checkSignature( 1073 try:
1074 sign_data["signature"], 1074 return await self.apg.checkSignature(
1075 key_id, 1075 sign_data["signature"],
1076 headers 1076 key_id,
1077 ) 1077 headers
1078 )
1079 except exceptions.EncryptionError:
1080 method, url = headers["(request-target)"].rsplit(' ', 1)
1081 headers["(request-target)"] = f"{method} {parse.unquote(url)}"
1082 log.debug(
1083 "Using workaround for (request-target) encoding bug in signature, "
1084 "see https://github.com/mastodon/mastodon/issues/18871"
1085 )
1086 return await self.apg.checkSignature(
1087 sign_data["signature"],
1088 key_id,
1089 headers
1090 )
1078 1091
1079 def render(self, request): 1092 def render(self, request):
1080 request.setHeader("server", VERSION) 1093 request.setHeader("server", VERSION)
1081 return super().render(request) 1094 return super().render(request)
1082 1095