Fix auth checks to all use the given old_event_state

This commit is contained in:
Erik Johnston 2014-11-05 11:07:54 +00:00
parent 4a5e95511e
commit 96c001e668
4 changed files with 53 additions and 33 deletions

View file

@ -22,7 +22,7 @@ from synapse.api.errors import AuthError, StoreError, Codes, SynapseError
from synapse.api.events.room import ( from synapse.api.events.room import (
RoomMemberEvent, RoomPowerLevelsEvent, RoomRedactionEvent, RoomMemberEvent, RoomPowerLevelsEvent, RoomRedactionEvent,
RoomJoinRulesEvent, RoomOpsPowerLevelsEvent, InviteJoinEvent, RoomJoinRulesEvent, RoomOpsPowerLevelsEvent, InviteJoinEvent,
RoomCreateEvent, RoomCreateEvent, RoomSendEventLevelEvent, RoomAddStateLevelEvent,
) )
from synapse.util.logutils import log_function from synapse.util.logutils import log_function
@ -37,8 +37,7 @@ class Auth(object):
self.hs = hs self.hs = hs
self.store = hs.get_datastore() self.store = hs.get_datastore()
@defer.inlineCallbacks def check(self, event, raises=False):
def check(self, event, snapshot, raises=False):
""" Checks if this event is correctly authed. """ Checks if this event is correctly authed.
Returns: Returns:
@ -52,17 +51,17 @@ class Auth(object):
if event.old_state_events is None: if event.old_state_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
# are trusting that this is allowed (at least for now) # are trusting that this is allowed (at least for now)
defer.returnValue(True) return True
if hasattr(event, "outlier") and event.outlier is True: if hasattr(event, "outlier") and event.outlier is True:
# TODO (erikj): Auth for outliers is done differently. # TODO (erikj): Auth for outliers is done differently.
defer.returnValue(True) return True
is_state = hasattr(event, "state_key") is_state = hasattr(event, "state_key")
if event.type == RoomCreateEvent.TYPE: if event.type == RoomCreateEvent.TYPE:
# FIXME # FIXME
defer.returnValue(True) return True
if event.type == RoomMemberEvent.TYPE: if event.type == RoomMemberEvent.TYPE:
self._can_replace_state(event) self._can_replace_state(event)
@ -71,8 +70,7 @@ class Auth(object):
logger.debug("Allowing! %s", event) logger.debug("Allowing! %s", event)
else: else:
logger.debug("Denying! %s", event) logger.debug("Denying! %s", event)
defer.returnValue(allowed) return allowed
return
if not event.type == InviteJoinEvent.TYPE: if not event.type == InviteJoinEvent.TYPE:
self.check_event_sender_in_room(event) self.check_event_sender_in_room(event)
@ -80,10 +78,10 @@ class Auth(object):
if is_state: if is_state:
# TODO (erikj): This really only should be called for *new* # TODO (erikj): This really only should be called for *new*
# state # state
yield self._can_add_state(event) self._can_add_state(event)
self._can_replace_state(event) self._can_replace_state(event)
else: else:
yield self._can_send_event(event) self._can_send_event(event)
if event.type == RoomPowerLevelsEvent.TYPE: if event.type == RoomPowerLevelsEvent.TYPE:
self._check_power_levels(event) self._check_power_levels(event)
@ -91,9 +89,8 @@ class Auth(object):
if event.type == RoomRedactionEvent.TYPE: if event.type == RoomRedactionEvent.TYPE:
self._check_redaction(event) self._check_redaction(event)
logger.debug("Allowing! %s", event) logger.debug("Allowing! %s", event)
defer.returnValue(True) return True
else: else:
raise AuthError(500, "Unknown event: %s" % event) raise AuthError(500, "Unknown event: %s" % event)
except AuthError as e: except AuthError as e:
@ -103,7 +100,7 @@ class Auth(object):
if raises: if raises:
raise e raise e
defer.returnValue(False) return False
@defer.inlineCallbacks @defer.inlineCallbacks
def check_joined_room(self, room_id, user_id): def check_joined_room(self, room_id, user_id):
@ -326,10 +323,15 @@ class Auth(object):
def is_server_admin(self, user): def is_server_admin(self, user):
return self.store.is_server_admin(user) return self.store.is_server_admin(user)
@defer.inlineCallbacks
@log_function @log_function
def _can_send_event(self, event): def _can_send_event(self, event):
send_level = yield self.store.get_send_event_level(event.room_id) key = (RoomSendEventLevelEvent.TYPE, "", )
send_level_event = event.old_state_events.get(key)
send_level = None
if send_level_event:
send_level = send_level_event.content.get(event.user_id)
if not send_level:
send_level = send_level_event.content.get("level", 0)
if send_level: if send_level:
send_level = int(send_level) send_level = int(send_level)
@ -351,16 +353,21 @@ class Auth(object):
403, "You don't have permission to post to the room" 403, "You don't have permission to post to the room"
) )
defer.returnValue(True) return True
@defer.inlineCallbacks
def _can_add_state(self, event): def _can_add_state(self, event):
add_level = yield self.store.get_add_state_level(event.room_id) key = (RoomAddStateLevelEvent.TYPE, "", )
add_level_event = event.old_state_events.get(key)
add_level = None
if add_level_event:
add_level = add_level_event.content.get(event.user_id)
if not add_level:
add_level = add_level_event.content.get("level", 0)
if not add_level: if add_level:
defer.returnValue(True) add_level = int(add_level)
else:
add_level = int(add_level) add_level = 0
user_level = self._get_power_level_from_event_state( user_level = self._get_power_level_from_event_state(
event, event,
@ -374,7 +381,7 @@ class Auth(object):
403, "You don't have permission to add state to the room" 403, "You don't have permission to add state to the room"
) )
defer.returnValue(True) return True
def _can_replace_state(self, event): def _can_replace_state(self, event):
user_level = self._get_power_level_from_event_state( user_level = self._get_power_level_from_event_state(

View file

@ -20,6 +20,12 @@ from synapse.util.async import run_on_reactor
from synapse.crypto.event_signing import add_hashes_and_signatures from synapse.crypto.event_signing import add_hashes_and_signatures
import logging
logger = logging.getLogger(__name__)
class BaseHandler(object): class BaseHandler(object):
def __init__(self, hs): def __init__(self, hs):
@ -58,15 +64,18 @@ class BaseHandler(object):
yield self.state_handler.annotate_state_groups(event) yield self.state_handler.annotate_state_groups(event)
yield add_hashes_and_signatures( logger.debug("Signing event...")
add_hashes_and_signatures(
event, self.server_name, self.signing_key event, self.server_name, self.signing_key
) )
if not suppress_auth: logger.debug("Signed event.")
yield self.auth.check(event, snapshot, raises=True)
if hasattr(event, "state_key"): if not suppress_auth:
yield self.state_handler.handle_new_event(event, snapshot) logger.debug("Authing...")
self.auth.check(event, raises=True)
logger.debug("Authed")
yield self.store.persist_event(event) yield self.store.persist_event(event)

View file

@ -118,7 +118,7 @@ class FederationHandler(BaseHandler):
logger.debug("Event: %s", event) logger.debug("Event: %s", event)
try: try:
yield self.auth.check(event, None, raises=True) self.auth.check(event, raises=True)
except AuthError as e: except AuthError as e:
raise FederationError( raise FederationError(
"ERROR", "ERROR",
@ -319,7 +319,7 @@ class FederationHandler(BaseHandler):
snapshot.fill_out_prev_events(event) snapshot.fill_out_prev_events(event)
yield self.state_handler.annotate_state_groups(event) yield self.state_handler.annotate_state_groups(event)
yield self.auth.check(event, None, raises=True) self.auth.check(event, raises=True)
pdu = self.pdu_codec.pdu_from_event(event) pdu = self.pdu_codec.pdu_from_event(event)
@ -333,7 +333,7 @@ class FederationHandler(BaseHandler):
event.outlier = False event.outlier = False
is_new_state = yield self.state_handler.annotate_state_groups(event) is_new_state = yield self.state_handler.annotate_state_groups(event)
yield self.auth.check(event, None, raises=True) self.auth.check(event, raises=True)
# FIXME (erikj): All this is duplicated above :( # FIXME (erikj): All this is duplicated above :(

View file

@ -188,11 +188,15 @@ class StateHandler(object):
consumeErrors=True consumeErrors=True
) )
max_power = max([int(p) for p in new_powers]) new_powers = [
int(p) if p else 0 for p in new_powers
]
max_power = max(new_powers)
curr_events = [ curr_events = [
z[0] for z in zip(curr_events, new_powers) z[0] for z in zip(curr_events, new_powers)
if int(z[1]) == max_power if z[1] == max_power
] ]
if not curr_events: if not curr_events: