diff --git a/Cargo.lock b/Cargo.lock index 795da91..3b1278c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -631,9 +631,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -641,9 +641,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-executor" @@ -658,15 +658,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-macro" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", @@ -675,21 +675,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-channel", "futures-core", diff --git a/examples/federation/instance.rs b/examples/federation/instance.rs index c3eec7f..3a40e1a 100644 --- a/examples/federation/instance.rs +++ b/examples/federation/instance.rs @@ -16,7 +16,7 @@ use activitypub_federation::{ UrlVerifier, 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 http_signature_normalization_actix::prelude::VerifyDigest; use reqwest::Client; @@ -90,8 +90,6 @@ impl Instance { web::scope("") // Important: this ensures that the activity json matches the hashsum in signed // HTTP header - // TODO: it would be possible to get rid of this by verifying hash in - // receive_activity() .wrap(VerifyDigest::new(Sha256::new())) // Just a single, global inbox for simplicity .route("/inbox", web::post().to(http_post_user_inbox)), @@ -126,14 +124,13 @@ async fn http_get_user( /// Handles messages received in user inbox async fn http_post_user_inbox( request: HttpRequest, - payload: String, + payload: Payload, data: web::Data, ) -> Result { let data: InstanceHandle = data.into_inner().deref().clone(); - let activity = serde_json::from_str(&payload)?; receive_activity::, MyUser, InstanceHandle>( request, - activity, + payload, &data.clone().local_instance, &Data::new(data), ) diff --git a/src/core/inbox.rs b/src/core/inbox.rs index b8dde54..ab6d7fb 100644 --- a/src/core/inbox.rs +++ b/src/core/inbox.rs @@ -6,14 +6,21 @@ use crate::{ Error, 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 tracing::log::debug; +use tracing::{log::debug, warn}; /// Receive an activity and perform some basic checks, including HTTP signature verification. pub async fn receive_activity( request: HttpRequest, - activity: Activity, + payload: Payload, local_instance: &LocalInstance, data: &Data, ) -> Result::Error> @@ -21,10 +28,25 @@ where Activity: ActivityHandler + DeserializeOwned + Send + 'static, ActorT: ApubObject + Actor + Send + 'static, for<'de2> ::ApubType: serde::Deserialize<'de2>, - ::Error: - From + From + From<::Error>, + ::Error: From + + From + + From<::Error> + + From + + From, ::Error: From + From, { + 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_url_valid(activity.id(), &local_instance.settings).await?; if local_instance.is_local_url(activity.id()) { diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}