mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-13 19:23:17 +01:00
Make handling of federation Authorization header (more) compliant with RFC7230 (#12774)
The main differences are: - values with delimiters (such as colons) should be quoted, so always quote the origin, since it could contain a colon followed by a port number - should allow more than one space after "X-Matrix" - quoted values with backslash-escaped characters should be unescaped - names should be case insensitive
This commit is contained in:
parent
37935b5183
commit
8afb7b55d0
4 changed files with 35 additions and 5 deletions
1
changelog.d/12774.misc
Normal file
1
changelog.d/12774.misc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Make handling of federation Authorization header (more) compliant with RFC7230.
|
|
@ -169,14 +169,16 @@ def _parse_auth_header(header_bytes: bytes) -> Tuple[str, str, str, Optional[str
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
header_str = header_bytes.decode("utf-8")
|
header_str = header_bytes.decode("utf-8")
|
||||||
params = header_str.split(" ")[1].split(",")
|
params = re.split(" +", header_str)[1].split(",")
|
||||||
param_dict: Dict[str, str] = {
|
param_dict: Dict[str, str] = {
|
||||||
k: v for k, v in [param.split("=", maxsplit=1) for param in params]
|
k.lower(): v for k, v in [param.split("=", maxsplit=1) for param in params]
|
||||||
}
|
}
|
||||||
|
|
||||||
def strip_quotes(value: str) -> str:
|
def strip_quotes(value: str) -> str:
|
||||||
if value.startswith('"'):
|
if value.startswith('"'):
|
||||||
return value[1:-1]
|
return re.sub(
|
||||||
|
"\\\\(.)", lambda matchobj: matchobj.group(1), value[1:-1]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
@ -747,7 +747,7 @@ class MatrixFederationHttpClient:
|
||||||
for key, sig in request["signatures"][self.server_name].items():
|
for key, sig in request["signatures"][self.server_name].items():
|
||||||
auth_headers.append(
|
auth_headers.append(
|
||||||
(
|
(
|
||||||
'X-Matrix origin=%s,key="%s",sig="%s",destination="%s"'
|
'X-Matrix origin="%s",key="%s",sig="%s",destination="%s"'
|
||||||
% (
|
% (
|
||||||
self.server_name,
|
self.server_name,
|
||||||
key,
|
key,
|
||||||
|
|
|
@ -17,7 +17,7 @@ from typing import Dict, List, Tuple
|
||||||
|
|
||||||
from synapse.api.errors import Codes
|
from synapse.api.errors import Codes
|
||||||
from synapse.federation.transport.server import BaseFederationServlet
|
from synapse.federation.transport.server import BaseFederationServlet
|
||||||
from synapse.federation.transport.server._base import Authenticator
|
from synapse.federation.transport.server._base import Authenticator, _parse_auth_header
|
||||||
from synapse.http.server import JsonResource, cancellable
|
from synapse.http.server import JsonResource, cancellable
|
||||||
from synapse.server import HomeServer
|
from synapse.server import HomeServer
|
||||||
from synapse.types import JsonDict
|
from synapse.types import JsonDict
|
||||||
|
@ -112,3 +112,30 @@ class BaseFederationServletCancellationTests(
|
||||||
expect_cancellation=False,
|
expect_cancellation=False,
|
||||||
expected_body={"result": True},
|
expected_body={"result": True},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFederationAuthorizationTests(unittest.TestCase):
|
||||||
|
def test_authorization_header(self) -> None:
|
||||||
|
"""Tests that the Authorization header is parsed correctly."""
|
||||||
|
|
||||||
|
# test a "normal" Authorization header
|
||||||
|
self.assertEqual(
|
||||||
|
_parse_auth_header(
|
||||||
|
b'X-Matrix origin=foo,key="ed25519:1",sig="sig",destination="bar"'
|
||||||
|
),
|
||||||
|
("foo", "ed25519:1", "sig", "bar"),
|
||||||
|
)
|
||||||
|
# test an Authorization with extra spaces, upper-case names, and escaped
|
||||||
|
# characters
|
||||||
|
self.assertEqual(
|
||||||
|
_parse_auth_header(
|
||||||
|
b'X-Matrix ORIGIN=foo,KEY="ed25\\519:1",SIG="sig",destination="bar"'
|
||||||
|
),
|
||||||
|
("foo", "ed25519:1", "sig", "bar"),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
_parse_auth_header(
|
||||||
|
b'X-Matrix origin=foo,key="ed25519:1",sig="sig",destination="bar",extra_field=ignored'
|
||||||
|
),
|
||||||
|
("foo", "ed25519:1", "sig", "bar"),
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue