mirror of
https://gitlab.com/famedly/conduit.git
synced 2025-06-27 16:35:59 +00:00
fix: don't perform UIA when uploading cross-signing keys for the first time
as per MSC3967
This commit is contained in:
parent
263bc61ec8
commit
1ea5f412b6
1 changed files with 96 additions and 7 deletions
|
@ -21,7 +21,7 @@ use std::{
|
||||||
collections::{hash_map, BTreeMap, HashMap, HashSet},
|
collections::{hash_map, BTreeMap, HashMap, HashSet},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tracing::debug;
|
use tracing::{debug, error};
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/upload`
|
/// # `POST /_matrix/client/r0/keys/upload`
|
||||||
///
|
///
|
||||||
|
@ -128,12 +128,101 @@ pub async fn upload_signing_keys_route(
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
}
|
}
|
||||||
// Success!
|
// Success!
|
||||||
} else if let Some(json) = body.json_body {
|
} else if let Some(json) = &body.json_body {
|
||||||
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
// Checks whether the request contains keys that are not currently stored in the database,
|
||||||
services()
|
// as per [MSC3967](https://github.com/matrix-org/matrix-spec-proposals/pull/3967).
|
||||||
.uiaa
|
let req_has_new_keys = || -> Result<bool> {
|
||||||
.create(sender_user, sender_device, &uiaainfo, &json)?;
|
if let Some(master_key) = &body.master_key {
|
||||||
return Err(Error::Uiaa(uiaainfo));
|
let new_keys = master_key
|
||||||
|
.deserialize()
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid master key"))?
|
||||||
|
.keys;
|
||||||
|
let current_keys = services()
|
||||||
|
.users
|
||||||
|
.get_self_signing_key(None, sender_user, &|u| u == sender_user)?
|
||||||
|
.map(|raw| raw.deserialize())
|
||||||
|
.transpose()
|
||||||
|
.map_err(|_| {
|
||||||
|
error!("Invalid master key in database for user {sender_user}");
|
||||||
|
Error::BadDatabase("Invalid master key in database")
|
||||||
|
})?
|
||||||
|
.map(|keys| keys.keys);
|
||||||
|
|
||||||
|
// Master key in database must match exactly with the one provided in the request
|
||||||
|
if Some(new_keys) != current_keys {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(self_signing_keys) = &body.self_signing_key {
|
||||||
|
let new_keys = self_signing_keys
|
||||||
|
.deserialize()
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid self-signing keys")
|
||||||
|
})?
|
||||||
|
.keys;
|
||||||
|
let current_keys = services()
|
||||||
|
.users
|
||||||
|
.get_self_signing_key(None, sender_user, &|u| u == sender_user)?
|
||||||
|
.map(|raw| raw.deserialize())
|
||||||
|
.transpose()
|
||||||
|
.map_err(|_| {
|
||||||
|
error!("Invalid self-signing keys in database for user {sender_user}");
|
||||||
|
Error::BadDatabase("Invalid self-signing keys in database")
|
||||||
|
})?
|
||||||
|
.map(|keys| keys.keys)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// For the other keys, we only need to ensure that there are no new keys
|
||||||
|
for (key, value) in new_keys {
|
||||||
|
if current_keys.get(&key).is_none_or(|v| v != &value) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(user_signing_keys) = &body.user_signing_key {
|
||||||
|
let new_keys = user_signing_keys
|
||||||
|
.deserialize()
|
||||||
|
.map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid user-signing keys")
|
||||||
|
})?
|
||||||
|
.keys;
|
||||||
|
let current_keys = services()
|
||||||
|
.users
|
||||||
|
.get_user_signing_key(sender_user)?
|
||||||
|
.map(|raw| raw.deserialize())
|
||||||
|
.transpose()
|
||||||
|
.map_err(|_| {
|
||||||
|
error!("Invalid user-signing keys in database for user {sender_user}");
|
||||||
|
Error::BadDatabase("Invalid user-signing keys in database")
|
||||||
|
})?
|
||||||
|
.map(|keys| keys.keys)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// same as self-signing keys above
|
||||||
|
for (key, value) in new_keys {
|
||||||
|
if current_keys.get(&key).is_none_or(|v| v != &value) {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(false)
|
||||||
|
};
|
||||||
|
|
||||||
|
if services()
|
||||||
|
.users
|
||||||
|
.get_master_key(None, sender_user, &|u| u == sender_user)?
|
||||||
|
.is_some()
|
||||||
|
&& req_has_new_keys()?
|
||||||
|
{
|
||||||
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
||||||
|
services()
|
||||||
|
.uiaa
|
||||||
|
.create(sender_user, sender_device, &uiaainfo, json)?;
|
||||||
|
return Err(Error::Uiaa(uiaainfo));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
return Err(Error::BadRequest(ErrorKind::NotJson, "Not json."));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue