logo

mastofe

My custom branche(s) on git.pleroma.social/pleroma/mastofe
commit: 72bb3e03fdf4d8c886d41f3459000b336a3a362b
parent: f391a4673adc6d79bb3a46b493d599a4bf6d558f
Author: Eugen Rochko <eugen@zeonfederated.com>
Date:   Mon, 21 Aug 2017 22:57:34 +0200

Support more variations of ActivityPub keyId in signature (#4630)

- Tries to avoid performing HTTP request if the keyId is an actor URI
- Likewise if the URI is a fragment URI on top of actor URI
- Resolves public key, returns owner if the owner links back to the key

Diffstat:

Mapp/controllers/concerns/signature_verification.rb4+++-
Mapp/helpers/jsonld_helper.rb6+++++-
Mapp/lib/activitypub/activity.rb2+-
Mapp/lib/activitypub/activity/accept.rb2+-
Mapp/lib/activitypub/activity/reject.rb2+-
Mapp/lib/activitypub/activity/undo.rb2+-
Mapp/lib/activitypub/tag_manager.rb2+-
Aapp/services/activitypub/fetch_remote_key_service.rb47+++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb @@ -98,7 +98,9 @@ module SignatureVerification if key_id.start_with?('acct:') ResolveRemoteAccountService.new.call(key_id.gsub(/\Aacct:/, '')) elsif !ActivityPub::TagManager.instance.local_uri?(key_id) - ActivityPub::FetchRemoteAccountService.new.call(key_id) + account = ActivityPub::TagManager.instance.uri_to_resource(key_id, Account) + account ||= ActivityPub::FetchRemoteKeyService.new.call(key_id) + account end end end diff --git a/app/helpers/jsonld_helper.rb b/app/helpers/jsonld_helper.rb @@ -9,6 +9,10 @@ module JsonLdHelper value.is_a?(Array) ? value.first : value end + def value_or_id(value) + value.is_a?(String) ? value : value['id'] + end + def supported_context?(json) equals_or_includes?(json['@context'], ActivityPub::TagManager::CONTEXT) end @@ -20,7 +24,7 @@ module JsonLdHelper end def body_to_json(body) - body.nil? ? nil : Oj.load(body, mode: :strict) + body.is_a?(String) ? Oj.load(body, mode: :strict) : body rescue Oj::ParseError nil end diff --git a/app/lib/activitypub/activity.rb b/app/lib/activitypub/activity.rb @@ -58,7 +58,7 @@ class ActivityPub::Activity end def object_uri - @object_uri ||= @object.is_a?(String) ? @object : @object['id'] + @object_uri ||= value_or_id(@object) end def redis diff --git a/app/lib/activitypub/activity/accept.rb b/app/lib/activitypub/activity/accept.rb @@ -20,6 +20,6 @@ class ActivityPub::Activity::Accept < ActivityPub::Activity end def target_uri - @target_uri ||= @object['actor'] + @target_uri ||= value_or_id(@object['actor']) end end diff --git a/app/lib/activitypub/activity/reject.rb b/app/lib/activitypub/activity/reject.rb @@ -20,6 +20,6 @@ class ActivityPub::Activity::Reject < ActivityPub::Activity end def target_uri - @target_uri ||= @object['actor'] + @target_uri ||= value_or_id(@object['actor']) end end diff --git a/app/lib/activitypub/activity/undo.rb b/app/lib/activitypub/activity/undo.rb @@ -64,6 +64,6 @@ class ActivityPub::Activity::Undo < ActivityPub::Activity end def target_uri - @target_uri ||= @object['object'].is_a?(String) ? @object['object'] : @object['object']['id'] + @target_uri ||= value_or_id(@object['object']) end end diff --git a/app/lib/activitypub/tag_manager.rb b/app/lib/activitypub/tag_manager.rb @@ -93,7 +93,7 @@ class ActivityPub::TagManager elsif ::TagManager.instance.local_id?(uri) klass.find_by(id: ::TagManager.instance.unique_tag_to_local_id(uri, klass.to_s)) else - klass.find_by(uri: uri) + klass.find_by(uri: uri.split('#').first) end end end diff --git a/app/services/activitypub/fetch_remote_key_service.rb b/app/services/activitypub/fetch_remote_key_service.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +class ActivityPub::FetchRemoteKeyService < BaseService + include JsonLdHelper + + # Returns account that owns the key + def call(uri, prefetched_json = nil) + @json = body_to_json(prefetched_json) || fetch_resource(uri) + + return unless supported_context?(@json) && expected_type? + return find_account(uri, @json) if person? + + @owner = fetch_resource(owner_uri) + + return unless supported_context?(@owner) && confirmed_owner? + + find_account(owner_uri, @owner) + end + + private + + def find_account(uri, prefetched_json) + account = ActivityPub::TagManager.instance.uri_to_resource(uri, Account) + account ||= ActivityPub::FetchRemoteAccountService.new.call(uri, prefetched_json) + account + end + + def expected_type? + person? || public_key? + end + + def person? + @json['type'] == 'Person' + end + + def public_key? + @json['publicKeyPem'].present? && @json['owner'].present? + end + + def owner_uri + @owner_uri ||= value_or_id(@json['owner']) + end + + def confirmed_owner? + @owner['type'] == 'Person' && value_or_id(@owner['publicKey']) == @json['id'] + end +end