From 4dfc40324b1f3b20550982621501e162d2ed3bed Mon Sep 17 00:00:00 2001 From: multiple creatures Date: Thu, 8 Aug 2019 09:59:14 -0500 Subject: add new `reject unknown` policy option to prevent spam & harassment from large/undermoderated servers --- app/lib/activitypub/activity.rb | 24 ++++++++++++++++++------ app/lib/activitypub/activity/announce.rb | 2 +- app/lib/activitypub/activity/create.rb | 8 ++++++++ app/lib/activitypub/activity/follow.rb | 2 +- 4 files changed, 28 insertions(+), 8 deletions(-) (limited to 'app/lib/activitypub') diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index fee8fcd25..a708925a6 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -137,7 +137,7 @@ class ActivityPub::Activity redis.setex("delete_upon_arrival:#{@account.id}:#{uri}", 6.hours.seconds, uri) end - def status_from_object + def status_from_object(announced_by: nil) # If the status is already known, return it status = status_from_uri(object_uri) @@ -148,19 +148,20 @@ class ActivityPub::Activity actor_id = value_or_id(first_of_value(@object['attributedTo'])) || @account.uri if actor_id == @account.uri - return ActivityPub::Activity.factory({ 'type' => 'Create', 'actor' => actor_id, 'object' => @object }, @account).perform + return ActivityPub::Activity.factory({ 'type' => 'Create', 'actor' => actor_id, 'object' => @object }, @account, announced_by: announced_by).perform end end - fetch_remote_original_status + fetch_remote_original_status(announced_by: announced_by) end - def fetch_remote_original_status + def fetch_remote_original_status(announced_by: nil) if object_uri.start_with?('http') return if ActivityPub::TagManager.instance.local_uri?(object_uri) - ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first) + ActivityPub::FetchRemoteStatusService.new.call(object_uri, id: true, on_behalf_of: @account.followers.local.first, announced_by: announced_by) elsif @object['url'].present? - ::FetchRemoteStatusService.new.call(@object['url']) + options[:id] = true + ::FetchRemoteStatusService.new.call(@object['url'], announced_by: announced_by) end end @@ -182,6 +183,17 @@ class ActivityPub::Activity @options[:relayed_through_account] && Relay.find_by(inbox_url: @options[:relayed_through_account].inbox_url)&.enabled? end + def rejecting_unknown?(account = nil) + account = @account if account.nil? + DomainBlock.where(domain: account.domain, reject_unknown: true).exists? + end + + def known?(account = nil) + account = @account if account.nil? + return true if account.known? + account.passive_relationships.exists? + end + def reject_payload! Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}") nil diff --git a/app/lib/activitypub/activity/announce.rb b/app/lib/activitypub/activity/announce.rb index ada46b378..245126123 100644 --- a/app/lib/activitypub/activity/announce.rb +++ b/app/lib/activitypub/activity/announce.rb @@ -5,7 +5,7 @@ class ActivityPub::Activity::Announce < ActivityPub::Activity return if autoreject? return reject_payload! if !@options[:imported] && (delete_arrived_first?(@json['id']) || !related_to_local_activity?) - original_status = status_from_object + original_status = status_from_object(announced_by: @account) return reject_payload! if original_status.nil? || !announceable?(original_status) diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb index 140226481..37aac4d59 100644 --- a/app/lib/activitypub/activity/create.rb +++ b/app/lib/activitypub/activity/create.rb @@ -5,6 +5,14 @@ class ActivityPub::Activity::Create < ActivityPub::Activity return if autoreject? return reject_payload! if unsupported_object_type? || !@options[:imported] && (invalid_origin?(@object['id']) || Tombstone.exists?(uri: @object['id']) || !related_to_local_activity?) + unless known? + if @options[:announced_by].nil? + return reject_payload! if !@options[:requested] && rejecting_unknown? + else + @account.mark_known! if known?(@options[:announced_by]) + end + end + RedisLock.acquire(lock_options) do |lock| if lock.acquired? return if !@options[:imported] && (delete_arrived_first?(object_uri) || poll_vote?) diff --git a/app/lib/activitypub/activity/follow.rb b/app/lib/activitypub/activity/follow.rb index 84041ec8d..bde507dcf 100644 --- a/app/lib/activitypub/activity/follow.rb +++ b/app/lib/activitypub/activity/follow.rb @@ -7,7 +7,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id']) || @account.requested?(target_account) - if target_account.blocking?(@account) || target_account.domain_blocking?(@account.domain) || target_account.moved? + if (rejecting_unknown? && !known?) || target_account.blocking?(@account) || target_account.domain_blocking?(@account.domain) || target_account.moved? reject_follow_request!(target_account) return end -- cgit