forked from MirrorHub/synapse
Merge pull request #1136 from matrix-org/erikj/fix_signed_3pid
Allow invites via 3pid to bypass sender sig check
This commit is contained in:
commit
667fcd54e8
3 changed files with 35 additions and 12 deletions
|
@ -72,7 +72,7 @@ class Auth(object):
|
||||||
auth_events = {
|
auth_events = {
|
||||||
(e.type, e.state_key): e for e in auth_events.values()
|
(e.type, e.state_key): e for e in auth_events.values()
|
||||||
}
|
}
|
||||||
self.check(event, auth_events=auth_events, do_sig_check=False)
|
self.check(event, auth_events=auth_events, do_sig_check=do_sig_check)
|
||||||
|
|
||||||
def check(self, event, auth_events, do_sig_check=True):
|
def check(self, event, auth_events, do_sig_check=True):
|
||||||
""" Checks if this event is correctly authed.
|
""" Checks if this event is correctly authed.
|
||||||
|
@ -91,11 +91,28 @@ class Auth(object):
|
||||||
if not hasattr(event, "room_id"):
|
if not hasattr(event, "room_id"):
|
||||||
raise AuthError(500, "Event has no room_id: %s" % event)
|
raise AuthError(500, "Event has no room_id: %s" % event)
|
||||||
|
|
||||||
sender_domain = get_domain_from_id(event.sender)
|
if do_sig_check:
|
||||||
|
sender_domain = get_domain_from_id(event.sender)
|
||||||
|
event_id_domain = get_domain_from_id(event.event_id)
|
||||||
|
|
||||||
# Check the sender's domain has signed the event
|
is_invite_via_3pid = (
|
||||||
if do_sig_check and not event.signatures.get(sender_domain):
|
event.type == EventTypes.Member
|
||||||
raise AuthError(403, "Event not signed by sending server")
|
and event.membership == Membership.INVITE
|
||||||
|
and "third_party_invite" in event.content
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check the sender's domain has signed the event
|
||||||
|
if not event.signatures.get(sender_domain):
|
||||||
|
# We allow invites via 3pid to have a sender from a different
|
||||||
|
# HS, as the sender must match the sender of the original
|
||||||
|
# 3pid invite. This is checked further down with the
|
||||||
|
# other dedicated membership checks.
|
||||||
|
if not is_invite_via_3pid:
|
||||||
|
raise AuthError(403, "Event not signed by sender's server")
|
||||||
|
|
||||||
|
# Check the event_id's domain has signed the event
|
||||||
|
if not event.signatures.get(event_id_domain):
|
||||||
|
raise AuthError(403, "Event not signed by sending server")
|
||||||
|
|
||||||
if auth_events is None:
|
if auth_events is None:
|
||||||
# Oh, we don't know what the state of the room was, so we
|
# Oh, we don't know what the state of the room was, so we
|
||||||
|
@ -491,6 +508,9 @@ class Auth(object):
|
||||||
if not invite_event:
|
if not invite_event:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if invite_event.sender != event.sender:
|
||||||
|
return False
|
||||||
|
|
||||||
if event.user_id != invite_event.user_id:
|
if event.user_id != invite_event.user_id:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -1922,15 +1922,18 @@ class FederationHandler(BaseHandler):
|
||||||
original_invite = yield self.store.get_event(
|
original_invite = yield self.store.get_event(
|
||||||
original_invite_id, allow_none=True
|
original_invite_id, allow_none=True
|
||||||
)
|
)
|
||||||
if not original_invite:
|
if original_invite:
|
||||||
|
display_name = original_invite.content["display_name"]
|
||||||
|
event_dict["content"]["third_party_invite"]["display_name"] = display_name
|
||||||
|
else:
|
||||||
logger.info(
|
logger.info(
|
||||||
"Could not find invite event for third_party_invite - "
|
"Could not find invite event for third_party_invite: %r",
|
||||||
"discarding: %s" % (event_dict,)
|
event_dict
|
||||||
)
|
)
|
||||||
return
|
# We don't discard here as this is not the appropriate place to do
|
||||||
|
# auth checks. If we need the invite and don't have it then the
|
||||||
|
# auth check code will explode appropriately.
|
||||||
|
|
||||||
display_name = original_invite.content["display_name"]
|
|
||||||
event_dict["content"]["third_party_invite"]["display_name"] = display_name
|
|
||||||
builder = self.event_builder_factory.new(event_dict)
|
builder = self.event_builder_factory.new(event_dict)
|
||||||
EventValidator().validate_new(builder)
|
EventValidator().validate_new(builder)
|
||||||
message_handler = self.hs.get_handlers().message_handler
|
message_handler = self.hs.get_handlers().message_handler
|
||||||
|
|
|
@ -56,7 +56,7 @@ def get_domain_from_id(string):
|
||||||
try:
|
try:
|
||||||
return string.split(":", 1)[1]
|
return string.split(":", 1)[1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise SynapseError(400, "Invalid ID: %r", string)
|
raise SynapseError(400, "Invalid ID: %r" % (string,))
|
||||||
|
|
||||||
|
|
||||||
class DomainSpecificString(
|
class DomainSpecificString(
|
||||||
|
|
Loading…
Reference in a new issue