diff --git a/Cargo.lock b/Cargo.lock index 6eb301d..8ffcb41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -189,6 +189,7 @@ name = "conduit" version = "0.1.0" dependencies = [ "base64 0.13.0", + "bytes", "directories", "http", "image", @@ -1703,7 +1704,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.0.3" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "assign", "js_int", @@ -1723,8 +1724,9 @@ dependencies = [ [[package]] name = "ruma-api" version = "0.17.0-alpha.4" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ + "bytes", "http", "percent-encoding", "ruma-api-macros", @@ -1738,7 +1740,7 @@ dependencies = [ [[package]] name = "ruma-api-macros" version = "0.17.0-alpha.4" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1749,7 +1751,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.2.0-alpha.3" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "ruma-api", "ruma-common", @@ -1763,9 +1765,10 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.10.0-alpha.3" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "assign", + "bytes", "http", "js_int", "maplit", @@ -1782,7 +1785,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.5.0" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "indexmap", "js_int", @@ -1798,7 +1801,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.22.0-alpha.3" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "js_int", "ruma-common", @@ -1812,7 +1815,7 @@ dependencies = [ [[package]] name = "ruma-events-macros" version = "0.22.0-alpha.3" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1823,7 +1826,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.1.0-alpha.2" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "js_int", "ruma-api", @@ -1838,7 +1841,7 @@ dependencies = [ [[package]] name = "ruma-identifiers" version = "0.19.0" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "paste", "rand", @@ -1852,7 +1855,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-macros" version = "0.19.0" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro2", "quote", @@ -1863,12 +1866,12 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.3.0" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" [[package]] name = "ruma-identity-service-api" version = "0.1.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "ruma-api", "ruma-common", @@ -1881,7 +1884,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.1.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "js_int", "ruma-api", @@ -1896,8 +1899,9 @@ dependencies = [ [[package]] name = "ruma-serde" version = "0.3.1" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ + "bytes", "form_urlencoded", "itoa", "js_int", @@ -1909,7 +1913,7 @@ dependencies = [ [[package]] name = "ruma-serde-macros" version = "0.3.1" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1920,7 +1924,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.7.0" -source = "git+https://github.com/ruma/ruma?rev=4f16b9357c15d649075393a723f23cf560251754#4f16b9357c15d649075393a723f23cf560251754" +source = "git+https://github.com/ruma/ruma?rev=12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88#12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88" dependencies = [ "base64 0.13.0", "ring", @@ -2221,7 +2225,7 @@ dependencies = [ [[package]] name = "state-res" version = "0.1.0" -source = "git+https://github.com/ruma/state-res?rev=aa53d07f51ffb7258f5c1e499bddffd4c630f7df#aa53d07f51ffb7258f5c1e499bddffd4c630f7df" +source = "git+https://github.com/ruma/state-res?rev=1dd252d1c97a38def74bc097c197a33179ed8fbb#1dd252d1c97a38def74bc097c197a33179ed8fbb" dependencies = [ "itertools 0.10.0", "log", diff --git a/Cargo.toml b/Cargo.toml index 189cd15..3f0a34c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,12 +18,12 @@ rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "e1307ddf4 #rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", default-features = false, features = ["tls"] } # Used for matrix spec type definitions and helpers -ruma = { git = "https://github.com/ruma/ruma", rev = "4f16b9357c15d649075393a723f23cf560251754", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } +ruma = { git = "https://github.com/ruma/ruma", rev = "12ec0fb1680ebc4fec4fbefbbd0890ae4eaf3a88", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } #ruma = { git = "https://github.com/timokoesters/ruma", rev = "220d5b4a76b3b781f7f8297fbe6b14473b04214b", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } #ruma = { path = "../ruma/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "unstable-pre-spec", "unstable-exhaustive-types"] } # Used when doing state resolution -state-res = { git = "https://github.com/ruma/state-res", rev = "aa53d07f51ffb7258f5c1e499bddffd4c630f7df", features = ["unstable-pre-spec"] } +state-res = { git = "https://github.com/ruma/state-res", rev = "1dd252d1c97a38def74bc097c197a33179ed8fbb", features = ["unstable-pre-spec"] } #state-res = { path = "../state-res", features = ["unstable-pre-spec"] } # Used for long polling and federation sender, should be the same as rocket::tokio @@ -32,6 +32,8 @@ tokio = "1.2.0" sled = { version = "0.34.6", features = ["compression", "no_metrics"] } #sled = { git = "https://github.com/spacejam/sled.git", rev = "e4640e0773595229f398438886f19bca6f7326a2", features = ["compression"] } +# Used for the http request / response body type for Ruma endpoints used with reqwest +bytes = "1.0.1" # Used for emitting log entries log = "0.4.14" # Used for rocket<->ruma conversions diff --git a/src/appservice_server.rs b/src/appservice_server.rs index 1b72c76..8f64edf 100644 --- a/src/appservice_server.rs +++ b/src/appservice_server.rs @@ -1,7 +1,8 @@ use crate::{utils, Error, Result}; +use bytes::BytesMut; use http::header::{HeaderValue, CONTENT_TYPE}; use log::warn; -use ruma::api::{IncomingResponse, OutgoingRequest}; +use ruma::api::{IncomingResponse, OutgoingRequest, SendAccessToken}; use std::{ convert::{TryFrom, TryInto}, fmt::Debug, @@ -20,8 +21,9 @@ where let hs_token = registration.get("hs_token").unwrap().as_str().unwrap(); let mut http_request = request - .try_into_http_request(&destination, Some("")) - .unwrap(); + .try_into_http_request::(&destination, SendAccessToken::IfRequired("")) + .unwrap() + .map(|body| body.freeze()); let mut parts = http_request.uri().clone().into_parts(); let old_path_and_query = parts.path_and_query.unwrap().as_str().to_owned(); @@ -49,51 +51,46 @@ where *reqwest_request.timeout_mut() = Some(Duration::from_secs(30)); let url = reqwest_request.url().clone(); - let reqwest_response = globals.reqwest_client().execute(reqwest_request).await; + let mut reqwest_response = globals.reqwest_client().execute(reqwest_request).await?; // Because reqwest::Response -> http::Response is complicated: - match reqwest_response { - Ok(mut reqwest_response) => { - let status = reqwest_response.status(); - let mut http_response = http::Response::builder().status(status); - let headers = http_response.headers_mut().unwrap(); + let status = reqwest_response.status(); + let mut http_response = http::Response::builder().status(status); + let headers = http_response.headers_mut().unwrap(); - for (k, v) in reqwest_response.headers_mut().drain() { - if let Some(key) = k { - headers.insert(key, v); - } - } - - let status = reqwest_response.status(); + for (k, v) in reqwest_response.headers_mut().drain() { + if let Some(key) = k { + headers.insert(key, v); + } + } - let body = reqwest_response.bytes().await.unwrap_or_else(|e| { - warn!("server error: {}", e); - Vec::new().into() - }); // TODO: handle timeout + let status = reqwest_response.status(); - if status != 200 { - warn!( - "Appservice returned bad response {} {}\n{}\n{:?}", - destination, - status, - url, - utils::string_from_bytes(&body) - ); - } + let body = reqwest_response.bytes().await.unwrap_or_else(|e| { + warn!("server error: {}", e); + Vec::new().into() + }); // TODO: handle timeout - let response = T::IncomingResponse::try_from_http_response( - http_response - .body(body) - .expect("reqwest body is valid http body"), - ); - response.map_err(|_| { - warn!( - "Appservice returned invalid response bytes {}\n{}", - destination, url - ); - Error::BadServerResponse("Server returned bad response.") - }) - } - Err(e) => Err(e.into()), + if status != 200 { + warn!( + "Appservice returned bad response {} {}\n{}\n{:?}", + destination, + status, + url, + utils::string_from_bytes(&body) + ); } + + let response = T::IncomingResponse::try_from_http_response( + http_response + .body(body) + .expect("reqwest body is valid http body"), + ); + response.map_err(|_| { + warn!( + "Appservice returned invalid response bytes {}\n{}", + destination, url + ); + Error::BadServerResponse("Server returned bad response.") + }) } diff --git a/src/database/pusher.rs b/src/database/pusher.rs index 28da236..7c7abb3 100644 --- a/src/database/pusher.rs +++ b/src/database/pusher.rs @@ -1,4 +1,5 @@ use crate::{Database, Error, PduEvent, Result}; +use bytes::BytesMut; use log::{error, info, warn}; use ruma::{ api::{ @@ -7,7 +8,7 @@ use ruma::{ self, v1::{Device, Notification, NotificationCounts, NotificationPriority}, }, - IncomingResponse, OutgoingRequest, + IncomingResponse, OutgoingRequest, SendAccessToken, }, events::{room::power_levels::PowerLevelsEventContent, EventType}, push::{Action, PushConditionRoomCtx, PushFormat, Ruleset, Tweak}, @@ -99,11 +100,12 @@ where let destination = destination.replace("/_matrix/push/v1/notify", ""); let http_request = request - .try_into_http_request(&destination, Some("")) + .try_into_http_request::(&destination, SendAccessToken::IfRequired("")) .map_err(|e| { warn!("Failed to find destination {}: {}", destination, e); Error::BadServerResponse("Invalid destination") - })?; + })? + .map(|body| body.freeze()); let reqwest_request = reqwest::Request::try_from(http_request) .expect("all http requests are valid reqwest requests"); diff --git a/src/ruma_wrapper.rs b/src/ruma_wrapper.rs index eb3802e..7777e12 100644 --- a/src/ruma_wrapper.rs +++ b/src/ruma_wrapper.rs @@ -34,7 +34,8 @@ pub struct Ruma { pub body: T::Incoming, pub sender_user: Option, pub sender_device: Option>, - pub json_body: Option>, // This is None when body is not a valid string + // This is None when body is not a valid string + pub json_body: Option>, pub from_appservice: bool, } @@ -124,22 +125,24 @@ where } AuthScheme::ServerSignatures => { // Get origin from header - let x_matrix = match request - .headers() - .get_one("Authorization") - .map(|s| { - s[9..] - .split_terminator(',').map(|field| {let mut splits = field.splitn(2, '='); (splits.next(), splits.next().map(|s| s.trim_matches('"')))}).collect::>() - }) // Split off "X-Matrix " and parse the rest - { - Some(t) => t, - None => { - warn!("No Authorization header"); - - // Forbidden - return Failure((Status::raw(580), ())); - } - }; + let x_matrix = match request.headers().get_one("Authorization").map(|s| { + // Split off "X-Matrix " and parse the rest + s[9..] + .split_terminator(',') + .map(|field| { + let mut splits = field.splitn(2, '='); + (splits.next(), splits.next().map(|s| s.trim_matches('"'))) + }) + .collect::>() + }) { + Some(t) => t, + None => { + warn!("No Authorization header"); + + // Forbidden + return Failure((Status::raw(580), ())); + } + }; let origin_str = match x_matrix.get(&Some("origin")) { Some(Some(o)) => *o, @@ -314,36 +317,34 @@ where 'o: 'r, { fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> { - let http_response: Result, _> = self.0.try_into_http_response(); - match http_response { - Ok(http_response) => { - let mut response = rocket::response::Response::build(); + let http_response = self + .0 + .try_into_http_response::>() + .map_err(|_| Status::InternalServerError)?; - let status = http_response.status(); - response.raw_status(status.into(), ""); + let mut response = rocket::response::Response::build(); - for header in http_response.headers() { - response - .raw_header(header.0.to_string(), header.1.to_str().unwrap().to_owned()); - } + let status = http_response.status(); + response.raw_status(status.into(), ""); - let http_body = http_response.into_body(); - - response.sized_body(http_body.len(), Cursor::new(http_body)); - - response.raw_header("Access-Control-Allow-Origin", "*"); - response.raw_header( - "Access-Control-Allow-Methods", - "GET, POST, PUT, DELETE, OPTIONS", - ); - response.raw_header( - "Access-Control-Allow-Headers", - "Origin, X-Requested-With, Content-Type, Accept, Authorization", - ); - response.raw_header("Access-Control-Max-Age", "86400"); - response.ok() - } - Err(_) => Err(Status::InternalServerError), + for header in http_response.headers() { + response.raw_header(header.0.to_string(), header.1.to_str().unwrap().to_owned()); } + + let http_body = http_response.into_body(); + + response.sized_body(http_body.len(), Cursor::new(http_body)); + + response.raw_header("Access-Control-Allow-Origin", "*"); + response.raw_header( + "Access-Control-Allow-Methods", + "GET, POST, PUT, DELETE, OPTIONS", + ); + response.raw_header( + "Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept, Authorization", + ); + response.raw_header("Access-Control-Max-Age", "86400"); + response.ok() } } diff --git a/src/server_server.rs b/src/server_server.rs index c3ae02d..1d32637 100644 --- a/src/server_server.rs +++ b/src/server_server.rs @@ -23,7 +23,7 @@ use ruma::{ query::{get_profile_information, get_room_information}, transactions::{edu::Edu, send_transaction_message}, }, - IncomingResponse, OutgoingRequest, OutgoingResponse, + IncomingResponse, OutgoingRequest, OutgoingResponse, SendAccessToken, }, directory::{IncomingFilter, IncomingRoomNetwork}, events::{ @@ -86,7 +86,7 @@ where }; let mut http_request = request - .try_into_http_request(&actual_destination, Some("")) + .try_into_http_request::>(&actual_destination, SendAccessToken::IfRequired("")) .map_err(|e| { warn!("Failed to find destination {}: {}", actual_destination, e); Error::BadServerResponse("Invalid destination") @@ -382,7 +382,7 @@ pub fn get_server_keys_route(db: State<'_, Database>) -> Json { valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2), }, } - .try_into_http_response() + .try_into_http_response::>() .unwrap() .body(), )