From 120683f52266900d0fede7bd67c43133bbc26bea Mon Sep 17 00:00:00 2001 From: Fire Demon Date: Fri, 17 Jul 2020 19:46:24 -0500 Subject: [Federation] Add support for signing fetches as the participating local user in various scenarios --- app/lib/activitypub/activity.rb | 4 ++-- app/services/activitypub/fetch_featured_collection_service.rb | 3 ++- app/services/activitypub/fetch_replies_service.rb | 4 ++-- app/services/fetch_remote_status_service.rb | 7 +++++-- app/services/fetch_resource_service.rb | 6 ++++-- app/services/resolve_url_service.rb | 4 ++-- app/workers/fetch_reply_worker.rb | 4 ++-- app/workers/thread_resolve_worker.rb | 4 ++-- 8 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb index ab946470b..cff6b569a 100644 --- a/app/lib/activitypub/activity.rb +++ b/app/lib/activitypub/activity.rb @@ -196,9 +196,9 @@ class ActivityPub::Activity def fetch_remote_original_status 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: signed_fetch_account) elsif @object['url'].present? - ::FetchRemoteStatusService.new.call(@object['url']) + ::FetchRemoteStatusService.new.call(@object['url'], nil, signed_fetch_account) end end diff --git a/app/services/activitypub/fetch_featured_collection_service.rb b/app/services/activitypub/fetch_featured_collection_service.rb index 2c2770466..c8006afce 100644 --- a/app/services/activitypub/fetch_featured_collection_service.rb +++ b/app/services/activitypub/fetch_featured_collection_service.rb @@ -22,9 +22,10 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService private def process_items(items) + first_local_follower = @account.followers.local.first status_ids = items.map { |item| value_or_id(item) } .reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) } - .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) } + .map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri, on_behalf_of: first_local_follower) } .compact .select { |status| status.account_id == @account.id } .map(&:id) diff --git a/app/services/activitypub/fetch_replies_service.rb b/app/services/activitypub/fetch_replies_service.rb index 8cb309e52..0145f25da 100644 --- a/app/services/activitypub/fetch_replies_service.rb +++ b/app/services/activitypub/fetch_replies_service.rb @@ -43,7 +43,7 @@ class ActivityPub::FetchRepliesService < BaseService # Only fetch replies to the same server as the original status to avoid # 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) + # Also limit to 25 fetched replies to limit potential for DoS. + @items.map { |item| value_or_id(item) }.reject { |uri| invalid_origin?(uri) }.take(25) end end diff --git a/app/services/fetch_remote_status_service.rb b/app/services/fetch_remote_status_service.rb index eafde4d4a..c5e8c5d0f 100644 --- a/app/services/fetch_remote_status_service.rb +++ b/app/services/fetch_remote_status_service.rb @@ -1,14 +1,17 @@ # frozen_string_literal: true class FetchRemoteStatusService < BaseService - def call(url, prefetched_body = nil) + def call(url, prefetched_body = nil, on_behalf_of = nil) if prefetched_body.nil? - resource_url, resource_options = FetchResourceService.new.call(url) + resource_url, resource_options = FetchResourceService.new.call(url, on_behalf_of: on_behalf_of) else resource_url = url resource_options = { prefetched_body: prefetched_body } end + resource_options ||= {} + resource_options[:on_behalf_of] = on_behalf_of + ActivityPub::FetchRemoteStatusService.new.call(resource_url, **resource_options) unless resource_url.nil? end end diff --git a/app/services/fetch_resource_service.rb b/app/services/fetch_resource_service.rb index 6c0093cd4..3264d14c2 100644 --- a/app/services/fetch_resource_service.rb +++ b/app/services/fetch_resource_service.rb @@ -7,9 +7,11 @@ class FetchResourceService < BaseService attr_reader :response_code - def call(url) + def call(url, on_behalf_of: nil) return if url.blank? + @on_behalf_of = on_behalf_of + process(url) rescue HTTP::Error, OpenSSL::SSL::SSLError, Addressable::URI::InvalidURIError, Mastodon::HostValidationError, Mastodon::LengthValidationError => e Rails.logger.debug "Error fetching resource #{@url}: #{e}" @@ -35,7 +37,7 @@ class FetchResourceService < BaseService # and prevents even public resources from being fetched, so # don't do it - request.on_behalf_of(Account.representative) unless Rails.env.development? + request.on_behalf_of(@on_behalf_of || Account.representative) unless Rails.env.development? end.perform(&block) end diff --git a/app/services/resolve_url_service.rb b/app/services/resolve_url_service.rb index 78080d878..bac41f961 100644 --- a/app/services/resolve_url_service.rb +++ b/app/services/resolve_url_service.rb @@ -23,7 +23,7 @@ class ResolveURLService < BaseService if equals_or_includes_any?(type, ActivityPub::FetchRemoteAccountService::SUPPORTED_TYPES) ActivityPub::FetchRemoteAccountService.new.call(resource_url, prefetched_body: body) elsif equals_or_includes_any?(type, ActivityPub::Activity::Create::SUPPORTED_TYPES + ActivityPub::Activity::Create::CONVERTED_TYPES) - status = FetchRemoteStatusService.new.call(resource_url, body) + status = FetchRemoteStatusService.new.call(resource_url, body, @on_behalf_of) authorize_with @on_behalf_of, status, :show? unless status.nil? status end @@ -42,7 +42,7 @@ class ResolveURLService < BaseService end def fetched_resource - @fetched_resource ||= fetch_resource_service.call(@url) + @fetched_resource ||= fetch_resource_service.call(@url, on_behalf_of: @on_behalf_of) end def fetch_resource_service diff --git a/app/workers/fetch_reply_worker.rb b/app/workers/fetch_reply_worker.rb index f7aa25e81..1490f283c 100644 --- a/app/workers/fetch_reply_worker.rb +++ b/app/workers/fetch_reply_worker.rb @@ -6,7 +6,7 @@ class FetchReplyWorker sidekiq_options queue: 'pull', retry: 3 - def perform(child_url) - FetchRemoteStatusService.new.call(child_url) + def perform(child_url, on_behalf_of = nil) + FetchRemoteStatusService.new.call(child_url, nil, on_behalf_of) end end diff --git a/app/workers/thread_resolve_worker.rb b/app/workers/thread_resolve_worker.rb index 8bba9ca75..6516d1bc0 100644 --- a/app/workers/thread_resolve_worker.rb +++ b/app/workers/thread_resolve_worker.rb @@ -6,9 +6,9 @@ class ThreadResolveWorker sidekiq_options queue: 'pull', retry: 3 - def perform(child_status_id, parent_url) + def perform(child_status_id, parent_url, on_behalf_of = nil) child_status = Status.find(child_status_id) - parent_status = FetchRemoteStatusService.new.call(parent_url) + parent_status = FetchRemoteStatusService.new.call(parent_url, nil, on_behalf_of) return if parent_status.nil? -- cgit