about summary refs log tree commit diff
path: root/app/lib/activitypub
diff options
context:
space:
mode:
authormultiple creatures <dev@multiple-creature.party>2019-08-08 09:59:14 -0500
committermultiple creatures <dev@multiple-creature.party>2019-08-08 12:46:17 -0500
commit4dfc40324b1f3b20550982621501e162d2ed3bed (patch)
tree1578cba8809b7db27dc82f4d439471194d5fad31 /app/lib/activitypub
parentd019e55b7bc496d3c4d942fb4ffe65bb7e149249 (diff)
add new `reject unknown` policy option to prevent spam & harassment from large/undermoderated servers
Diffstat (limited to 'app/lib/activitypub')
-rw-r--r--app/lib/activitypub/activity.rb24
-rw-r--r--app/lib/activitypub/activity/announce.rb2
-rw-r--r--app/lib/activitypub/activity/create.rb8
-rw-r--r--app/lib/activitypub/activity/follow.rb2
4 files changed, 28 insertions, 8 deletions
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