Refactor server_keys service/interface and related callsites

Signed-off-by: Jason Volk <jason@zemos.net>
Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
Jason Volk 2024-10-11 18:57:59 +00:00 committed by strawberry
parent d82ea331cf
commit c0939c3e9a
30 changed files with 1025 additions and 1378 deletions

View file

@ -1,16 +1,9 @@
use std::{
collections::BTreeMap,
sync::{Arc, RwLock},
};
use std::sync::{Arc, RwLock};
use conduit::{trace, utils, utils::rand, Error, Result, Server};
use database::{Database, Deserialized, Json, Map};
use conduit::{trace, utils, Result, Server};
use database::{Database, Deserialized, Map};
use futures::{pin_mut, stream::FuturesUnordered, FutureExt, StreamExt};
use ruma::{
api::federation::discovery::{ServerSigningKeys, VerifyKey},
signatures::Ed25519KeyPair,
DeviceId, MilliSecondsSinceUnixEpoch, OwnedServerSigningKeyId, ServerName, UserId,
};
use ruma::{DeviceId, UserId};
use crate::{rooms, Dep};
@ -25,7 +18,6 @@ pub struct Data {
pduid_pdu: Arc<Map>,
keychangeid_userid: Arc<Map>,
roomusertype_roomuserdataid: Arc<Map>,
server_signingkeys: Arc<Map>,
readreceiptid_readreceipt: Arc<Map>,
userid_lastonetimekeyupdate: Arc<Map>,
counter: RwLock<u64>,
@ -56,7 +48,6 @@ impl Data {
pduid_pdu: db["pduid_pdu"].clone(),
keychangeid_userid: db["keychangeid_userid"].clone(),
roomusertype_roomuserdataid: db["roomusertype_roomuserdataid"].clone(),
server_signingkeys: db["server_signingkeys"].clone(),
readreceiptid_readreceipt: db["readreceiptid_readreceipt"].clone(),
userid_lastonetimekeyupdate: db["userid_lastonetimekeyupdate"].clone(),
counter: RwLock::new(Self::stored_count(&db["global"]).expect("initialized global counter")),
@ -205,107 +196,6 @@ impl Data {
Ok(())
}
pub fn load_keypair(&self) -> Result<Ed25519KeyPair> {
let generate = |_| {
let keypair = Ed25519KeyPair::generate().expect("Ed25519KeyPair generation always works (?)");
let mut value = rand::string(8).as_bytes().to_vec();
value.push(0xFF);
value.extend_from_slice(&keypair);
self.global.insert(b"keypair", &value);
value
};
let keypair_bytes: Vec<u8> = self
.global
.get_blocking(b"keypair")
.map_or_else(generate, Into::into);
let mut parts = keypair_bytes.splitn(2, |&b| b == 0xFF);
utils::string_from_bytes(
// 1. version
parts
.next()
.expect("splitn always returns at least one element"),
)
.map_err(|_| Error::bad_database("Invalid version bytes in keypair."))
.and_then(|version| {
// 2. key
parts
.next()
.ok_or_else(|| Error::bad_database("Invalid keypair format in database."))
.map(|key| (version, key))
})
.and_then(|(version, key)| {
Ed25519KeyPair::from_der(key, version)
.map_err(|_| Error::bad_database("Private or public keys are invalid."))
})
}
#[inline]
pub fn remove_keypair(&self) -> Result<()> {
self.global.remove(b"keypair");
Ok(())
}
/// TODO: the key valid until timestamp (`valid_until_ts`) is only honored
/// in room version > 4
///
/// Remove the outdated keys and insert the new ones.
///
/// This doesn't actually check that the keys provided are newer than the
/// old set.
pub async fn add_signing_key(
&self, origin: &ServerName, new_keys: ServerSigningKeys,
) -> BTreeMap<OwnedServerSigningKeyId, VerifyKey> {
// (timo) Not atomic, but this is not critical
let mut keys: ServerSigningKeys = self
.server_signingkeys
.get(origin)
.await
.deserialized()
.unwrap_or_else(|_| {
// Just insert "now", it doesn't matter
ServerSigningKeys::new(origin.to_owned(), MilliSecondsSinceUnixEpoch::now())
});
keys.verify_keys.extend(new_keys.verify_keys);
keys.old_verify_keys.extend(new_keys.old_verify_keys);
self.server_signingkeys.raw_put(origin, Json(&keys));
let mut tree = keys.verify_keys;
tree.extend(
keys.old_verify_keys
.into_iter()
.map(|old| (old.0, VerifyKey::new(old.1.key))),
);
tree
}
/// This returns an empty `Ok(BTreeMap<..>)` when there are no keys found
/// for the server.
pub async fn verify_keys_for(&self, origin: &ServerName) -> Result<BTreeMap<OwnedServerSigningKeyId, VerifyKey>> {
self.signing_keys_for(origin).await.map_or_else(
|_| Ok(BTreeMap::new()),
|keys: ServerSigningKeys| {
let mut tree = keys.verify_keys;
tree.extend(
keys.old_verify_keys
.into_iter()
.map(|old| (old.0, VerifyKey::new(old.1.key))),
);
Ok(tree)
},
)
}
pub async fn signing_keys_for(&self, origin: &ServerName) -> Result<ServerSigningKeys> {
self.server_signingkeys.get(origin).await.deserialized()
}
pub async fn database_version(&self) -> u64 {
self.global
.get(b"version")