From ca0a853134649c8f62cbc8333e9e012afcd65064 Mon Sep 17 00:00:00 2001 From: Benjamin Neff Date: Sun, 20 Mar 2016 21:13:03 +0100 Subject: [PATCH] return MagicEnvelope after parsing a Slap --- .../federation/receiver.rb | 10 ++-- .../salmon/encrypted_slap.rb | 29 ++++++------ lib/diaspora_federation/salmon/slap.rb | 47 +++++-------------- .../salmon/encrypted_slap_spec.rb | 46 +++++++++--------- .../salmon/magic_envelope_spec.rb | 42 ++++------------- .../diaspora_federation/salmon/slap_spec.rb | 40 +++++++++------- spec/support/shared_magic_envelope_specs.rb | 21 +++++++++ spec/support/shared_slap_specs.rb | 17 ------- 8 files changed, 105 insertions(+), 147 deletions(-) create mode 100644 spec/support/shared_magic_envelope_specs.rb delete mode 100644 spec/support/shared_slap_specs.rb diff --git a/lib/diaspora_federation/federation/receiver.rb b/lib/diaspora_federation/federation/receiver.rb index cfd6d4d..94a26f9 100644 --- a/lib/diaspora_federation/federation/receiver.rb +++ b/lib/diaspora_federation/federation/receiver.rb @@ -7,10 +7,10 @@ module DiasporaFederation # @param [Boolean] legacy use old slap parser def self.receive_public(data, legacy=false) received_message = if legacy - Salmon::Slap.from_xml(data).entity + Salmon::Slap.from_xml(data) else magic_env_xml = Nokogiri::XML::Document.parse(data).root - Salmon::MagicEnvelope.unenvelop(magic_env_xml).payload + Salmon::MagicEnvelope.unenvelop(magic_env_xml) end receive(received_message) end @@ -24,16 +24,16 @@ module DiasporaFederation def self.receive_private(data, recipient_private_key, recipient_id, legacy=false) raise ArgumentError, "no recipient key provided" unless recipient_private_key.instance_of?(OpenSSL::PKey::RSA) received_message = if legacy - Salmon::EncryptedSlap.from_xml(data, recipient_private_key).entity + Salmon::EncryptedSlap.from_xml(data, recipient_private_key) else magic_env_xml = Salmon::EncryptedMagicEnvelope.decrypt(data, recipient_private_key) - Salmon::MagicEnvelope.unenvelop(magic_env_xml).payload + Salmon::MagicEnvelope.unenvelop(magic_env_xml) end receive(received_message, recipient_id) end def self.receive(received_message, recipient_id=nil) - DiasporaFederation.callbacks.trigger(:receive_entity, received_message, recipient_id) + DiasporaFederation.callbacks.trigger(:receive_entity, received_message.payload, recipient_id) end private_class_method :receive end diff --git a/lib/diaspora_federation/salmon/encrypted_slap.rb b/lib/diaspora_federation/salmon/encrypted_slap.rb index 7b96991..041d791 100644 --- a/lib/diaspora_federation/salmon/encrypted_slap.rb +++ b/lib/diaspora_federation/salmon/encrypted_slap.rb @@ -58,13 +58,14 @@ module DiasporaFederation # # @example Parsing a Salmon Slap # recipient_privkey = however_you_retrieve_the_recipients_private_key() - # slap = EncryptedSlap.from_xml(slap_xml, recipient_privkey) - # author_pubkey = however_you_retrieve_the_authors_public_key(slap.author_id) - # - # entity = slap.entity(author_pubkey) + # entity = EncryptedSlap.from_xml(slap_xml, recipient_privkey).payload # # @deprecated class EncryptedSlap < Slap + # the author of the slap + # @param [String] value the author diaspora id + attr_writer :author_id + # the key and iv if it is an encrypted slap # @param [Hash] value hash containing the key and iv attr_writer :cipher_params @@ -73,13 +74,13 @@ module DiasporaFederation # @param [Nokogiri::XML::Element] value magic envelope xml attr_writer :magic_envelope_xml - # Creates a Slap instance from the data within the given XML string + # Creates a {MagicEnvelope} instance from the data within the given XML string # containing an encrypted payload. # # @param [String] slap_xml encrypted Salmon xml # @param [OpenSSL::PKey::RSA] privkey recipient private_key for decryption # - # @return [EncryptedSlap] new Slap instance + # @return [MagicEnvelope] magic envelope instance with payload and sender # # @raise [ArgumentError] if any of the arguments is of the wrong type # @raise [MissingHeader] if the +encrypted_header+ element is missing in the XML @@ -88,15 +89,13 @@ module DiasporaFederation raise ArgumentError unless slap_xml.instance_of?(String) && privkey.instance_of?(OpenSSL::PKey::RSA) doc = Nokogiri::XML::Document.parse(slap_xml) - EncryptedSlap.new.tap do |slap| - header_elem = doc.at_xpath("d:diaspora/d:encrypted_header", Slap::NS) - raise MissingHeader if header_elem.nil? - header = header_data(header_elem.content, privkey) - slap.author_id = header[:author_id] - slap.cipher_params = {key: Base64.decode64(header[:aes_key]), iv: Base64.decode64(header[:iv])} + header_elem = doc.at_xpath("d:diaspora/d:encrypted_header", Slap::NS) + raise MissingHeader if header_elem.nil? + header = header_data(header_elem.content, privkey) + sender = header[:author_id] + cipher_params = {key: Base64.decode64(header[:aes_key]), iv: Base64.decode64(header[:iv])} - slap.add_magic_env_from_doc(doc) - end + MagicEnvelope.unenvelop(magic_env_from_doc(doc), sender, cipher_params) end # Creates an encrypted Salmon Slap. @@ -129,7 +128,7 @@ module DiasporaFederation raise ArgumentError unless pubkey.instance_of?(OpenSSL::PKey::RSA) Slap.build_xml do |xml| - xml.encrypted_header(encrypted_header(author_id, @cipher_params, pubkey)) + xml.encrypted_header(encrypted_header(@author_id, @cipher_params, pubkey)) xml.parent << @magic_envelope_xml end diff --git a/lib/diaspora_federation/salmon/slap.rb b/lib/diaspora_federation/salmon/slap.rb index 800feb1..f11b41c 100644 --- a/lib/diaspora_federation/salmon/slap.rb +++ b/lib/diaspora_federation/salmon/slap.rb @@ -21,42 +21,20 @@ module DiasporaFederation # slap_xml = Slap.generate_xml(author_id, author_privkey, entity) # # @example Parsing a Salmon Slap - # slap = Slap.from_xml(slap_xml) - # author_pubkey = however_you_retrieve_the_authors_public_key(slap.author_id) - # - # entity = slap.entity(author_pubkey) + # entity = Slap.from_xml(slap_xml).payload # # @deprecated class Slap - # the author of the slap - # @overload author_id - # @return [String] the author diaspora id - # @overload author_id= - # @param [String] the author diaspora id - attr_accessor :author_id - # Namespaces NS = {d: Salmon::XMLNS, me: MagicEnvelope::XMLNS}.freeze - # Returns new instance of the Entity that is contained within the XML of - # this Slap. - # - # The first time this is called, a public key has to be specified to verify - # the Magic Envelope signature. On repeated calls, the key may be omitted. - # - # @see MagicEnvelope.unenvelop - # - # @return [Entity] entity instance from the XML - # @raise [ArgumentError] if the public key is of the wrong type - def entity - MagicEnvelope.unenvelop(@magic_envelope, author_id, @cipher_params) - end - # Parses an unencrypted Salmon XML string and returns a new instance of - # {Slap} populated with the XML data. + # {MagicEnvelope} with the XML data. # # @param [String] slap_xml Salmon XML - # @return [Slap] new Slap instance + # + # @return [MagicEnvelope] magic envelope instance with payload and sender + # # @raise [ArgumentError] if the argument is not a String # @raise [MissingAuthor] if the +author_id+ element is missing from the XML # @raise [MissingMagicEnvelope] if the +me:env+ element is missing from the XML @@ -64,13 +42,11 @@ module DiasporaFederation raise ArgumentError unless slap_xml.instance_of?(String) doc = Nokogiri::XML::Document.parse(slap_xml) - Slap.new.tap do |slap| - author_elem = doc.at_xpath("d:diaspora/d:header/d:author_id", Slap::NS) - raise MissingAuthor if author_elem.nil? || author_elem.content.empty? - slap.author_id = author_elem.content + author_elem = doc.at_xpath("d:diaspora/d:header/d:author_id", Slap::NS) + raise MissingAuthor if author_elem.nil? || author_elem.content.empty? + sender = author_elem.content - slap.add_magic_env_from_doc(doc) - end + MagicEnvelope.unenvelop(magic_env_from_doc(doc), sender) end # Creates an unencrypted Salmon Slap and returns the XML string. @@ -110,11 +86,12 @@ module DiasporaFederation # Parses the magic envelop from the document. # # @param [Nokogiri::XML::Document] doc Salmon XML Document - def add_magic_env_from_doc(doc) - @magic_envelope = doc.at_xpath("d:diaspora/me:env", Slap::NS).tap do |env| + def self.magic_env_from_doc(doc) + doc.at_xpath("d:diaspora/me:env", Slap::NS).tap do |env| raise MissingMagicEnvelope if env.nil? end end + private_class_method :magic_env_from_doc end end end diff --git a/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb b/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb index be11fa3..157342b 100644 --- a/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb +++ b/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb @@ -1,26 +1,26 @@ module DiasporaFederation describe Salmon::EncryptedSlap do - let(:author_id) { "user_test@diaspora.example.tld" } + let(:sender) { "user_test@diaspora.example.tld" } let(:privkey) { OpenSSL::PKey::RSA.generate(512) } # use small key for speedy specs let(:recipient_key) { OpenSSL::PKey::RSA.generate(1024) } # use small key for speedy specs - let(:entity) { Entities::TestEntity.new(test: "qwertzuiop") } - let(:slap_xml) { Salmon::EncryptedSlap.prepare(author_id, privkey, entity).generate_xml(recipient_key.public_key) } + let(:payload) { Entities::TestEntity.new(test: "qwertzuiop") } + let(:slap_xml) { Salmon::EncryptedSlap.prepare(sender, privkey, payload).generate_xml(recipient_key.public_key) } context "generate" do describe ".prepare" do context "sanity" do - it "raises an error when the author_id is the wrong type" do - [1234, true, :symbol, entity, privkey].each do |val| + it "raises an error when the sender is the wrong type" do + [1234, true, :symbol, payload, privkey].each do |val| expect { - Salmon::EncryptedSlap.prepare(val, privkey, entity) + Salmon::EncryptedSlap.prepare(val, privkey, payload) }.to raise_error ArgumentError end end it "raises an error when the privkey is the wrong type" do - ["asdf", 1234, true, :symbol, entity].each do |val| + ["asdf", 1234, true, :symbol, payload].each do |val| expect { - Salmon::EncryptedSlap.prepare(author_id, val, entity) + Salmon::EncryptedSlap.prepare(sender, val, payload) }.to raise_error ArgumentError end end @@ -28,7 +28,7 @@ module DiasporaFederation it "raises an error when the entity is the wrong type" do ["asdf", 1234, true, :symbol, privkey].each do |val| expect { - Salmon::EncryptedSlap.prepare(author_id, privkey, val) + Salmon::EncryptedSlap.prepare(sender, privkey, val) }.to raise_error ArgumentError end end @@ -41,14 +41,14 @@ module DiasporaFederation context "sanity" do it "accepts correct params" do expect { - Salmon::EncryptedSlap.prepare(author_id, privkey, entity).generate_xml(recipient_key.public_key) + Salmon::EncryptedSlap.prepare(sender, privkey, payload).generate_xml(recipient_key.public_key) }.not_to raise_error end it "raises an error when the params are the wrong type" do - ["asdf", 1234, true, :symbol, entity].each do |val| + ["asdf", 1234, true, :symbol, payload].each do |val| expect { - Salmon::EncryptedSlap.prepare(author_id, privkey, entity).generate_xml(val) + Salmon::EncryptedSlap.prepare(sender, privkey, payload).generate_xml(val) }.to raise_error ArgumentError end end @@ -62,7 +62,7 @@ module DiasporaFederation end it "can generate xml for two people" do - slap = Salmon::EncryptedSlap.prepare(author_id, privkey, entity) + slap = Salmon::EncryptedSlap.prepare(sender, privkey, payload) doc1 = Nokogiri::XML::Document.parse(slap.generate_xml(recipient_key.public_key)) enc_header1 = doc1.at_xpath("d:diaspora/d:encrypted_header", ns).content @@ -130,7 +130,7 @@ module DiasporaFederation expect(header_doc.xpath("//iv")).to have(1).item expect(header_doc.xpath("//aes_key")).to have(1).item expect(header_doc.xpath("//author_id")).to have(1).item - expect(header_doc.at_xpath("//author_id").content).to eq(author_id) + expect(header_doc.at_xpath("//author_id").content).to eq(sender) end end end @@ -139,13 +139,17 @@ module DiasporaFederation describe ".from_xml" do context "sanity" do it "accepts correct params" do + allow(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_public_key_by_diaspora_id, sender + ).and_return(privkey.public_key) + expect { Salmon::EncryptedSlap.from_xml(slap_xml, recipient_key) }.not_to raise_error end it "raises an error when the params have a wrong type" do - [1234, false, :symbol, entity, privkey].each do |val| + [1234, false, :symbol, payload, privkey].each do |val| expect { Salmon::EncryptedSlap.from_xml(val, val) }.to raise_error ArgumentError @@ -174,16 +178,12 @@ XML }.to raise_error Salmon::MissingMagicEnvelope end end - end - context "generated instance" do - subject { Salmon::EncryptedSlap.from_xml(slap_xml, recipient_key) } - - it "should have cipher params set" do - expect(subject.instance_variable_get(:@cipher_params)).to_not be_nil + context "generated instance" do + it_behaves_like "a MagicEnvelope instance" do + subject { Salmon::EncryptedSlap.from_xml(slap_xml, recipient_key) } + end end - - it_behaves_like "a Slap instance" end end end diff --git a/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb b/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb index e1c5a62..e8eb12f 100644 --- a/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb +++ b/spec/lib/diaspora_federation/salmon/magic_envelope_spec.rb @@ -167,23 +167,10 @@ module DiasporaFederation end end - it "returns the original entity" do - allow(DiasporaFederation.callbacks).to receive(:trigger).with( - :fetch_public_key_by_diaspora_id, sender - ).and_return(privkey.public_key) - - magic_env = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), sender) - expect(magic_env.payload).to be_an_instance_of Entities::TestEntity - expect(magic_env.payload.test).to eq("asdf") - end - - it "returns the original sender" do - allow(DiasporaFederation.callbacks).to receive(:trigger).with( - :fetch_public_key_by_diaspora_id, sender - ).and_return(privkey.public_key) - - magic_env = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), sender) - expect(magic_env.sender).to eq(sender) + context "generated instance" do + it_behaves_like "a MagicEnvelope instance" do + subject { Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey), sender) } + end end it "decrypts on the fly, when cipher params are present" do @@ -201,23 +188,10 @@ module DiasporaFederation end context "use key_id from magic envelope" do - it "returns the original entity" do - expect(DiasporaFederation.callbacks).to receive(:trigger).with( - :fetch_public_key_by_diaspora_id, sender - ).and_return(privkey.public_key) - - magic_env = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey)) - expect(magic_env.payload).to be_an_instance_of Entities::TestEntity - expect(magic_env.payload.test).to eq("asdf") - end - - it "returns the original sender" do - expect(DiasporaFederation.callbacks).to receive(:trigger).with( - :fetch_public_key_by_diaspora_id, sender - ).and_return(privkey.public_key) - - magic_env = Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey)) - expect(magic_env.sender).to eq(sender) + context "generated instance" do + it_behaves_like "a MagicEnvelope instance" do + subject { Salmon::MagicEnvelope.unenvelop(envelope.envelop(privkey)) } + end end it "raises if the magic envelope has no key_id" do diff --git a/spec/lib/diaspora_federation/salmon/slap_spec.rb b/spec/lib/diaspora_federation/salmon/slap_spec.rb index 4d3b3c6..46d7861 100644 --- a/spec/lib/diaspora_federation/salmon/slap_spec.rb +++ b/spec/lib/diaspora_federation/salmon/slap_spec.rb @@ -1,38 +1,38 @@ module DiasporaFederation describe Salmon::Slap do - let(:author_id) { "test_user@pod.somedomain.tld" } + let(:sender) { "test_user@pod.somedomain.tld" } let(:privkey) { OpenSSL::PKey::RSA.generate(512) } # use small key for speedy specs - let(:entity) { Entities::TestEntity.new(test: "qwertzuiop") } - let(:slap_xml) { Salmon::Slap.generate_xml(author_id, privkey, entity) } + let(:payload) { Entities::TestEntity.new(test: "qwertzuiop") } + let(:slap_xml) { Salmon::Slap.generate_xml(sender, privkey, payload) } describe ".generate_xml" do context "sanity" do it "accepts correct params" do expect { - Salmon::Slap.generate_xml(author_id, privkey, entity) + Salmon::Slap.generate_xml(sender, privkey, payload) }.not_to raise_error end - it "raises an error when the author_id is the wrong type" do - [1234, true, :symbol, entity, privkey].each do |val| + it "raises an error when the sender is the wrong type" do + [1234, true, :symbol, payload, privkey].each do |val| expect { - Salmon::Slap.generate_xml(val, privkey, entity) + Salmon::Slap.generate_xml(val, privkey, payload) }.to raise_error ArgumentError end end it "raises an error when the privkey is the wrong type" do - ["asdf", 1234, true, :symbol, entity].each do |val| + ["asdf", 1234, true, :symbol, payload].each do |val| expect { - Salmon::Slap.generate_xml(author_id, val, entity) + Salmon::Slap.generate_xml(sender, val, payload) }.to raise_error ArgumentError end end - it "raises an error when the entity is the wrong type" do + it "raises an error when the payload is the wrong type" do ["asdf", 1234, true, :symbol, privkey].each do |val| expect { - Salmon::Slap.generate_xml(author_id, privkey, val) + Salmon::Slap.generate_xml(sender, privkey, val) }.to raise_error ArgumentError end end @@ -42,7 +42,7 @@ module DiasporaFederation ns = {d: Salmon::XMLNS, me: Salmon::MagicEnvelope::XMLNS} doc = Nokogiri::XML::Document.parse(slap_xml) expect(doc.root.name).to eq("diaspora") - expect(doc.at_xpath("d:diaspora/d:header/d:author_id", ns).content).to eq(author_id) + expect(doc.at_xpath("d:diaspora/d:header/d:author_id", ns).content).to eq(sender) expect(doc.xpath("d:diaspora/me:env", ns)).to have(1).item end end @@ -50,13 +50,17 @@ module DiasporaFederation describe ".from_xml" do context "sanity" do it "accepts salmon xml as param" do + allow(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_public_key_by_diaspora_id, sender + ).and_return(privkey.public_key) + expect { Salmon::Slap.from_xml(slap_xml) }.not_to raise_error end it "raises an error when the param has a wrong type" do - [1234, false, :symbol, entity, privkey].each do |val| + [1234, false, :symbol, payload, privkey].each do |val| expect { Salmon::Slap.from_xml(val) }.to raise_error ArgumentError @@ -78,7 +82,7 @@ XML faulty_xml = <<-XML
- #{author_id} + #{sender}
XML @@ -87,11 +91,11 @@ XML }.to raise_error Salmon::MissingMagicEnvelope end end - end - context "generated instance" do - it_behaves_like "a Slap instance" do - subject { Salmon::Slap.from_xml(slap_xml) } + context "generated instance" do + it_behaves_like "a MagicEnvelope instance" do + subject { Salmon::Slap.from_xml(slap_xml) } + end end end end diff --git a/spec/support/shared_magic_envelope_specs.rb b/spec/support/shared_magic_envelope_specs.rb new file mode 100644 index 0000000..a2c0400 --- /dev/null +++ b/spec/support/shared_magic_envelope_specs.rb @@ -0,0 +1,21 @@ +shared_examples "a MagicEnvelope instance" do + before do + allow(DiasporaFederation.callbacks).to receive(:trigger).with( + :fetch_public_key_by_diaspora_id, sender + ).and_return(privkey.public_key) + end + + it "is an instance of MagicEnvelope" do + expect(subject).to be_an_instance_of DiasporaFederation::Salmon::MagicEnvelope + end + + it "should match the sender" do + expect(subject.sender).to eq(sender) + end + + it "returns the entity" do + entity = subject.payload + expect(entity).to be_an_instance_of DiasporaFederation::Entities::TestEntity + expect(entity.test).to eq(payload.test) + end +end diff --git a/spec/support/shared_slap_specs.rb b/spec/support/shared_slap_specs.rb deleted file mode 100644 index da15993..0000000 --- a/spec/support/shared_slap_specs.rb +++ /dev/null @@ -1,17 +0,0 @@ -shared_examples "a Slap instance" do - it "should match the author_id" do - expect(subject.author_id).to eq(author_id) - end - - context "#entity" do - it "returns the entity" do - allow(DiasporaFederation.callbacks).to receive(:trigger).with( - :fetch_public_key_by_diaspora_id, author_id - ).and_return(privkey.public_key) - - entity = subject.entity - expect(entity).to be_an_instance_of DiasporaFederation::Entities::TestEntity - expect(entity.test).to eq("qwertzuiop") - end - end -end