diff options
author | Claire <claire.github-309c@sitedethib.com> | 2022-09-21 22:45:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-21 22:45:57 +0200 |
commit | 8cf7006d4efbcfdd4a4ab688db1bcc73a2915a47 (patch) | |
tree | e07bfabeb68cdd8ff5832069d1d64bf3b7ae685a /app/controllers | |
parent | 84aff598ea0b5670ef2a0d1009bca9c9136c2d50 (diff) |
Refactor ActivityPub handling to prepare for non-Account actors (#19212)
* Move ActivityPub::FetchRemoteAccountService to ActivityPub::FetchRemoteActorService ActivityPub::FetchRemoteAccountService is kept as a wrapper for when the actor is specifically required to be an Account * Refactor SignatureVerification to allow non-Account actors * fixup! Move ActivityPub::FetchRemoteAccountService to ActivityPub::FetchRemoteActorService * Refactor ActivityPub::FetchRemoteKeyService to potentially return non-Account actors * Refactor inbound ActivityPub payload processing to accept non-Account actors * Refactor inbound ActivityPub processing to accept activities relayed through non-Account * Refactor how Account key URIs are built * Refactor Request and drop unused key_id_format parameter * Rename ActivityPub::Dereferencer `signature_account` to `signature_actor`
Diffstat (limited to 'app/controllers')
-rw-r--r-- | app/controllers/accounts_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/activitypub/claims_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/activitypub/collections_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/activitypub/followers_synchronizations_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/activitypub/inboxes_controller.rb | 10 | ||||
-rw-r--r-- | app/controllers/activitypub/outboxes_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/activitypub/replies_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/concerns/signature_verification.rb | 52 | ||||
-rw-r--r-- | app/controllers/follower_accounts_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/following_accounts_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/statuses_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/tags_controller.rb | 2 |
12 files changed, 46 insertions, 36 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index fe7d934dc..d92f91b30 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -7,7 +7,7 @@ class AccountsController < ApplicationController include AccountControllerConcern include SignatureAuthentication - before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } + before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_cache_headers before_action :set_body_classes diff --git a/app/controllers/activitypub/claims_controller.rb b/app/controllers/activitypub/claims_controller.rb index 08ad952df..339333e46 100644 --- a/app/controllers/activitypub/claims_controller.rb +++ b/app/controllers/activitypub/claims_controller.rb @@ -6,7 +6,7 @@ class ActivityPub::ClaimsController < ActivityPub::BaseController skip_before_action :authenticate_user! - before_action :require_signature! + before_action :require_account_signature! before_action :set_claim_result def create diff --git a/app/controllers/activitypub/collections_controller.rb b/app/controllers/activitypub/collections_controller.rb index e4e994a98..d94a285ea 100644 --- a/app/controllers/activitypub/collections_controller.rb +++ b/app/controllers/activitypub/collections_controller.rb @@ -4,7 +4,7 @@ class ActivityPub::CollectionsController < ActivityPub::BaseController include SignatureVerification include AccountOwnedConcern - before_action :require_signature!, if: :authorized_fetch_mode? + before_action :require_account_signature!, if: :authorized_fetch_mode? before_action :set_items before_action :set_size before_action :set_type diff --git a/app/controllers/activitypub/followers_synchronizations_controller.rb b/app/controllers/activitypub/followers_synchronizations_controller.rb index 940b77cf0..4e445bcb1 100644 --- a/app/controllers/activitypub/followers_synchronizations_controller.rb +++ b/app/controllers/activitypub/followers_synchronizations_controller.rb @@ -4,7 +4,7 @@ class ActivityPub::FollowersSynchronizationsController < ActivityPub::BaseContro include SignatureVerification include AccountOwnedConcern - before_action :require_signature! + before_action :require_account_signature! before_action :set_items before_action :set_cache_headers diff --git a/app/controllers/activitypub/inboxes_controller.rb b/app/controllers/activitypub/inboxes_controller.rb index 92dcb5ac7..5ee85474e 100644 --- a/app/controllers/activitypub/inboxes_controller.rb +++ b/app/controllers/activitypub/inboxes_controller.rb @@ -6,7 +6,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController include AccountOwnedConcern before_action :skip_unknown_actor_activity - before_action :require_signature! + before_action :require_actor_signature! skip_before_action :authenticate_user! def create @@ -49,17 +49,17 @@ class ActivityPub::InboxesController < ActivityPub::BaseController end def upgrade_account - if signed_request_account.ostatus? + if signed_request_account&.ostatus? signed_request_account.update(last_webfingered_at: nil) ResolveAccountWorker.perform_async(signed_request_account.acct) end - DeliveryFailureTracker.reset!(signed_request_account.inbox_url) + DeliveryFailureTracker.reset!(signed_request_actor.inbox_url) end def process_collection_synchronization raw_params = request.headers['Collection-Synchronization'] - return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' + return if raw_params.blank? || ENV['DISABLE_FOLLOWERS_SYNCHRONIZATION'] == 'true' || signed_request_account.nil? # Re-using the syntax for signature parameters tree = SignatureParamsParser.new.parse(raw_params) @@ -71,6 +71,6 @@ class ActivityPub::InboxesController < ActivityPub::BaseController end def process_payload - ActivityPub::ProcessingWorker.perform_async(signed_request_account.id, body, @account&.id) + ActivityPub::ProcessingWorker.perform_async(signed_request_actor.id, body, @account&.id, signed_request_actor.class.name) end end diff --git a/app/controllers/activitypub/outboxes_controller.rb b/app/controllers/activitypub/outboxes_controller.rb index cd3992502..60d201f76 100644 --- a/app/controllers/activitypub/outboxes_controller.rb +++ b/app/controllers/activitypub/outboxes_controller.rb @@ -6,7 +6,7 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController include SignatureVerification include AccountOwnedConcern - before_action :require_signature!, if: :authorized_fetch_mode? + before_action :require_account_signature!, if: :authorized_fetch_mode? before_action :set_statuses before_action :set_cache_headers diff --git a/app/controllers/activitypub/replies_controller.rb b/app/controllers/activitypub/replies_controller.rb index 4ff7cfa08..8e0f9de2e 100644 --- a/app/controllers/activitypub/replies_controller.rb +++ b/app/controllers/activitypub/replies_controller.rb @@ -7,7 +7,7 @@ class ActivityPub::RepliesController < ActivityPub::BaseController DESCENDANTS_LIMIT = 60 - before_action :require_signature!, if: :authorized_fetch_mode? + before_action :require_account_signature!, if: :authorized_fetch_mode? before_action :set_status before_action :set_cache_headers before_action :set_replies diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index 4da068aed..2394574b3 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -45,10 +45,14 @@ module SignatureVerification end end - def require_signature! + def require_account_signature! render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_account end + def require_actor_signature! + render plain: signature_verification_failure_reason, status: signature_verification_failure_code unless signed_request_actor + end + def signed_request? request.headers['Signature'].present? end @@ -68,7 +72,11 @@ module SignatureVerification end def signed_request_account - return @signed_request_account if defined?(@signed_request_account) + signed_request_actor.is_a?(Account) ? signed_request_actor : nil + end + + def signed_request_actor + return @signed_request_actor if defined?(@signed_request_actor) raise SignatureVerificationError, 'Request not signed' unless signed_request? raise SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters? @@ -78,22 +86,22 @@ module SignatureVerification verify_signature_strength! verify_body_digest! - account = account_from_key_id(signature_params['keyId']) + actor = actor_from_key_id(signature_params['keyId']) - raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if account.nil? + raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil? signature = Base64.decode64(signature_params['signature']) compare_signed_string = build_signed_string - return account unless verify_signature(account, signature, compare_signed_string).nil? + return actor unless verify_signature(actor, signature, compare_signed_string).nil? - account = stoplight_wrap_request { account.possibly_stale? ? account.refresh! : account_refresh_key(account) } + actor = stoplight_wrap_request { actor_refresh_key!(actor) } - raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if account.nil? + raise SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil? - return account unless verify_signature(account, signature, compare_signed_string).nil? + return actor unless verify_signature(actor, signature, compare_signed_string).nil? - fail_with! "Verification failed for #{account.username}@#{account.domain} #{account.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)" + fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)" rescue SignatureVerificationError => e fail_with! e.message rescue HTTP::Error, OpenSSL::SSL::SSLError => e @@ -112,7 +120,7 @@ module SignatureVerification def fail_with!(message) @signature_verification_failure_reason = message - @signed_request_account = nil + @signed_request_actor = nil end def signature_params @@ -160,10 +168,10 @@ module SignatureVerification raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}" end - def verify_signature(account, signature, compare_signed_string) - if account.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string) - @signed_request_account = account - @signed_request_account + def verify_signature(actor, signature, compare_signed_string) + if actor.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string) + @signed_request_actor = actor + @signed_request_actor end rescue OpenSSL::PKey::RSAError nil @@ -226,7 +234,7 @@ module SignatureVerification signature_params['keyId'].blank? || signature_params['signature'].blank? end - def account_from_key_id(key_id) + def actor_from_key_id(key_id) domain = key_id.start_with?('acct:') ? key_id.split('@').last : key_id if domain_not_allowed?(domain) @@ -237,13 +245,13 @@ module SignatureVerification if key_id.start_with?('acct:') stoplight_wrap_request { ResolveAccountService.new.call(key_id.gsub(/\Aacct:/, ''), suppress_errors: false) } elsif !ActivityPub::TagManager.instance.local_uri?(key_id) - account = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account) + account = ActivityPub::TagManager.instance.uri_to_actor(key_id) account ||= stoplight_wrap_request { ActivityPub::FetchRemoteKeyService.new.call(key_id, id: false, suppress_errors: false) } account end rescue Mastodon::PrivateNetworkAddressError => e raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})" - rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteAccountService::Error, ActivityPub::FetchRemoteKeyService::Error, Webfinger::Error => e + rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, ActivityPub::FetchRemoteKeyService::Error, Webfinger::Error => e raise SignatureVerificationError, e.message end @@ -255,12 +263,14 @@ module SignatureVerification .run end - def account_refresh_key(account) - return if account.local? || !account.activitypub? - ActivityPub::FetchRemoteAccountService.new.call(account.uri, only_key: true, suppress_errors: false) + def actor_refresh_key!(actor) + return if actor.local? || !actor.activitypub? + return actor.refresh! if actor.respond_to?(:refresh!) && actor.possibly_stale? + + ActivityPub::FetchRemoteActorService.new.call(actor.uri, only_key: true, suppress_errors: false) rescue Mastodon::PrivateNetworkAddressError => e raise SignatureVerificationError, "Requests to private network addresses are disallowed (tried to query #{e.host})" - rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteAccountService::Error, Webfinger::Error => e + rescue Mastodon::HostValidationError, ActivityPub::FetchRemoteActorService::Error, Webfinger::Error => e raise SignatureVerificationError, e.message end end diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb index f3f8336c9..da7bb4ed2 100644 --- a/app/controllers/follower_accounts_controller.rb +++ b/app/controllers/follower_accounts_controller.rb @@ -4,7 +4,7 @@ class FollowerAccountsController < ApplicationController include AccountControllerConcern include SignatureVerification - before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } + before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_cache_headers skip_around_action :set_locale, if: -> { request.format == :json } diff --git a/app/controllers/following_accounts_controller.rb b/app/controllers/following_accounts_controller.rb index 69f0321f8..c37e3b68c 100644 --- a/app/controllers/following_accounts_controller.rb +++ b/app/controllers/following_accounts_controller.rb @@ -4,7 +4,7 @@ class FollowingAccountsController < ApplicationController include AccountControllerConcern include SignatureVerification - before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } + before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_cache_headers skip_around_action :set_locale, if: -> { request.format == :json } diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb index c52170d08..7d9db4d5b 100644 --- a/app/controllers/statuses_controller.rb +++ b/app/controllers/statuses_controller.rb @@ -8,7 +8,7 @@ class StatusesController < ApplicationController layout 'public' - before_action :require_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? } + before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? } before_action :set_status before_action :set_instance_presenter before_action :set_link_headers diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index b82da8f0c..6dbc2667a 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -8,7 +8,7 @@ class TagsController < ApplicationController layout 'public' - before_action :require_signature!, if: -> { request.format == :json && authorized_fetch_mode? } + before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? } before_action :authenticate_user!, if: :whitelist_mode? before_action :set_local before_action :set_tag |