State-reset and security mitigations.

Upgrade Ruma to present.

The following are intentionally benign for activation in a later commit:

- Hydra backports not default.
- Room version 12 not default.
- Room version 12 not listed as stable.

Do not enable them manually or you can brick your database.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk
2025-06-29 03:33:29 +00:00
parent 2c6dd78502
commit 628597c318
134 changed files with 14961 additions and 4935 deletions

View File

@@ -1,8 +1,8 @@
use std::borrow::Borrow;
use ruma::{
CanonicalJsonObject, RoomVersionId, ServerName, ServerSigningKeyId,
api::federation::discovery::VerifyKey,
CanonicalJsonObject, ServerName, ServerSigningKeyId, api::federation::discovery::VerifyKey,
room_version_rules::RoomVersionRules,
};
use tuwunel_core::{Err, Result, implement};
@@ -12,11 +12,11 @@ use super::{PubKeyMap, PubKeys, extract_key};
pub async fn get_event_keys(
&self,
object: &CanonicalJsonObject,
version: &RoomVersionId,
version: &RoomVersionRules,
) -> Result<PubKeyMap> {
use ruma::signatures::required_keys;
let required = match required_keys(object, version) {
let required = match required_keys(object, &version.signatures) {
| Ok(required) => required,
| Err(e) => {
return Err!(BadServerResponse("Failed to determine keys required to verify: {e}"));

View File

@@ -9,9 +9,10 @@ use std::{collections::BTreeMap, sync::Arc, time::Duration};
use futures::StreamExt;
use ruma::{
CanonicalJsonObject, MilliSecondsSinceUnixEpoch, OwnedServerSigningKeyId, RoomVersionId,
ServerName, ServerSigningKeyId,
CanonicalJsonObject, MilliSecondsSinceUnixEpoch, OwnedServerSigningKeyId, ServerName,
ServerSigningKeyId,
api::federation::discovery::{ServerSigningKeys, VerifyKey},
room_version_rules::RoomVersionRules,
serde::Raw,
signatures::{Ed25519KeyPair, PublicKeyMap, PublicKeySet},
};
@@ -109,6 +110,7 @@ async fn add_signing_keys(&self, new_keys: ServerSigningKeys) {
keys.verify_keys.extend(new_keys.verify_keys);
keys.old_verify_keys
.extend(new_keys.old_verify_keys);
self.db
.server_signingkeys
.raw_put(origin, Json(&keys));
@@ -118,11 +120,11 @@ async fn add_signing_keys(&self, new_keys: ServerSigningKeys) {
pub async fn required_keys_exist(
&self,
object: &CanonicalJsonObject,
version: &RoomVersionId,
rules: &RoomVersionRules,
) -> bool {
use ruma::signatures::required_keys;
let Ok(required_keys) = required_keys(object, version) else {
let Ok(required_keys) = required_keys(object, &rules.signatures) else {
return false;
};
@@ -191,6 +193,7 @@ pub async fn signing_keys_for(&self, origin: &ServerName) -> Result<ServerSignin
fn minimum_valid_ts(&self) -> MilliSecondsSinceUnixEpoch {
let timepoint =
timepoint_from_now(self.minimum_valid).expect("SystemTime should not overflow");
MilliSecondsSinceUnixEpoch::from_system_time(timepoint).expect("UInt should not overflow")
}

View File

@@ -1,5 +1,5 @@
use ruma::{CanonicalJsonObject, RoomVersionId};
use tuwunel_core::{Result, implement};
use tuwunel_core::{Result, err, implement};
#[implement(super::Service)]
pub fn sign_json(&self, object: &mut CanonicalJsonObject) -> Result {
@@ -17,6 +17,18 @@ pub fn hash_and_sign_event(
) -> Result {
use ruma::signatures::hash_and_sign_event;
let server_name = self.services.globals.server_name().as_str();
hash_and_sign_event(server_name, self.keypair(), object, room_version).map_err(Into::into)
let server_name = &self.services.server.name;
let room_version_rules = room_version.rules().ok_or_else(|| {
err!(Request(UnsupportedRoomVersion(
"Cannot hash and sign event for unknown room version {room_version:?}."
)))
})?;
hash_and_sign_event(
server_name.as_str(),
self.keypair(),
object,
&room_version_rules.redaction,
)
.map_err(Into::into)
}

View File

@@ -2,7 +2,7 @@ use ruma::{
CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomVersionId, signatures::Verified,
};
use serde_json::value::RawValue as RawJsonValue;
use tuwunel_core::{Err, Result, implement, matrix::event::gen_event_id_canonical_json};
use tuwunel_core::{Err, Result, err, implement, matrix::event::gen_event_id_canonical_json};
#[implement(super::Service)]
pub async fn validate_and_add_event_id(
@@ -32,8 +32,14 @@ pub async fn validate_and_add_event_id_no_fetch(
room_version: &RoomVersionId,
) -> Result<(OwnedEventId, CanonicalJsonObject)> {
let (event_id, mut value) = gen_event_id_canonical_json(pdu, room_version)?;
let room_version_rules = room_version.rules().ok_or_else(|| {
err!(Request(UnsupportedRoomVersion(
"Cannot verify event for unknown room version {room_version:?}."
)))
})?;
if !self
.required_keys_exist(&value, room_version)
.required_keys_exist(&value, &room_version_rules)
.await
{
return Err!(BadServerResponse(debug_warn!(
@@ -62,8 +68,17 @@ pub async fn verify_event(
room_version: Option<&RoomVersionId>,
) -> Result<Verified> {
let room_version = room_version.unwrap_or(&RoomVersionId::V11);
let keys = self.get_event_keys(event, room_version).await?;
ruma::signatures::verify_event(&keys, event, room_version).map_err(Into::into)
let room_version_rules = room_version.rules().ok_or_else(|| {
err!(Request(UnsupportedRoomVersion(
"Cannot verify event for unknown room version {room_version:?}."
)))
})?;
let event_keys = self
.get_event_keys(event, &room_version_rules)
.await?;
ruma::signatures::verify_event(&event_keys, event, &room_version_rules).map_err(Into::into)
}
#[implement(super::Service)]
@@ -73,6 +88,15 @@ pub async fn verify_json(
room_version: Option<&RoomVersionId>,
) -> Result {
let room_version = room_version.unwrap_or(&RoomVersionId::V11);
let keys = self.get_event_keys(event, room_version).await?;
ruma::signatures::verify_json(&keys, event.clone()).map_err(Into::into)
let room_version_rules = room_version.rules().ok_or_else(|| {
err!(Request(UnsupportedRoomVersion(
"Cannot verify json for unknown room version {room_version:?}."
)))
})?;
let event_keys = self
.get_event_keys(event, &room_version_rules)
.await?;
ruma::signatures::verify_json(&event_keys, event).map_err(Into::into)
}