diff --git a/Cargo.lock b/Cargo.lock index d009df4b09aa43f60ec53d400536e84ff5a29043..ac079d9146293c9d9b317ec90af70201cedcb1ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1552,6 +1552,15 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-auth" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643c9bbf6a4ea8a656d6b4cd53d34f79e3f841ad5203c1a55fb7d761923bc255" +dependencies = [ + "memchr", +] + [[package]] name = "http-body" version = "0.4.6" @@ -2906,6 +2915,7 @@ dependencies = [ "ruma-federation-api", "ruma-identity-service-api", "ruma-push-gateway-api", + "ruma-server-util", "ruma-signatures", "ruma-state-res", "web-time 1.1.0", @@ -3066,6 +3076,19 @@ dependencies = [ "serde_json", ] +[[package]] +name = "ruma-server-util" +version = "0.3.0" +source = "git+https://github.com/girlbossceo/ruwuma?rev=9a5bfad8494b7a4e6c40421c3d0675db4b434ec0#9a5bfad8494b7a4e6c40421c3d0675db4b434ec0" +dependencies = [ + "headers", + "http 1.1.0", + "http-auth", + "ruma-common", + "thiserror", + "tracing", +] + [[package]] name = "ruma-signatures" version = "0.15.0" diff --git a/Cargo.toml b/Cargo.toml index 755ff46ae9d37392cdd080b012a139a79f79297f..e63dcef51ae6f00d94026d3b3defabab60625d35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -284,6 +284,7 @@ features = [ "markdown", "push-gateway-api-c", "state-res", + "server-util", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified", diff --git a/src/api/router/auth.rs b/src/api/router/auth.rs index da36c82c9f86a6c81da1259d98aa3d854a6345a9..08a08e08bff9406149709eeaca646a51aef4e3d9 100644 --- a/src/api/router/auth.rs +++ b/src/api/router/auth.rs @@ -9,11 +9,12 @@ use http::uri::PathAndQuery; use ruma::{ api::{client::error::ErrorKind, AuthScheme, Metadata}, + server_util::authorization::XMatrix, CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId, }; use tracing::warn; -use super::{request::Request, xmatrix::XMatrix}; +use super::request::Request; use crate::{service::appservice::RegistrationInfo, services, Error, Result}; enum Token { @@ -202,8 +203,17 @@ async fn auth_server(request: &mut Request, json_body: &Option<CanonicalJsonValu })?; let origin = &x_matrix.origin; - let signatures = BTreeMap::from_iter([(x_matrix.key.clone(), CanonicalJsonValue::String(x_matrix.sig))]); - let signatures = BTreeMap::from_iter([(origin.as_str().to_owned(), CanonicalJsonValue::Object(signatures))]); + let signatures = + BTreeMap::from_iter([(x_matrix.key.clone(), CanonicalJsonValue::String(x_matrix.sig.to_string()))]); + let signatures = BTreeMap::from_iter([( + origin.as_str().to_owned(), + CanonicalJsonValue::Object( + signatures + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + ), + )]); let server_destination = services().globals.server_name().as_str().to_owned(); if let Some(destination) = x_matrix.destination.as_ref() { @@ -239,7 +249,7 @@ async fn auth_server(request: &mut Request, json_body: &Option<CanonicalJsonValu let keys_result = services() .rooms .event_handler - .fetch_signing_keys_for_server(origin, vec![x_matrix.key.clone()]) + .fetch_signing_keys_for_server(origin, vec![x_matrix.key.to_string()]) .await; let keys = keys_result.map_err(|e| { diff --git a/src/api/router/mod.rs b/src/api/router/mod.rs index 09c07cef9907cb7711eb153e3951e9be13779878..2c439d655297400b1e0e6b3a6299e7642a79ba84 100644 --- a/src/api/router/mod.rs +++ b/src/api/router/mod.rs @@ -1,7 +1,6 @@ mod auth; mod handler; mod request; -mod xmatrix; use std::{mem, ops::Deref}; diff --git a/src/api/router/xmatrix.rs b/src/api/router/xmatrix.rs deleted file mode 100644 index 74fb7d20cfc88ed7168a0f785610469df06fe38f..0000000000000000000000000000000000000000 --- a/src/api/router/xmatrix.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::str; - -use axum_extra::headers::authorization::Credentials; -use ruma::OwnedServerName; -use tracing::debug; - -pub(crate) struct XMatrix { - pub(crate) origin: OwnedServerName, - pub(crate) destination: Option<String>, - pub(crate) key: String, // KeyName? - pub(crate) sig: String, -} - -impl Credentials for XMatrix { - const SCHEME: &'static str = "X-Matrix"; - - fn decode(value: &http::HeaderValue) -> Option<Self> { - debug_assert!( - value.as_bytes().starts_with(b"X-Matrix "), - "HeaderValue to decode should start with \"X-Matrix ..\", received = {value:?}", - ); - - let parameters = str::from_utf8(&value.as_bytes()["X-Matrix ".len()..]) - .ok()? - .trim_start(); - - let mut origin = None; - let mut destination = None; - let mut key = None; - let mut sig = None; - - for entry in parameters.split_terminator(',') { - let (name, value) = entry.split_once('=')?; - - // It's not at all clear why some fields are quoted and others not in the spec, - // let's simply accept either form for every field. - let value = value - .strip_prefix('"') - .and_then(|rest| rest.strip_suffix('"')) - .unwrap_or(value); - - // FIXME: Catch multiple fields of the same name - match name { - "origin" => origin = Some(value.try_into().ok()?), - "key" => key = Some(value.to_owned()), - "sig" => sig = Some(value.to_owned()), - "destination" => destination = Some(value.to_owned()), - _ => debug!("Unexpected field `{name}` in X-Matrix Authorization header"), - } - } - - Some(Self { - origin: origin?, - key: key?, - sig: sig?, - destination, - }) - } - - fn encode(&self) -> http::HeaderValue { todo!() } -}