From e282fda1d5636b9e3df59f4c8fea0ad28cbddb33 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 3 Nov 2020 17:37:11 +0100 Subject: [PATCH] Ensure that posts, comments etc are addressed to public (ref #1220) --- .../src/activities/receive/community.rs | 10 ++- lemmy_apub/src/inbox/community_inbox.rs | 6 +- lemmy_apub/src/inbox/mod.rs | 15 +++- lemmy_apub/src/inbox/receive_for_community.rs | 74 +++++++++++-------- lemmy_apub/src/inbox/user_inbox.rs | 4 +- 5 files changed, 72 insertions(+), 37 deletions(-) diff --git a/lemmy_apub/src/activities/receive/community.rs b/lemmy_apub/src/activities/receive/community.rs index 78d8e5dafc..06c5192de4 100644 --- a/lemmy_apub/src/activities/receive/community.rs +++ b/lemmy_apub/src/activities/receive/community.rs @@ -1,4 +1,4 @@ -use crate::activities::receive::verify_activity_domains_valid; +use crate::{activities::receive::verify_activity_domains_valid, inbox::check_activity_is_public}; use activitystreams::{ activity::{ActorAndObjectRefExt, Delete, Remove, Undo}, base::{AnyBase, ExtendsExt}, @@ -45,6 +45,8 @@ pub(crate) async fn receive_remove_community( ) -> Result<(), LemmyError> { let remove = Delete::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&remove, expected_domain, true)?; + check_activity_is_public(&remove)?; + let community_uri = remove .object() .to_owned() @@ -85,9 +87,11 @@ pub(crate) async fn receive_undo_delete_community( community: Community, expected_domain: &Url, ) -> Result<(), LemmyError> { + check_activity_is_public(&undo)?; let inner = undo.object().to_owned().one().context(location_info!())?; let delete = Delete::from_any_base(inner)?.context(location_info!())?; verify_activity_domains_valid(&delete, expected_domain, true)?; + check_activity_is_public(&delete)?; let deleted_community = blocking(context.pool(), move |conn| { Community::update_deleted(conn, community.id, false) @@ -120,9 +124,13 @@ pub(crate) async fn receive_undo_remove_community( ) -> Result<(), LemmyError> { let undo = Undo::from_any_base(undo)?.context(location_info!())?; verify_activity_domains_valid(&undo, &expected_domain, true)?; + check_activity_is_public(&undo)?; + let inner = undo.object().to_owned().one().context(location_info!())?; let remove = Remove::from_any_base(inner)?.context(location_info!())?; verify_activity_domains_valid(&remove, &expected_domain, true)?; + check_activity_is_public(&remove)?; + let community_uri = remove .object() .to_owned() diff --git a/lemmy_apub/src/inbox/community_inbox.rs b/lemmy_apub/src/inbox/community_inbox.rs index d1ec91433f..f78020f931 100644 --- a/lemmy_apub/src/inbox/community_inbox.rs +++ b/lemmy_apub/src/inbox/community_inbox.rs @@ -1,6 +1,7 @@ use crate::{ activities::receive::verify_activity_domains_valid, inbox::{ + check_activity_is_public, get_activity_id, get_activity_to_and_cc, inbox_verify_http_signature, @@ -118,9 +119,6 @@ pub(crate) async fn community_receive_message( ) -> Result { // TODO: check if the sending user is banned by the community - // TODO: check that post/comment actions are addressed to public() (meaning activities from user - // to community need to be public() - let any_base = activity.clone().into_any_base()?; let actor_url = actor.actor_id()?; let activity_kind = activity.kind().context(location_info!())?; @@ -167,6 +165,8 @@ pub(crate) async fn community_receive_message( }; if do_announce { + // Check again that the activity is public, just to be sure + check_activity_is_public(&activity)?; to_community .send_announce(activity.into_any_base()?, context) .await?; diff --git a/lemmy_apub/src/inbox/mod.rs b/lemmy_apub/src/inbox/mod.rs index 0d8c76f910..c6ffe0bce4 100644 --- a/lemmy_apub/src/inbox/mod.rs +++ b/lemmy_apub/src/inbox/mod.rs @@ -8,9 +8,10 @@ use activitystreams::{ activity::ActorAndObjectRefExt, base::{AsBase, BaseExt, Extends}, object::{AsObject, ObjectExt}, + public, }; use actix_web::HttpRequest; -use anyhow::Context; +use anyhow::{anyhow, Context}; use lemmy_db::{activity::Activity, DbPool}; use lemmy_structs::blocking; use lemmy_utils::{location_info, LemmyError}; @@ -77,6 +78,18 @@ where Ok(to_and_cc) } +pub(crate) fn check_activity_is_public(activity: &T) -> Result<(), LemmyError> +where + T: AsBase + AsObject + ActorAndObjectRefExt, +{ + let to_and_cc = get_activity_to_and_cc(activity)?; + if to_and_cc.contains(&public()) { + Ok(()) + } else { + Err(anyhow!("Activity is not addressed to public").into()) + } +} + pub(crate) async fn inbox_verify_http_signature( activity: &T, context: &LemmyContext, diff --git a/lemmy_apub/src/inbox/receive_for_community.rs b/lemmy_apub/src/inbox/receive_for_community.rs index 59155f4af6..be518b172e 100644 --- a/lemmy_apub/src/inbox/receive_for_community.rs +++ b/lemmy_apub/src/inbox/receive_for_community.rs @@ -1,34 +1,37 @@ -use crate::activities::receive::{ - comment::{ - receive_create_comment, - receive_delete_comment, - receive_dislike_comment, - receive_like_comment, - receive_remove_comment, - receive_update_comment, +use crate::{ + activities::receive::{ + comment::{ + receive_create_comment, + receive_delete_comment, + receive_dislike_comment, + receive_like_comment, + receive_remove_comment, + receive_update_comment, + }, + comment_undo::{ + receive_undo_delete_comment, + receive_undo_dislike_comment, + receive_undo_like_comment, + receive_undo_remove_comment, + }, + post::{ + receive_create_post, + receive_delete_post, + receive_dislike_post, + receive_like_post, + receive_remove_post, + receive_update_post, + }, + post_undo::{ + receive_undo_delete_post, + receive_undo_dislike_post, + receive_undo_like_post, + receive_undo_remove_post, + }, + receive_unhandled_activity, + verify_activity_domains_valid, }, - comment_undo::{ - receive_undo_delete_comment, - receive_undo_dislike_comment, - receive_undo_like_comment, - receive_undo_remove_comment, - }, - post::{ - receive_create_post, - receive_delete_post, - receive_dislike_post, - receive_like_post, - receive_remove_post, - receive_update_post, - }, - post_undo::{ - receive_undo_delete_post, - receive_undo_dislike_post, - receive_undo_like_post, - receive_undo_remove_post, - }, - receive_unhandled_activity, - verify_activity_domains_valid, + inbox::check_activity_is_public, }; use activitystreams::{ activity::{Create, Delete, Dislike, Like, Remove, Undo, Update}, @@ -55,6 +58,7 @@ pub(in crate::inbox) async fn receive_create_for_community( ) -> Result<(), LemmyError> { let create = Create::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&create, &expected_domain, true)?; + check_activity_is_public(&create)?; match create.object().as_single_kind_str() { Some("Page") => receive_create_post(create, context, request_counter).await, @@ -72,6 +76,7 @@ pub(in crate::inbox) async fn receive_update_for_community( ) -> Result<(), LemmyError> { let update = Update::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&update, &expected_domain, true)?; + check_activity_is_public(&update)?; match update.object().as_single_kind_str() { Some("Page") => receive_update_post(update, context, request_counter).await, @@ -89,6 +94,7 @@ pub(in crate::inbox) async fn receive_like_for_community( ) -> Result<(), LemmyError> { let like = Like::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&like, &expected_domain, false)?; + check_activity_is_public(&like)?; match like.object().as_single_kind_str() { Some("Page") => receive_like_post(like, context, request_counter).await, @@ -114,6 +120,7 @@ pub(in crate::inbox) async fn receive_dislike_for_community( let dislike = Dislike::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&dislike, &expected_domain, false)?; + check_activity_is_public(&dislike)?; match dislike.object().as_single_kind_str() { Some("Page") => receive_dislike_post(dislike, context, request_counter).await, @@ -130,6 +137,7 @@ pub(in crate::inbox) async fn receive_delete_for_community( ) -> Result<(), LemmyError> { let delete = Delete::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&delete, &expected_domain, true)?; + check_activity_is_public(&delete)?; let object = delete .object() @@ -153,6 +161,7 @@ pub(in crate::inbox) async fn receive_remove_for_community( ) -> Result<(), LemmyError> { let remove = Remove::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&remove, &expected_domain, false)?; + check_activity_is_public(&remove)?; let cc = remove .cc() @@ -191,6 +200,7 @@ pub(in crate::inbox) async fn receive_undo_for_community( ) -> Result<(), LemmyError> { let undo = Undo::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&undo, &expected_domain.to_owned(), true)?; + check_activity_is_public(&undo)?; match undo.object().as_single_kind_str() { Some("Delete") => receive_undo_delete_for_community(context, undo, expected_domain).await, @@ -214,6 +224,7 @@ pub(in crate::inbox) async fn receive_undo_delete_for_community( let delete = Delete::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; verify_activity_domains_valid(&delete, &expected_domain, true)?; + check_activity_is_public(&delete)?; let object = delete .object() @@ -237,6 +248,7 @@ pub(in crate::inbox) async fn receive_undo_remove_for_community( let remove = Remove::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; verify_activity_domains_valid(&remove, &expected_domain, false)?; + check_activity_is_public(&remove)?; let object = remove .object() @@ -261,6 +273,7 @@ pub(in crate::inbox) async fn receive_undo_like_for_community( let like = Like::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; verify_activity_domains_valid(&like, &expected_domain, false)?; + check_activity_is_public(&like)?; let type_ = like .object() @@ -283,6 +296,7 @@ pub(in crate::inbox) async fn receive_undo_dislike_for_community( let dislike = Dislike::from_any_base(undo.object().to_owned().one().context(location_info!())?)? .context(location_info!())?; verify_activity_domains_valid(&dislike, &expected_domain, false)?; + check_activity_is_public(&dislike)?; let type_ = dislike .object() diff --git a/lemmy_apub/src/inbox/user_inbox.rs b/lemmy_apub/src/inbox/user_inbox.rs index 4c8cf28ba3..4b4470e5be 100644 --- a/lemmy_apub/src/inbox/user_inbox.rs +++ b/lemmy_apub/src/inbox/user_inbox.rs @@ -18,6 +18,7 @@ use crate::{ check_is_apub_id_valid, fetcher::get_or_fetch_and_upsert_community, inbox::{ + check_activity_is_public, get_activity_id, get_activity_to_and_cc, inbox_verify_http_signature, @@ -135,8 +136,6 @@ pub(crate) async fn user_receive_message( context: &LemmyContext, request_counter: &mut i32, ) -> Result { - // TODO: check that messages from community are addressed to public() - // TODO: must be addressed to one or more local users, or to followers of a remote community // TODO: if it is addressed to community followers, check that at least one local user is following it @@ -219,6 +218,7 @@ async fn receive_announce( ) -> Result<(), LemmyError> { let announce = Announce::from_any_base(activity)?.context(location_info!())?; verify_activity_domains_valid(&announce, &actor.actor_id()?, false)?; + check_activity_is_public(&announce)?; let kind = announce.object().as_single_kind_str(); let inner_activity = announce