diff --git a/app/controllers/diaspora_federation/receive_controller.rb b/app/controllers/diaspora_federation/receive_controller.rb
index a477dfd..a9568b5 100644
--- a/app/controllers/diaspora_federation/receive_controller.rb
+++ b/app/controllers/diaspora_federation/receive_controller.rb
@@ -5,18 +5,14 @@ require_dependency "diaspora_federation/application_controller"
module DiasporaFederation
# This controller processes receiving messages.
class ReceiveController < ApplicationController
- before_action :check_for_xml
-
# Receives public messages
#
# POST /receive/public
def public
- legacy = request.content_type != "application/magic-envelope+xml"
-
- data = data_for_public_message(legacy)
+ data = request.body.read
logger.debug data
- DiasporaFederation.callbacks.trigger(:queue_public_receive, data, legacy)
+ DiasporaFederation.callbacks.trigger(:queue_public_receive, data)
head :accepted
end
@@ -25,43 +21,12 @@ module DiasporaFederation
#
# POST /receive/users/:guid
def private
- legacy = request.content_type != "application/json"
-
- data = data_for_private_message(legacy)
+ data = request.body.read
logger.debug data
- success = DiasporaFederation.callbacks.trigger(:queue_private_receive, params[:guid], data, legacy)
+ success = DiasporaFederation.callbacks.trigger(:queue_private_receive, params[:guid], data)
head success ? :accepted : :not_found
end
-
- private
-
- # Checks the xml parameter for legacy salmon slaps
- # @deprecated
- def check_for_xml
- legacy_request = request.content_type.nil? || request.content_type == "application/x-www-form-urlencoded"
- head :unprocessable_entity if params[:xml].nil? && legacy_request
- end
-
- def data_for_public_message(legacy)
- if legacy
- logger.info "received a public salmon slap"
- CGI.unescape(params[:xml])
- else
- logger.info "received a public magic envelope"
- request.body.read
- end
- end
-
- def data_for_private_message(legacy)
- if legacy
- logger.info "received a private salmon slap for #{params[:guid]}"
- CGI.unescape(params[:xml])
- else
- logger.info "received a private encrypted magic envelope for #{params[:guid]}"
- request.body.read
- end
- end
end
end
diff --git a/lib/diaspora_federation.rb b/lib/diaspora_federation.rb
index ec2b036..f5079d6 100644
--- a/lib/diaspora_federation.rb
+++ b/lib/diaspora_federation.rb
@@ -184,13 +184,11 @@ module DiasporaFederation
# queue_public_receive
# Queue a public salmon xml to process in background
# @param [String] data salmon slap xml or magic envelope xml
- # @param [Boolean] legacy true if it is a legacy salmon slap, false if it is a magic envelope xml
#
# queue_private_receive
# Queue a private salmon xml to process in background
# @param [String] guid guid of the receiver person
# @param [String] data salmon slap xml or encrypted magic envelope json
- # @param [Boolean] legacy true if it is a legacy salmon slap, false if it is a encrypted magic envelope json
# @return [Boolean] true if successful, false if the user was not found
#
# receive_entity
diff --git a/lib/diaspora_federation/federation/receiver.rb b/lib/diaspora_federation/federation/receiver.rb
index 4b6eb76..7552631 100644
--- a/lib/diaspora_federation/federation/receiver.rb
+++ b/lib/diaspora_federation/federation/receiver.rb
@@ -8,14 +8,9 @@ module DiasporaFederation
# Receive a public message
# @param [String] data message to receive
- # @param [Boolean] legacy use old slap parser
- def self.receive_public(data, legacy=false)
- magic_env = if legacy
- Salmon::Slap.from_xml(data)
- else
- magic_env_xml = Nokogiri::XML(data).root
- Salmon::MagicEnvelope.unenvelop(magic_env_xml)
- end
+ def self.receive_public(data)
+ magic_env_xml = Nokogiri::XML(data).root
+ magic_env = Salmon::MagicEnvelope.unenvelop(magic_env_xml)
Public.new(magic_env).receive
rescue => e # rubocop:disable Style/RescueStandardError
logger.error "failed to receive public message: #{e.class}: #{e.message}"
@@ -28,16 +23,11 @@ module DiasporaFederation
# @param [OpenSSL::PKey::RSA] recipient_private_key recipient private key to decrypt the message
# @param [Object] recipient_id the identifier to persist the entity for the correct user,
# see +receive_entity+ callback
- # @param [Boolean] legacy use old slap parser
- def self.receive_private(data, recipient_private_key, recipient_id, legacy=false)
+ def self.receive_private(data, recipient_private_key, recipient_id)
raise ArgumentError, "no recipient key provided" unless recipient_private_key.instance_of?(OpenSSL::PKey::RSA)
- magic_env = if legacy
- 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)
- end
+ magic_env_xml = Salmon::EncryptedMagicEnvelope.decrypt(data, recipient_private_key)
+ magic_env = Salmon::MagicEnvelope.unenvelop(magic_env_xml)
Private.new(magic_env, recipient_id).receive
rescue => e # rubocop:disable Style/RescueStandardError
logger.error "failed to receive private message for #{recipient_id}: #{e.class}: #{e.message}"
diff --git a/lib/diaspora_federation/salmon.rb b/lib/diaspora_federation/salmon.rb
index 0fc3ef9..0267598 100644
--- a/lib/diaspora_federation/salmon.rb
+++ b/lib/diaspora_federation/salmon.rb
@@ -16,5 +16,3 @@ require "diaspora_federation/salmon/exceptions"
require "diaspora_federation/salmon/xml_payload"
require "diaspora_federation/salmon/magic_envelope"
require "diaspora_federation/salmon/encrypted_magic_envelope"
-require "diaspora_federation/salmon/slap"
-require "diaspora_federation/salmon/encrypted_slap"
diff --git a/lib/diaspora_federation/salmon/encrypted_slap.rb b/lib/diaspora_federation/salmon/encrypted_slap.rb
deleted file mode 100644
index 23da393..0000000
--- a/lib/diaspora_federation/salmon/encrypted_slap.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-require "json"
-
-module DiasporaFederation
- module Salmon
- # +EncryptedSlap+ provides class methods for generating and parsing encrypted
- # Slaps. (In principle the same as {Slap}, but with encryption.)
- #
- # The basic encryption mechanism used here is based on the knowledge that
- # asymmetrical encryption is slow and symmetrical encryption is fast. Keeping in
- # mind that a message we want to de-/encrypt may greatly vary in length,
- # performance considerations must play a part of this scheme.
- #
- # A diaspora*-flavored encrypted magic-enveloped XML message looks like the following:
- #
- #
- #
- # {encrypted_header}
- # {magic_envelope with encrypted data}
- #
- #
- # The encrypted header is encoded in JSON like this (when in plain text):
- #
- # {
- # "aes_key" => "...",
- # "ciphertext" => "..."
- # }
- #
- # +aes_key+ is encrypted using the recipients public key, and contains the AES
- # +key+ and +iv+ used to encrypt the +ciphertext+ also encoded as JSON.
- #
- # {
- # "key" => "...",
- # "iv" => "..."
- # }
- #
- # +ciphertext+, once decrypted, contains the +author_id+, +aes_key+ and +iv+
- # relevant to the decryption of the data in the magic_envelope and the
- # verification of its signature.
- #
- # The decrypted cyphertext has this XML structure:
- #
- #
- # {iv}
- # {aes_key}
- # {author_id}
- #
- #
- # Finally, before decrypting the magic envelope payload, the signature should
- # first be verified.
- #
- # @example Parsing a Salmon Slap
- # recipient_privkey = however_you_retrieve_the_recipients_private_key()
- # entity = EncryptedSlap.from_xml(slap_xml, recipient_privkey).payload
- #
- # @deprecated
- class EncryptedSlap < Slap
- # 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 [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
- # @raise [MissingMagicEnvelope] if the +me:env+ element is missing in the XML
- def self.from_xml(slap_xml, privkey)
- raise ArgumentError unless slap_xml.instance_of?(String) && privkey.instance_of?(OpenSSL::PKey::RSA)
-
- doc = Nokogiri::XML(slap_xml)
-
- 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])}
-
- MagicEnvelope.unenvelop(magic_env_from_doc(doc), sender, cipher_params)
- end
-
- # Decrypts and reads the data from the encrypted XML header
- # @param [String] data base64 encoded, encrypted header data
- # @param [OpenSSL::PKey::RSA] privkey private key for decryption
- # @return [Hash] { iv: "...", aes_key: "...", author_id: "..." }
- private_class_method def self.header_data(data, privkey)
- header_elem = decrypt_header(data, privkey)
- raise InvalidHeader unless header_elem.name == "decrypted_header"
-
- iv = header_elem.at_xpath("iv").content
- key = header_elem.at_xpath("aes_key").content
- author_id = header_elem.at_xpath("author_id").content
-
- {iv: iv, aes_key: key, author_id: author_id}
- end
-
- # Decrypts the xml header
- # @param [String] data base64 encoded, encrypted header data
- # @param [OpenSSL::PKey::RSA] privkey private key for decryption
- # @return [Nokogiri::XML::Element] header xml document
- private_class_method def self.decrypt_header(data, privkey)
- cipher_header = JSON.parse(Base64.decode64(data))
- key = JSON.parse(privkey.private_decrypt(Base64.decode64(cipher_header["aes_key"])))
-
- xml = AES.decrypt(cipher_header["ciphertext"], Base64.decode64(key["key"]), Base64.decode64(key["iv"]))
- Nokogiri::XML(xml).root
- end
- end
- end
-end
diff --git a/lib/diaspora_federation/salmon/exceptions.rb b/lib/diaspora_federation/salmon/exceptions.rb
index 07061be..b9bde07 100644
--- a/lib/diaspora_federation/salmon/exceptions.rb
+++ b/lib/diaspora_federation/salmon/exceptions.rb
@@ -2,26 +2,6 @@
module DiasporaFederation
module Salmon
- # Raised, if the element containing the Magic Envelope is missing from the XML
- # @deprecated
- class MissingMagicEnvelope < RuntimeError
- end
-
- # Raised, if the element containing the author is empty.
- # @deprecated
- class MissingAuthor < RuntimeError
- end
-
- # Raised, if the element containing the header is missing from the XML
- # @deprecated
- class MissingHeader < RuntimeError
- end
-
- # Raised, if the decrypted header has an unexpected XML structure
- # @deprecated
- class InvalidHeader < RuntimeError
- end
-
# Raised, if failed to fetch the public key of the sender of the received message
class SenderKeyNotFound < RuntimeError
end
diff --git a/lib/diaspora_federation/salmon/slap.rb b/lib/diaspora_federation/salmon/slap.rb
deleted file mode 100644
index 242337d..0000000
--- a/lib/diaspora_federation/salmon/slap.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module DiasporaFederation
- module Salmon
- # +Slap+ provides class methods to create unencrypted Slap XML from payload
- # data and parse incoming XML into a Slap instance.
- #
- # A diaspora* flavored magic-enveloped XML message looks like the following:
- #
- #
- #
- #
- # {magic_envelope}
- #
- #
- # @example Parsing a Salmon Slap
- # entity = Slap.from_xml(slap_xml).payload
- #
- # @deprecated
- class Slap
- # Namespaces
- NS = {d: Salmon::XMLNS, me: MagicEnvelope::XMLNS}.freeze
-
- # Parses an unencrypted Salmon XML string and returns a new instance of
- # {MagicEnvelope} with the XML data.
- #
- # @param [String] slap_xml Salmon XML
- #
- # @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
- def self.from_xml(slap_xml)
- raise ArgumentError unless slap_xml.instance_of?(String)
-
- doc = Nokogiri::XML(slap_xml)
-
- 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
-
- MagicEnvelope.unenvelop(magic_env_from_doc(doc), sender)
- end
-
- # Parses the magic envelop from the document.
- #
- # @param [Nokogiri::XML::Document] doc Salmon XML Document
- private_class_method 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
- end
- end
-end
diff --git a/spec/controllers/diaspora_federation/receive_controller_spec.rb b/spec/controllers/diaspora_federation/receive_controller_spec.rb
index 0d5b684..b0aaaaa 100644
--- a/spec/controllers/diaspora_federation/receive_controller_spec.rb
+++ b/spec/controllers/diaspora_federation/receive_controller_spec.rb
@@ -5,32 +5,6 @@ module DiasporaFederation
routes { DiasporaFederation::Engine.routes }
describe "POST #public" do
- context "legacy salmon slap" do
- it "returns a 422 if no xml is passed" do
- post :public
- expect(response.code).to eq("422")
- end
-
- it "returns a 422 if no xml is passed with content-type application/x-www-form-urlencoded" do
- @request.env["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
- post :public
- expect(response.code).to eq("422")
- end
-
- it "returns a 202 if queued correctly" do
- expect_callback(:queue_public_receive, "", true)
-
- post :public, params: {xml: ""}
- expect(response.code).to eq("202")
- end
-
- it "unescapes the xml before sending it to the callback" do
- expect_callback(:queue_public_receive, "", true)
-
- post :public, params: {xml: CGI.escape("")}
- end
- end
-
context "magic envelope" do
before do
Mime::Type.register("application/magic-envelope+xml", :magic_envelope)
@@ -38,7 +12,7 @@ module DiasporaFederation
end
it "returns a 202 if queued correctly" do
- expect_callback(:queue_public_receive, "", false)
+ expect_callback(:queue_public_receive, "")
post :public, body: +""
expect(response.code).to eq("202")
@@ -47,39 +21,6 @@ module DiasporaFederation
end
describe "POST #private" do
- context "legacy salmon slap" do
- it "return a 404 if not queued successfully (unknown user guid)" do
- expect_callback(:queue_private_receive, "any-guid", "", true).and_return(false)
-
- post :private, params: {guid: "any-guid", xml: ""}
- expect(response.code).to eq("404")
- end
-
- it "returns a 422 if no xml is passed" do
- post :private, params: {guid: "any-guid"}
- expect(response.code).to eq("422")
- end
-
- it "returns a 422 if no xml is passed with content-type application/x-www-form-urlencoded" do
- @request.env["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
- post :private, params: {guid: "any-guid"}
- expect(response.code).to eq("422")
- end
-
- it "returns a 202 if the callback returned true" do
- expect_callback(:queue_private_receive, "any-guid", "", true).and_return(true)
-
- post :private, params: {guid: "any-guid", xml: ""}
- expect(response.code).to eq("202")
- end
-
- it "unescapes the xml before sending it to the callback" do
- expect_callback(:queue_private_receive, "any-guid", "", true).and_return(true)
-
- post :private, params: {guid: "any-guid", xml: CGI.escape("")}
- end
- end
-
context "encrypted magic envelope" do
before do
@request.env["CONTENT_TYPE"] = "application/json"
@@ -87,7 +28,7 @@ module DiasporaFederation
it "return a 404 if not queued successfully (unknown user guid)" do
expect_callback(
- :queue_private_receive, "any-guid", "{\"aes_key\": \"key\", \"encrypted_magic_envelope\": \"env\"}", false
+ :queue_private_receive, "any-guid", "{\"aes_key\": \"key\", \"encrypted_magic_envelope\": \"env\"}"
).and_return(false)
post :private,
@@ -98,7 +39,7 @@ module DiasporaFederation
it "returns a 202 if the callback returned true" do
expect_callback(
- :queue_private_receive, "any-guid", "{\"aes_key\": \"key\", \"encrypted_magic_envelope\": \"env\"}", false
+ :queue_private_receive, "any-guid", "{\"aes_key\": \"key\", \"encrypted_magic_envelope\": \"env\"}"
).and_return(true)
post :private,
diff --git a/spec/lib/diaspora_federation/federation/receiver_spec.rb b/spec/lib/diaspora_federation/federation/receiver_spec.rb
index b5b2d33..5df17c0 100644
--- a/spec/lib/diaspora_federation/federation/receiver_spec.rb
+++ b/spec/lib/diaspora_federation/federation/receiver_spec.rb
@@ -23,21 +23,6 @@ module DiasporaFederation
described_class.receive_public(data)
end
- it "parses the entity with legacy slap receiver" do
- expect_callback(:fetch_public_key, post.author).and_return(sender_key)
-
- data = generate_legacy_salmon_slap(post, post.author, sender_key)
-
- expect_callback(:receive_entity, kind_of(Entities::StatusMessage), post.author, nil) do |_, entity|
- expect(entity.guid).to eq(post.guid)
- expect(entity.author).to eq(post.author)
- expect(entity.text).to eq(post.text)
- expect(entity.public).to eq("true")
- end
-
- described_class.receive_public(data, true)
- end
-
it "redirects exceptions from the receiver" do
expect {
described_class.receive_public("")
@@ -64,21 +49,6 @@ module DiasporaFederation
described_class.receive_private(data, recipient_key, 1234)
end
- it "parses the entity with legacy slap receiver" do
- expect_callback(:fetch_public_key, post.author).and_return(sender_key)
-
- data = generate_legacy_encrypted_salmon_slap(post, post.author, sender_key, recipient_key)
-
- expect_callback(:receive_entity, kind_of(Entities::StatusMessage), post.author, 1234) do |_, entity|
- expect(entity.guid).to eq(post.guid)
- expect(entity.author).to eq(post.author)
- expect(entity.text).to eq(post.text)
- expect(entity.public).to eq("false")
- end
-
- described_class.receive_private(data, recipient_key, 1234, true)
- end
-
it "raises when recipient private key is not available" do
magic_env = Salmon::MagicEnvelope.new(post, post.author).envelop(sender_key)
data = Salmon::EncryptedMagicEnvelope.encrypt(magic_env, recipient_key.public_key)
diff --git a/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb b/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb
deleted file mode 100644
index 348dcfb..0000000
--- a/spec/lib/diaspora_federation/salmon/encrypted_slap_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-module DiasporaFederation
- describe Salmon::EncryptedSlap do
- 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(:payload) { Entities::TestEntity.new(test: "qwertzuiop") }
- let(:slap_xml) { generate_legacy_encrypted_salmon_slap(payload, sender, privkey, recipient_key.public_key) }
-
- describe ".from_xml" do
- context "sanity" do
- it "accepts correct params" do
- expect_callback(:fetch_public_key, 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, payload, privkey].each do |val|
- expect {
- Salmon::EncryptedSlap.from_xml(val, val)
- }.to raise_error ArgumentError
- end
- end
-
- it "verifies the existence of 'encrypted_header'" do
- faulty_xml = <<~XML
-
-
- XML
- expect {
- Salmon::EncryptedSlap.from_xml(faulty_xml, recipient_key)
- }.to raise_error Salmon::MissingHeader
- end
-
- it "verifies the existence of a magic envelope" do
- faulty_xml = <<~XML
-
-
-
- XML
- expect(Salmon::EncryptedSlap).to receive(:header_data).and_return(aes_key: "", iv: "", author_id: "")
- expect {
- Salmon::EncryptedSlap.from_xml(faulty_xml, recipient_key)
- }.to raise_error Salmon::MissingMagicEnvelope
- end
- end
-
- context "generated instance" do
- it_behaves_like "a MagicEnvelope instance" do
- subject { Salmon::EncryptedSlap.from_xml(slap_xml, recipient_key) }
- end
- end
- end
- end
-end
diff --git a/spec/lib/diaspora_federation/salmon/slap_spec.rb b/spec/lib/diaspora_federation/salmon/slap_spec.rb
deleted file mode 100644
index a79729d..0000000
--- a/spec/lib/diaspora_federation/salmon/slap_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module DiasporaFederation
- describe Salmon::Slap do
- let(:sender) { "test_user@pod.somedomain.tld" }
- let(:privkey) { OpenSSL::PKey::RSA.generate(512) } # use small key for speedy specs
- let(:payload) { Entities::TestEntity.new(test: "qwertzuiop") }
- let(:slap_xml) { generate_legacy_salmon_slap(payload, sender, privkey) }
-
- describe ".from_xml" do
- context "sanity" do
- it "accepts salmon xml as param" do
- expect_callback(:fetch_public_key, 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, payload, privkey].each do |val|
- expect {
- Salmon::Slap.from_xml(val)
- }.to raise_error ArgumentError
- end
- end
-
- it "verifies the existence of an author_id" do
- faulty_xml = <<~XML
-
-
-
- XML
- expect {
- Salmon::Slap.from_xml(faulty_xml)
- }.to raise_error Salmon::MissingAuthor
- end
-
- it "verifies the existence of a magic envelope" do
- faulty_xml = <<~XML
-
-
-
- XML
- expect {
- Salmon::Slap.from_xml(faulty_xml)
- }.to raise_error Salmon::MissingMagicEnvelope
- end
- end
-
- context "generated instance" do
- it_behaves_like "a MagicEnvelope instance" do
- subject { Salmon::Slap.from_xml(slap_xml) }
- end
- end
- end
- end
-end