Merge branch 'feature/turn-server-settings' into 'next'

Implement turn server settings

Closes #97

See merge request famedly/conduit!208
This commit is contained in:
Timo Kösters 2021-11-19 16:39:24 +00:00
commit da00f611e9
5 changed files with 118 additions and 9 deletions

35
Cargo.lock generated
View File

@ -245,6 +245,7 @@ dependencies = [
"crossbeam", "crossbeam",
"directories", "directories",
"heed", "heed",
"hmac",
"http", "http",
"image", "image",
"jsonwebtoken", "jsonwebtoken",
@ -266,6 +267,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_yaml", "serde_yaml",
"sha-1",
"sled", "sled",
"thiserror", "thiserror",
"thread_local", "thread_local",
@ -428,6 +430,16 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "crypto-mac"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
dependencies = [
"generic-array",
"subtle",
]
[[package]] [[package]]
name = "curve25519-dalek" name = "curve25519-dalek"
version = "3.2.0" version = "3.2.0"
@ -897,6 +909,16 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hmac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
dependencies = [
"crypto-mac",
"digest",
]
[[package]] [[package]]
name = "hostname" name = "hostname"
version = "0.3.1" version = "0.3.1"
@ -2422,6 +2444,19 @@ dependencies = [
"yaml-rust", "yaml-rust",
] ]
[[package]]
name = "sha-1"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
dependencies = [
"block-buffer",
"cfg-if 1.0.0",
"cpufeatures",
"digest",
"opaque-debug",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.6.0" version = "0.6.0"

View File

@ -79,6 +79,9 @@ num_cpus = "1.13.0"
threadpool = "1.8.1" threadpool = "1.8.1"
heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true } heed = { git = "https://github.com/timokoesters/heed.git", rev = "f6f825da7fb2c758867e05ad973ef800a6fe1d5d", optional = true }
thread_local = "1.1.3" thread_local = "1.1.3"
# used for TURN server authentication
hmac = "0.11.0"
sha-1 = "0.9.8"
[features] [features]
default = ["conduit_bin", "backend_sqlite"] default = ["conduit_bin", "backend_sqlite"]

View File

@ -1,6 +1,11 @@
use crate::ConduitResult; use crate::{database::DatabaseGuard, ConduitResult, Ruma};
use hmac::{Hmac, Mac, NewMac};
use ruma::api::client::r0::voip::get_turn_server_info; use ruma::api::client::r0::voip::get_turn_server_info;
use std::time::Duration; use ruma::SecondsSinceUnixEpoch;
use sha1::Sha1;
use std::time::{Duration, SystemTime};
type HmacSha1 = Hmac<Sha1>;
#[cfg(feature = "conduit_bin")] #[cfg(feature = "conduit_bin")]
use rocket::get; use rocket::get;
@ -8,14 +13,46 @@ use rocket::get;
/// # `GET /_matrix/client/r0/voip/turnServer` /// # `GET /_matrix/client/r0/voip/turnServer`
/// ///
/// TODO: Returns information about the recommended turn server. /// TODO: Returns information about the recommended turn server.
#[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/voip/turnServer"))] #[cfg_attr(
#[tracing::instrument] feature = "conduit_bin",
pub async fn turn_server_route() -> ConduitResult<get_turn_server_info::Response> { get("/_matrix/client/r0/voip/turnServer", data = "<body>")
)]
#[tracing::instrument(skip(body, db))]
pub async fn turn_server_route(
body: Ruma<get_turn_server_info::Request>,
db: DatabaseGuard,
) -> ConduitResult<get_turn_server_info::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let turn_secret = db.globals.turn_secret();
let (username, password) = if turn_secret != "" {
let expiry = SecondsSinceUnixEpoch::from_system_time(
SystemTime::now() + Duration::from_secs(db.globals.turn_ttl()),
)
.expect("time is valid");
let username: String = format!("{}:{}", expiry.get(), sender_user);
let mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes())
.expect("HMAC can take key of any size");
mac.update(username.as_bytes());
let password: String = base64::encode_config(mac.finalize().into_bytes(), base64::STANDARD);
(username, password)
} else {
(
db.globals.turn_username().clone(),
db.globals.turn_password().clone(),
)
};
Ok(get_turn_server_info::Response { Ok(get_turn_server_info::Response {
username: "".to_owned(), username: username,
password: "".to_owned(), password: password,
uris: Vec::new(), uris: db.globals.turn_uris().to_vec(),
ttl: Duration::from_secs(60 * 60 * 24), ttl: Duration::from_secs(db.globals.turn_ttl()),
} }
.into()) .into())
} }

View File

@ -74,6 +74,16 @@ pub struct Config {
trusted_servers: Vec<Box<ServerName>>, trusted_servers: Vec<Box<ServerName>>,
#[serde(default = "default_log")] #[serde(default = "default_log")]
pub log: String, pub log: String,
#[serde(default)]
turn_username: String,
#[serde(default)]
turn_password: String,
#[serde(default = "Vec::new")]
turn_uris: Vec<String>,
#[serde(default)]
turn_secret: String,
#[serde(default = "default_turn_ttl")]
turn_ttl: u64,
#[serde(flatten)] #[serde(flatten)]
catchall: BTreeMap<String, IgnoredAny>, catchall: BTreeMap<String, IgnoredAny>,
@ -131,6 +141,10 @@ fn default_log() -> String {
"info,state_res=warn,rocket=off,_=off,sled=off".to_owned() "info,state_res=warn,rocket=off,_=off,sled=off".to_owned()
} }
fn default_turn_ttl() -> u64 {
60 * 60 * 24
}
#[cfg(feature = "sled")] #[cfg(feature = "sled")]
pub type Engine = abstraction::sled::Engine; pub type Engine = abstraction::sled::Engine;

View File

@ -226,6 +226,26 @@ impl Globals {
self.jwt_decoding_key.as_ref() self.jwt_decoding_key.as_ref()
} }
pub fn turn_password(&self) -> &String {
&self.config.turn_password
}
pub fn turn_ttl(&self) -> u64 {
self.config.turn_ttl
}
pub fn turn_uris(&self) -> &[String] {
&self.config.turn_uris
}
pub fn turn_username(&self) -> &String {
&self.config.turn_username
}
pub fn turn_secret(&self) -> &String {
&self.config.turn_secret
}
/// TODO: the key valid until timestamp is only honored in room version > 4 /// TODO: the key valid until timestamp is only honored in room version > 4
/// Remove the outdated keys and insert the new ones. /// Remove the outdated keys and insert the new ones.
/// ///