Ask multiple servers for keys when not known or sending server failed
This commit is contained in:
		
							parent
							
								
									f3253f2033
								
							
						
					
					
						commit
						c9f4ff5cf8
					
				
					 2 changed files with 53 additions and 10 deletions
				
			
		|  | @ -1605,7 +1605,7 @@ impl Rooms { | |||
|             }) | ||||
|     } | ||||
| 
 | ||||
|     /// Returns an iterator over all joined members of a room.
 | ||||
|     /// Returns an iterator of all servers participating in this room.
 | ||||
|     pub fn room_servers(&self, room_id: &RoomId) -> impl Iterator<Item = Result<Box<ServerName>>> { | ||||
|         let mut prefix = room_id.as_bytes().to_vec(); | ||||
|         prefix.push(0xff); | ||||
|  |  | |||
|  | @ -8,8 +8,8 @@ use ruma::{ | |||
|         federation::{ | ||||
|             directory::{get_public_rooms, get_public_rooms_filtered}, | ||||
|             discovery::{ | ||||
|                 get_server_keys, get_server_version::v1 as get_server_version, ServerSigningKeys, | ||||
|                 VerifyKey, | ||||
|                 get_remote_server_keys, get_server_keys, | ||||
|                 get_server_version::v1 as get_server_version, ServerSigningKeys, VerifyKey, | ||||
|             }, | ||||
|             event::{get_event, get_missing_events, get_room_state_ids}, | ||||
|             query::get_profile_information, | ||||
|  | @ -575,7 +575,7 @@ pub async fn send_transaction_message_route<'a>( | |||
|                 return None; | ||||
|             } | ||||
| 
 | ||||
|             Some((event_id, value)) | ||||
|             Some((event_id, room_id, value)) | ||||
|         }) | ||||
|         .collect::<Vec<_>>(); | ||||
| 
 | ||||
|  | @ -586,7 +586,7 @@ pub async fn send_transaction_message_route<'a>( | |||
|     // events over federation. For example, the Federation API's /send endpoint would
 | ||||
|     // discard the event whereas the Client Server API's /send/{eventType} endpoint
 | ||||
|     // would return a M_BAD_JSON error.
 | ||||
|     'main_pdu_loop: for (event_id, value) in pdus_to_resolve { | ||||
|     'main_pdu_loop: for (event_id, room_id, value) in pdus_to_resolve { | ||||
|         let server_name = &body.body.origin; | ||||
|         let mut pub_key_map = BTreeMap::new(); | ||||
| 
 | ||||
|  | @ -595,7 +595,7 @@ pub async fn send_transaction_message_route<'a>( | |||
|                 UserId::try_from(sender.as_str()).expect("All PDUs have a valid sender field"); | ||||
|             let origin = sender.server_name(); | ||||
| 
 | ||||
|             let keys = match fetch_signing_keys(&db, origin).await { | ||||
|             let keys = match fetch_signing_keys(&db, &room_id, origin).await { | ||||
|                 Ok(keys) => keys, | ||||
|                 Err(_) => { | ||||
|                     resolved_map.insert( | ||||
|  | @ -1122,18 +1122,61 @@ pub(crate) async fn fetch_events( | |||
| /// fetch them from the server and save to our DB.
 | ||||
| pub(crate) async fn fetch_signing_keys( | ||||
|     db: &Database, | ||||
|     room_id: &RoomId, | ||||
|     origin: &ServerName, | ||||
| ) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> { | ||||
|     match db.globals.signing_keys_for(origin)? { | ||||
|         keys if !keys.is_empty() => Ok(keys), | ||||
|         _ => { | ||||
|             let keys = db | ||||
|             match db | ||||
|                 .sending | ||||
|                 .send_federation_request(&db.globals, origin, get_server_keys::v2::Request::new()) | ||||
|                 .await | ||||
|                 .map_err(|_| Error::BadServerResponse("Failed to request server keys"))?; | ||||
|             db.globals.add_signing_key(origin, &keys.server_key)?; | ||||
|             Ok(keys.server_key.verify_keys) | ||||
|             { | ||||
|                 Ok(keys) => { | ||||
|                     db.globals.add_signing_key(origin, &keys.server_key)?; | ||||
|                     Ok(keys.server_key.verify_keys) | ||||
|                 } | ||||
|                 _ => { | ||||
|                     for server in db.rooms.room_servers(room_id) { | ||||
|                         let server = server?; | ||||
|                         if let Ok(keys) = db | ||||
|                             .sending | ||||
|                             .send_federation_request( | ||||
|                                 &db.globals, | ||||
|                                 &server, | ||||
|                                 get_remote_server_keys::v2::Request::new( | ||||
|                                     &server, | ||||
|                                     SystemTime::now() | ||||
|                                         .checked_add(Duration::from_secs(3600)) | ||||
|                                         .expect("SystemTime to large"), | ||||
|                                 ), | ||||
|                             ) | ||||
|                             .await | ||||
|                         { | ||||
|                             let keys: Vec<ServerSigningKeys> = keys.server_keys; | ||||
|                             let key = keys.into_iter().fold(None, |mut key, next| { | ||||
|                                 if let Some(verified) = &key { | ||||
|                                     // rustc cannot elide this type for some reason
 | ||||
|                                     let v: &ServerSigningKeys = verified; | ||||
|                                     if v.verify_keys | ||||
|                                         .iter() | ||||
|                                         .zip(next.verify_keys.iter()) | ||||
|                                         .all(|(a, b)| a.1.key == b.1.key) | ||||
|                                     { | ||||
|                                     } | ||||
|                                 } else { | ||||
|                                     key = Some(next) | ||||
|                                 } | ||||
|                                 key | ||||
|                             }); | ||||
|                         } | ||||
|                     } | ||||
|                     Err(Error::BadServerResponse( | ||||
|                         "Failed to find public key for server", | ||||
|                     )) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue