Fix bug where people could join private rooms
parent
5ffe5ab43f
commit
b3b1961496
|
@ -49,12 +49,12 @@ class Auth(object):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if hasattr(event, "room_id"):
|
if hasattr(event, "room_id"):
|
||||||
if not event.old_state_events:
|
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)
|
defer.returnValue(True)
|
||||||
|
|
||||||
if hasattr(event, "outlier") and event.outlier:
|
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)
|
defer.returnValue(True)
|
||||||
|
|
||||||
|
@ -65,8 +65,12 @@ class Auth(object):
|
||||||
defer.returnValue(True)
|
defer.returnValue(True)
|
||||||
|
|
||||||
if event.type == RoomMemberEvent.TYPE:
|
if event.type == RoomMemberEvent.TYPE:
|
||||||
yield self._can_replace_state(event)
|
self._can_replace_state(event)
|
||||||
allowed = yield self.is_membership_change_allowed(event)
|
allowed = self.is_membership_change_allowed(event)
|
||||||
|
if allowed:
|
||||||
|
logger.debug("Allowing! %s", event)
|
||||||
|
else:
|
||||||
|
logger.debug("Denying! %s", event)
|
||||||
defer.returnValue(allowed)
|
defer.returnValue(allowed)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -77,24 +81,28 @@ class Auth(object):
|
||||||
# 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)
|
yield self._can_add_state(event)
|
||||||
yield self._can_replace_state(event)
|
self._can_replace_state(event)
|
||||||
else:
|
else:
|
||||||
yield self._can_send_event(event)
|
yield self._can_send_event(event)
|
||||||
|
|
||||||
if event.type == RoomPowerLevelsEvent.TYPE:
|
if event.type == RoomPowerLevelsEvent.TYPE:
|
||||||
yield self._check_power_levels(event)
|
self._check_power_levels(event)
|
||||||
|
|
||||||
if event.type == RoomRedactionEvent.TYPE:
|
if event.type == RoomRedactionEvent.TYPE:
|
||||||
yield self._check_redaction(event)
|
self._check_redaction(event)
|
||||||
|
|
||||||
|
|
||||||
|
logger.debug("Allowing! %s", event)
|
||||||
defer.returnValue(True)
|
defer.returnValue(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:
|
||||||
logger.info("Event auth check failed on event %s with msg: %s",
|
logger.info("Event auth check failed on event %s with msg: %s",
|
||||||
event, e.msg)
|
event, e.msg)
|
||||||
|
logger.info("Denying! %s", event)
|
||||||
if raises:
|
if raises:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
defer.returnValue(False)
|
defer.returnValue(False)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@ -126,7 +134,7 @@ class Auth(object):
|
||||||
user_id, room_id, repr(member)
|
user_id, room_id, repr(member)
|
||||||
))
|
))
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@log_function
|
||||||
def is_membership_change_allowed(self, event):
|
def is_membership_change_allowed(self, event):
|
||||||
target_user_id = event.state_key
|
target_user_id = event.state_key
|
||||||
|
|
||||||
|
@ -159,11 +167,23 @@ class Auth(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
ban_level, kick_level, redact_level = (
|
ban_level, kick_level, redact_level = (
|
||||||
yield self._get_ops_level_from_event_state(
|
self._get_ops_level_from_event_state(
|
||||||
event
|
event
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger.debug(
|
||||||
|
"is_membership_change_allowed: %s",
|
||||||
|
{
|
||||||
|
"caller_in_room": caller_in_room,
|
||||||
|
"target_in_room": target_in_room,
|
||||||
|
"membership": membership,
|
||||||
|
"join_rule": join_rule,
|
||||||
|
"target_user_id": target_user_id,
|
||||||
|
"event.user_id": event.user_id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if Membership.INVITE == membership:
|
if Membership.INVITE == membership:
|
||||||
# TODO (erikj): We should probably handle this more intelligently
|
# TODO (erikj): We should probably handle this more intelligently
|
||||||
# PRIVATE join rules.
|
# PRIVATE join rules.
|
||||||
|
@ -183,10 +203,7 @@ class Auth(object):
|
||||||
elif join_rule == JoinRules.PUBLIC:
|
elif join_rule == JoinRules.PUBLIC:
|
||||||
pass
|
pass
|
||||||
elif join_rule == JoinRules.INVITE:
|
elif join_rule == JoinRules.INVITE:
|
||||||
if (
|
if not caller_in_room:
|
||||||
not caller or caller.membership not in
|
|
||||||
[Membership.INVITE, Membership.JOIN]
|
|
||||||
):
|
|
||||||
raise AuthError(403, "You are not invited to this room.")
|
raise AuthError(403, "You are not invited to this room.")
|
||||||
else:
|
else:
|
||||||
# TODO (erikj): may_join list
|
# TODO (erikj): may_join list
|
||||||
|
@ -218,7 +235,7 @@ class Auth(object):
|
||||||
else:
|
else:
|
||||||
raise AuthError(500, "Unknown membership %s" % membership)
|
raise AuthError(500, "Unknown membership %s" % membership)
|
||||||
|
|
||||||
defer.returnValue(True)
|
return True
|
||||||
|
|
||||||
def _get_power_level_from_event_state(self, event, user_id):
|
def _get_power_level_from_event_state(self, event, user_id):
|
||||||
key = (RoomPowerLevelsEvent.TYPE, "", )
|
key = (RoomPowerLevelsEvent.TYPE, "", )
|
||||||
|
@ -359,17 +376,7 @@ class Auth(object):
|
||||||
|
|
||||||
defer.returnValue(True)
|
defer.returnValue(True)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def _can_replace_state(self, event):
|
def _can_replace_state(self, event):
|
||||||
current_state = yield self.store.get_current_state(
|
|
||||||
event.room_id,
|
|
||||||
event.type,
|
|
||||||
event.state_key,
|
|
||||||
)
|
|
||||||
|
|
||||||
if current_state:
|
|
||||||
current_state = current_state[0]
|
|
||||||
|
|
||||||
user_level = self._get_power_level_from_event_state(
|
user_level = self._get_power_level_from_event_state(
|
||||||
event,
|
event,
|
||||||
event.user_id,
|
event.user_id,
|
||||||
|
@ -383,6 +390,10 @@ class Auth(object):
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Checking power level for %s, %s", event.user_id, user_level
|
"Checking power level for %s, %s", event.user_id, user_level
|
||||||
)
|
)
|
||||||
|
|
||||||
|
key = (event.type, event.state_key, )
|
||||||
|
current_state = event.old_state_events.get(key)
|
||||||
|
|
||||||
if current_state and hasattr(current_state, "required_power_level"):
|
if current_state and hasattr(current_state, "required_power_level"):
|
||||||
req = current_state.required_power_level
|
req = current_state.required_power_level
|
||||||
|
|
||||||
|
@ -393,19 +404,20 @@ class Auth(object):
|
||||||
"You don't have permission to change that state"
|
"You don't have permission to change that state"
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def _check_redaction(self, event):
|
def _check_redaction(self, event):
|
||||||
user_level = yield self.store.get_power_level(
|
|
||||||
event.room_id,
|
|
||||||
event.user_id,
|
|
||||||
)
|
|
||||||
|
|
||||||
user_level = self._get_power_level_from_event_state(
|
user_level = self._get_power_level_from_event_state(
|
||||||
event,
|
event,
|
||||||
event.user_id,
|
event.user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
_, _, redact_level = yield self.store.get_ops_levels(event.room_id)
|
if user_level:
|
||||||
|
user_level = int(user_level)
|
||||||
|
else:
|
||||||
|
user_level = 0
|
||||||
|
|
||||||
|
_, _, redact_level = self.store._get_ops_level_from_event_state(
|
||||||
|
event.room_id
|
||||||
|
)
|
||||||
|
|
||||||
if not redact_level:
|
if not redact_level:
|
||||||
redact_level = 50
|
redact_level = 50
|
||||||
|
@ -416,7 +428,6 @@ class Auth(object):
|
||||||
"You don't have permission to redact events"
|
"You don't have permission to redact events"
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
|
||||||
def _check_power_levels(self, event):
|
def _check_power_levels(self, event):
|
||||||
for k, v in event.content.items():
|
for k, v in event.content.items():
|
||||||
if k == "default":
|
if k == "default":
|
||||||
|
@ -436,19 +447,16 @@ class Auth(object):
|
||||||
except:
|
except:
|
||||||
raise SynapseError(400, "Not a valid power level: %s" % (v,))
|
raise SynapseError(400, "Not a valid power level: %s" % (v,))
|
||||||
|
|
||||||
current_state = yield self.store.get_current_state(
|
key = (event.type, event.state_key, )
|
||||||
event.room_id,
|
current_state = event.old_state_events.get(key)
|
||||||
event.type,
|
|
||||||
event.state_key,
|
|
||||||
)
|
|
||||||
|
|
||||||
if not current_state:
|
if not current_state:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
current_state = current_state[0]
|
current_state = current_state[0]
|
||||||
|
|
||||||
user_level = yield self.store.get_power_level(
|
user_level = self._get_power_level_from_event_state(
|
||||||
event.room_id,
|
event,
|
||||||
event.user_id,
|
event.user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -269,12 +269,12 @@ class FederationHandler(BaseHandler):
|
||||||
del self.room_queues[room_id]
|
del self.room_queues[room_id]
|
||||||
|
|
||||||
for p in room_queue:
|
for p in room_queue:
|
||||||
p.outlier = True
|
|
||||||
yield self.on_receive_pdu(p, backfilled=False)
|
yield self.on_receive_pdu(p, backfilled=False)
|
||||||
|
|
||||||
defer.returnValue(True)
|
defer.returnValue(True)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@log_function
|
||||||
def on_make_join_request(self, context, user_id):
|
def on_make_join_request(self, context, user_id):
|
||||||
event = self.event_factory.create_event(
|
event = self.event_factory.create_event(
|
||||||
etype=RoomMemberEvent.TYPE,
|
etype=RoomMemberEvent.TYPE,
|
||||||
|
@ -289,15 +289,21 @@ 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.auth.check(event, None, raises=True)
|
||||||
|
|
||||||
pdu = self.pdu_codec.pdu_from_event(event)
|
pdu = self.pdu_codec.pdu_from_event(event)
|
||||||
|
|
||||||
defer.returnValue(pdu)
|
defer.returnValue(pdu)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
|
@log_function
|
||||||
def on_send_join_request(self, origin, pdu):
|
def on_send_join_request(self, origin, pdu):
|
||||||
event = self.pdu_codec.event_from_pdu(pdu)
|
event = self.pdu_codec.event_from_pdu(pdu)
|
||||||
|
|
||||||
is_new_state= yield self.state_handler.annotate_state_groups(event)
|
event.outlier = False
|
||||||
|
|
||||||
|
is_new_state = yield self.state_handler.annotate_state_groups(event)
|
||||||
yield self.auth.check(event, None, raises=True)
|
yield self.auth.check(event, None, raises=True)
|
||||||
|
|
||||||
# FIXME (erikj): All this is duplicated above :(
|
# FIXME (erikj): All this is duplicated above :(
|
||||||
|
|
|
@ -22,6 +22,7 @@ from synapse.federation.pdu_codec import encode_event_id
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
|
import copy
|
||||||
import logging
|
import logging
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
|
@ -143,13 +144,13 @@ class StateHandler(object):
|
||||||
if hasattr(event, "outlier") and event.outlier:
|
if hasattr(event, "outlier") and event.outlier:
|
||||||
event.state_group = None
|
event.state_group = None
|
||||||
event.old_state_events = None
|
event.old_state_events = None
|
||||||
event.state_events = None
|
event.state_events = {}
|
||||||
defer.returnValue(False)
|
defer.returnValue(False)
|
||||||
return
|
return
|
||||||
|
|
||||||
new_state = yield self.resolve_state_groups(event.prev_events)
|
new_state = yield self.resolve_state_groups(event.prev_events)
|
||||||
|
|
||||||
event.old_state_events = new_state
|
event.old_state_events = copy.deepcopy(new_state)
|
||||||
|
|
||||||
if hasattr(event, "state_key"):
|
if hasattr(event, "state_key"):
|
||||||
new_state[(event.type, event.state_key)] = event
|
new_state[(event.type, event.state_key)] = event
|
||||||
|
@ -164,9 +165,12 @@ class StateHandler(object):
|
||||||
# FIXME: HACK!
|
# FIXME: HACK!
|
||||||
pdus = yield self.store.get_latest_pdus_in_context(room_id)
|
pdus = yield self.store.get_latest_pdus_in_context(room_id)
|
||||||
|
|
||||||
event_ids = [encode_event_id(p.pdu_id, p.origin) for p in pdus]
|
event_ids = [
|
||||||
|
encode_event_id(pdu_id, origin)
|
||||||
|
for pdu_id, origin, _ in pdus
|
||||||
|
]
|
||||||
|
|
||||||
res = self.resolve_state_groups(event_ids)
|
res = yield self.resolve_state_groups(event_ids)
|
||||||
|
|
||||||
if event_type:
|
if event_type:
|
||||||
defer.returnValue(res.get((event_type, state_key)))
|
defer.returnValue(res.get((event_type, state_key)))
|
||||||
|
|
Loading…
Reference in New Issue