From 595129463856cc4b03cccebba678ced4af3865c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Wed, 14 Apr 2021 09:39:06 +0200 Subject: [PATCH] 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) --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/client_server/membership.rs | 25 ++++++++++++++++++++----- src/pdu.rs | 25 ++++++++++--------------- src/server_server.rs | 27 ++++++++++++++++----------- 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d153c28..f6af8b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2120,7 +2120,7 @@ checksum = "3015a7d0a5fd5105c91c3710d42f9ccf0abfb287d62206484dcc67f9569a6483" [[package]] name = "state-res" 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 = [ "itertools 0.10.0", "log", diff --git a/Cargo.toml b/Cargo.toml index 9aa9cee..fba7e5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } # 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"] } # Used for long polling and federation sender, should be the same as rocket::tokio diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs index c348409..4be0d5f 100644 --- a/src/client_server/membership.rs +++ b/src/client_server/membership.rs @@ -527,7 +527,7 @@ async fn join_room_by_id_helper( .map_err(|_| Error::BadServerResponse("Invalid PDU in send_join response."))?; 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( send_join_response @@ -538,7 +538,11 @@ async fn join_room_by_id_helper( ) .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| { warn!("{:?}: {}", value, e); 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)?; - for pdu in send_join_response.room_state.auth_chain.iter() { - let (event_id, value) = - validate_and_add_event_id(pdu, &room_version, &mut pub_key_map, &db).await?; + for result in futures::future::join_all( + send_join_response + .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| { warn!("{:?}: {}", value, e); Error::BadServerResponse("Invalid PDU in send_join response.") diff --git a/src/pdu.rs b/src/pdu.rs index 009fde6..a7d9432 100644 --- a/src/pdu.rs +++ b/src/pdu.rs @@ -166,22 +166,17 @@ impl PduEvent { #[tracing::instrument(skip(self))] pub fn to_sync_state_event(&self) -> Raw { - let json = format!( - r#"{{"content":{},"type":"{}","event_id":"{}","sender":"{}","origin_server_ts":{},"unsigned":{},"state_key":"{}"}}"#, - self.content, - self.kind, - self.event_id, - self.sender, - self.origin_server_ts, - serde_json::to_string(&self.unsigned).expect("Map::to_string always works"), - self.state_key - .as_ref() - .expect("state events have state keys") - ); + let json = json!({ + "content": self.content, + "type": self.kind, + "event_id": self.event_id, + "sender": self.sender, + "origin_server_ts": self.origin_server_ts, + "unsigned": self.unsigned, + "state_key": self.state_key, + }); - Raw::from_json( - serde_json::value::RawValue::from_string(json).expect("our string is valid json"), - ) + serde_json::from_value(json).expect("Raw::from_value always works") } #[tracing::instrument(skip(self))] diff --git a/src/server_server.rs b/src/server_server.rs index 791ec1c..538540a 100644 --- a/src/server_server.rs +++ b/src/server_server.rs @@ -685,7 +685,7 @@ fn handle_incoming_pdu<'a>( ) { Err(e) => { // Drop - error!("{:?}: {}", value, e); + warn!("{:?}: {}", value, e); return Err("Signature verification failed".to_string()); } Ok(ruma::signatures::Verified::Signatures) => { @@ -1147,7 +1147,7 @@ pub(crate) async fn fetch_and_handle_events( debug!("Got {} over federation: {:?}", id, res); let (event_id, value) = crate::pdu::gen_event_id_canonical_json(&res.pdu)?; - let pdu = handle_incoming_pdu( + let pdu = match handle_incoming_pdu( origin, &event_id, value, @@ -1157,14 +1157,20 @@ pub(crate) async fn fetch_and_handle_events( auth_cache, ) .await - .map_err(|e| { - error!("Error: {:?}", e); - Error::Conflict("Authentication of event failed") - })?; + { + Ok(pdu) => pdu, + Err(e) => { + warn!("Authentication of event {} failed: {:?}", id, e); + continue; + } + }; 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 { Ok(keys) => keys, - Err(e) => { - return Err(Error::BadServerResponse( - "Signature verification failed: Could not fetch signing key.", - )); + Err(_) => { + warn!("Signature verification failed: Could not fetch signing key.",); + continue; } };