|
|
|
@ -1,7 +1,10 @@ |
|
|
|
use crate::{client_server, utils, ConduitResult, Database, Error, PduEvent, Result, Ruma}; |
|
|
|
use crate::{ |
|
|
|
|
|
|
|
client_server::{self, get_keys_helper}, |
|
|
|
|
|
|
|
utils, ConduitResult, Database, Error, PduEvent, Result, Ruma, |
|
|
|
|
|
|
|
}; |
|
|
|
use get_profile_information::v1::ProfileField; |
|
|
|
use get_profile_information::v1::ProfileField; |
|
|
|
use http::header::{HeaderValue, AUTHORIZATION, HOST}; |
|
|
|
use http::header::{HeaderValue, AUTHORIZATION, HOST}; |
|
|
|
use log::{debug, error, info, warn}; |
|
|
|
use log::{debug, error, info, trace, warn}; |
|
|
|
use regex::Regex; |
|
|
|
use regex::Regex; |
|
|
|
use rocket::{response::content::Json, State}; |
|
|
|
use rocket::{response::content::Json, State}; |
|
|
|
use ruma::{ |
|
|
|
use ruma::{ |
|
|
|
@ -15,6 +18,7 @@ use ruma::{ |
|
|
|
VerifyKey, |
|
|
|
VerifyKey, |
|
|
|
}, |
|
|
|
}, |
|
|
|
event::{get_event, get_missing_events, get_room_state_ids}, |
|
|
|
event::{get_event, get_missing_events, get_room_state_ids}, |
|
|
|
|
|
|
|
keys::get_keys, |
|
|
|
membership::{ |
|
|
|
membership::{ |
|
|
|
create_invite, |
|
|
|
create_invite, |
|
|
|
create_join_event::{self, RoomState}, |
|
|
|
create_join_event::{self, RoomState}, |
|
|
|
@ -32,12 +36,14 @@ use ruma::{ |
|
|
|
create::CreateEventContent, |
|
|
|
create::CreateEventContent, |
|
|
|
member::{MemberEventContent, MembershipState}, |
|
|
|
member::{MemberEventContent, MembershipState}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
AnyEphemeralRoomEvent, AnyEvent as EduEvent, EventType, |
|
|
|
AnyEphemeralRoomEvent, EventType, |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
receipt::ReceiptType, |
|
|
|
serde::Raw, |
|
|
|
serde::Raw, |
|
|
|
signatures::{CanonicalJsonObject, CanonicalJsonValue}, |
|
|
|
signatures::{CanonicalJsonObject, CanonicalJsonValue}, |
|
|
|
state_res::{self, Event, EventMap, RoomVersion, StateMap}, |
|
|
|
state_res::{self, Event, EventMap, RoomVersion, StateMap}, |
|
|
|
uint, EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UserId, |
|
|
|
uint, EventId, MilliSecondsSinceUnixEpoch, RoomId, RoomVersionId, ServerName, |
|
|
|
|
|
|
|
ServerSigningKeyId, UserId, |
|
|
|
}; |
|
|
|
}; |
|
|
|
use std::{ |
|
|
|
use std::{ |
|
|
|
collections::{btree_map::Entry, BTreeMap, BTreeSet, HashSet}, |
|
|
|
collections::{btree_map::Entry, BTreeMap, BTreeSet, HashSet}, |
|
|
|
@ -49,8 +55,9 @@ use std::{ |
|
|
|
pin::Pin, |
|
|
|
pin::Pin, |
|
|
|
result::Result as StdResult, |
|
|
|
result::Result as StdResult, |
|
|
|
sync::{Arc, RwLock}, |
|
|
|
sync::{Arc, RwLock}, |
|
|
|
time::{Duration, SystemTime}, |
|
|
|
time::{Duration, Instant, SystemTime}, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
use tokio::sync::Semaphore; |
|
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "conduit_bin")] |
|
|
|
#[cfg(feature = "conduit_bin")] |
|
|
|
use rocket::{get, post, put}; |
|
|
|
use rocket::{get, post, put}; |
|
|
|
@ -452,7 +459,10 @@ pub fn get_server_keys_route(db: State<'_, Database>) -> Json<String> { |
|
|
|
verify_keys, |
|
|
|
verify_keys, |
|
|
|
old_verify_keys: BTreeMap::new(), |
|
|
|
old_verify_keys: BTreeMap::new(), |
|
|
|
signatures: BTreeMap::new(), |
|
|
|
signatures: BTreeMap::new(), |
|
|
|
valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2), |
|
|
|
valid_until_ts: MilliSecondsSinceUnixEpoch::from_system_time( |
|
|
|
|
|
|
|
SystemTime::now() + Duration::from_secs(60 * 2), |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
.expect("time is valid"), |
|
|
|
}, |
|
|
|
}, |
|
|
|
} |
|
|
|
} |
|
|
|
.try_into_http_response::<Vec<u8>>() |
|
|
|
.try_into_http_response::<Vec<u8>>() |
|
|
|
@ -608,6 +618,7 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let start_time = Instant::now(); |
|
|
|
if let Err(e) = handle_incoming_pdu( |
|
|
|
if let Err(e) = handle_incoming_pdu( |
|
|
|
&body.origin, |
|
|
|
&body.origin, |
|
|
|
&event_id, |
|
|
|
&event_id, |
|
|
|
@ -619,7 +630,17 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
) |
|
|
|
) |
|
|
|
.await |
|
|
|
.await |
|
|
|
{ |
|
|
|
{ |
|
|
|
resolved_map.insert(event_id, Err(e)); |
|
|
|
resolved_map.insert(event_id.clone(), Err(e)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let elapsed = start_time.elapsed(); |
|
|
|
|
|
|
|
if elapsed > Duration::from_secs(1) { |
|
|
|
|
|
|
|
warn!( |
|
|
|
|
|
|
|
"Handling event {} took {}m{}s", |
|
|
|
|
|
|
|
event_id, |
|
|
|
|
|
|
|
elapsed.as_secs() / 60, |
|
|
|
|
|
|
|
elapsed.as_secs() % 60 |
|
|
|
|
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -653,19 +674,16 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
let mut user_receipts = BTreeMap::new(); |
|
|
|
let mut user_receipts = BTreeMap::new(); |
|
|
|
user_receipts.insert(user_id.clone(), user_updates.data); |
|
|
|
user_receipts.insert(user_id.clone(), user_updates.data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut receipts = BTreeMap::new(); |
|
|
|
|
|
|
|
receipts.insert(ReceiptType::Read, user_receipts); |
|
|
|
|
|
|
|
|
|
|
|
let mut receipt_content = BTreeMap::new(); |
|
|
|
let mut receipt_content = BTreeMap::new(); |
|
|
|
receipt_content.insert( |
|
|
|
receipt_content.insert(event_id.to_owned(), receipts); |
|
|
|
event_id.to_owned(), |
|
|
|
|
|
|
|
ruma::events::receipt::Receipts { |
|
|
|
|
|
|
|
read: Some(user_receipts), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let event = |
|
|
|
let event = AnyEphemeralRoomEvent::Receipt(ReceiptEvent { |
|
|
|
EduEvent::Ephemeral(AnyEphemeralRoomEvent::Receipt(ReceiptEvent { |
|
|
|
|
|
|
|
content: ReceiptEventContent(receipt_content), |
|
|
|
content: ReceiptEventContent(receipt_content), |
|
|
|
room_id: room_id.clone(), |
|
|
|
room_id: room_id.clone(), |
|
|
|
})); |
|
|
|
}); |
|
|
|
db.rooms.edus.readreceipt_update( |
|
|
|
db.rooms.edus.readreceipt_update( |
|
|
|
&user_id, |
|
|
|
&user_id, |
|
|
|
&room_id, |
|
|
|
&room_id, |
|
|
|
@ -698,6 +716,8 @@ pub async fn send_transaction_message_route<'a>( |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info!("/send/{} done", body.transaction_id); |
|
|
|
|
|
|
|
|
|
|
|
Ok(send_transaction_message::v1::Response { pdus: resolved_map }.into()) |
|
|
|
Ok(send_transaction_message::v1::Response { pdus: resolved_map }.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -794,7 +814,7 @@ pub fn handle_incoming_pdu<'a>( |
|
|
|
) { |
|
|
|
) { |
|
|
|
Err(e) => { |
|
|
|
Err(e) => { |
|
|
|
// Drop
|
|
|
|
// Drop
|
|
|
|
warn!("{:?}: {}", value, e); |
|
|
|
warn!("Dropping bad event {}: {}", event_id, 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) => { |
|
|
|
@ -821,6 +841,7 @@ pub fn handle_incoming_pdu<'a>( |
|
|
|
|
|
|
|
|
|
|
|
// 4. fetch any missing auth events doing all checks listed here starting at 1. These are not timeline events
|
|
|
|
// 4. fetch any missing auth events doing all checks listed here starting at 1. These are not timeline events
|
|
|
|
// 5. Reject "due to auth events" if can't get all the auth events or some of the auth events are also rejected "due to auth events"
|
|
|
|
// 5. Reject "due to auth events" if can't get all the auth events or some of the auth events are also rejected "due to auth events"
|
|
|
|
|
|
|
|
// EDIT: Step 5 is not applied anymore because it failed too often
|
|
|
|
debug!("Fetching auth events for {}", incoming_pdu.event_id); |
|
|
|
debug!("Fetching auth events for {}", incoming_pdu.event_id); |
|
|
|
fetch_and_handle_events( |
|
|
|
fetch_and_handle_events( |
|
|
|
db, |
|
|
|
db, |
|
|
|
@ -1292,12 +1313,30 @@ pub(crate) fn fetch_and_handle_events<'a>( |
|
|
|
auth_cache: &'a mut EventMap<Arc<PduEvent>>, |
|
|
|
auth_cache: &'a mut EventMap<Arc<PduEvent>>, |
|
|
|
) -> AsyncRecursiveResult<'a, Vec<Arc<PduEvent>>, Error> { |
|
|
|
) -> AsyncRecursiveResult<'a, Vec<Arc<PduEvent>>, Error> { |
|
|
|
Box::pin(async move { |
|
|
|
Box::pin(async move { |
|
|
|
|
|
|
|
let back_off = |id| match db.globals.bad_event_ratelimiter.write().unwrap().entry(id) { |
|
|
|
|
|
|
|
Entry::Vacant(e) => { |
|
|
|
|
|
|
|
e.insert((Instant::now(), 1)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
let mut pdus = vec![]; |
|
|
|
let mut pdus = vec![]; |
|
|
|
for id in events { |
|
|
|
for id in events { |
|
|
|
|
|
|
|
if let Some((time, tries)) = db.globals.bad_event_ratelimiter.read().unwrap().get(&id) { |
|
|
|
|
|
|
|
// Exponential backoff
|
|
|
|
|
|
|
|
let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries); |
|
|
|
|
|
|
|
if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { |
|
|
|
|
|
|
|
min_elapsed_duration = Duration::from_secs(60 * 60 * 24); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if time.elapsed() < min_elapsed_duration { |
|
|
|
|
|
|
|
debug!("Backing off from {}", id); |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
// a. Look at auth cache
|
|
|
|
// a. Look at auth cache
|
|
|
|
let pdu = match auth_cache.get(id) { |
|
|
|
let pdu = match auth_cache.get(id) { |
|
|
|
Some(pdu) => { |
|
|
|
Some(pdu) => { |
|
|
|
debug!("Found {} in cache", id); |
|
|
|
|
|
|
|
// We already have the auth chain for events in cache
|
|
|
|
// We already have the auth chain for events in cache
|
|
|
|
pdu.clone() |
|
|
|
pdu.clone() |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1306,7 +1345,7 @@ pub(crate) fn fetch_and_handle_events<'a>( |
|
|
|
// (get_pdu checks both)
|
|
|
|
// (get_pdu checks both)
|
|
|
|
None => match db.rooms.get_pdu(&id)? { |
|
|
|
None => match db.rooms.get_pdu(&id)? { |
|
|
|
Some(pdu) => { |
|
|
|
Some(pdu) => { |
|
|
|
debug!("Found {} in db", id); |
|
|
|
trace!("Found {} in db", id); |
|
|
|
// We need to fetch the auth chain
|
|
|
|
// We need to fetch the auth chain
|
|
|
|
let _ = fetch_and_handle_events( |
|
|
|
let _ = fetch_and_handle_events( |
|
|
|
db, |
|
|
|
db, |
|
|
|
@ -1331,7 +1370,7 @@ pub(crate) fn fetch_and_handle_events<'a>( |
|
|
|
.await |
|
|
|
.await |
|
|
|
{ |
|
|
|
{ |
|
|
|
Ok(res) => { |
|
|
|
Ok(res) => { |
|
|
|
debug!("Got {} over federation: {:?}", id, res); |
|
|
|
debug!("Got {} over federation", id); |
|
|
|
let (event_id, mut value) = |
|
|
|
let (event_id, mut value) = |
|
|
|
crate::pdu::gen_event_id_canonical_json(&res.pdu)?; |
|
|
|
crate::pdu::gen_event_id_canonical_json(&res.pdu)?; |
|
|
|
// This will also fetch the auth chain
|
|
|
|
// This will also fetch the auth chain
|
|
|
|
@ -1358,12 +1397,14 @@ pub(crate) fn fetch_and_handle_events<'a>( |
|
|
|
} |
|
|
|
} |
|
|
|
Err(e) => { |
|
|
|
Err(e) => { |
|
|
|
warn!("Authentication of event {} failed: {:?}", id, e); |
|
|
|
warn!("Authentication of event {} failed: {:?}", id, e); |
|
|
|
|
|
|
|
back_off(id.clone()); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
Err(_) => { |
|
|
|
Err(_) => { |
|
|
|
warn!("Failed to fetch event: {}", id); |
|
|
|
warn!("Failed to fetch event: {}", id); |
|
|
|
|
|
|
|
back_off(id.clone()); |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1383,10 +1424,67 @@ pub(crate) fn fetch_and_handle_events<'a>( |
|
|
|
pub(crate) async fn fetch_signing_keys( |
|
|
|
pub(crate) async fn fetch_signing_keys( |
|
|
|
db: &Database, |
|
|
|
db: &Database, |
|
|
|
origin: &ServerName, |
|
|
|
origin: &ServerName, |
|
|
|
signature_ids: Vec<&String>, |
|
|
|
signature_ids: Vec<String>, |
|
|
|
) -> Result<BTreeMap<String, String>> { |
|
|
|
) -> Result<BTreeMap<String, String>> { |
|
|
|
let contains_all_ids = |
|
|
|
let contains_all_ids = |
|
|
|
|keys: &BTreeMap<String, String>| signature_ids.iter().all(|&id| keys.contains_key(id)); |
|
|
|
|keys: &BTreeMap<String, String>| signature_ids.iter().all(|id| keys.contains_key(id)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let permit = db |
|
|
|
|
|
|
|
.globals |
|
|
|
|
|
|
|
.servername_ratelimiter |
|
|
|
|
|
|
|
.read() |
|
|
|
|
|
|
|
.unwrap() |
|
|
|
|
|
|
|
.get(origin) |
|
|
|
|
|
|
|
.map(|s| Arc::clone(s).acquire_owned()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let permit = match permit { |
|
|
|
|
|
|
|
Some(p) => p, |
|
|
|
|
|
|
|
None => { |
|
|
|
|
|
|
|
let mut write = db.globals.servername_ratelimiter.write().unwrap(); |
|
|
|
|
|
|
|
let s = Arc::clone( |
|
|
|
|
|
|
|
write |
|
|
|
|
|
|
|
.entry(origin.to_owned()) |
|
|
|
|
|
|
|
.or_insert_with(|| Arc::new(Semaphore::new(1))), |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.acquire_owned() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
.await; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let back_off = |id| match db |
|
|
|
|
|
|
|
.globals |
|
|
|
|
|
|
|
.bad_signature_ratelimiter |
|
|
|
|
|
|
|
.write() |
|
|
|
|
|
|
|
.unwrap() |
|
|
|
|
|
|
|
.entry(id) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Entry::Vacant(e) => { |
|
|
|
|
|
|
|
e.insert((Instant::now(), 1)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Entry::Occupied(mut e) => *e.get_mut() = (Instant::now(), e.get().1 + 1), |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some((time, tries)) = db |
|
|
|
|
|
|
|
.globals |
|
|
|
|
|
|
|
.bad_signature_ratelimiter |
|
|
|
|
|
|
|
.read() |
|
|
|
|
|
|
|
.unwrap() |
|
|
|
|
|
|
|
.get(&signature_ids) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Exponential backoff
|
|
|
|
|
|
|
|
let mut min_elapsed_duration = Duration::from_secs(30) * (*tries) * (*tries); |
|
|
|
|
|
|
|
if min_elapsed_duration > Duration::from_secs(60 * 60 * 24) { |
|
|
|
|
|
|
|
min_elapsed_duration = Duration::from_secs(60 * 60 * 24); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if time.elapsed() < min_elapsed_duration { |
|
|
|
|
|
|
|
debug!("Backing off from {:?}", signature_ids); |
|
|
|
|
|
|
|
return Err(Error::BadServerResponse("bad signature, still backing off")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Loading signing keys for {}", origin); |
|
|
|
|
|
|
|
|
|
|
|
let mut result = db |
|
|
|
let mut result = db |
|
|
|
.globals |
|
|
|
.globals |
|
|
|
@ -1399,6 +1497,8 @@ pub(crate) async fn fetch_signing_keys( |
|
|
|
return Ok(result); |
|
|
|
return Ok(result); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
debug!("Fetching signing keys for {} over federation", origin); |
|
|
|
|
|
|
|
|
|
|
|
if let Ok(get_keys_response) = db |
|
|
|
if let Ok(get_keys_response) = 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()) |
|
|
|
@ -1436,14 +1536,17 @@ pub(crate) async fn fetch_signing_keys( |
|
|
|
&server, |
|
|
|
&server, |
|
|
|
get_remote_server_keys::v2::Request::new( |
|
|
|
get_remote_server_keys::v2::Request::new( |
|
|
|
origin, |
|
|
|
origin, |
|
|
|
|
|
|
|
MilliSecondsSinceUnixEpoch::from_system_time( |
|
|
|
SystemTime::now() |
|
|
|
SystemTime::now() |
|
|
|
.checked_add(Duration::from_secs(3600)) |
|
|
|
.checked_add(Duration::from_secs(3600)) |
|
|
|
.expect("SystemTime to large"), |
|
|
|
.expect("SystemTime to large"), |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
.expect("time is valid"), |
|
|
|
), |
|
|
|
), |
|
|
|
) |
|
|
|
) |
|
|
|
.await |
|
|
|
.await |
|
|
|
{ |
|
|
|
{ |
|
|
|
debug!("Got signing keys: {:?}", keys); |
|
|
|
trace!("Got signing keys: {:?}", keys); |
|
|
|
for k in keys.server_keys { |
|
|
|
for k in keys.server_keys { |
|
|
|
db.globals.add_signing_key(origin, &k)?; |
|
|
|
db.globals.add_signing_key(origin, &k)?; |
|
|
|
result.extend( |
|
|
|
result.extend( |
|
|
|
@ -1464,6 +1567,10 @@ pub(crate) async fn fetch_signing_keys( |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
drop(permit); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
back_off(signature_ids); |
|
|
|
|
|
|
|
|
|
|
|
warn!("Failed to find public key for server: {}", origin); |
|
|
|
warn!("Failed to find public key for server: {}", origin); |
|
|
|
Err(Error::BadServerResponse( |
|
|
|
Err(Error::BadServerResponse( |
|
|
|
"Failed to find public key for server", |
|
|
|
"Failed to find public key for server", |
|
|
|
@ -1581,7 +1688,7 @@ pub fn get_event_route<'a>( |
|
|
|
|
|
|
|
|
|
|
|
Ok(get_event::v1::Response { |
|
|
|
Ok(get_event::v1::Response { |
|
|
|
origin: db.globals.server_name().to_owned(), |
|
|
|
origin: db.globals.server_name().to_owned(), |
|
|
|
origin_server_ts: SystemTime::now(), |
|
|
|
origin_server_ts: MilliSecondsSinceUnixEpoch::now(), |
|
|
|
pdu: PduEvent::convert_to_outgoing_federation_event( |
|
|
|
pdu: PduEvent::convert_to_outgoing_federation_event( |
|
|
|
db.rooms |
|
|
|
db.rooms |
|
|
|
.get_pdu_json(&body.event_id)? |
|
|
|
.get_pdu_json(&body.event_id)? |
|
|
|
@ -2186,6 +2293,34 @@ pub fn get_profile_information_route<'a>( |
|
|
|
.into()) |
|
|
|
.into()) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg_attr(
|
|
|
|
|
|
|
|
feature = "conduit_bin", |
|
|
|
|
|
|
|
post("/_matrix/federation/v1/user/keys/query", data = "<body>") |
|
|
|
|
|
|
|
)] |
|
|
|
|
|
|
|
#[tracing::instrument(skip(db, body))] |
|
|
|
|
|
|
|
pub fn get_keys_route<'a>( |
|
|
|
|
|
|
|
db: State<'a, Database>, |
|
|
|
|
|
|
|
body: Ruma<get_keys::v1::Request>, |
|
|
|
|
|
|
|
) -> ConduitResult<get_keys::v1::Response> { |
|
|
|
|
|
|
|
if !db.globals.allow_federation() { |
|
|
|
|
|
|
|
return Err(Error::bad_config("Federation is disabled.")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let result = get_keys_helper( |
|
|
|
|
|
|
|
None, |
|
|
|
|
|
|
|
&body.device_keys, |
|
|
|
|
|
|
|
|u| Some(u.server_name()) == body.sender_servername.as_deref(), |
|
|
|
|
|
|
|
&db, |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(get_keys::v1::Response { |
|
|
|
|
|
|
|
device_keys: result.device_keys, |
|
|
|
|
|
|
|
master_keys: result.master_keys, |
|
|
|
|
|
|
|
self_signing_keys: result.self_signing_keys, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
.into()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub async fn fetch_required_signing_keys( |
|
|
|
pub async fn fetch_required_signing_keys( |
|
|
|
event: &BTreeMap<String, CanonicalJsonValue>, |
|
|
|
event: &BTreeMap<String, CanonicalJsonValue>, |
|
|
|
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>, |
|
|
|
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>, |
|
|
|
@ -2208,9 +2343,8 @@ pub async fn fetch_required_signing_keys( |
|
|
|
"Invalid signatures content object in server response pdu.", |
|
|
|
"Invalid signatures content object in server response pdu.", |
|
|
|
))?; |
|
|
|
))?; |
|
|
|
|
|
|
|
|
|
|
|
let signature_ids = signature_object.keys().collect::<Vec<_>>(); |
|
|
|
let signature_ids = signature_object.keys().cloned().collect::<Vec<_>>(); |
|
|
|
|
|
|
|
|
|
|
|
debug!("Fetching signing keys for {}", signature_server); |
|
|
|
|
|
|
|
let fetch_res = fetch_signing_keys( |
|
|
|
let fetch_res = fetch_signing_keys( |
|
|
|
db, |
|
|
|
db, |
|
|
|
&Box::<ServerName>::try_from(&**signature_server).map_err(|_| { |
|
|
|
&Box::<ServerName>::try_from(&**signature_server).map_err(|_| { |
|
|
|
|