From 2822fbc443addf08651961543e1a63abdd409d87 Mon Sep 17 00:00:00 2001 From: multiple creatures Date: Mon, 22 Jul 2019 21:12:54 -0500 Subject: [PATCH] move autoreject check to own module & check for reject before pulling resources --- app/helpers/autoreject_helper.rb | 53 +++++++++++++++++++ app/lib/activitypub/activity.rb | 34 +----------- .../fetch_remote_account_service.rb | 7 +++ .../fetch_remote_status_service.rb | 8 +++ .../activitypub/fetch_replies_service.rb | 7 ++- 5 files changed, 75 insertions(+), 34 deletions(-) create mode 100644 app/helpers/autoreject_helper.rb diff --git a/app/helpers/autoreject_helper.rb b/app/helpers/autoreject_helper.rb new file mode 100644 index 000000000..1fed32c3d --- /dev/null +++ b/app/helpers/autoreject_helper.rb @@ -0,0 +1,53 @@ +module AutorejectHelper + def should_reject?(uri = nil) + if @json + oid = @json['id'] + return true if ENV.fetch('REJECT_IF_ID_STARTS_WITH', '').split.any? { |r| oid.start_with?(r) } + return true if ENV.fetch('REJECT_IF_ID_CONTAINS', '').split.any? { |r| r.in?(oid) } + end + + if uri.nil? + if @object + uri = object_uri.start_with?('http') ? object_uri : @object['url'] + elsif @json + uri = @json['id'] + end + end + + return if uri.nil? + + domain = uri.scan(/[\w\-]+\.[\w\-]+(?:\.[\w\-]+)*/).first + blocks = DomainBlock.suspend + return true if blocks.where(domain: domain).or(blocks.where('domain LIKE ?', "%.#{domain}")).exists? + + if @object + context = @object['@context'] + elsif @json + context = @json['@context'] + else + return + end + + return unless context + + if context.is_a?(Array) + inline_context = context.find { |item| item.is_a?(Hash) } + if inline_context + keys = inline_context.keys + return true if ENV.fetch('REJECT_IF_CONTEXT_EQUALS', '').split.any? { |r| r.in?(keys) } + return true if ENV.fetch('REJECT_IF_CONTEXT_STARTS_WITH', '').split.any? { |r| keys.any? { |k| k.start_with?(r) } } + return true if ENV.fetch('REJECT_IF_CONTEXT_CONTAINS', '').split.any? { |r| keys.any? { |k| r.in?(k) } } + end + end + + false + end + + def autoreject?(uri = nil) + if (@options && @options[:imported]) || should_reject?(uri) + Rails.logger.info("Auto-rejected #{@json['type']} activity #{@json['id']}") + return true + end + false + end +end diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index d7a805ab3..fee8fcd25 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -2,6 +2,7 @@ class ActivityPub::Activity include JsonLdHelper + include AutorejectHelper include Redisable SUPPORTED_TYPES = %w(Note Question).freeze @@ -185,37 +186,4 @@ class ActivityPub::Activity Rails.logger.info("Rejected #{@json['type']} activity #{@json['id']} from #{@account.uri}#{@options[:relayed_through_account] && "via #{@options[:relayed_through_account].uri}"}") nil end - - def should_reject? - return unless @object - - oid = @json['id'] - return true if ENV.fetch('REJECT_IF_ID_STARTS_WITH', '').split.any? { |r| oid.start_with?(r) } - return true if ENV.fetch('REJECT_IF_ID_CONTAINS', '').split.any? { |r| r.in?(oid) } - - url = object_uri.start_with?('http') ? object_uri : @object['url'] - return if url.nil? - - domain = url.scan(/[\w\-]+\.[\w\-]+(?:\.[\w\-]+)*/).first - blocks = DomainBlock.suspend - return true if blocks.where(domain: domain).or(blocks.where('domain LIKE ?', "%.#{domain}")).exists? - - if @object['@context'].is_a?(Array) - inline_context = @object['@context'].find { |item| item.is_a?(Hash) } - if inline_context - keys = inline_context.keys - return true if ENV.fetch('REJECT_IF_CONTEXT_EQUALS', '').split.any? { |r| r.in?(keys) } - return true if ENV.fetch('REJECT_IF_CONTEXT_STARTS_WITH', '').split.any? { |r| keys.any? { |k| k.start_with?(r) } } - return true if ENV.fetch('REJECT_IF_CONTEXT_CONTAINS', '').split.any? { |r| keys.any? { |k| r.in?(k) } } - end - end - end - - def autoreject? - if @options[:imported] || should_reject? - Rails.logger.info("Auto-rejected #{@json['type']} activity #{@json['id']}") - return true - end - false - end end diff --git a/app/services/activitypub/fetch_remote_account_service.rb b/app/services/activitypub/fetch_remote_account_service.rb index 3c2044941..df1e79d7d 100644 --- a/app/services/activitypub/fetch_remote_account_service.rb +++ b/app/services/activitypub/fetch_remote_account_service.rb @@ -2,6 +2,7 @@ class ActivityPub::FetchRemoteAccountService < BaseService include JsonLdHelper + include AutorejectHelper SUPPORTED_TYPES = %w(Application Group Organization Person Service).freeze @@ -9,12 +10,14 @@ class ActivityPub::FetchRemoteAccountService < BaseService def call(uri, id: true, prefetched_body: nil, break_on_redirect: false, only_key: false) return ActivityPub::TagManager.instance.uri_to_resource(uri, Account) if ActivityPub::TagManager.instance.local_uri?(uri) + return if autoreject?(uri) @json = if prefetched_body.nil? fetch_resource(uri, id) else body_to_json(prefetched_body, compare_id: id ? uri : nil) end + return if autoreject? return if !supported_context? || !expected_type? || (break_on_redirect && @json['movedTo'].present?) @uri = @json['id'] @@ -59,4 +62,8 @@ class ActivityPub::FetchRemoteAccountService < BaseService def expected_type? equals_or_includes_any?(@json['type'], SUPPORTED_TYPES) end + + def object_uri + nil + end end diff --git a/app/services/activitypub/fetch_remote_status_service.rb b/app/services/activitypub/fetch_remote_status_service.rb index 469821032..42280ad74 100644 --- a/app/services/activitypub/fetch_remote_status_service.rb +++ b/app/services/activitypub/fetch_remote_status_service.rb @@ -2,15 +2,19 @@ class ActivityPub::FetchRemoteStatusService < BaseService include JsonLdHelper + include AutorejectHelper # Should be called when uri has already been checked for locality def call(uri, id: true, prefetched_body: nil, on_behalf_of: nil) + return if autoreject?(uri) + @json = if prefetched_body.nil? fetch_resource(uri, id, on_behalf_of) else body_to_json(prefetched_body, compare_id: id ? uri : nil) end + return if autoreject? return unless supported_context? && expected_type? return if actor_id.nil? || !trustworthy_attribution?(@json['id'], actor_id) @@ -49,4 +53,8 @@ class ActivityPub::FetchRemoteStatusService < BaseService def needs_update(actor) actor.possibly_stale? end + + def object_uri + nil + end end diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index 8cb309e52..3e9a2f02a 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -2,6 +2,7 @@ class ActivityPub::FetchRepliesService < BaseService include JsonLdHelper + include AutorejectHelper def call(parent_status, collection_or_uri, allow_synchronous_requests = true) @account = parent_status.account @@ -44,6 +45,10 @@ class ActivityPub::FetchRepliesService < BaseService # amplification attacks. # Also limit to 5 fetched replies to limit potential for DoS. - @items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(5) + @items.map { |item| value_or_id(item) }.reject { |uri| autoreject?(uri) || invalid_origin?(uri) }.take(5) + end + + def object_uri + nil end end