|
|
|
@ -8,7 +8,12 @@ use ruma::{ |
|
|
|
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, RoomAliasId, UInt, |
|
|
|
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MilliSecondsSinceUnixEpoch, RoomAliasId, UInt, |
|
|
|
UserId, |
|
|
|
UserId, |
|
|
|
}; |
|
|
|
}; |
|
|
|
use std::{collections::BTreeMap, convert::TryInto, mem, sync::Arc}; |
|
|
|
use std::{ |
|
|
|
|
|
|
|
collections::BTreeMap, |
|
|
|
|
|
|
|
convert::{TryFrom, TryInto}, |
|
|
|
|
|
|
|
mem, |
|
|
|
|
|
|
|
sync::Arc, |
|
|
|
|
|
|
|
}; |
|
|
|
use tracing::warn; |
|
|
|
use tracing::warn; |
|
|
|
|
|
|
|
|
|
|
|
use super::abstraction::Tree; |
|
|
|
use super::abstraction::Tree; |
|
|
|
@ -359,7 +364,7 @@ impl Users { |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
device_id: &DeviceId, |
|
|
|
device_id: &DeviceId, |
|
|
|
one_time_key_key: &DeviceKeyId, |
|
|
|
one_time_key_key: &DeviceKeyId, |
|
|
|
one_time_key_value: &OneTimeKey, |
|
|
|
one_time_key_value: &Raw<OneTimeKey>, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
) -> Result<()> { |
|
|
|
) -> Result<()> { |
|
|
|
let mut key = user_id.as_bytes().to_vec(); |
|
|
|
let mut key = user_id.as_bytes().to_vec(); |
|
|
|
@ -409,7 +414,7 @@ impl Users { |
|
|
|
device_id: &DeviceId, |
|
|
|
device_id: &DeviceId, |
|
|
|
key_algorithm: &DeviceKeyAlgorithm, |
|
|
|
key_algorithm: &DeviceKeyAlgorithm, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
) -> Result<Option<(Box<DeviceKeyId>, OneTimeKey)>> { |
|
|
|
) -> Result<Option<(Box<DeviceKeyId>, Raw<OneTimeKey>)>> { |
|
|
|
let mut prefix = user_id.as_bytes().to_vec(); |
|
|
|
let mut prefix = user_id.as_bytes().to_vec(); |
|
|
|
prefix.push(0xff); |
|
|
|
prefix.push(0xff); |
|
|
|
prefix.extend_from_slice(device_id.as_bytes()); |
|
|
|
prefix.extend_from_slice(device_id.as_bytes()); |
|
|
|
@ -480,7 +485,7 @@ impl Users { |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
device_id: &DeviceId, |
|
|
|
device_id: &DeviceId, |
|
|
|
device_keys: &DeviceKeys, |
|
|
|
device_keys: &Raw<DeviceKeys>, |
|
|
|
rooms: &super::rooms::Rooms, |
|
|
|
rooms: &super::rooms::Rooms, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
) -> Result<()> { |
|
|
|
) -> Result<()> { |
|
|
|
@ -509,9 +514,9 @@ impl Users { |
|
|
|
pub fn add_cross_signing_keys( |
|
|
|
pub fn add_cross_signing_keys( |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
master_key: &CrossSigningKey, |
|
|
|
master_key: &Raw<CrossSigningKey>, |
|
|
|
self_signing_key: &Option<CrossSigningKey>, |
|
|
|
self_signing_key: &Option<Raw<CrossSigningKey>>, |
|
|
|
user_signing_key: &Option<CrossSigningKey>, |
|
|
|
user_signing_key: &Option<Raw<CrossSigningKey>>, |
|
|
|
rooms: &super::rooms::Rooms, |
|
|
|
rooms: &super::rooms::Rooms, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
globals: &super::globals::Globals, |
|
|
|
) -> Result<()> { |
|
|
|
) -> Result<()> { |
|
|
|
@ -521,7 +526,12 @@ impl Users { |
|
|
|
prefix.push(0xff); |
|
|
|
prefix.push(0xff); |
|
|
|
|
|
|
|
|
|
|
|
// Master key
|
|
|
|
// Master key
|
|
|
|
let mut master_key_ids = master_key.keys.values(); |
|
|
|
let master_key_map = master_key |
|
|
|
|
|
|
|
.deserialize() |
|
|
|
|
|
|
|
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid master key"))? |
|
|
|
|
|
|
|
.keys; |
|
|
|
|
|
|
|
let mut master_key_ids = master_key_map.values(); |
|
|
|
|
|
|
|
|
|
|
|
let master_key_id = master_key_ids.next().ok_or(Error::BadRequest( |
|
|
|
let master_key_id = master_key_ids.next().ok_or(Error::BadRequest( |
|
|
|
ErrorKind::InvalidParam, |
|
|
|
ErrorKind::InvalidParam, |
|
|
|
"Master key contained no key.", |
|
|
|
"Master key contained no key.", |
|
|
|
@ -537,17 +547,21 @@ impl Users { |
|
|
|
let mut master_key_key = prefix.clone(); |
|
|
|
let mut master_key_key = prefix.clone(); |
|
|
|
master_key_key.extend_from_slice(master_key_id.as_bytes()); |
|
|
|
master_key_key.extend_from_slice(master_key_id.as_bytes()); |
|
|
|
|
|
|
|
|
|
|
|
self.keyid_key.insert( |
|
|
|
self.keyid_key |
|
|
|
&master_key_key, |
|
|
|
.insert(&master_key_key, master_key.json().get().as_bytes())?; |
|
|
|
&serde_json::to_vec(&master_key).expect("CrossSigningKey::to_vec always works"), |
|
|
|
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.userid_masterkeyid |
|
|
|
self.userid_masterkeyid |
|
|
|
.insert(user_id.as_bytes(), &master_key_key)?; |
|
|
|
.insert(user_id.as_bytes(), &master_key_key)?; |
|
|
|
|
|
|
|
|
|
|
|
// Self-signing key
|
|
|
|
// Self-signing key
|
|
|
|
if let Some(self_signing_key) = self_signing_key { |
|
|
|
if let Some(self_signing_key) = self_signing_key { |
|
|
|
let mut self_signing_key_ids = self_signing_key.keys.values(); |
|
|
|
let self_signing_key_map = self_signing_key |
|
|
|
|
|
|
|
.deserialize() |
|
|
|
|
|
|
|
.map_err(|_| { |
|
|
|
|
|
|
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid self signing key") |
|
|
|
|
|
|
|
})? |
|
|
|
|
|
|
|
.keys; |
|
|
|
|
|
|
|
let mut self_signing_key_ids = self_signing_key_map.values(); |
|
|
|
let self_signing_key_id = self_signing_key_ids.next().ok_or(Error::BadRequest( |
|
|
|
let self_signing_key_id = self_signing_key_ids.next().ok_or(Error::BadRequest( |
|
|
|
ErrorKind::InvalidParam, |
|
|
|
ErrorKind::InvalidParam, |
|
|
|
"Self signing key contained no key.", |
|
|
|
"Self signing key contained no key.", |
|
|
|
@ -565,8 +579,7 @@ impl Users { |
|
|
|
|
|
|
|
|
|
|
|
self.keyid_key.insert( |
|
|
|
self.keyid_key.insert( |
|
|
|
&self_signing_key_key, |
|
|
|
&self_signing_key_key, |
|
|
|
&serde_json::to_vec(&self_signing_key) |
|
|
|
self_signing_key.json().get().as_bytes(), |
|
|
|
.expect("CrossSigningKey::to_vec always works"), |
|
|
|
|
|
|
|
)?; |
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
self.userid_selfsigningkeyid |
|
|
|
self.userid_selfsigningkeyid |
|
|
|
@ -575,7 +588,13 @@ impl Users { |
|
|
|
|
|
|
|
|
|
|
|
// User-signing key
|
|
|
|
// User-signing key
|
|
|
|
if let Some(user_signing_key) = user_signing_key { |
|
|
|
if let Some(user_signing_key) = user_signing_key { |
|
|
|
let mut user_signing_key_ids = user_signing_key.keys.values(); |
|
|
|
let user_signing_key_map = user_signing_key |
|
|
|
|
|
|
|
.deserialize() |
|
|
|
|
|
|
|
.map_err(|_| { |
|
|
|
|
|
|
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid user signing key") |
|
|
|
|
|
|
|
})? |
|
|
|
|
|
|
|
.keys; |
|
|
|
|
|
|
|
let mut user_signing_key_ids = user_signing_key_map.values(); |
|
|
|
let user_signing_key_id = user_signing_key_ids.next().ok_or(Error::BadRequest( |
|
|
|
let user_signing_key_id = user_signing_key_ids.next().ok_or(Error::BadRequest( |
|
|
|
ErrorKind::InvalidParam, |
|
|
|
ErrorKind::InvalidParam, |
|
|
|
"User signing key contained no key.", |
|
|
|
"User signing key contained no key.", |
|
|
|
@ -593,8 +612,7 @@ impl Users { |
|
|
|
|
|
|
|
|
|
|
|
self.keyid_key.insert( |
|
|
|
self.keyid_key.insert( |
|
|
|
&user_signing_key_key, |
|
|
|
&user_signing_key_key, |
|
|
|
&serde_json::to_vec(&user_signing_key) |
|
|
|
user_signing_key.json().get().as_bytes(), |
|
|
|
.expect("CrossSigningKey::to_vec always works"), |
|
|
|
|
|
|
|
)?; |
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
|
|
self.userid_usersigningkeyid |
|
|
|
self.userid_usersigningkeyid |
|
|
|
@ -727,7 +745,7 @@ impl Users { |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
device_id: &DeviceId, |
|
|
|
device_id: &DeviceId, |
|
|
|
) -> Result<Option<DeviceKeys>> { |
|
|
|
) -> Result<Option<Raw<DeviceKeys>>> { |
|
|
|
let mut key = user_id.as_bytes().to_vec(); |
|
|
|
let mut key = user_id.as_bytes().to_vec(); |
|
|
|
key.push(0xff); |
|
|
|
key.push(0xff); |
|
|
|
key.extend_from_slice(device_id.as_bytes()); |
|
|
|
key.extend_from_slice(device_id.as_bytes()); |
|
|
|
@ -744,25 +762,19 @@ impl Users { |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
allowed_signatures: F, |
|
|
|
allowed_signatures: F, |
|
|
|
) -> Result<Option<CrossSigningKey>> { |
|
|
|
) -> Result<Option<Raw<CrossSigningKey>>> { |
|
|
|
self.userid_masterkeyid |
|
|
|
self.userid_masterkeyid |
|
|
|
.get(user_id.as_bytes())? |
|
|
|
.get(user_id.as_bytes())? |
|
|
|
.map_or(Ok(None), |key| { |
|
|
|
.map_or(Ok(None), |key| { |
|
|
|
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| { |
|
|
|
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| { |
|
|
|
let mut cross_signing_key = serde_json::from_slice::<CrossSigningKey>(&bytes) |
|
|
|
let mut cross_signing_key = serde_json::from_slice::<serde_json::Value>(&bytes) |
|
|
|
.map_err(|_| { |
|
|
|
.map_err(|_| Error::bad_database("CrossSigningKey in db is invalid."))?; |
|
|
|
Error::bad_database("CrossSigningKey in db is invalid.") |
|
|
|
clean_signatures(&mut cross_signing_key, user_id, allowed_signatures)?; |
|
|
|
})?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A user is not allowed to see signatures from users other than himself and
|
|
|
|
Ok(Some(Raw::from_json( |
|
|
|
// the target user
|
|
|
|
serde_json::value::to_raw_value(&cross_signing_key) |
|
|
|
cross_signing_key.signatures = cross_signing_key |
|
|
|
.expect("Value to RawValue serialization"), |
|
|
|
.signatures |
|
|
|
))) |
|
|
|
.into_iter() |
|
|
|
|
|
|
|
.filter(|(user, _)| allowed_signatures(user)) |
|
|
|
|
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(Some(cross_signing_key)) |
|
|
|
|
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
@ -772,31 +784,25 @@ impl Users { |
|
|
|
&self, |
|
|
|
&self, |
|
|
|
user_id: &UserId, |
|
|
|
user_id: &UserId, |
|
|
|
allowed_signatures: F, |
|
|
|
allowed_signatures: F, |
|
|
|
) -> Result<Option<CrossSigningKey>> { |
|
|
|
) -> Result<Option<Raw<CrossSigningKey>>> { |
|
|
|
self.userid_selfsigningkeyid |
|
|
|
self.userid_selfsigningkeyid |
|
|
|
.get(user_id.as_bytes())? |
|
|
|
.get(user_id.as_bytes())? |
|
|
|
.map_or(Ok(None), |key| { |
|
|
|
.map_or(Ok(None), |key| { |
|
|
|
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| { |
|
|
|
self.keyid_key.get(&key)?.map_or(Ok(None), |bytes| { |
|
|
|
let mut cross_signing_key = serde_json::from_slice::<CrossSigningKey>(&bytes) |
|
|
|
let mut cross_signing_key = serde_json::from_slice::<serde_json::Value>(&bytes) |
|
|
|
.map_err(|_| { |
|
|
|
.map_err(|_| Error::bad_database("CrossSigningKey in db is invalid."))?; |
|
|
|
Error::bad_database("CrossSigningKey in db is invalid.") |
|
|
|
clean_signatures(&mut cross_signing_key, user_id, allowed_signatures)?; |
|
|
|
})?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// A user is not allowed to see signatures from users other than himself and
|
|
|
|
Ok(Some(Raw::from_json( |
|
|
|
// the target user
|
|
|
|
serde_json::value::to_raw_value(&cross_signing_key) |
|
|
|
cross_signing_key.signatures = cross_signing_key |
|
|
|
.expect("Value to RawValue serialization"), |
|
|
|
.signatures |
|
|
|
))) |
|
|
|
.into_iter() |
|
|
|
|
|
|
|
.filter(|(user, _)| user == user_id || allowed_signatures(user)) |
|
|
|
|
|
|
|
.collect(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(Some(cross_signing_key)) |
|
|
|
|
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[tracing::instrument(skip(self, user_id))] |
|
|
|
#[tracing::instrument(skip(self, user_id))] |
|
|
|
pub fn get_user_signing_key(&self, user_id: &UserId) -> Result<Option<CrossSigningKey>> { |
|
|
|
pub fn get_user_signing_key(&self, user_id: &UserId) -> Result<Option<Raw<CrossSigningKey>>> { |
|
|
|
self.userid_usersigningkeyid |
|
|
|
self.userid_usersigningkeyid |
|
|
|
.get(user_id.as_bytes())? |
|
|
|
.get(user_id.as_bytes())? |
|
|
|
.map_or(Ok(None), |key| { |
|
|
|
.map_or(Ok(None), |key| { |
|
|
|
@ -991,3 +997,30 @@ impl Users { |
|
|
|
Ok(()) |
|
|
|
Ok(()) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Ensure that a user only sees signatures from themselves and the target user
|
|
|
|
|
|
|
|
fn clean_signatures<F: Fn(&UserId) -> bool>( |
|
|
|
|
|
|
|
cross_signing_key: &mut serde_json::Value, |
|
|
|
|
|
|
|
user_id: &UserId, |
|
|
|
|
|
|
|
allowed_signatures: F, |
|
|
|
|
|
|
|
) -> Result<(), Error> { |
|
|
|
|
|
|
|
if let Some(signatures) = cross_signing_key |
|
|
|
|
|
|
|
.get_mut("signatures") |
|
|
|
|
|
|
|
.and_then(|v| v.as_object_mut()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Don't allocate for the full size of the current signatures, but require
|
|
|
|
|
|
|
|
// at most one resize if nothing is dropped
|
|
|
|
|
|
|
|
let new_capacity = signatures.len() / 2; |
|
|
|
|
|
|
|
for (user, signature) in |
|
|
|
|
|
|
|
mem::replace(signatures, serde_json::Map::with_capacity(new_capacity)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
let id = <&UserId>::try_from(user.as_str()) |
|
|
|
|
|
|
|
.map_err(|_| Error::bad_database("Invalid user ID in database."))?; |
|
|
|
|
|
|
|
if id == user_id || allowed_signatures(id) { |
|
|
|
|
|
|
|
signatures.insert(user, signature); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
|
|
|
} |
|
|
|
|