fix filter and sig middleware
This commit is contained in:
parent
bdb2d58157
commit
257fd8900e
|
@ -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'),
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue