fix filter and sig middleware

This commit is contained in:
Izalia Mae 2020-01-15 01:55:07 -05:00
parent bdb2d58157
commit 257fd8900e
3 changed files with 47 additions and 77 deletions

View file

@ -69,7 +69,7 @@ else:
MASTOCONFIG={
'domain': env.get('WEB_DOMAIN', env.get('LOCAL_DOMAIN', 'localhost:3000')),
'auth_fetch': bool_check(env.get('AUTHENTICATED_FETCH')),
'auth_fetch': bool_check(env.get('AUTHORIZED_FETCH')),
'dbhost': env.get('DB_HOST', '/var/run/postgresql'),
'dbport': int(env.get('DB_PORT', 5432)),
'dbname': env.get('DB_NAME', 'mastodon_production'),

View file

@ -27,7 +27,7 @@ def jsondb():
'bans': db.table('bans'),
'follows': db.table('follows'),
'users': db.table('users'),
'tokens': db.table('tokens')
'domains': db.table('domains')
}
return tables
@ -46,15 +46,18 @@ def pgdb():
sys.exit()
def get_bans():
def get_bans(suspend=True, details=False):
domains = mastodb.query('SELECT * FROM public.domain_blocks;').dictresult()
banlist = {}
banlist = {} if details else []
for domain in domains:
instance = domain['domain']
severity = domain['severity']
if severity == 1:
if suspend and severity != 1:
continue
if details:
banlist[instance] = {
'severity': domain['severity'],
'media': bool_check(domain['reject_media']),
@ -64,37 +67,25 @@ def get_bans():
'updated': domain['updated_at']
}
else:
banlist.append(instance)
return banlist
def update_bans():
'''I'll implement this later'''
pass
def update_bancache():
bans = get_bans()
banlist = cache.get('bans')
for domain in bans:
if domain not in banlist or bans[domain]['updated'] > banlist[domain]['updated']:
banlist[domain] = bans[domain]
cache['bans'] = banlist
logging.debug('Updated ban cache')
def ban_check(url):
instance = urlparse(url).netloc if url.startswith('http') else url
domain = extract(url)
parsed = f'{domain.domain}.{domain.suffix}'
banlist = get_bans()
for ban in get_bans():
for ban in banlist:
if ban in [instance, parsed]:
return True
logging.debug(f'{parsed} not in blocklist')
pawsdb = jsondb()
query = Query()
mastodb = pgdb()

View file

@ -30,7 +30,8 @@ blocked_agents = [
'shitposter.club',
'baraag',
'gameliberty',
'neckbeard'
'neckbeard',
'soapbox'
]
auth_paths = [
@ -39,11 +40,11 @@ auth_paths = [
]
def parse_sig(signature):
def parse_sig(signature, short=False):
for line in signature.split(','):
if 'keyId' in line:
if 'keyid' in line.lower():
actor = line.split('=')[1].split('#')[0].replace('"', '')
return actor
return urlparse(actor).netloc if short else actor
def parse_ua(agent):
@ -54,7 +55,7 @@ def parse_ua(agent):
if len(ua1) < 2:
logging.warning(f'No url in user-agent: {agent}')
return
return 'unknown'
if 'Mastodon' in agent:
ua2 = ua1[1].split('/')
@ -65,21 +66,18 @@ def parse_ua(agent):
elif 'Misskey' in agent or 'BarksharkRelay' in agent:
ua2 = ua1[1].split(')')
elif 'Friendica' in agent:
logging.debug(ua1[1])
return ua1[1]
elif 'activityrelay' in agent.lower():
return ''
elif 'Friendica' in agent or 'microblog.pub' in agent:
ua2 = ua1[1]
else:
logging.warning(f'Unhandled user-agent: {agent}')
return 'unknown'
if len(ua2) > 1:
logging.debug(ua2[0])
logging.debug(f'domain: {ua2}')
return ua2[0]
logging.warning(f'Invalid user-agent: {agent}')
logging.warning(f'Invalid user-agent: {ua2}')
async def raise_auth_error(request, auth_realm):
@ -143,41 +141,26 @@ async def http_redirect(app, handler):
async def http_signatures(app, handler):
async def http_signatures_handler(request):
request['validated'] = False
json_req = True if 'json' in request.headers.get('Accept', '') else False
if request.method == 'POST':
if 'signature' in request.headers:
data = await request.json()
if 'actor' not in data:
logging.info('signature check failed, no actor in message')
raise json_error(401, 'signature check failed, no actor in message')
actor = data["actor"]
if not (await validate(actor, request)):
logging.info(f'Signature validation failed for: {actor}')
raise json_error(401, 'signature check failed, signature did not match key')
else:
logging.info('missing signature')
raise json_error(401, 'Missing signature')
if any(map(request.path.startswith, auth_paths)) and request.method != 'POST':
if json_req or request.path.endswith('.json'):
if not user_check(request.path) and MASTOCONFIG['auth_fetch']:
if 'json' in request.headers.get('Accept', '') or request.path.endswith('.json'):
request['reqtype'] = 'json'
if not user_check(request.path) and not MASTOCONFIG['auth_fetch']:
signature = request.headers.get('signature', '')
actor = parse_sig(signature)
if not signature:
logging.info('missing signature')
logging.warning('missing signature')
raise json_error(401, 'Missing signature')
actor = parse_sig(signature)
if not (await validate(actor, request)):
logging.info(f'Signature validation failed for: {actor}')
raise json_error(401, 'signature check failed, signature did not match key')
else:
request['reqtype'] = 'html'
auth_username = PAWSCONFIG['user']
auth_password = PAWSCONFIG['pass']
auth_realm = 'Nope'
@ -210,29 +193,25 @@ async def http_signatures(app, handler):
async def http_filter(app, handler):
async def http_filter_handler(request):
ua = request.headers.get('user-agent')
if request.get('reqtype') == 'json':
signature = request.headers.get('signature').lower()
ua = request.headers.get('user-agent').lower()
if not user_check(request.path):
try:
data = await request.json()
actor = data.get('actor')
if actor:
domain = urlparse(actor).netloc
except:
domain = parse_ua(ua)
if not user_check(request.path):
sig_domain = parse_sig(signature, short=True)
ua_domain = parse_ua(ua)
domain = ua_domain if not sig_domain else sig_domain
if not domain:
raise json_error(401, 'Can\'t parse user-agent')
raise json_error(401, 'Can\'t find instance domain')
if [agent for agent in blocked_agents if agent in request.headers.get('User-Agent', '').lower()]:
logging.info(f'Blocked garbage: {domain}')
raise HTTPTeapot(body='418 This teapot kills fascists', content_type='text/plain')
if [agent for agent in blocked_agents if agent in ua]:
logging.info(f'Blocked garbage: {domain}')
raise HTTPTeapot(body='418 This teapot kills fascists', content_type='text/plain')
if db.ban_check(domain):
logging.info(f'Blocked instance: {domain}')
raise json_error(403, 'Forbidden')
if db.ban_check(domain):
logging.info(f'Blocked instance: {domain}')
raise json_error(403, 'Forbidden')
return (await handler(request))
return http_filter_handler