Check PDU formats
This commit is contained in:
@@ -6,6 +6,7 @@ use ruma::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
Result, extract_variant, is_equal_to,
|
Result, extract_variant, is_equal_to,
|
||||||
matrix::{PduEvent, room_version},
|
matrix::{PduEvent, room_version},
|
||||||
|
state_res::{self},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn into_outgoing_federation(
|
pub fn into_outgoing_federation(
|
||||||
@@ -95,6 +96,8 @@ pub fn from_incoming_federation(
|
|||||||
pdu_json.insert("event_id".into(), CanonicalJsonValue::String(event_id.into()));
|
pdu_json.insert("event_id".into(), CanonicalJsonValue::String(event_id.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state_res::check_pdu_format(pdu_json, &room_rules.event_format)?;
|
||||||
|
|
||||||
PduEvent::from_val(pdu_json)
|
PduEvent::from_val(pdu_json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ pub fn check_pdu_format(pdu: &CanonicalJsonObject, rules: &EventFormatRules) ->
|
|||||||
.map_err(|e| err!(Request(BadJson("Failed to serialize canonical JSON: {e}"))))?;
|
.map_err(|e| err!(Request(BadJson("Failed to serialize canonical JSON: {e}"))))?;
|
||||||
|
|
||||||
if json.len() > MAX_PDU_BYTES {
|
if json.len() > MAX_PDU_BYTES {
|
||||||
return Err!(Request(InvalidParam(
|
return Err!(Request(TooLarge("PDU is larger than maximum of {MAX_PDU_BYTES} bytes")));
|
||||||
"PDU is larger than maximum of {MAX_PDU_BYTES} bytes"
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the presence, type and length of the `type` field.
|
// Check the presence, type and length of the `type` field.
|
||||||
@@ -133,7 +131,7 @@ fn extract_optional_string_field<'a>(
|
|||||||
match object.get(field) {
|
match object.get(field) {
|
||||||
| Some(CanonicalJsonValue::String(value)) =>
|
| Some(CanonicalJsonValue::String(value)) =>
|
||||||
if value.len() > ID_MAX_BYTES {
|
if value.len() > ID_MAX_BYTES {
|
||||||
Err!(Request(InvalidParam(
|
Err!(Request(TooLarge(
|
||||||
"invalid `{field}` field in PDU: string length is larger than maximum of \
|
"invalid `{field}` field in PDU: string length is larger than maximum of \
|
||||||
{ID_MAX_BYTES} bytes"
|
{ID_MAX_BYTES} bytes"
|
||||||
)))
|
)))
|
||||||
@@ -177,7 +175,7 @@ fn extract_required_array_field<'a>(
|
|||||||
match object.get(field) {
|
match object.get(field) {
|
||||||
| Some(CanonicalJsonValue::Array(value)) =>
|
| Some(CanonicalJsonValue::Array(value)) =>
|
||||||
if value.len() > max_len {
|
if value.len() > max_len {
|
||||||
Err!(Request(InvalidParam(
|
Err!(Request(TooLarge(
|
||||||
"invalid `{field}` field in PDU: array length is larger than maximum of \
|
"invalid `{field}` field in PDU: array length is larger than maximum of \
|
||||||
{max_len}"
|
{max_len}"
|
||||||
)))
|
)))
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ pub async fn join_remote(
|
|||||||
.server_keys
|
.server_keys
|
||||||
.gen_id_hash_and_sign_event(&mut join_event_stub, &room_version_id)?;
|
.gen_id_hash_and_sign_event(&mut join_event_stub, &room_version_id)?;
|
||||||
|
|
||||||
|
state_res::check_pdu_format(&join_event_stub, &room_version_rules.event_format)?;
|
||||||
|
|
||||||
// It has enough fields to be called a proper event now
|
// It has enough fields to be called a proper event now
|
||||||
let mut join_event = join_event_stub;
|
let mut join_event = join_event_stub;
|
||||||
|
|
||||||
@@ -634,6 +636,8 @@ pub async fn join_local(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let room_version_rules = room_version::rules(&room_version_id)?;
|
||||||
|
|
||||||
let mut join_event_stub: CanonicalJsonObject =
|
let mut join_event_stub: CanonicalJsonObject =
|
||||||
serde_json::from_str(make_join_response.event.get()).map_err(|e| {
|
serde_json::from_str(make_join_response.event.get()).map_err(|e| {
|
||||||
err!(BadServerResponse("Invalid make_join event json received from server: {e:?}"))
|
err!(BadServerResponse("Invalid make_join event json received from server: {e:?}"))
|
||||||
@@ -699,6 +703,8 @@ pub async fn join_local(
|
|||||||
.server_keys
|
.server_keys
|
||||||
.gen_id_hash_and_sign_event(&mut join_event_stub, &room_version_id)?;
|
.gen_id_hash_and_sign_event(&mut join_event_stub, &room_version_id)?;
|
||||||
|
|
||||||
|
state_res::check_pdu_format(&join_event_stub, &room_version_rules.event_format)?;
|
||||||
|
|
||||||
// It has enough fields to be called a proper event now
|
// It has enough fields to be called a proper event now
|
||||||
let join_event = join_event_stub;
|
let join_event = join_event_stub;
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,9 @@ use ruma::{
|
|||||||
};
|
};
|
||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Err, Result, debug_info, debug_warn, err, implement,
|
Err, Result, debug_info, debug_warn, err, implement,
|
||||||
matrix::PduCount,
|
matrix::{PduCount, room_version},
|
||||||
pdu::PduBuilder,
|
pdu::PduBuilder,
|
||||||
|
state_res,
|
||||||
utils::{self, FutureBoolExt, future::ReadyBoolExt},
|
utils::{self, FutureBoolExt, future::ReadyBoolExt},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
@@ -278,6 +279,8 @@ async fn remote_leave(&self, user_id: &UserId, room_id: &RoomId) -> Result {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let room_version_rules = room_version::rules(&room_version_id)?;
|
||||||
|
|
||||||
let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>(
|
let mut leave_event_stub = serde_json::from_str::<CanonicalJsonObject>(
|
||||||
make_leave_response.event.get(),
|
make_leave_response.event.get(),
|
||||||
)
|
)
|
||||||
@@ -312,6 +315,8 @@ async fn remote_leave(&self, user_id: &UserId, room_id: &RoomId) -> Result {
|
|||||||
.server_keys
|
.server_keys
|
||||||
.gen_id_hash_and_sign_event(&mut leave_event_stub, &room_version_id)?;
|
.gen_id_hash_and_sign_event(&mut leave_event_stub, &room_version_id)?;
|
||||||
|
|
||||||
|
state_res::check_pdu_format(&leave_event_stub, &room_version_rules.event_format)?;
|
||||||
|
|
||||||
// It has enough fields to be called a proper event now
|
// It has enough fields to be called a proper event now
|
||||||
let leave_event = leave_event_stub;
|
let leave_event = leave_event_stub;
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ pub(super) async fn handle_outlier_pdu(
|
|||||||
|
|
||||||
let room_rules = room_version::rules(room_version)?;
|
let room_rules = room_version::rules(room_version)?;
|
||||||
|
|
||||||
|
state_res::check_pdu_format(&pdu_json, &room_rules.event_format)?;
|
||||||
|
|
||||||
// Now that we have checked the signature and hashes we can make mutations and
|
// Now that we have checked the signature and hashes we can make mutations and
|
||||||
// convert to our PduEvent type.
|
// convert to our PduEvent type.
|
||||||
let event = from_incoming_federation(room_id, event_id, &mut pdu_json, &room_rules)?;
|
let event = from_incoming_federation(room_id, event_id, &mut pdu_json, &room_rules)?;
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ pub(super) async fn upgrade_outlier_to_timeline_pdu(
|
|||||||
let timer = Instant::now();
|
let timer = Instant::now();
|
||||||
let room_rules = room_version::rules(room_version)?;
|
let room_rules = room_version::rules(room_version)?;
|
||||||
|
|
||||||
|
state_res::check_pdu_format(&val, &room_rules.event_format)?;
|
||||||
|
|
||||||
// 10. Fetch missing state and auth chain events by calling /state_ids at
|
// 10. Fetch missing state and auth chain events by calling /state_ids at
|
||||||
// backwards extremities doing all the checks in this list starting at 1.
|
// backwards extremities doing all the checks in this list starting at 1.
|
||||||
// These are not timeline events.
|
// These are not timeline events.
|
||||||
|
|||||||
@@ -187,17 +187,7 @@ pub async fn create_hash_and_sign_event(
|
|||||||
pdu.event_id = self
|
pdu.event_id = self
|
||||||
.services
|
.services
|
||||||
.server_keys
|
.server_keys
|
||||||
.gen_id_hash_and_sign_event(&mut pdu_json, &room_version)
|
.gen_id_hash_and_sign_event(&mut pdu_json, &room_version)?;
|
||||||
.map_err(|e| {
|
|
||||||
use Error::Signatures;
|
|
||||||
use ruma::signatures::Error::PduSize;
|
|
||||||
match e {
|
|
||||||
| Signatures(PduSize) => {
|
|
||||||
err!(Request(TooLarge("PDU exceeds 65535 bytes")))
|
|
||||||
},
|
|
||||||
| _ => err!(Request(Unknown(warn!("Signing event failed: {e}")))),
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Room id is event id for V12+
|
// Room id is event id for V12+
|
||||||
if matches!(version_rules.room_id_format, RoomIdFormatVersion::V2)
|
if matches!(version_rules.room_id_format, RoomIdFormatVersion::V2)
|
||||||
@@ -207,6 +197,8 @@ pub async fn create_hash_and_sign_event(
|
|||||||
pdu_json.insert("room_id".into(), CanonicalJsonValue::String(pdu.room_id.clone().into()));
|
pdu_json.insert("room_id".into(), CanonicalJsonValue::String(pdu.room_id.clone().into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state_res::check_pdu_format(&pdu_json, &version_rules.event_format)?;
|
||||||
|
|
||||||
// Generate short event id
|
// Generate short event id
|
||||||
let _shorteventid = self
|
let _shorteventid = self
|
||||||
.services
|
.services
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomVersionId};
|
use ruma::{CanonicalJsonObject, CanonicalJsonValue, OwnedEventId, RoomVersionId};
|
||||||
use tuwunel_core::{
|
use tuwunel_core::{
|
||||||
Result, implement,
|
Result, err, implement,
|
||||||
matrix::{event::gen_event_id, room_version},
|
matrix::{event::gen_event_id, room_version},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,7 +73,15 @@ pub fn hash_and_sign_event(
|
|||||||
object,
|
object,
|
||||||
&room_version_rules.redaction,
|
&room_version_rules.redaction,
|
||||||
)
|
)
|
||||||
.map_err(Into::into)
|
.map_err(|e| {
|
||||||
|
use ruma::signatures::Error::PduSize;
|
||||||
|
match e {
|
||||||
|
| PduSize => {
|
||||||
|
err!(Request(TooLarge("PDU exceeds 65535 bytes")))
|
||||||
|
},
|
||||||
|
| _ => err!(Request(Unknown(warn!("Signing event failed: {e}")))),
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[implement(super::Service)]
|
#[implement(super::Service)]
|
||||||
|
|||||||
Reference in New Issue
Block a user