2020-12-05 20:03:43 +00:00
|
|
|
use crate::{database::Config, utils, Error, Result};
|
2020-09-15 19:46:10 +00:00
|
|
|
use log::error;
|
2021-01-15 02:32:22 +00:00
|
|
|
use ruma::{
|
|
|
|
api::federation::discovery::{ServerSigningKeys, VerifyKey},
|
|
|
|
ServerName, ServerSigningKeyId,
|
|
|
|
};
|
|
|
|
use std::collections::{BTreeMap, HashMap};
|
2020-12-05 20:03:43 +00:00
|
|
|
use std::sync::Arc;
|
2020-12-06 10:05:51 +00:00
|
|
|
use std::sync::RwLock;
|
2020-12-19 15:00:11 +00:00
|
|
|
use std::time::Duration;
|
2020-12-08 09:33:44 +00:00
|
|
|
use trust_dns_resolver::TokioAsyncResolver;
|
2020-07-24 03:03:24 +00:00
|
|
|
|
2020-05-03 15:25:31 +00:00
|
|
|
pub const COUNTER: &str = "c";
|
|
|
|
|
2021-03-04 12:35:12 +00:00
|
|
|
type WellKnownMap = HashMap<Box<ServerName>, (String, Option<String>)>;
|
2021-01-05 14:21:41 +00:00
|
|
|
|
2020-09-15 14:13:54 +00:00
|
|
|
#[derive(Clone)]
|
2020-05-03 15:25:31 +00:00
|
|
|
pub struct Globals {
|
2021-03-04 12:35:12 +00:00
|
|
|
pub actual_destination_cache: Arc<RwLock<WellKnownMap>>, // actual_destination, host
|
2020-05-03 15:25:31 +00:00
|
|
|
pub(super) globals: sled::Tree,
|
2020-12-06 10:05:51 +00:00
|
|
|
config: Config,
|
2020-09-15 14:13:54 +00:00
|
|
|
keypair: Arc<ruma::signatures::Ed25519KeyPair>,
|
2020-05-03 15:25:31 +00:00
|
|
|
reqwest_client: reqwest::Client,
|
2020-12-06 10:05:51 +00:00
|
|
|
dns_resolver: TokioAsyncResolver,
|
2021-02-07 16:38:45 +00:00
|
|
|
jwt_decoding_key: Option<jsonwebtoken::DecodingKey<'static>>,
|
2021-01-15 02:32:22 +00:00
|
|
|
pub(super) servertimeout_signingkey: sled::Tree, // ServerName -> algorithm:key + pubkey
|
2020-05-03 15:25:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Globals {
|
2021-02-04 01:00:01 +00:00
|
|
|
pub fn load(
|
|
|
|
globals: sled::Tree,
|
|
|
|
servertimeout_signingkey: sled::Tree,
|
|
|
|
config: Config,
|
|
|
|
) -> Result<Self> {
|
2020-09-15 19:46:10 +00:00
|
|
|
let bytes = &*globals
|
|
|
|
.update_and_fetch("keypair", utils::generate_keypair)?
|
|
|
|
.expect("utils::generate_keypair always returns Some");
|
|
|
|
|
|
|
|
let mut parts = bytes.splitn(2, |&b| b == 0xff);
|
|
|
|
|
|
|
|
let keypair = 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)| {
|
|
|
|
ruma::signatures::Ed25519KeyPair::new(&key, version)
|
|
|
|
.map_err(|_| Error::bad_database("Private or public keys are invalid."))
|
|
|
|
});
|
|
|
|
|
|
|
|
let keypair = match keypair {
|
|
|
|
Ok(k) => k,
|
|
|
|
Err(e) => {
|
|
|
|
error!("Keypair invalid. Deleting...");
|
|
|
|
globals.remove("keypair")?;
|
|
|
|
return Err(e);
|
|
|
|
}
|
|
|
|
};
|
2020-05-03 15:25:31 +00:00
|
|
|
|
2020-12-19 15:00:11 +00:00
|
|
|
let reqwest_client = reqwest::Client::builder()
|
|
|
|
.connect_timeout(Duration::from_secs(30))
|
|
|
|
.timeout(Duration::from_secs(60 * 3))
|
|
|
|
.pool_max_idle_per_host(1)
|
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
|
2021-02-07 16:38:45 +00:00
|
|
|
let jwt_decoding_key = config
|
|
|
|
.jwt_secret
|
|
|
|
.as_ref()
|
|
|
|
.map(|secret| jsonwebtoken::DecodingKey::from_secret(secret.as_bytes()).into_static());
|
|
|
|
|
2020-06-09 13:13:17 +00:00
|
|
|
Ok(Self {
|
2020-05-03 15:25:31 +00:00
|
|
|
globals,
|
2020-12-06 10:05:51 +00:00
|
|
|
config,
|
2020-09-15 19:46:10 +00:00
|
|
|
keypair: Arc::new(keypair),
|
2020-12-19 15:00:11 +00:00
|
|
|
reqwest_client,
|
2021-01-29 16:20:33 +00:00
|
|
|
dns_resolver: TokioAsyncResolver::tokio_from_system_conf().map_err(|_| {
|
|
|
|
Error::bad_config("Failed to set up trust dns resolver with system config.")
|
|
|
|
})?,
|
2020-12-06 10:05:51 +00:00
|
|
|
actual_destination_cache: Arc::new(RwLock::new(HashMap::new())),
|
2021-02-07 16:38:45 +00:00
|
|
|
jwt_decoding_key,
|
2021-02-04 01:00:01 +00:00
|
|
|
servertimeout_signingkey,
|
2020-06-09 13:13:17 +00:00
|
|
|
})
|
2020-05-03 15:25:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns this server's keypair.
|
2020-06-05 16:19:26 +00:00
|
|
|
pub fn keypair(&self) -> &ruma::signatures::Ed25519KeyPair {
|
2020-05-03 15:25:31 +00:00
|
|
|
&self.keypair
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a reqwest client which can be used to send requests.
|
|
|
|
pub fn reqwest_client(&self) -> &reqwest::Client {
|
|
|
|
&self.reqwest_client
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_count(&self) -> Result<u64> {
|
|
|
|
Ok(utils::u64_from_bytes(
|
|
|
|
&self
|
|
|
|
.globals
|
|
|
|
.update_and_fetch(COUNTER, utils::increment)?
|
|
|
|
.expect("utils::increment will always put in a value"),
|
2020-06-09 13:13:17 +00:00
|
|
|
)
|
2020-06-11 08:03:08 +00:00
|
|
|
.map_err(|_| Error::bad_database("Count has invalid bytes."))?)
|
2020-05-03 15:25:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn current_count(&self) -> Result<u64> {
|
2020-06-09 13:13:17 +00:00
|
|
|
self.globals.get(COUNTER)?.map_or(Ok(0_u64), |bytes| {
|
|
|
|
Ok(utils::u64_from_bytes(&bytes)
|
2020-06-11 08:03:08 +00:00
|
|
|
.map_err(|_| Error::bad_database("Count has invalid bytes."))?)
|
2020-06-09 13:13:17 +00:00
|
|
|
})
|
2020-05-03 15:25:31 +00:00
|
|
|
}
|
2020-06-06 17:02:31 +00:00
|
|
|
|
2020-07-17 20:00:39 +00:00
|
|
|
pub fn server_name(&self) -> &ServerName {
|
2020-12-05 20:03:43 +00:00
|
|
|
self.config.server_name.as_ref()
|
2020-06-06 17:02:31 +00:00
|
|
|
}
|
|
|
|
|
2020-07-24 03:03:24 +00:00
|
|
|
pub fn max_request_size(&self) -> u32 {
|
2020-12-05 20:03:43 +00:00
|
|
|
self.config.max_request_size
|
2020-07-24 03:03:24 +00:00
|
|
|
}
|
|
|
|
|
2021-01-01 12:47:53 +00:00
|
|
|
pub fn allow_registration(&self) -> bool {
|
|
|
|
self.config.allow_registration
|
2020-06-06 17:02:31 +00:00
|
|
|
}
|
2020-07-26 18:41:10 +00:00
|
|
|
|
2021-01-01 12:47:53 +00:00
|
|
|
pub fn allow_encryption(&self) -> bool {
|
|
|
|
self.config.allow_encryption
|
2020-07-26 18:41:10 +00:00
|
|
|
}
|
2020-10-06 19:04:51 +00:00
|
|
|
|
2021-01-01 12:47:53 +00:00
|
|
|
pub fn allow_federation(&self) -> bool {
|
|
|
|
self.config.allow_federation
|
2020-10-06 19:04:51 +00:00
|
|
|
}
|
2020-12-06 10:05:51 +00:00
|
|
|
|
2021-03-01 14:17:53 +00:00
|
|
|
pub fn trusted_servers(&self) -> &[Box<ServerName>] {
|
|
|
|
&self.config.trusted_servers
|
|
|
|
}
|
|
|
|
|
2020-12-06 10:05:51 +00:00
|
|
|
pub fn dns_resolver(&self) -> &TokioAsyncResolver {
|
|
|
|
&self.dns_resolver
|
|
|
|
}
|
2021-02-07 16:38:45 +00:00
|
|
|
|
|
|
|
pub fn jwt_decoding_key(&self) -> Option<&jsonwebtoken::DecodingKey<'_>> {
|
|
|
|
self.jwt_decoding_key.as_ref()
|
|
|
|
}
|
2021-01-15 02:32:22 +00:00
|
|
|
|
|
|
|
/// TODO: the key valid until timestamp 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 fn add_signing_key(&self, origin: &ServerName, keys: &ServerSigningKeys) -> Result<()> {
|
|
|
|
// Remove outdated keys
|
|
|
|
let now = crate::utils::millis_since_unix_epoch();
|
|
|
|
for item in self.servertimeout_signingkey.scan_prefix(origin.as_bytes()) {
|
|
|
|
let (k, _) = item?;
|
|
|
|
let valid_until = k
|
|
|
|
.splitn(2, |&b| b == 0xff)
|
|
|
|
.nth(1)
|
|
|
|
.map(crate::utils::u64_from_bytes)
|
|
|
|
.ok_or_else(|| Error::bad_database("Invalid signing keys."))?
|
|
|
|
.map_err(|_| Error::bad_database("Invalid signing key valid until bytes"))?;
|
|
|
|
|
|
|
|
if now > valid_until {
|
|
|
|
self.servertimeout_signingkey.remove(k)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut key = origin.as_bytes().to_vec();
|
|
|
|
key.push(0xff);
|
|
|
|
key.extend_from_slice(
|
|
|
|
&(keys
|
|
|
|
.valid_until_ts
|
|
|
|
.duration_since(std::time::UNIX_EPOCH)
|
|
|
|
.expect("time is valid")
|
|
|
|
.as_millis() as u64)
|
|
|
|
.to_be_bytes(),
|
|
|
|
);
|
|
|
|
|
|
|
|
self.servertimeout_signingkey.insert(
|
|
|
|
key,
|
|
|
|
serde_json::to_vec(&keys.verify_keys).expect("ServerSigningKeys are a valid string"),
|
|
|
|
)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This returns an empty `Ok(BTreeMap<..>)` when there are no keys found for the server.
|
|
|
|
pub fn signing_keys_for(
|
|
|
|
&self,
|
|
|
|
origin: &ServerName,
|
|
|
|
) -> Result<BTreeMap<ServerSigningKeyId, VerifyKey>> {
|
|
|
|
let now = crate::utils::millis_since_unix_epoch();
|
|
|
|
for item in self.servertimeout_signingkey.scan_prefix(origin.as_bytes()) {
|
|
|
|
let (k, bytes) = item?;
|
|
|
|
let valid_until = k
|
|
|
|
.splitn(2, |&b| b == 0xff)
|
|
|
|
.nth(1)
|
|
|
|
.map(crate::utils::u64_from_bytes)
|
|
|
|
.ok_or_else(|| Error::bad_database("Invalid signing keys."))?
|
|
|
|
.map_err(|_| Error::bad_database("Invalid signing key valid until bytes"))?;
|
|
|
|
// If these keys are still valid use em!
|
|
|
|
if valid_until > now {
|
|
|
|
return serde_json::from_slice(&bytes)
|
|
|
|
.map_err(|_| Error::bad_database("Invalid BTreeMap<> of signing keys"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(BTreeMap::default())
|
|
|
|
}
|
2020-05-03 15:25:31 +00:00
|
|
|
}
|