From 79276c245cdcde2d9deaae4062b7639e8ccb731f Mon Sep 17 00:00:00 2001 From: Izalia Mae <2908-izalia@users.noreply.git.pleroma.social> Date: Wed, 15 Sep 2021 02:17:27 +0000 Subject: [PATCH] Sign headers when fetching actor --- relay/http_signatures.py | 10 ++++------ relay/remote_actor.py | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/relay/http_signatures.py b/relay/http_signatures.py index 1093f5e..377f468 100644 --- a/relay/http_signatures.py +++ b/relay/http_signatures.py @@ -88,13 +88,11 @@ async def fetch_actor_key(actor): if not actor_data: return None - if 'publicKey' not in actor_data: - return None + try: + return RSA.importKey(actor_data['publicKey']['publicKeyPem']) - if 'publicKeyPem' not in actor_data['publicKey']: - return None - - return RSA.importKey(actor_data['publicKey']['publicKeyPem']) + except Exception as e: + logging.debug(f'Exception occured while fetching actor key: {e}') async def validate(actor, request): diff --git a/relay/remote_actor.py b/relay/remote_actor.py index 279ada7..2e4b92e 100644 --- a/relay/remote_actor.py +++ b/relay/remote_actor.py @@ -1,9 +1,12 @@ import logging import aiohttp -from . import CONFIG -from .http_debug import http_debug from cachetools import TTLCache +from datetime import datetime +from urllib.parse import urlsplit + +from . import CONFIG +from .http_debug import http_debug CACHE_SIZE = CONFIG.get('cache-size', 16384) @@ -12,22 +15,42 @@ CACHE_TTL = CONFIG.get('cache-ttl', 3600) ACTORS = TTLCache(CACHE_SIZE, CACHE_TTL) -async def fetch_actor(uri, headers={}, force=False): +async def fetch_actor(uri, headers={}, force=False, sign_headers=True): if uri in ACTORS and not force: return ACTORS[uri] - new_headers = {'Accept': 'application/activity+json'} + from .actor import PRIVKEY + from .http_signatures import sign_headers - for k,v in headers.items(): - new_headers[k.capitalize()] = v + url = urlsplit(uri) + key_id = 'https://{}/actor#main-key'.format(CONFIG['ap']['host']) + + headers.update({ + 'Accept': 'application/activity+json', + 'User-Agent': 'ActivityRelay' + }) + + if sign_headers: + headers.update({ + '(request-target)': 'get {}'.format(url.path), + 'Date': datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'), + 'Host': url.netloc + }) + + headers['signature'] = sign_headers(headers, PRIVKEY, key_id) + headers.pop('(request-target)') + headers.pop('Host') try: async with aiohttp.ClientSession(trace_configs=[http_debug()]) as session: - async with session.get(uri, headers=new_headers) as resp: + async with session.get(uri, headers=headers) as resp: + if resp.status != 200: return None + ACTORS[uri] = (await resp.json(encoding='utf-8', content_type=None)) return ACTORS[uri] + except Exception as e: logging.info('Caught %r while fetching actor %r.', e, uri) return None