2020-05-13 11:26:07 +00:00
|
|
|
from collections import namedtuple
|
2020-05-13 10:18:48 +00:00
|
|
|
from urllib.parse import urlsplit
|
|
|
|
|
2020-05-13 11:26:07 +00:00
|
|
|
from Crypto import Random
|
|
|
|
from Crypto.PublicKey import RSA
|
|
|
|
|
|
|
|
import responses
|
|
|
|
|
2020-05-13 10:18:48 +00:00
|
|
|
from django.test import TestCase, Client
|
|
|
|
from django.utils.http import http_date
|
|
|
|
|
|
|
|
from fedireads.models import User
|
|
|
|
from fedireads.broadcast import make_signature
|
|
|
|
from fedireads.activitypub import get_follow_request
|
|
|
|
from fedireads.settings import DOMAIN
|
|
|
|
|
2020-05-14 01:23:54 +00:00
|
|
|
Sender = namedtuple('Sender', ('remote_id', 'private_key', 'public_key'))
|
2020-05-13 11:26:07 +00:00
|
|
|
|
2020-05-13 10:18:48 +00:00
|
|
|
class Signature(TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
self.mouse = User.objects.create_user('mouse', 'mouse@example.com', '')
|
|
|
|
self.rat = User.objects.create_user('rat', 'rat@example.com', '')
|
|
|
|
self.cat = User.objects.create_user('cat', 'cat@example.com', '')
|
|
|
|
|
2020-05-13 11:26:07 +00:00
|
|
|
random_generator = Random.new().read
|
|
|
|
key = RSA.generate(1024, random_generator)
|
|
|
|
private_key = key.export_key().decode('utf8')
|
|
|
|
public_key = key.publickey().export_key().decode('utf8')
|
|
|
|
|
|
|
|
self.fake_remote = Sender(
|
|
|
|
'http://localhost/user/remote',
|
|
|
|
private_key,
|
|
|
|
public_key,
|
|
|
|
)
|
|
|
|
|
|
|
|
def send_follow(self, sender, signature, now):
|
2020-05-13 10:18:48 +00:00
|
|
|
c = Client()
|
2020-05-13 10:40:57 +00:00
|
|
|
return c.post(
|
2020-05-13 10:18:48 +00:00
|
|
|
urlsplit(self.rat.inbox).path,
|
2020-05-13 10:40:57 +00:00
|
|
|
data=get_follow_request(
|
2020-05-13 11:26:07 +00:00
|
|
|
sender,
|
2020-05-13 10:40:57 +00:00
|
|
|
self.rat,
|
|
|
|
),
|
2020-05-13 10:18:48 +00:00
|
|
|
content_type='application/json',
|
|
|
|
**{
|
|
|
|
'HTTP_DATE': now,
|
|
|
|
'HTTP_SIGNATURE': signature,
|
|
|
|
'HTTP_CONTENT_TYPE': 'application/activity+json; charset=utf-8',
|
|
|
|
'HTTP_HOST': DOMAIN,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2020-05-13 10:40:57 +00:00
|
|
|
def test_correct_signature(self):
|
|
|
|
now = http_date()
|
|
|
|
signature = make_signature(self.mouse, self.rat.inbox, now)
|
2020-05-13 11:26:07 +00:00
|
|
|
return self.send_follow(self.mouse, signature, now).status_code == 200
|
2020-05-13 10:40:57 +00:00
|
|
|
|
|
|
|
def test_wrong_signature(self):
|
|
|
|
''' Messages must be signed by the right actor.
|
|
|
|
(cat cannot sign messages on behalf of mouse)
|
|
|
|
'''
|
|
|
|
now = http_date()
|
|
|
|
signature = make_signature(self.cat, self.rat.inbox, now)
|
2020-05-13 11:26:07 +00:00
|
|
|
assert self.send_follow(self.mouse, signature, now).status_code == 401
|
|
|
|
|
|
|
|
@responses.activate
|
|
|
|
def test_remote_signer(self):
|
|
|
|
responses.add(
|
|
|
|
responses.GET,
|
2020-05-14 01:23:54 +00:00
|
|
|
self.fake_remote.remote_id,
|
2020-05-13 11:26:07 +00:00
|
|
|
json={'publicKey': {
|
|
|
|
'publicKeyPem': self.fake_remote.public_key
|
|
|
|
}},
|
|
|
|
status=200)
|
|
|
|
|
|
|
|
now = http_date()
|
|
|
|
sender = self.fake_remote
|
|
|
|
signature = make_signature(sender, self.rat.inbox, now)
|
|
|
|
assert self.send_follow(sender, signature, now).status_code == 200
|
|
|
|
|
|
|
|
@responses.activate
|
|
|
|
def test_nonexistent_signer(self):
|
|
|
|
responses.add(
|
|
|
|
responses.GET,
|
2020-05-14 01:23:54 +00:00
|
|
|
self.fake_remote.remote_id,
|
2020-05-13 11:26:07 +00:00
|
|
|
json={'error': 'not found'},
|
|
|
|
status=404)
|
|
|
|
|
|
|
|
now = http_date()
|
|
|
|
sender = self.fake_remote
|
|
|
|
signature = make_signature(sender, self.rat.inbox, now)
|
|
|
|
assert self.send_follow(sender, signature, now).status_code == 401
|