parent
da32da5a67
commit
3a8dd5c6db
4 changed files with 44 additions and 28 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -631,9 +631,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
|
checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
|
@ -641,9 +641,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
|
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
|
@ -658,15 +658,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
|
checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
|
checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -675,21 +675,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
|
checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
|
checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.24"
|
version = "0.3.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
|
checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
|
|
@ -16,7 +16,7 @@ use activitypub_federation::{
|
||||||
UrlVerifier,
|
UrlVerifier,
|
||||||
APUB_JSON_CONTENT_TYPE,
|
APUB_JSON_CONTENT_TYPE,
|
||||||
};
|
};
|
||||||
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer};
|
use actix_web::{web, web::Payload, App, HttpRequest, HttpResponse, HttpServer};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use http_signature_normalization_actix::prelude::VerifyDigest;
|
use http_signature_normalization_actix::prelude::VerifyDigest;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
@ -90,8 +90,6 @@ impl Instance {
|
||||||
web::scope("")
|
web::scope("")
|
||||||
// Important: this ensures that the activity json matches the hashsum in signed
|
// Important: this ensures that the activity json matches the hashsum in signed
|
||||||
// HTTP header
|
// HTTP header
|
||||||
// TODO: it would be possible to get rid of this by verifying hash in
|
|
||||||
// receive_activity()
|
|
||||||
.wrap(VerifyDigest::new(Sha256::new()))
|
.wrap(VerifyDigest::new(Sha256::new()))
|
||||||
// Just a single, global inbox for simplicity
|
// Just a single, global inbox for simplicity
|
||||||
.route("/inbox", web::post().to(http_post_user_inbox)),
|
.route("/inbox", web::post().to(http_post_user_inbox)),
|
||||||
|
@ -126,14 +124,13 @@ async fn http_get_user(
|
||||||
/// Handles messages received in user inbox
|
/// Handles messages received in user inbox
|
||||||
async fn http_post_user_inbox(
|
async fn http_post_user_inbox(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
payload: String,
|
payload: Payload,
|
||||||
data: web::Data<InstanceHandle>,
|
data: web::Data<InstanceHandle>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let data: InstanceHandle = data.into_inner().deref().clone();
|
let data: InstanceHandle = data.into_inner().deref().clone();
|
||||||
let activity = serde_json::from_str(&payload)?;
|
|
||||||
receive_activity::<WithContext<PersonAcceptedActivities>, MyUser, InstanceHandle>(
|
receive_activity::<WithContext<PersonAcceptedActivities>, MyUser, InstanceHandle>(
|
||||||
request,
|
request,
|
||||||
activity,
|
payload,
|
||||||
&data.clone().local_instance,
|
&data.clone().local_instance,
|
||||||
&Data::new(data),
|
&Data::new(data),
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,14 +6,21 @@ use crate::{
|
||||||
Error,
|
Error,
|
||||||
LocalInstance,
|
LocalInstance,
|
||||||
};
|
};
|
||||||
use actix_web::{HttpRequest, HttpResponse};
|
use actix_web::{
|
||||||
|
web::{Bytes, Payload},
|
||||||
|
FromRequest,
|
||||||
|
HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use http_signature_normalization_actix::prelude::DigestVerified;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use tracing::log::debug;
|
use tracing::{log::debug, warn};
|
||||||
|
|
||||||
/// Receive an activity and perform some basic checks, including HTTP signature verification.
|
/// Receive an activity and perform some basic checks, including HTTP signature verification.
|
||||||
pub async fn receive_activity<Activity, ActorT, Datatype>(
|
pub async fn receive_activity<Activity, ActorT, Datatype>(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
activity: Activity,
|
payload: Payload,
|
||||||
local_instance: &LocalInstance,
|
local_instance: &LocalInstance,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<HttpResponse, <Activity as ActivityHandler>::Error>
|
) -> Result<HttpResponse, <Activity as ActivityHandler>::Error>
|
||||||
|
@ -21,10 +28,25 @@ where
|
||||||
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
Activity: ActivityHandler<DataType = Datatype> + DeserializeOwned + Send + 'static,
|
||||||
ActorT: ApubObject<DataType = Datatype> + Actor + Send + 'static,
|
ActorT: ApubObject<DataType = Datatype> + Actor + Send + 'static,
|
||||||
for<'de2> <ActorT as ApubObject>::ApubType: serde::Deserialize<'de2>,
|
for<'de2> <ActorT as ApubObject>::ApubType: serde::Deserialize<'de2>,
|
||||||
<Activity as ActivityHandler>::Error:
|
<Activity as ActivityHandler>::Error: From<anyhow::Error>
|
||||||
From<anyhow::Error> + From<Error> + From<<ActorT as ApubObject>::Error>,
|
+ From<Error>
|
||||||
|
+ From<<ActorT as ApubObject>::Error>
|
||||||
|
+ From<serde_json::Error>
|
||||||
|
+ From<http_signature_normalization_actix::digest::middleware::VerifyError>,
|
||||||
<ActorT as ApubObject>::Error: From<Error> + From<anyhow::Error>,
|
<ActorT as ApubObject>::Error: From<Error> + From<anyhow::Error>,
|
||||||
{
|
{
|
||||||
|
let mut payload = payload.into_inner();
|
||||||
|
// ensure that payload hash was checked against digest header by middleware
|
||||||
|
DigestVerified::from_request(&request, &mut payload).await?;
|
||||||
|
|
||||||
|
let bytes = Bytes::from_request(&request, &mut payload)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
warn!("{}", e);
|
||||||
|
anyhow!("Failed to parse request body")
|
||||||
|
})?;
|
||||||
|
let activity: Activity = serde_json::from_slice(&bytes)?;
|
||||||
|
|
||||||
verify_domains_match(activity.id(), activity.actor())?;
|
verify_domains_match(activity.id(), activity.actor())?;
|
||||||
verify_url_valid(activity.id(), &local_instance.settings).await?;
|
verify_url_valid(activity.id(), &local_instance.settings).await?;
|
||||||
if local_instance.is_local_url(activity.id()) {
|
if local_instance.is_local_url(activity.id()) {
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
println!("Hello, world!");
|
|
||||||
}
|
|
Loading…
Reference in a new issue