Don't check parent_author_signature for relayables

This isn't needed, but we need to check if the sender of the Magic
Envelope is the parent author (so we have a valid signature from the
parent author there).
This commit is contained in:
Benjamin Neff 2017-05-14 03:46:47 +02:00
parent 99a703ff5d
commit 6817579072
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
7 changed files with 36 additions and 121 deletions

View file

@ -16,7 +16,6 @@ See also: [Relayable][relayable]
| `text` | [Markdown][markdown] (65535) | The comment text. |
| `created_at` | [Timestamp][timestamp] | The create timestamp of the comment. |
| `author_signature` | [Signature][signature] | The signature from the author of the comment. |
| `parent_author_signature` | [Signature][signature] | The signature from the parent entity author. |
## Optional Properties
@ -26,8 +25,6 @@ See also: [Relayable][relayable]
## Examples
### From author
~~~xml
<comment>
<author>alice@example.org</author>
@ -36,21 +33,6 @@ See also: [Relayable][relayable]
<parent_guid>c3893bf029e7013487753131731751e9</parent_guid>
<text>this is a very informative comment</text>
<author_signature>cGIsxB5hU/94+rmgIg/Z+OUvXVYcY/kMOvc267ybpk1pT44P1JiWfnI26F1Mta62UjzIW/SjeAO0RIsJRguaISLpXX/d5DJCMpePAZaZiagUbdgH/w4L++fXiPxBKkSm+PB4txxmHGN8FHjwEUJFHJ1m3VfU4w2JC8+IBU93eag=</author_signature>
<parent_author_signature/>
</comment>
~~~
### From parent author
~~~xml
<comment>
<author>alice@example.org</author>
<guid>5c241a3029f8013487763131731751e9</guid>
<created_at>2016-07-12T00:49:06Z</created_at>
<parent_guid>c3893bf029e7013487753131731751e9</parent_guid>
<text>this is a very informative comment</text>
<author_signature>cGIsxB5hU/94+rmgIg/Z+OUvXVYcY/kMOvc267ybpk1pT44P1JiWfnI26F1Mta62UjzIW/SjeAO0RIsJRguaISLpXX/d5DJCMpePAZaZiagUbdgH/w4L++fXiPxBKkSm+PB4txxmHGN8FHjwEUJFHJ1m3VfU4w2JC8+IBU93eag=</author_signature>
<parent_author_signature>uzjxUSqR8DQBSBa6abY7R/s9DVzT6UAgTctRcUu5rV5o0iXJD2MR6kp6bsVH3nMbbNvOjwAtrdfz3SVHT2gD8M5PmoFagxK7m5T1c9FB0i+wknoAah0Si0c2sP/BPLnkQ83DgLjF+JZCzMX4sWKvYfyaMjnih1MtQILGyuiwA0E=</parent_author_signature>
</comment>
~~~

View file

@ -21,12 +21,9 @@ See also: [Relayable][relayable]
| `parent_type` | [Type][type] | The entity type of the parent. |
| `positive` | [Boolean][boolean] | `true` if it is a like, `false` if it is a dislike. |
| `author_signature` | [Signature][signature] | The signature from the author of the like. |
| `parent_author_signature` | [Signature][signature] | The signature from the parent entity author. |
## Examples
### From author
~~~xml
<like>
<positive>true</positive>
@ -35,21 +32,6 @@ See also: [Relayable][relayable]
<parent_guid>947a854029f7013487753131731751e9</parent_guid>
<author>alice@example.org</author>
<author_signature>gk8e+K7XRjVRblv8B8PVOf7BpURbf5HrXO5rmq8D/AkPO7lA0+Akwouu5JGKAHIhPR3dfXVp0o6bIDD+e8gtMYRdDd5IHRfBGNk3WsQecnbhmesHy40Qca/dCQcdcXd5aeWHJKeyUrSAvS55U6VUpk/DK/4IIEZfnr0T9+jM8I0=</author_signature>
<parent_author_signature/>
</like>
~~~
### From parent author
~~~xml
<like>
<positive>true</positive>
<guid>947a88f029f7013487753131731751e9</guid>
<parent_type>Post</parent_type>
<parent_guid>947a854029f7013487753131731751e9</parent_guid>
<author>alice@example.org</author>
<author_signature>gk8e+K7XRjVRblv8B8PVOf7BpURbf5HrXO5rmq8D/AkPO7lA0+Akwouu5JGKAHIhPR3dfXVp0o6bIDD+e8gtMYRdDd5IHRfBGNk3WsQecnbhmesHy40Qca/dCQcdcXd5aeWHJKeyUrSAvS55U6VUpk/DK/4IIEZfnr0T9+jM8I0=</author_signature>
<parent_author_signature>0oAjHO8uIn2Z3Gcmo1KF8su0c7bqI6MzTRq5JagGaZVkFVU8WlNqtwamu6xlmpcAoClGpI5xvbnHzyw5YA8NS8KmUy8BUpg67Mq4QsHHBtueNxHuhgRjszN2V0S8BUKFHGJnnvXmZ/P6YGOOomDgp9I/7zIOownvIm5wj2MotWw=</parent_author_signature>
</like>
~~~

View file

@ -15,12 +15,9 @@ See also: [Relayable][relayable]
| `parent_guid` | [GUID][guid] | The GUID of the [Poll][poll]. |
| `poll_answer_guid` | [GUID][guid] | The GUID of the [PollAnswer][poll_answer]. |
| `author_signature` | [Signature][signature] | The signature from the author of the poll participation. |
| `parent_author_signature` | [Signature][signature] | The signature from the author of the [Poll][poll]. |
## Examples
### From author
~~~xml
<poll_participation>
<guid>f1eb866029f7013487753131731751e9</guid>
@ -28,20 +25,6 @@ See also: [Relayable][relayable]
<author>alice@example.org</author>
<poll_answer_guid>2a22db2029e9013487753131731751e9</poll_answer_guid>
<author_signature>dT6KbT7kp0bE+s3//ZErxO1wvVIqtD0lY67i81+dO43B4D2m5kjCdzW240eWt/jZmcHIsdxXf4WHNdrb6ZDnamA8I1FUVnLjHA9xexBITQsSLXrcV88UdammSmmOxl1Ac4VUXqFpdavm6a7/MwOJ7+JHP8TbUO9siN+hMfgUbtY=</author_signature>
<parent_author_signature/>
</poll_participation>
~~~
### From parent author
~~~xml
<poll_participation>
<guid>f1eb866029f7013487753131731751e9</guid>
<parent_guid>2a22d6c029e9013487753131731751e9</parent_guid>
<author>alice@example.org</author>
<poll_answer_guid>2a22db2029e9013487753131731751e9</poll_answer_guid>
<author_signature>dT6KbT7kp0bE+s3//ZErxO1wvVIqtD0lY67i81+dO43B4D2m5kjCdzW240eWt/jZmcHIsdxXf4WHNdrb6ZDnamA8I1FUVnLjHA9xexBITQsSLXrcV88UdammSmmOxl1Ac4VUXqFpdavm6a7/MwOJ7+JHP8TbUO9siN+hMfgUbtY=</author_signature>
<parent_author_signature>gWasNPpSnMcKBIMWyzfoVO6sr8eRYkhUqy3PIkkh53n/ki+DM9mnh3ayotI0+6un9aq1N3XkS7Vn05ZD3+nHVby6i21XkYgPnbD8pWYuBBj7VGPyahT70BUs/vSvY8KX8V3wYfsPsaiAgJsAFg2UHYdY3r4/oWdIIbBZc21O3zk=</parent_author_signature>
</poll_participation>
~~~

View file

@ -21,24 +21,22 @@ All relayables have the following properties:
| `guid` | [GUID][guid] | The GUID of the relayable. |
| `parent_guid` | [GUID][guid] | The GUID of the parent entity. |
| `author_signature` | [Signature][signature] | The signature from the author of the relayable. |
| `parent_author_signature` | [Signature][signature] | The signature from the parent entity author. |
## Relaying
The author of the relayable sends the entity to the parent author. The author must include the `author_signature`. The
`parent_author_signature` may be empty or missing.
The author of the relayable sends the entity to the parent author. The author must include the `author_signature`.
The parent author then must add the `parent_author_signature` and send the entity to all the recipients of the parent
entity.
The parent author then must envelop it in a new [Magic Envelope][magicsig] and send the entity to all the recipients
of the parent entity. If the author and the parent author are on the same server, the author must sign the
`author_signature` and the parent author needs to sign the Magic Envelope.
If someone other then the parent author receives an relayable without a valid `parent_author_signature`, it must be
ignored. If the `author_signature` is missing or invalid, it also must be ignored.
If someone other then the parent author receives a relayable without a valid Magic Envelope signed from
the parent author, it must be ignored. If the `author_signature` is missing or invalid, it also must be ignored.
## Signatures
The string to sign is built with the content of all properties (except the `author_signature` and
`parent_author_signature` itself), concatenated using `;` as separator in the same order as they appear in the XML. The
order in the XML is not specified.
The string to sign is built with the content of all properties (except the `author_signature` itself),
concatenated using `;` as separator in the same order as they appear in the XML. The order in the XML is not specified.
This ensures that relayables even work, if the parent author or another recipient does not know all properties of the
relayable entity (e.g. older version of diaspora\*).

View file

@ -28,16 +28,15 @@ module DiasporaFederation
# @return [String] parent guid
#
# @!attribute [r] author_signature
# Contains a signature of the entity using the private key of the author of a post itself
# Contains a signature of the entity using the private key of the author of a relayable itself.
# The presence of this signature is mandatory. Without it the entity won't be accepted by
# a target pod.
# @return [String] author signature
#
# @!attribute [r] parent_author_signature
# Contains a signature of the entity using the private key of the author of a parent post
# This signature is required only when federating from upstream (parent) post author to
# downstream subscribers. This is the case when the parent author has to resend a relayable
# received from one of their subscribers to all others.
# Contains a signature of the entity using the private key of the author of a parent post.
# @deprecated This signature isn't required anymore, because we can check the signature from
# the parent author in the MagicEnvelope.
# @return [String] parent author signature
#
# @!attribute [r] parent
@ -71,18 +70,17 @@ module DiasporaFederation
super(data)
end
# Verifies the signatures (+author_signature+ and +parent_author_signature+ if needed).
# Verifies the +author_signature+.
# @see DiasporaFederation::Entities::Signable#verify_signature
#
# @raise [SignatureVerificationFailed] if the signature is not valid
# @raise [PublicKeyNotFound] if no public key is found
def verify_signatures
verify_signature(author, :author_signature)
# This happens only on downstream federation.
verify_signature(parent.author, :parent_author_signature) unless parent.local
def verify_signature
super(author, :author_signature)
end
def sender_valid?(sender)
sender == author || sender == parent.author
(sender == author && parent.local) || sender == parent.author
end
# @return [String] string representation of this object
@ -178,7 +176,7 @@ module DiasporaFederation
additional_data = properties_hash.reject {|key, _| class_props.has_key?(key) }
fetch_parent(properties_hash)
new(properties_hash, property_order, additional_data).tap(&:verify_signatures)
new(properties_hash, property_order, additional_data).tap(&:verify_signature)
end
private

View file

@ -224,7 +224,6 @@ XML
before do
expect_callback(:fetch_public_key, author).and_return(author_key.public_key)
expect_callback(:fetch_public_key, parent.author).and_return(parent_key.public_key)
expect_callback(:fetch_related_entity, "Post", parent_guid).and_return(parent)
end

View file

@ -25,16 +25,15 @@ module DiasporaFederation
end
end
describe "#verify_signatures" do
describe "#verify_signature" do
it "doesn't raise anything if correct signatures were passed" do
hash[:author_signature] = sign_with_key(author_pkey, signature_data)
hash[:parent_author_signature] = sign_with_key(parent_pkey, signature_data)
hash[:parent] = remote_parent
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
expect { Entities::SomeRelayable.new(hash, signature_order).verify_signatures }.not_to raise_error
expect { Entities::SomeRelayable.new(hash, signature_order).verify_signature }.not_to raise_error
end
it "doesn't raise anything if correct signatures with new property were passed" do
@ -46,10 +45,9 @@ module DiasporaFederation
hash[:parent] = remote_parent
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
expect {
Entities::SomeRelayable.new(hash, signature_order, "new_property" => new_property).verify_signatures
Entities::SomeRelayable.new(hash, signature_order, "new_property" => new_property).verify_signature
}.not_to raise_error
end
@ -57,7 +55,7 @@ module DiasporaFederation
expect_callback(:fetch_public_key, anything).and_return(nil)
expect {
Entities::SomeRelayable.new(hash, signature_order).verify_signatures
Entities::SomeRelayable.new(hash, signature_order).verify_signature
}.to raise_error Entities::Relayable::PublicKeyNotFound
end
@ -67,7 +65,7 @@ module DiasporaFederation
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect {
Entities::SomeRelayable.new(hash, signature_order).verify_signatures
Entities::SomeRelayable.new(hash, signature_order).verify_signature
}.to raise_error Entities::Relayable::SignatureVerificationFailed
end
@ -77,56 +75,28 @@ module DiasporaFederation
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect {
Entities::SomeRelayable.new(hash, signature_order).verify_signatures
Entities::SomeRelayable.new(hash, signature_order).verify_signature
}.to raise_error Entities::Relayable::SignatureVerificationFailed
end
it "raises when no public key for parent author was fetched" do
hash[:author_signature] = sign_with_key(author_pkey, signature_data)
hash[:parent] = remote_parent
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(nil)
expect {
Entities::SomeRelayable.new(hash, signature_order).verify_signatures
}.to raise_error Entities::Relayable::PublicKeyNotFound
end
it "raises when no parent author signature was passed" do
it "doesn't raise when no parent author signature was passed" do
hash[:author_signature] = sign_with_key(author_pkey, signature_data)
hash[:parent_author_signature] = nil
hash[:parent] = remote_parent
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
expect {
Entities::SomeRelayable.new(hash, signature_order).verify_signatures
}.to raise_error Entities::Relayable::SignatureVerificationFailed
expect { Entities::SomeRelayable.new(hash, signature_order).verify_signature }.not_to raise_error
end
it "raises when bad parent author signature was passed" do
hash[:author_signature] = sign_with_key(author_pkey, signature_data)
hash[:parent_author_signature] = sign_with_key(parent_pkey, "bad signed string")
hash[:parent] = remote_parent
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
expect {
Entities::SomeRelayable.new(hash, signature_order).verify_signatures
}.to raise_error Entities::Relayable::SignatureVerificationFailed
end
it "doesn't raise if parent_author_signature isn't set but we're on upstream federation" do
it "doesn't raise when no parent author signature was passed and we're on upstream federation" do
hash[:author_signature] = sign_with_key(author_pkey, signature_data)
hash[:parent_author_signature] = nil
hash[:parent] = local_parent
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect { Entities::SomeRelayable.new(hash, signature_order).verify_signatures }.not_to raise_error
expect { Entities::SomeRelayable.new(hash, signature_order).verify_signature }.not_to raise_error
end
end
@ -228,7 +198,6 @@ XML
before do
expect_callback(:fetch_related_entity, "Parent", parent_guid).and_return(remote_parent)
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
end
let(:new_signature_data) { "#{author};#{guid};#{parent_guid};#{new_property};#{property}" }
@ -374,7 +343,6 @@ XML
before do
expect_callback(:fetch_related_entity, "Parent", parent_guid).and_return(remote_parent)
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
end
context "when properties are sorted and there is an unknown property" do
@ -475,7 +443,6 @@ XML
context "fetch parent" do
before do
expect_callback(:fetch_public_key, author).and_return(author_pkey.public_key)
expect_callback(:fetch_public_key, remote_parent.author).and_return(parent_pkey.public_key)
expect_callback(:fetch_private_key, author).and_return(author_pkey)
expect_callback(:fetch_private_key, remote_parent.author).and_return(parent_pkey)
end
@ -508,12 +475,18 @@ XML
end
describe "#sender_valid?" do
it "allows author" do
it "allows author if the parent is local" do
entity = Entities::SomeRelayable.new(hash)
expect(entity.sender_valid?(author)).to be_truthy
end
it "does not allow the author if the parent is not local" do
entity = Entities::SomeRelayable.new(hash.merge(parent: remote_parent))
expect(entity.sender_valid?(author)).to be_falsey
end
it "allows parent author" do
entity = Entities::SomeRelayable.new(hash)