From 9374b74e7708939695ef7b51e106784a28911499 Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 8 May 2024 16:51:07 +0100 Subject: [PATCH] refactor: let ruma-server-util handle X-Matrix parsing --- Cargo.lock | 18 +++++++++ Cargo.toml | 1 + src/api/ruma_wrapper/axum.rs | 78 +++++------------------------------- 3 files changed, 29 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8453335a..a3b15593 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2039,6 +2039,7 @@ dependencies = [ "ruma-federation-api", "ruma-identity-service-api", "ruma-push-gateway-api", + "ruma-server-util", "ruma-signatures", "ruma-state-res", ] @@ -2184,6 +2185,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "ruma-server-util" +version = "0.2.0" +source = "git+https://github.com/ruma/ruma?rev=5495b85aa311c2805302edb0a7de40399e22b397#5495b85aa311c2805302edb0a7de40399e22b397" +dependencies = [ + "headers", + "ruma-common", + "tracing", + "yap", +] + [[package]] name = "ruma-signatures" version = "0.14.0" @@ -3453,6 +3465,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" +[[package]] +name = "yap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index 3a5c2647..e23501ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ ruma = { git = "https://github.com/ruma/ruma", rev = "5495b85aa311c2805302edb0a7 "push-gateway-api-c", "rand", "ring-compat", + "server-util", "state-res", "unstable-exhaustive-types", "unstable-msc2448", diff --git a/src/api/ruma_wrapper/axum.rs b/src/api/ruma_wrapper/axum.rs index a56ee359..136f4539 100644 --- a/src/api/ruma_wrapper/axum.rs +++ b/src/api/ruma_wrapper/axum.rs @@ -4,10 +4,7 @@ use axum::{ async_trait, body::{Full, HttpBody}, extract::{rejection::TypedHeaderRejectionReason, FromRequest, Path, TypedHeader}, - headers::{ - authorization::{Bearer, Credentials}, - Authorization, - }, + headers::{authorization::Bearer, Authorization}, response::{IntoResponse, Response}, BoxError, RequestExt, RequestPartsExt, }; @@ -15,7 +12,8 @@ use bytes::{Buf, BufMut, Bytes, BytesMut}; use http::{Request, StatusCode}; use ruma::{ api::{client::error::ErrorKind, AuthScheme, IncomingRequest, OutgoingResponse}, - CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId, + server_util::authorization::XMatrix, + CanonicalJsonValue, OwnedDeviceId, OwnedUserId, UserId, }; use serde::Deserialize; use tracing::{debug, error, warn}; @@ -191,7 +189,12 @@ where let signatures = BTreeMap::from_iter([( x_matrix.origin.as_str().to_owned(), - CanonicalJsonValue::Object(origin_signatures), + CanonicalJsonValue::Object( + origin_signatures + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + ), )]); let mut request_map = BTreeMap::from_iter([ @@ -226,7 +229,7 @@ where let keys_result = services() .rooms .event_handler - .fetch_signing_keys(&x_matrix.origin, vec![x_matrix.key.to_owned()]) + .fetch_signing_keys(&x_matrix.origin, vec![x_matrix.key.to_string()]) .await; let keys = match keys_result { @@ -340,67 +343,6 @@ where } } -struct XMatrix { - destination: Option, - origin: OwnedServerName, - key: String, // KeyName? - sig: String, -} - -impl Credentials for XMatrix { - const SCHEME: &'static str = "X-Matrix"; - - fn decode(value: &http::HeaderValue) -> Option { - 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 key = None; - let mut sig = None; - let mut destination = 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.try_into().ok()?), - _ => debug!( - "Unexpected field `{}` in X-Matrix Authorization header", - name - ), - } - } - - Some(Self { - destination, - origin: origin?, - key: key?, - sig: sig?, - }) - } - - fn encode(&self) -> http::HeaderValue { - todo!() - } -} - impl IntoResponse for RumaResponse { fn into_response(self) -> Response { match self.0.try_into_http_response::() {