Formatting improvements in httpapis

This commit is contained in:
Kevin Froman 2020-08-26 08:25:43 +00:00
parent 3422ca43ff
commit 14f2d03ebf
14 changed files with 88 additions and 60 deletions

View file

@ -1,5 +1,7 @@
from gevent.pywsgi import WSGIServer, WSGIHandler
from gevent import Timeout
class FDSafeHandler(WSGIHandler):
'''Our WSGI handler. Doesn't do much non-default except timeouts'''
def handle(self):
@ -10,5 +12,5 @@ class FDSafeHandler(WSGIHandler):
except Timeout as ex:
if ex is self.timeout:
pass
else:
else:
raise

View file

@ -10,7 +10,7 @@ from flask import Blueprint, Response, request, g
if TYPE_CHECKING:
from deadsimplekv import DeadSimpleKV
import onionrblocks
from onionrcrypto import hashers
from onionrutils import bytesconverter
@ -78,7 +78,7 @@ def client_api_insert_block():
pass
try:
# The setting in the UI is for if forward secrecy is enabled, not disabled
# Setting in the mail UI is for if forward secrecy is *enabled*
disable_forward_secrecy = not insert_data['forward']
except KeyError:
disable_forward_secrecy = False

View file

@ -9,7 +9,6 @@ import logger
from etc import onionrvalues
from onionrutils import stringvalidators, bytesconverter
import filepaths
from communicator import OnionrCommunicatorDaemon
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View file

@ -1,9 +1,13 @@
'''
Onionr - Private P2P Communication
"""Onionr - Private P2P Communication.
Misc public API endpoints too small to need their own file and that need access to the public api inst
'''
'''
Misc public API endpoints too small to need their own file
and that need access to the public api inst
"""
from flask import Response, Blueprint, request, send_from_directory, abort, g
from . import getblocks, upload, announce
from coredb import keydb
import config
"""
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
@ -16,11 +20,9 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
'''
from flask import Response, Blueprint, request, send_from_directory, abort, g
from . import getblocks, upload, announce
from coredb import keydb
import config
"""
class PublicEndpoints:
def __init__(self, public_api):
@ -39,7 +41,8 @@ class PublicEndpoints:
@public_endpoints_bp.route('/getblocklist')
def get_block_list():
'''Get a list of blocks, optionally filtered by epoch time stamp, excluding those hidden'''
"""Get a list of blocks, optionally filtered by epoch time stamp,
excluding those hidden"""
return getblocks.get_public_block_list(public_api, request)
@public_endpoints_bp.route('/getdata/<name>')
@ -68,14 +71,15 @@ class PublicEndpoints:
@public_endpoints_bp.route('/announce', methods=['post'])
def accept_announce():
'''Accept announcements with pow token to prevent spam'''
"""Accept announcements with pow token to prevent spam"""
g.shared_state = public_api._too_many
resp = announce.handle_announce(request)
return resp
@public_endpoints_bp.route('/upload', methods=['post'])
def upload_endpoint():
'''Accept file uploads. In the future this will be done more often than on creation
"""Accept file uploads.
In the future this will be done more often than on creation
to speed up block sync
'''
"""
return upload.accept_upload(request)

View file

@ -45,11 +45,14 @@ def get_block_data(publicAPI, data):
"""data is the block hash in hex"""
resp = ''
if stringvalidators.validate_hash(data):
if not config.get('general.hide_created_blocks', True) or data not in publicAPI.hideBlocks:
if not config.get('general.hide_created_blocks', True) \
or data not in publicAPI.hideBlocks:
if data in publicAPI._too_many.get(BlockList).get():
block = apiutils.GetBlockData().get_block_data(data, raw=True, decrypt=False)
block = apiutils.GetBlockData().get_block_data(
data, raw=True, decrypt=False)
try:
block = block.encode('utf-8') # Encode in case data is binary
# Encode in case data is binary
block = block.encode('utf-8')
except AttributeError:
if len(block) == 0:
abort(404)

View file

@ -5,7 +5,6 @@ Accept block uploads to the public API server
import sys
from gevent import spawn
from gevent import threading
from flask import Response
from flask import abort
from flask import g
@ -43,7 +42,7 @@ def accept_upload(request):
if g.too_many.get_by_string("DeadSimpleKV").get('onlinePeers'):
spawn(
localcommand.local_command,
f'/daemon-event/upload_event',
'/daemon-event/upload_event',
post=True,
is_json=True,
post_data={'block': b_hash}

View file

@ -1,6 +1,7 @@
"""Onionr - Private P2P Communication.
Process incoming requests to the client api server to validate they are legitimate
Process incoming requests to the client api server to validate
that they are legitimate and not DNSR/XSRF or other local adversary
"""
import hmac
from flask import Blueprint, request, abort, g
@ -21,17 +22,23 @@ from . import pluginwhitelist
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
# Be extremely mindful of this. These are endpoints available without a password
whitelist_endpoints = ['www', 'staticfiles.homedata', 'staticfiles.sharedContent',
'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site', 'siteapi.siteFile', 'staticfiles.onionrhome',
'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex']
# Be extremely mindful of this.
# These are endpoints available without a password
whitelist_endpoints = [
'www', 'staticfiles.homedata',
'staticfiles.sharedContent',
'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site',
'siteapi.siteFile', 'staticfiles.onionrhome',
'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex']
class ClientAPISecurity:
def __init__(self, client_api):
client_api_security_bp = Blueprint('clientapisecurity', __name__)
self.client_api_security_bp = client_api_security_bp
self.client_api = client_api
pluginwhitelist.load_plugin_security_whitelist_endpoints(whitelist_endpoints)
pluginwhitelist.load_plugin_security_whitelist_endpoints(
whitelist_endpoints)
@client_api_security_bp.before_app_request
def validate_request():
@ -48,14 +55,18 @@ class ClientAPISecurity:
if request.endpoint in whitelist_endpoints:
return
if request.path.startswith('/site/'): return
if request.path.startswith('/site/'):
return
try:
if not hmac.compare_digest(request.headers['token'], client_api.clientToken):
if not hmac.compare_digest(request.form['token'], client_api.clientToken):
if not hmac.compare_digest(
request.headers['token'], client_api.clientToken):
if not hmac.compare_digest(
request.form['token'], client_api.clientToken):
abort(403)
except KeyError:
if not hmac.compare_digest(request.form['token'], client_api.clientToken):
if not hmac.compare_digest(
request.form['token'], client_api.clientToken):
abort(403)
@client_api_security_bp.after_app_request
@ -63,7 +74,9 @@ class ClientAPISecurity:
# Security headers
resp = httpheaders.set_default_onionr_http_headers(resp)
if request.endpoint in ('siteapi.site', 'siteapi.siteFile'):
resp.headers['Content-Security-Policy'] = "default-src 'none'; style-src 'self' data: 'unsafe-inline'; img-src 'self' data:; media-src 'self' data:"
resp.headers['Content-Security-Policy'] = \
"default-src 'none'; style-src 'self' data: 'unsafe-inline'; img-src 'self' data:; media-src 'self' data:" # noqa
else:
resp.headers['Content-Security-Policy'] = "default-src 'none'; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; media-src 'self'; frame-src 'none'; font-src 'self'; connect-src 'self'"
resp.headers['Content-Security-Policy'] = \
"default-src 'none'; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; media-src 'self'; frame-src 'none'; font-src 'self'; connect-src 'self'" # noqa
return resp

View file

@ -59,7 +59,8 @@ class LANAPISecurity:
'Clear-Site-Data', 'Referrer-Policy')
try:
if g.is_onionr_client:
for header in NON_NETWORK_HEADERS: del resp.headers[header]
for header in NON_NETWORK_HEADERS:
del resp.headers[header]
except AttributeError:
abort(403)
lan_client.lastRequest = epoch.get_rounded_epoch(roundS=5)

View file

@ -30,4 +30,4 @@ def load_plugin_security_whitelist_endpoints(whitelist: list):
try:
whitelist.extend(getattr(plugin, "security_whitelist"))
except AttributeError:
pass
pass

View file

@ -64,13 +64,15 @@ class PublicAPISecurity:
# Network API version
resp.headers['X-API'] = public_api.API_VERSION
# Delete some HTTP headers for Onionr user agents
NON_NETWORK_HEADERS = ('Content-Security-Policy', 'X-Frame-Options',
'X-Content-Type-Options', 'Feature-Policy',
'Clear-Site-Data', 'Referrer-Policy')
NON_NETWORK_HEADERS = (
'Content-Security-Policy', 'X-Frame-Options',
'X-Content-Type-Options', 'Feature-Policy',
'Clear-Site-Data', 'Referrer-Policy')
try:
if g.is_onionr_client:
for header in NON_NETWORK_HEADERS: del resp.headers[header]
for header in NON_NETWORK_HEADERS:
del resp.headers[header]
except AttributeError:
abort(403)