feat: join cursed rooms

this removes several restrictions and tries to continue verifying a pdu
event if some auth events fail (it drops/ignores bad pdus)
next
Timo Kösters 2021-04-14 09:39:06 +02:00
parent 8b40e0a85f
commit 5951294638
No known key found for this signature in database
GPG Key ID: 24DA7517711A2BA4
5 changed files with 48 additions and 33 deletions

2
Cargo.lock generated
View File

@ -2120,7 +2120,7 @@ checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483"
[[package]] [[package]]
name = "state-res" name = "state-res"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/timokoesters/state-res?rev=84e70c062708213d01281438598e16f13dffeda4#84e70c062708213d01281438598e16f13dffeda4" source = "git+https://github.com/timokoesters/state-res?rev=9bb46ae681bfc361cff740e78dc42bb711db9779#9bb46ae681bfc361cff740e78dc42bb711db9779"
dependencies = [ dependencies = [
"itertools 0.10.0", "itertools 0.10.0",
"log", "log",

View File

@ -23,7 +23,7 @@ ruma = { git = "https://github.com/ruma/ruma", rev = "c1693569f15920e408aa6a26b7
#ruma = { path = "../ruma/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } #ruma = { path = "../ruma/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] }
# Used when doing state resolution # Used when doing state resolution
state-res = { git = "https://github.com/timokoesters/state-res", rev = "84e70c062708213d01281438598e16f13dffeda4", features = ["unstable-pre-spec"] } state-res = { git = "https://github.com/timokoesters/state-res", rev = "9bb46ae681bfc361cff740e78dc42bb711db9779", features = ["unstable-pre-spec"] }
#state-res = { path = "../state-res", features = ["unstable-pre-spec"] } #state-res = { path = "../state-res", features = ["unstable-pre-spec"] }
# Used for long polling and federation sender, should be the same as rocket::tokio # Used for long polling and federation sender, should be the same as rocket::tokio

View File

@ -527,7 +527,7 @@ async fn join_room_by_id_helper(
.map_err(|_| Error::BadServerResponse("Invalid PDU in send_join response."))?; .map_err(|_| Error::BadServerResponse("Invalid PDU in send_join response."))?;
let mut state = BTreeMap::new(); let mut state = BTreeMap::new();
let mut pub_key_map = RwLock::new(BTreeMap::new()); let pub_key_map = RwLock::new(BTreeMap::new());
for result in futures::future::join_all( for result in futures::future::join_all(
send_join_response send_join_response
@ -538,7 +538,11 @@ async fn join_room_by_id_helper(
) )
.await .await
{ {
let (event_id, value) = result?; let (event_id, value) = match result {
Ok(t) => t,
Err(_) => continue,
};
let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| { let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| {
warn!("{:?}: {}", value, e); warn!("{:?}: {}", value, e);
Error::BadServerResponse("Invalid PDU in send_join response.") Error::BadServerResponse("Invalid PDU in send_join response.")
@ -593,9 +597,20 @@ async fn join_room_by_id_helper(
db.rooms.force_state(room_id, state, &db.globals)?; db.rooms.force_state(room_id, state, &db.globals)?;
for pdu in send_join_response.room_state.auth_chain.iter() { for result in futures::future::join_all(
let (event_id, value) = send_join_response
validate_and_add_event_id(pdu, &room_version, &mut pub_key_map, &db).await?; .room_state
.auth_chain
.iter()
.map(|pdu| validate_and_add_event_id(pdu, &room_version, &pub_key_map, &db)),
)
.await
{
let (event_id, value) = match result {
Ok(t) => t,
Err(_) => continue,
};
let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| { let pdu = PduEvent::from_id_val(&event_id, value.clone()).map_err(|e| {
warn!("{:?}: {}", value, e); warn!("{:?}: {}", value, e);
Error::BadServerResponse("Invalid PDU in send_join response.") Error::BadServerResponse("Invalid PDU in send_join response.")

View File

@ -166,22 +166,17 @@ impl PduEvent {
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]
pub fn to_sync_state_event(&self) -> Raw<AnySyncStateEvent> { pub fn to_sync_state_event(&self) -> Raw<AnySyncStateEvent> {
let json = format!( let json = json!({
r#"{{"content":{},"type":"{}","event_id":"{}","sender":"{}","origin_server_ts":{},"unsigned":{},"state_key":"{}"}}"#, "content": self.content,
self.content, "type": self.kind,
self.kind, "event_id": self.event_id,
self.event_id, "sender": self.sender,
self.sender, "origin_server_ts": self.origin_server_ts,
self.origin_server_ts, "unsigned": self.unsigned,
serde_json::to_string(&self.unsigned).expect("Map::to_string always works"), "state_key": self.state_key,
self.state_key });
.as_ref()
.expect("state events have state keys")
);
Raw::from_json( serde_json::from_value(json).expect("Raw::from_value always works")
serde_json::value::RawValue::from_string(json).expect("our string is valid json"),
)
} }
#[tracing::instrument(skip(self))] #[tracing::instrument(skip(self))]

View File

@ -685,7 +685,7 @@ fn handle_incoming_pdu<'a>(
) { ) {
Err(e) => { Err(e) => {
// Drop // Drop
error!("{:?}: {}", value, e); warn!("{:?}: {}", value, e);
return Err("Signature verification failed".to_string()); return Err("Signature verification failed".to_string());
} }
Ok(ruma::signatures::Verified::Signatures) => { Ok(ruma::signatures::Verified::Signatures) => {
@ -1147,7 +1147,7 @@ pub(crate) async fn fetch_and_handle_events(
debug!("Got {} over federation: {:?}", id, res); debug!("Got {} over federation: {:?}", id, res);
let (event_id, value) = let (event_id, value) =
crate::pdu::gen_event_id_canonical_json(&res.pdu)?; crate::pdu::gen_event_id_canonical_json(&res.pdu)?;
let pdu = handle_incoming_pdu( let pdu = match handle_incoming_pdu(
origin, origin,
&event_id, &event_id,
value, value,
@ -1157,14 +1157,20 @@ pub(crate) async fn fetch_and_handle_events(
auth_cache, auth_cache,
) )
.await .await
.map_err(|e| { {
error!("Error: {:?}", e); Ok(pdu) => pdu,
Error::Conflict("Authentication of event failed") Err(e) => {
})?; warn!("Authentication of event {} failed: {:?}", id, e);
continue;
}
};
pdu pdu
} }
Err(_) => return Err(Error::BadServerResponse("Failed to fetch event")), Err(_) => {
warn!("Failed to fetch event: {}", id);
continue;
}
} }
} }
}, },
@ -1665,10 +1671,9 @@ pub async fn fetch_required_signing_keys(
.await .await
{ {
Ok(keys) => keys, Ok(keys) => keys,
Err(e) => { Err(_) => {
return Err(Error::BadServerResponse( warn!("Signature verification failed: Could not fetch signing key.",);
"Signature verification failed: Could not fetch signing key.", continue;
));
} }
}; };