State-reset and security mitigations.
Upgrade Ruma to present. The following are intentionally benign for activation in a later commit: - Hydra backports not default. - Room version 12 not default. - Room version 12 not listed as stable. Do not enable them manually or you can brick your database. Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -7,8 +7,9 @@ use ruma::{
|
||||
events::room::member::{MembershipState, RoomMemberEventContent},
|
||||
};
|
||||
use tuwunel_core::{
|
||||
Err, Result, debug_error, err, info,
|
||||
Err, Result, err,
|
||||
matrix::{event::gen_event_id_canonical_json, pdu::PduBuilder},
|
||||
warn,
|
||||
};
|
||||
use tuwunel_service::Services;
|
||||
|
||||
@@ -27,8 +28,8 @@ pub(crate) async fn invite_user_route(
|
||||
let sender_user = body.sender_user();
|
||||
|
||||
if !services.users.is_admin(sender_user).await && services.config.block_non_admin_invites {
|
||||
debug_error!(
|
||||
"User {sender_user} is not an admin and attempted to send an invite to room {}",
|
||||
warn!(
|
||||
"{sender_user} is not an admin and attempted to send an invite to {}",
|
||||
&body.room_id
|
||||
);
|
||||
return Err!(Request(Forbidden("Invites are not allowed on this server.")));
|
||||
@@ -104,10 +105,7 @@ pub(crate) async fn invite_helper(
|
||||
is_direct: bool,
|
||||
) -> Result {
|
||||
if !services.users.is_admin(sender_user).await && services.config.block_non_admin_invites {
|
||||
info!(
|
||||
"User {sender_user} is not an admin and attempted to send an invite to room \
|
||||
{room_id}"
|
||||
);
|
||||
warn!("{sender_user} is not an admin and attempted to send an invite to {room_id}");
|
||||
return Err!(Request(Forbidden("Invites are not allowed on this server.")));
|
||||
}
|
||||
|
||||
@@ -156,7 +154,10 @@ pub(crate) async fn invite_helper(
|
||||
.sending
|
||||
.convert_to_outgoing_federation_event(pdu_json.clone())
|
||||
.await,
|
||||
invite_room_state,
|
||||
invite_room_state: invite_room_state
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect(),
|
||||
via: services
|
||||
.rooms
|
||||
.state_cache
|
||||
|
||||
@@ -25,10 +25,9 @@ use ruma::{
|
||||
use tuwunel_core::{
|
||||
Err, Result, debug, debug_info, debug_warn, err, error, info,
|
||||
matrix::{
|
||||
StateKey,
|
||||
event::{gen_event_id, gen_event_id_canonical_json},
|
||||
pdu::{PduBuilder, PduEvent},
|
||||
state_res,
|
||||
room_version, state_res,
|
||||
},
|
||||
result::FlatOk,
|
||||
trace,
|
||||
@@ -551,7 +550,13 @@ async fn join_room_by_id_helper_remote(
|
||||
})
|
||||
.ready_filter_map(Result::ok)
|
||||
.fold(HashMap::new(), async |mut state, (event_id, value)| {
|
||||
let pdu = match PduEvent::from_id_val(&event_id, value.clone()) {
|
||||
let pdu = if value["type"] == "m.room.create" {
|
||||
PduEvent::from_rid_val(room_id, &event_id, value.clone())
|
||||
} else {
|
||||
PduEvent::from_id_val(&event_id, value.clone())
|
||||
};
|
||||
|
||||
let pdu = match pdu {
|
||||
| Ok(pdu) => pdu,
|
||||
| Err(e) => {
|
||||
debug_warn!("Invalid PDU in send_join response: {e:?}: {value:#?}");
|
||||
@@ -604,36 +609,26 @@ async fn join_room_by_id_helper_remote(
|
||||
drop(cork);
|
||||
|
||||
debug!("Running send_join auth check");
|
||||
let fetch_state = &state;
|
||||
let state_fetch = |k: StateEventType, s: StateKey| async move {
|
||||
let shortstatekey = services
|
||||
.rooms
|
||||
.short
|
||||
.get_shortstatekey(&k, &s)
|
||||
.await
|
||||
.ok()?;
|
||||
|
||||
let event_id = fetch_state.get(&shortstatekey)?;
|
||||
services
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu(event_id)
|
||||
.await
|
||||
.ok()
|
||||
};
|
||||
|
||||
let auth_check = state_res::event_auth::auth_check(
|
||||
&state_res::RoomVersion::new(&room_version_id)?,
|
||||
state_res::auth_check(
|
||||
&room_version::rules(&room_version_id)?,
|
||||
&parsed_join_pdu,
|
||||
None, // TODO: third party invite
|
||||
|k, s| state_fetch(k.clone(), s.into()),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| err!(Request(Forbidden(warn!("Auth check failed: {e:?}")))))?;
|
||||
&async |event_id| services.rooms.timeline.get_pdu(&event_id).await,
|
||||
&async |event_type, state_key| {
|
||||
let shortstatekey = services
|
||||
.rooms
|
||||
.short
|
||||
.get_shortstatekey(&event_type, state_key.as_str())
|
||||
.await?;
|
||||
|
||||
if !auth_check {
|
||||
return Err!(Request(Forbidden("Auth check failed")));
|
||||
}
|
||||
let event_id = state.get(&shortstatekey).ok_or_else(|| {
|
||||
err!(Request(NotFound("Missing fetch_state {shortstatekey:?}")))
|
||||
})?;
|
||||
|
||||
services.rooms.timeline.get_pdu(event_id).await
|
||||
},
|
||||
)
|
||||
.boxed()
|
||||
.await?;
|
||||
|
||||
info!("Compressing state from send_join");
|
||||
let compressed: CompressedState = services
|
||||
|
||||
@@ -8,7 +8,10 @@ use ruma::{
|
||||
RoomVersionId, UserId,
|
||||
api::{
|
||||
client::knock::knock_room,
|
||||
federation::{self},
|
||||
federation::{
|
||||
membership::RawStrippedState,
|
||||
{self},
|
||||
},
|
||||
},
|
||||
canonical_json::to_canonical_value,
|
||||
events::{
|
||||
@@ -17,7 +20,7 @@ use ruma::{
|
||||
},
|
||||
};
|
||||
use tuwunel_core::{
|
||||
Err, Result, debug, debug_info, debug_warn, err, info,
|
||||
Err, Result, debug, debug_info, debug_warn, err, extract_variant, info,
|
||||
matrix::{
|
||||
event::{Event, gen_event_id},
|
||||
pdu::{PduBuilder, PduEvent},
|
||||
@@ -346,7 +349,7 @@ async fn knock_room_helper_local(
|
||||
let knock_event = knock_event_stub;
|
||||
|
||||
info!("Asking {remote_server} for send_knock in room {room_id}");
|
||||
let send_knock_request = federation::knock::send_knock::v1::Request {
|
||||
let send_knock_request = federation::membership::create_knock_event::v1::Request {
|
||||
room_id: room_id.to_owned(),
|
||||
event_id: event_id.clone(),
|
||||
pdu: services
|
||||
@@ -384,7 +387,13 @@ async fn knock_room_helper_local(
|
||||
.get_content::<RoomMemberEventContent>()
|
||||
.expect("we just created this"),
|
||||
sender_user,
|
||||
Some(send_knock_response.knock_room_state),
|
||||
Some(
|
||||
send_knock_response
|
||||
.knock_room_state
|
||||
.into_iter()
|
||||
.filter_map(|s| extract_variant!(s, RawStrippedState::Stripped))
|
||||
.collect(),
|
||||
),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
@@ -477,7 +486,7 @@ async fn knock_room_helper_remote(
|
||||
let knock_event = knock_event_stub;
|
||||
|
||||
info!("Asking {remote_server} for send_knock in room {room_id}");
|
||||
let send_knock_request = federation::knock::send_knock::v1::Request {
|
||||
let send_knock_request = federation::membership::create_knock_event::v1::Request {
|
||||
room_id: room_id.to_owned(),
|
||||
event_id: event_id.clone(),
|
||||
pdu: services
|
||||
@@ -507,7 +516,14 @@ async fn knock_room_helper_remote(
|
||||
let state = send_knock_response
|
||||
.knock_room_state
|
||||
.iter()
|
||||
.map(|event| serde_json::from_str::<CanonicalJsonObject>(event.clone().into_json().get()))
|
||||
.map(|event| {
|
||||
serde_json::from_str::<CanonicalJsonObject>(
|
||||
extract_variant!(event.clone(), RawStrippedState::Stripped)
|
||||
.expect("Raw<AnyStrippedStateEvent>")
|
||||
.json()
|
||||
.get(),
|
||||
)
|
||||
})
|
||||
.filter_map(Result::ok);
|
||||
|
||||
let mut state_map: HashMap<u64, OwnedEventId> = HashMap::new();
|
||||
@@ -594,7 +610,13 @@ async fn knock_room_helper_remote(
|
||||
.get_content::<RoomMemberEventContent>()
|
||||
.expect("we just created this"),
|
||||
sender_user,
|
||||
Some(send_knock_response.knock_room_state),
|
||||
Some(
|
||||
send_knock_response
|
||||
.knock_room_state
|
||||
.into_iter()
|
||||
.filter_map(|s| extract_variant!(s, RawStrippedState::Stripped))
|
||||
.collect(),
|
||||
),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
@@ -628,7 +650,7 @@ async fn make_knock_request(
|
||||
sender_user: &UserId,
|
||||
room_id: &RoomId,
|
||||
servers: &[OwnedServerName],
|
||||
) -> Result<(federation::knock::create_knock_event_template::v1::Response, OwnedServerName)> {
|
||||
) -> Result<(federation::membership::prepare_knock_event::v1::Response, OwnedServerName)> {
|
||||
let mut make_knock_response_and_server =
|
||||
Err!(BadServerResponse("No server available to assist in knocking."));
|
||||
|
||||
@@ -645,7 +667,7 @@ async fn make_knock_request(
|
||||
.sending
|
||||
.send_federation_request(
|
||||
remote_server,
|
||||
federation::knock::create_knock_event_template::v1::Request {
|
||||
federation::membership::prepare_knock_event::v1::Request {
|
||||
room_id: room_id.to_owned(),
|
||||
user_id: sender_user.to_owned(),
|
||||
ver: services
|
||||
|
||||
@@ -70,15 +70,16 @@ pub(crate) async fn banned_room_check(
|
||||
|
||||
if let Some(room_id) = room_id {
|
||||
if services.rooms.metadata.is_banned(room_id).await
|
||||
|| services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(
|
||||
room_id
|
||||
.server_name()
|
||||
.expect("legacy room mxid")
|
||||
.host(),
|
||||
) {
|
||||
|| (room_id.server_name().is_some()
|
||||
&& services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(
|
||||
room_id
|
||||
.server_name()
|
||||
.expect("legacy room mxid")
|
||||
.host(),
|
||||
)) {
|
||||
warn!(
|
||||
"User {user_id} who is not an admin attempted to send an invite for or \
|
||||
attempted to join a banned room or banned room server name: {room_id}"
|
||||
|
||||
Reference in New Issue
Block a user