Fix processing LDSigned activities from actors with unknown public keys (#27474)
This commit is contained in:
		@@ -18,8 +18,8 @@ class ActivityPub::LinkedDataSignature
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return unless type == 'RsaSignature2017'
 | 
					    return unless type == 'RsaSignature2017'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    creator   = ActivityPub::TagManager.instance.uri_to_actor(creator_uri)
 | 
					    creator = ActivityPub::TagManager.instance.uri_to_actor(creator_uri)
 | 
				
			||||||
    creator ||= ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false)
 | 
					    creator = ActivityPub::FetchRemoteKeyService.new.call(creator_uri, id: false) if creator&.public_key.blank?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return if creator.nil?
 | 
					    return if creator.nil?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,6 +28,8 @@ class ActivityPub::LinkedDataSignature
 | 
				
			|||||||
    to_be_verified = options_hash + document_hash
 | 
					    to_be_verified = options_hash + document_hash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    creator if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified)
 | 
					    creator if creator.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), Base64.decode64(signature), to_be_verified)
 | 
				
			||||||
 | 
					  rescue OpenSSL::PKey::RSAError
 | 
				
			||||||
 | 
					    false
 | 
				
			||||||
  end
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def sign!(creator, sign_with: nil)
 | 
					  def sign!(creator, sign_with: nil)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,6 +34,40 @@ RSpec.describe ActivityPub::LinkedDataSignature do
 | 
				
			|||||||
      end
 | 
					      end
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    context 'when local account record is missing a public key' do
 | 
				
			||||||
 | 
					      let(:raw_signature) do
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          'creator' => 'http://example.com/alice',
 | 
				
			||||||
 | 
					          'created' => '2017-09-23T20:21:34Z',
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      let(:signature) { raw_signature.merge('type' => 'RsaSignature2017', 'signatureValue' => sign(sender, raw_signature, raw_json)) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      let(:service_stub) { instance_double(ActivityPub::FetchRemoteKeyService) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      before do
 | 
				
			||||||
 | 
					        # Ensure signature is computed with the old key
 | 
				
			||||||
 | 
					        signature
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Unset key
 | 
				
			||||||
 | 
					        old_key = sender.public_key
 | 
				
			||||||
 | 
					        sender.update!(private_key: '', public_key: '')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        allow(ActivityPub::FetchRemoteKeyService).to receive(:new).and_return(service_stub)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        allow(service_stub).to receive(:call).with('http://example.com/alice', id: false) do
 | 
				
			||||||
 | 
					          sender.update!(public_key: old_key)
 | 
				
			||||||
 | 
					          sender
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      it 'fetches key and returns creator' do
 | 
				
			||||||
 | 
					        expect(subject.verify_actor!).to eq sender
 | 
				
			||||||
 | 
					        expect(service_stub).to have_received(:call).with('http://example.com/alice', id: false).once
 | 
				
			||||||
 | 
					      end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context 'when signature is missing' do
 | 
					    context 'when signature is missing' do
 | 
				
			||||||
      let(:signature) { nil }
 | 
					      let(:signature) { nil }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user