Skip to content
Snippets Groups Projects
Commit de1ec901 authored by Mark Haines's avatar Mark Haines
Browse files

Validate signatures on incoming events

parent 44a24605
No related branches found
No related tags found
No related merge requests found
......@@ -19,6 +19,7 @@ from synapse.api.events.utils import prune_event
from syutil.jsonutil import encode_canonical_json
from syutil.base64util import encode_base64, decode_base64
from syutil.crypto.jsonsign import sign_json
from synapse.api.errors import SynapseError, Codes
import hashlib
import logging
......@@ -29,15 +30,24 @@ logger = logging.getLogger(__name__)
def check_event_content_hash(event, hash_algorithm=hashlib.sha256):
"""Check whether the hash for this PDU matches the contents"""
computed_hash = _compute_content_hash(event, hash_algorithm)
logging.debug("Expecting hash: %s", encode_base64(computed_hash.digest()))
if computed_hash.name not in event.hashes:
raise Exception("Algorithm %s not in hashes %s" % (
computed_hash.name, list(event.hashes)
))
raise SynapseError(
400,
"Algorithm %s not in hashes %s" % (
computed_hash.name, list(event.hashes),
),
Codes.UNAUTHORIZED,
)
message_hash_base64 = event.hashes[computed_hash.name]
try:
message_hash_bytes = decode_base64(message_hash_base64)
except:
raise Exception("Invalid base64: %s" % (message_hash_base64,))
raise SynapseError(
400,
"Invalid base64: %s" % (message_hash_base64,),
Codes.UNAUTHORIZED,
)
return message_hash_bytes == computed_hash.digest()
......
......@@ -17,13 +17,17 @@
from ._base import BaseHandler
from synapse.api.errors import AuthError, FederationError
from synapse.api.events.utils import prune_event
from synapse.api.errors import AuthError, FederationError, SynapseError
from synapse.api.events.room import RoomMemberEvent
from synapse.api.constants import Membership
from synapse.util.logutils import log_function
from synapse.federation.pdu_codec import PduCodec
from synapse.util.async import run_on_reactor
from synapse.crypto.event_signing import compute_event_signature
from synapse.crypto.event_signing import (
compute_event_signature, check_event_content_hash
)
from syutil.jsonutil import encode_canonical_json
from twisted.internet import defer
......@@ -59,6 +63,7 @@ class FederationHandler(BaseHandler):
self.state_handler = hs.get_state_handler()
# self.auth_handler = gs.get_auth_handler()
self.server_name = hs.hostname
self.keyring = hs.get_keyring()
self.lock_manager = hs.get_room_lock_manager()
......@@ -112,6 +117,34 @@ class FederationHandler(BaseHandler):
logger.debug("Processing event: %s", event.event_id)
redacted_event = prune_event(event)
redacted_event.origin = pdu.origin
redacted_event.origin_server_ts = pdu.origin_server_ts
redacted_pdu = self.pdu_codec.pdu_from_event(redacted_event)
redacted_pdu_json = redacted_pdu.get_dict()
try:
yield self.keyring.verify_json_for_server(
event.origin, redacted_pdu_json
)
except SynapseError as e:
logger.warn("Signature check failed for %s redacted to %s",
encode_canonical_json(pdu.get_dict()),
encode_canonical_json(redacted_pdu_json),
)
raise FederationError(
"ERROR",
e.code,
e.msg,
affected=event.event_id,
)
if not check_event_content_hash(pdu):
logger.warn(
"Event content has been tampered, redacting %s", event.event_id
)
event = redacted_event
if state:
state = [self.pdu_codec.event_from_pdu(p) for p in state]
......
......@@ -23,7 +23,7 @@ from synapse.handlers.federation import FederationHandler
from synapse.server import HomeServer
from synapse.federation.units import Pdu
from mock import NonCallableMock, ANY
from mock import NonCallableMock, ANY, Mock
from ..utils import MockKey
......@@ -62,6 +62,7 @@ class FederationTestCase(unittest.TestCase):
config=self.mock_config,
auth=self.auth,
state_handler=self.state_handler,
keyring=Mock(),
)
self.datastore = hs.get_datastore()
......@@ -80,6 +81,7 @@ class FederationTestCase(unittest.TestCase):
origin_server_ts=0,
event_id="$a:b",
origin="b",
hashes={"sha256":"PvbCLWrTBxnBsSO7/cJ76072ySTCgI/XGadESRAe02M"},
)
self.datastore.persist_event.return_value = defer.succeed(None)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment