Ask multiple servers for keys when not known or sending server failed
parent
f3253f2033
commit
c9f4ff5cf8
|
@ -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>>> {
|
pub fn room_servers(&self, room_id: &RoomId) -> impl Iterator<Item = Result<Box<ServerName>>> {
|
||||||
let mut prefix = room_id.as_bytes().to_vec();
|
let mut prefix = room_id.as_bytes().to_vec();
|
||||||
prefix.push(0xff);
|
prefix.push(0xff);
|
||||||
|
|
|
@ -8,8 +8,8 @@ use ruma::{
|
||||||
federation::{
|
federation::{
|
||||||
directory::{get_public_rooms, get_public_rooms_filtered},
|
directory::{get_public_rooms, get_public_rooms_filtered},
|
||||||
discovery::{
|
discovery::{
|
||||||
get_server_keys, get_server_version::v1 as get_server_version, ServerSigningKeys,
|
get_remote_server_keys, get_server_keys,
|
||||||
VerifyKey,
|
get_server_version::v1 as get_server_version, ServerSigningKeys, VerifyKey,
|
||||||
},
|
},
|
||||||
event::{get_event, get_missing_events, get_room_state_ids},
|
event::{get_event, get_missing_events, get_room_state_ids},
|
||||||
query::get_profile_information,
|
query::get_profile_information,
|
||||||
|
@ -575,7 +575,7 @@ pub async fn send_transaction_message_route<'a>(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((event_id, value))
|
Some((event_id, room_id, value))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.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
|
// events over federation. For example, the Federation API's /send endpoint would
|
||||||
// discard the event whereas the Client Server API's /send/{eventType} endpoint
|
// discard the event whereas the Client Server API's /send/{eventType} endpoint
|
||||||
// would return a M_BAD_JSON error.
|
// 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 server_name = &body.body.origin;
|
||||||
let mut pub_key_map = BTreeMap::new();
|
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");
|
UserId::try_from(sender.as_str()).expect("All PDUs have a valid sender field");
|
||||||
let origin = sender.server_name();
|
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,
|
Ok(keys) => keys,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
resolved_map.insert(
|
resolved_map.insert(
|
||||||
|
@ -1122,19 +1122,62 @@ pub(crate) async fn fetch_events(
|
||||||
/// fetch them from the server and save to our DB.
|
/// fetch them from the server and save to our DB.
|
||||||
pub(crate) async fn fetch_signing_keys(
|
pub(crate) async fn fetch_signing_keys(
|
||||||
db: &Database,
|
db: &Database,
|
||||||
|
room_id: &RoomId,
|
||||||
origin: &ServerName,
|
origin: &ServerName,
|
||||||
) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
|
) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
|
||||||
match db.globals.signing_keys_for(origin)? {
|
match db.globals.signing_keys_for(origin)? {
|
||||||
keys if !keys.is_empty() => Ok(keys),
|
keys if !keys.is_empty() => Ok(keys),
|
||||||
_ => {
|
_ => {
|
||||||
let keys = db
|
match db
|
||||||
.sending
|
.sending
|
||||||
.send_federation_request(&db.globals, origin, get_server_keys::v2::Request::new())
|
.send_federation_request(&db.globals, origin, get_server_keys::v2::Request::new())
|
||||||
.await
|
.await
|
||||||
.map_err(|_| Error::BadServerResponse("Failed to request server keys"))?;
|
{
|
||||||
|
Ok(keys) => {
|
||||||
db.globals.add_signing_key(origin, &keys.server_key)?;
|
db.globals.add_signing_key(origin, &keys.server_key)?;
|
||||||
Ok(keys.server_key.verify_keys)
|
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 New Issue