fix: signature key fetching, optimize push sending

This commit is contained in:
Timo Kösters 2021-03-22 14:04:11 +01:00
parent d4c76f4654
commit 363c629faf
No known key found for this signature in database
GPG key ID: 24DA7517711A2BA4
7 changed files with 396 additions and 336 deletions

View file

@ -21,9 +21,10 @@ use ruma::{
},
directory::{IncomingFilter, IncomingRoomNetwork},
events::EventType,
identifiers::{KeyId, KeyName},
serde::to_canonical_value,
signatures::{CanonicalJsonObject, CanonicalJsonValue, PublicKeyMap},
EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, UserId,
EventId, RoomId, RoomVersionId, ServerName, ServerSigningKeyId, SigningKeyAlgorithm, UserId,
};
use state_res::{Event, EventMap, StateMap};
use std::{
@ -600,7 +601,7 @@ pub async fn send_transaction_message_route<'a>(
// 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, _room_id, value) in pdus_to_resolve {
debug!("Working on incoming pdu: {:?}", value);
info!("Working on incoming pdu: {:?}", value);
let server_name = &body.body.origin;
let mut pub_key_map = BTreeMap::new();
@ -639,7 +640,7 @@ pub async fn send_transaction_message_route<'a>(
// 6. persist the event as an outlier.
db.rooms.add_pdu_outlier(&pdu)?;
debug!("Added pdu as outlier.");
info!("Added pdu as outlier.");
// Step 9. fetch missing state by calling /state_ids at backwards extremities doing all
// the checks in this list starting at 1. These are not timeline events.
@ -914,7 +915,7 @@ pub async fn send_transaction_message_route<'a>(
// We use the `state_at_event` instead of `state_after` so we accurately
// represent the state for this event.
append_incoming_pdu(&db, &pdu, &extremities, &state_at_event)?;
debug!("Appended incoming pdu.");
info!("Appended incoming pdu.");
// Set the new room state to the resolved state
update_resolved_state(
@ -961,21 +962,31 @@ fn validate_event<'a>(
auth_cache: &'a mut EventMap<Arc<PduEvent>>,
) -> AsyncRecursiveResult<'a, (Arc<PduEvent>, Option<Arc<PduEvent>>)> {
Box::pin(async move {
for signature_server in match value
for (signature_server, signature) in match value
.get("signatures")
.ok_or_else(|| "No signatures in server response pdu.".to_string())?
{
CanonicalJsonValue::Object(map) => map,
_ => return Err("Invalid signatures object in server response pdu.".to_string()),
}
.keys()
{
} {
let signature_object = match signature {
CanonicalJsonValue::Object(map) => map,
_ => {
return Err(
"Invalid signatures content object in server response pdu.".to_string()
)
}
};
let signature_ids = signature_object.keys().collect::<Vec<_>>();
debug!("Fetching signing keys for {}", signature_server);
let keys = match fetch_signing_keys(
&db,
&Box::<ServerName>::try_from(&**signature_server).map_err(|_| {
"Invalid servername in signatures of server response pdu.".to_string()
})?,
signature_ids,
)
.await
{
@ -987,26 +998,29 @@ fn validate_event<'a>(
}
};
pub_key_map.insert(signature_server.clone(), keys);
pub_key_map.insert(dbg!(signature_server.clone()), dbg!(keys));
}
let mut val =
match ruma::signatures::verify_event(pub_key_map, &value, &RoomVersionId::Version5) {
Ok(ver) => {
if let ruma::signatures::Verified::Signatures = ver {
match ruma::signatures::redact(&value, &RoomVersionId::Version6) {
Ok(obj) => obj,
Err(_) => return Err("Redaction failed".to_string()),
}
} else {
value
let mut val = match ruma::signatures::verify_event(
dbg!(&pub_key_map),
&value,
&RoomVersionId::Version5,
) {
Ok(ver) => {
if let ruma::signatures::Verified::Signatures = ver {
match ruma::signatures::redact(&value, &RoomVersionId::Version6) {
Ok(obj) => obj,
Err(_) => return Err("Redaction failed".to_string()),
}
} else {
value
}
Err(_e) => {
error!("{}", _e);
return Err("Signature verification failed".to_string());
}
};
}
Err(_e) => {
error!("{}", _e);
return Err("Signature verification failed".to_string());
}
};
// Now that we have checked the signature and hashes we can add the eventID and convert
// to our PduEvent type also finally verifying the first step listed above
@ -1116,7 +1130,7 @@ pub(crate) async fn fetch_events(
Arc::new(pdu)
}
None => {
debug!("Fetching event over federation");
debug!("Fetching event over federation: {:?}", id);
match db
.sending
.send_federation_request(
@ -1159,78 +1173,93 @@ pub(crate) async fn fetch_events(
pub(crate) async fn fetch_signing_keys(
db: &Database,
origin: &ServerName,
signature_ids: Vec<&String>,
) -> Result<BTreeMap<String, String>> {
let mut result = BTreeMap::new();
let contains_all_ids = |keys: &BTreeMap<String, String>| {
signature_ids
.iter()
.all(|&id| dbg!(dbg!(&keys).contains_key(dbg!(id))))
};
match db.globals.signing_keys_for(origin)? {
keys if !keys.is_empty() => Ok(keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key))
.collect()),
_ => {
match db
.sending
.send_federation_request(&db.globals, origin, get_server_keys::v2::Request::new())
.await
{
Ok(keys) => {
db.globals.add_signing_key(origin, &keys.server_key)?;
let mut result = db
.globals
.signing_keys_for(origin)?
.into_iter()
.map(|(k, v)| (k.to_string(), v.key))
.collect::<BTreeMap<_, _>>();
result.extend(
keys.server_key
.verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
result.extend(
keys.server_key
.old_verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
return Ok(result);
}
_ => {
for server in db.globals.trusted_servers() {
debug!("Asking {} for {}'s signing key", server, origin);
if let Ok(keys) = db
.sending
.send_federation_request(
&db.globals,
&server,
get_remote_server_keys::v2::Request::new(
origin,
SystemTime::now()
.checked_add(Duration::from_secs(3600))
.expect("SystemTime to large"),
),
)
.await
{
debug!("Got signing keys: {:?}", keys);
for k in keys.server_keys.into_iter() {
db.globals.add_signing_key(origin, &k)?;
result.extend(
k.verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
result.extend(
k.old_verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
}
return Ok(result);
}
}
Err(Error::BadServerResponse(
"Failed to find public key for server",
))
}
if contains_all_ids(&result) {
return Ok(result);
}
if let Ok(get_keys_response) = db
.sending
.send_federation_request(&db.globals, origin, get_server_keys::v2::Request::new())
.await
{
db.globals
.add_signing_key(origin, &get_keys_response.server_key)?;
result.extend(
get_keys_response
.server_key
.verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
result.extend(
get_keys_response
.server_key
.old_verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
if contains_all_ids(&result) {
return Ok(result);
}
}
for server in db.globals.trusted_servers() {
debug!("Asking {} for {}'s signing key", server, origin);
if let Ok(keys) = db
.sending
.send_federation_request(
&db.globals,
&server,
get_remote_server_keys::v2::Request::new(
origin,
SystemTime::now()
.checked_add(Duration::from_secs(3600))
.expect("SystemTime to large"),
),
)
.await
{
debug!("Got signing keys: {:?}", keys);
for k in keys.server_keys.into_iter() {
db.globals.add_signing_key(origin, &k)?;
result.extend(
k.verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
result.extend(
k.old_verify_keys
.into_iter()
.map(|(k, v)| (k.to_string(), v.key)),
);
}
if contains_all_ids(&result) {
return Ok(result);
}
}
}
Err(Error::BadServerResponse(
"Failed to find public key for server",
))
}
/// Gather all state snapshots needed to resolve the current state of the room.
@ -1244,7 +1273,7 @@ pub(crate) async fn calculate_forward_extremities(
db: &Database,
pdu: &PduEvent,
) -> Result<Vec<EventId>> {
let mut current_leaves = db.rooms.get_pdu_leaves(pdu.room_id())?;
let mut current_leaves = dbg!(db.rooms.get_pdu_leaves(pdu.room_id())?);
let mut is_incoming_leaf = true;
// Make sure the incoming event is not already a forward extremity
@ -1290,7 +1319,6 @@ pub(crate) async fn calculate_forward_extremities(
///
/// This guarantees that the incoming event will be in the state sets (at least our servers
/// and the sending server).
#[tracing::instrument(skip(db))]
pub(crate) async fn build_forward_extremity_snapshots(
db: &Database,
pdu: Arc<PduEvent>,
@ -1316,7 +1344,7 @@ pub(crate) async fn build_forward_extremity_snapshots(
Some(leave_pdu) => {
let pdu_shortstatehash = db
.rooms
.pdu_shortstatehash(&leave_pdu.event_id)?
.pdu_shortstatehash(dbg!(&leave_pdu.event_id))?
.ok_or_else(|| Error::bad_database("Found pdu with no statehash in db."))?;
if current_shortstatehash.as_ref() == Some(&pdu_shortstatehash) {
@ -1367,7 +1395,9 @@ pub(crate) fn update_resolved_state(
new_state.insert(
(
ev_type,
state_k.ok_or_else(|| Error::Conflict("State contained non state event"))?,
state_k.ok_or_else(|| {
Error::Conflict("update_resolved_state: State contained non state event")
})?,
),
pdu.event_id.clone(),
);
@ -1395,9 +1425,9 @@ pub(crate) fn append_incoming_pdu(
new_state.insert(
(
ev_type.clone(),
state_k
.clone()
.ok_or_else(|| Error::Conflict("State contained non state event"))?,
state_k.clone().ok_or_else(|| {
Error::Conflict("append_incoming_pdu: State contained non state event")
})?,
),
state_pdu.event_id.clone(),
);