Signing, basis for federation
parent
9b79798e56
commit
b0d9ccdb2d
|
@ -1260,7 +1260,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruma-federation-api"
|
name = "ruma-federation-api"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
source = "git+https://github.com/ruma/ruma-federation-api.git#5448c650f0a583382152d0f43f2dcf720d495390"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js_int",
|
"js_int",
|
||||||
"ruma-api",
|
"ruma-api",
|
||||||
|
|
|
@ -18,7 +18,7 @@ ruma-identifiers = "0.15.1"
|
||||||
ruma-api = "0.16.0-rc.1"
|
ruma-api = "0.16.0-rc.1"
|
||||||
ruma-events = "0.19.0"
|
ruma-events = "0.19.0"
|
||||||
ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git" }
|
ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git" }
|
||||||
ruma-federation-api = { git = "https://github.com/ruma/ruma-federation-api.git" }
|
ruma-federation-api = { path = "../ruma-federation-api" }
|
||||||
pretty_env_logger = "0.4.0"
|
pretty_env_logger = "0.4.0"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
sled = "0.31.0"
|
sled = "0.31.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{utils, Data, MatrixResult, Ruma};
|
use crate::{server_server, utils, Data, MatrixResult, Ruma};
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use rocket::{get, options, post, put, State};
|
use rocket::{get, options, post, put, State};
|
||||||
|
@ -674,7 +674,8 @@ pub fn join_room_by_id_or_alias_route(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
body.room_id_or_alias.try_into().unwrap()
|
todo!();
|
||||||
|
//body.room_id_or_alias.try_into().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
if data.room_join(
|
if data.room_join(
|
||||||
|
@ -725,8 +726,8 @@ pub fn invite_user_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/_matrix/client/r0/publicRooms", data = "<body>")]
|
#[post("/_matrix/client/r0/publicRooms", data = "<body>")]
|
||||||
pub fn get_public_rooms_filtered_route(
|
pub async fn get_public_rooms_filtered_route(
|
||||||
data: State<Data>,
|
data: State<'_, Data>,
|
||||||
body: Ruma<get_public_rooms_filtered::Request>,
|
body: Ruma<get_public_rooms_filtered::Request>,
|
||||||
) -> MatrixResult<get_public_rooms_filtered::Response> {
|
) -> MatrixResult<get_public_rooms_filtered::Response> {
|
||||||
let mut chunk = data
|
let mut chunk = data
|
||||||
|
@ -752,6 +753,25 @@ pub fn get_public_rooms_filtered_route(
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
chunk.extend_from_slice(
|
||||||
|
&server_server::send_request(
|
||||||
|
&data,
|
||||||
|
"https://matrix.org".to_owned(),
|
||||||
|
ruma_federation_api::v1::get_public_rooms::Request {
|
||||||
|
limit: None,
|
||||||
|
since: None,
|
||||||
|
include_all_networks: None,
|
||||||
|
third_party_instance_id: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.chunk
|
||||||
|
.into_iter()
|
||||||
|
.map(|c| serde_json::from_str(&serde_json::to_string(dbg!(&c)).unwrap()).unwrap())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
|
||||||
chunk.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members));
|
chunk.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members));
|
||||||
|
|
||||||
let total_room_count_estimate = (chunk.len() as u32).into();
|
let total_room_count_estimate = (chunk.len() as u32).into();
|
||||||
|
|
|
@ -457,7 +457,7 @@ impl Data {
|
||||||
))
|
))
|
||||||
.expect("ruma's reference hashes are correct");
|
.expect("ruma's reference hashes are correct");
|
||||||
|
|
||||||
let mut pdu_json = serde_json::to_value(pdu).unwrap();
|
let mut pdu_json = serde_json::to_value(&pdu).unwrap();
|
||||||
ruma_signatures::hash_and_sign_event(self.hostname(), self.keypair(), &mut pdu_json);
|
ruma_signatures::hash_and_sign_event(self.hostname(), self.keypair(), &mut pdu_json);
|
||||||
|
|
||||||
self.pdu_leaves_replace(&room_id, &pdu.event_id);
|
self.pdu_leaves_replace(&room_id, &pdu.event_id);
|
||||||
|
@ -483,7 +483,7 @@ impl Data {
|
||||||
|
|
||||||
self.db
|
self.db
|
||||||
.pduid_pdu
|
.pduid_pdu
|
||||||
.insert(&pdu_id, &*serde_json::to_string(&pdu_json).unwrap())
|
.insert(&pdu_id, &*pdu_json.to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
self.db
|
self.db
|
||||||
|
@ -497,7 +497,10 @@ impl Data {
|
||||||
key.extend_from_slice(pdu.kind.to_string().as_bytes());
|
key.extend_from_slice(pdu.kind.to_string().as_bytes());
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(state_key.to_string().as_bytes());
|
key.extend_from_slice(state_key.to_string().as_bytes());
|
||||||
self.db.roomstateid_pdu.insert(key, &*pdu_json).unwrap();
|
self.db
|
||||||
|
.roomstateid_pdu
|
||||||
|
.insert(key, &*pdu_json.to_string())
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pdu.event_id
|
pdu.event_id
|
||||||
|
|
|
@ -127,7 +127,7 @@ impl Database {
|
||||||
&*db.update_and_fetch("keypair", utils::generate_keypair)
|
&*db.update_and_fetch("keypair", utils::generate_keypair)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
"0.0.0".to_owned(),
|
"key1".to_owned(),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
_db: db,
|
_db: db,
|
||||||
|
|
|
@ -1,25 +1,89 @@
|
||||||
use std::convert::TryInto;
|
use log::error;
|
||||||
|
use http::header::{HeaderValue, AUTHORIZATION};
|
||||||
|
use ruma_api::{
|
||||||
|
error::{FromHttpRequestError, FromHttpResponseError},
|
||||||
|
Endpoint, Outgoing,
|
||||||
|
};
|
||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
pub fn send_request<T: TryInto<http::Request<Vec<u8>>>>(
|
pub async fn send_request<T: Endpoint>(
|
||||||
data: &crate::Data,
|
data: &crate::Data,
|
||||||
method: http::Method,
|
|
||||||
uri: String,
|
|
||||||
destination: String,
|
destination: String,
|
||||||
request: T,
|
request: T,
|
||||||
) where
|
) -> Option<<T::Response as Outgoing>::Incoming>
|
||||||
|
where
|
||||||
|
// We need to duplicate Endpoint's where clauses because the compiler is not smart enough yet.
|
||||||
|
// See https://github.com/rust-lang/rust/issues/54149
|
||||||
|
<T as Outgoing>::Incoming: TryFrom<http::Request<Vec<u8>>, Error = FromHttpRequestError>,
|
||||||
|
<T::Response as Outgoing>::Incoming: TryFrom<
|
||||||
|
http::Response<Vec<u8>>,
|
||||||
|
Error = FromHttpResponseError<<T as Endpoint>::ResponseError>,
|
||||||
|
>,
|
||||||
T::Error: std::fmt::Debug,
|
T::Error: std::fmt::Debug,
|
||||||
{
|
{
|
||||||
let mut http_request: http::Request<_> = request.try_into().unwrap();
|
let mut http_request: http::Request<_> = request.try_into().unwrap();
|
||||||
let request_json = serde_json::to_value(http_request.body()).unwrap();
|
let uri = destination.clone() + T::METADATA.path;
|
||||||
|
*http_request.uri_mut() = uri.parse().unwrap();
|
||||||
|
|
||||||
|
let body = http_request.body();
|
||||||
|
let mut request_json = if !body.is_empty() {
|
||||||
|
serde_json::to_value(http_request.body()).unwrap()
|
||||||
|
} else {
|
||||||
|
serde_json::Map::new().into()
|
||||||
|
};
|
||||||
|
|
||||||
let request_map = request_json.as_object_mut().unwrap();
|
let request_map = request_json.as_object_mut().unwrap();
|
||||||
|
|
||||||
request_map.insert("method".to_owned(), method.to_string().into());
|
request_map.insert("method".to_owned(), T::METADATA.method.to_string().into());
|
||||||
request_map.insert("uri".to_owned(), uri.to_string().into());
|
request_map.insert("uri".to_owned(), uri.into());
|
||||||
//TODO: request_map.insert("origin".to_owned(), data.origin().to_string().into());
|
request_map.insert("origin".to_owned(), data.hostname().into());
|
||||||
request_map.insert("destination".to_owned(), destination.to_string().into());
|
request_map.insert("destination".to_owned(), destination.to_string().into());
|
||||||
|
|
||||||
ruma_signatures::sign_json(data.hostname(), data.keypair(), &mut request_json).unwrap();
|
ruma_signatures::sign_json(data.hostname(), data.keypair(), dbg!(&mut request_json)).unwrap();
|
||||||
let signature = request_json["signatures"];
|
let signatures = request_json["signatures"]
|
||||||
data.reqwest_client().execute(http_request.into());
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.values()
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k, v.as_str().unwrap()));
|
||||||
|
|
||||||
|
for s in signatures {
|
||||||
|
http_request.headers_mut().insert(AUTHORIZATION, HeaderValue::from_str(dbg!(&format!("X-Matrix origin={},key=\"{}\",sig=\"{}\"", data.hostname(), s.0, s.1))).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let reqwest_response = data
|
||||||
|
.reqwest_client()
|
||||||
|
.execute(dbg!(http_request.into()))
|
||||||
|
.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();
|
||||||
|
|
||||||
|
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()
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
Some(<T::Response as Outgoing>::Incoming::try_from(dbg!(http_response.body(body).unwrap())).ok().unwrap())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("ERROR: {}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
36
src/test.rs
36
src/test.rs
|
@ -1,8 +1,7 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use rocket::{local::Client, http::Status};
|
use rocket::{http::Status, local::Client};
|
||||||
use serde_json::Value;
|
|
||||||
use serde_json::json;
|
|
||||||
use ruma_client_api::error::ErrorKind;
|
use ruma_client_api::error::ErrorKind;
|
||||||
|
use serde_json::{json, Value};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn setup_client() -> Client {
|
fn setup_client() -> Client {
|
||||||
|
@ -19,7 +18,8 @@ async fn register_login() {
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.post("/_matrix/client/r0/register?kind=user")
|
.post("/_matrix/client/r0/register?kind=user")
|
||||||
.body(registration_init())
|
.body(registration_init())
|
||||||
.dispatch().await;
|
.dispatch()
|
||||||
|
.await;
|
||||||
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
|
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
|
||||||
|
|
||||||
assert_eq!(response.status().code, 401);
|
assert_eq!(response.status().code, 401);
|
||||||
|
@ -33,14 +33,16 @@ async fn login_after_register_correct_password() {
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.post("/_matrix/client/r0/register?kind=user")
|
.post("/_matrix/client/r0/register?kind=user")
|
||||||
.body(registration_init())
|
.body(registration_init())
|
||||||
.dispatch().await;
|
.dispatch()
|
||||||
|
.await;
|
||||||
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
|
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
|
||||||
let session = body["session"].clone();
|
let session = body["session"].clone();
|
||||||
|
|
||||||
let response = client
|
let response = client
|
||||||
.post("/_matrix/client/r0/register?kind=user")
|
.post("/_matrix/client/r0/register?kind=user")
|
||||||
.body(registration(session.as_str().unwrap()))
|
.body(registration(session.as_str().unwrap()))
|
||||||
.dispatch().await;
|
.dispatch()
|
||||||
|
.await;
|
||||||
assert_eq!(response.status().code, 200);
|
assert_eq!(response.status().code, 200);
|
||||||
|
|
||||||
let login_response = client
|
let login_response = client
|
||||||
|
@ -57,14 +59,16 @@ async fn login_after_register_incorrect_password() {
|
||||||
let mut response = client
|
let mut response = client
|
||||||
.post("/_matrix/client/r0/register?kind=user")
|
.post("/_matrix/client/r0/register?kind=user")
|
||||||
.body(registration_init())
|
.body(registration_init())
|
||||||
.dispatch().await;
|
.dispatch()
|
||||||
|
.await;
|
||||||
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
|
let body = serde_json::from_str::<Value>(&response.body_string().await.unwrap()).unwrap();
|
||||||
let session = body["session"].clone();
|
let session = body["session"].clone();
|
||||||
|
|
||||||
let response = client
|
let response = client
|
||||||
.post("/_matrix/client/r0/register?kind=user")
|
.post("/_matrix/client/r0/register?kind=user")
|
||||||
.body(registration(session.as_str().unwrap()))
|
.body(registration(session.as_str().unwrap()))
|
||||||
.dispatch().await;
|
.dispatch()
|
||||||
|
.await;
|
||||||
assert_eq!(response.status().code, 200);
|
assert_eq!(response.status().code, 200);
|
||||||
|
|
||||||
let mut login_response = client
|
let mut login_response = client
|
||||||
|
@ -73,7 +77,15 @@ async fn login_after_register_incorrect_password() {
|
||||||
.dispatch()
|
.dispatch()
|
||||||
.await;
|
.await;
|
||||||
let body = serde_json::from_str::<Value>(&login_response.body_string().await.unwrap()).unwrap();
|
let body = serde_json::from_str::<Value>(&login_response.body_string().await.unwrap()).unwrap();
|
||||||
assert_eq!(body.as_object().unwrap().get("errcode").unwrap().as_str().unwrap(), "M_FORBIDDEN");
|
assert_eq!(
|
||||||
|
body.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("errcode")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap(),
|
||||||
|
"M_FORBIDDEN"
|
||||||
|
);
|
||||||
assert_eq!(login_response.status().code, 403);
|
assert_eq!(login_response.status().code, 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +110,8 @@ fn registration(session: &str) -> String {
|
||||||
"device_id": "GHTYAJCE",
|
"device_id": "GHTYAJCE",
|
||||||
"initial_device_display_name": "Jungle Phone",
|
"initial_device_display_name": "Jungle Phone",
|
||||||
"inhibit_login": false
|
"inhibit_login": false
|
||||||
}).to_string()
|
})
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn login_with_password(password: &str) -> String {
|
fn login_with_password(password: &str) -> String {
|
||||||
|
@ -110,5 +123,6 @@ fn login_with_password(password: &str) -> String {
|
||||||
},
|
},
|
||||||
"password": password,
|
"password": password,
|
||||||
"initial_device_display_name": "Jungle Phone"
|
"initial_device_display_name": "Jungle Phone"
|
||||||
}).to_string()
|
})
|
||||||
|
.to_string()
|
||||||
}
|
}
|
|
@ -27,8 +27,10 @@ pub fn increment(old: Option<&[u8]>) -> Option<Vec<u8>> {
|
||||||
|
|
||||||
pub fn generate_keypair(old: Option<&[u8]>) -> Option<Vec<u8>> {
|
pub fn generate_keypair(old: Option<&[u8]>) -> Option<Vec<u8>> {
|
||||||
Some(
|
Some(
|
||||||
|
/*
|
||||||
old.map(|s| s.to_vec())
|
old.map(|s| s.to_vec())
|
||||||
.unwrap_or_else(|| ruma_signatures::Ed25519KeyPair::generate().unwrap()),
|
.unwrap_or_else(|| */
|
||||||
|
ruma_signatures::Ed25519KeyPair::generate().unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue