This is a fix for public messages, where a malicious pod could spoof a message from someone a user was connected to, as the verified signatures were not checked that the object was also from said sender. This hole only affected public messages, and the private part of code had the correct checks THX to s-f-s(Stephan Schulz) for reporting and tracking down this issue, and props to Raven24(florian.staudacher@gmx.at) for helping me test the patch
85 lines
2.4 KiB
Ruby
85 lines
2.4 KiB
Ruby
# Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
# licensed under the Affero General Public License version 3 or later. See
|
|
# the COPYRIGHT file.
|
|
|
|
class Postzord::Receiver::Public < Postzord::Receiver
|
|
|
|
attr_accessor :salmon, :author
|
|
|
|
def initialize(xml)
|
|
@salmon = Salmon::Slap.from_xml(xml)
|
|
@author = Webfinger.new(@salmon.author_id).fetch
|
|
|
|
FEDERATION_LOGGER.info("Receving public post from person:#{@author.id}")
|
|
end
|
|
|
|
# @return [Boolean]
|
|
def verified_signature?
|
|
@salmon.verified_for_key?(@author.public_key)
|
|
end
|
|
|
|
# @return [void]
|
|
def receive!
|
|
return false unless verified_signature?
|
|
# return false unless account_deletion_is_from_author
|
|
|
|
return false unless save_object
|
|
|
|
FEDERATION_LOGGER.info("received a #{@object.inspect}")
|
|
if @object.respond_to?(:relayable?)
|
|
receive_relayable
|
|
elsif @object.is_a?(AccountDeletion)
|
|
#nothing
|
|
else
|
|
Resque.enqueue(Jobs::ReceiveLocalBatch, @object.class.to_s, @object.id, self.recipient_user_ids)
|
|
true
|
|
end
|
|
end
|
|
|
|
# @return [Object]
|
|
def receive_relayable
|
|
if @object.parent.author.local?
|
|
# receive relayable object only for the owner of the parent object
|
|
@object.receive(@object.parent.author.owner, @author)
|
|
end
|
|
# notify everyone who can see the parent object
|
|
receiver = Postzord::Receiver::LocalBatch.new(@object, self.recipient_user_ids)
|
|
receiver.notify_users
|
|
@object
|
|
end
|
|
|
|
# @return [Object]
|
|
def save_object
|
|
@object = Diaspora::Parser::from_xml(@salmon.parsed_data)
|
|
raise "Object is not public" if object_can_be_public_and_it_is_not?
|
|
raise "Author does not match XML author" if author_does_not_match_xml_author?
|
|
@object.save! if @object
|
|
end
|
|
|
|
# @return [Array<Integer>] User ids
|
|
def recipient_user_ids
|
|
User.all_sharing_with_person(@author).select('users.id').map!{ |u| u.id }
|
|
end
|
|
|
|
def xml_author
|
|
if @object.respond_to?(:relayable?)
|
|
#this is public, so it would only be owners sending us other people comments etc
|
|
@object.parent.author.local? ? @object.diaspora_handle : @object.parent.diaspora_handle
|
|
else
|
|
@object.diaspora_handle
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def account_deletion_is_from_author
|
|
return true unless @object.is_a?(AccountDeletion)
|
|
return false if @object.diaspora_handle != @author.diaspora_handle
|
|
return true
|
|
end
|
|
|
|
# @return [Boolean]
|
|
def object_can_be_public_and_it_is_not?
|
|
@object.respond_to?(:public) && !@object.public?
|
|
end
|
|
end
|