diff --git a/onionr/httpapi/__init__.py b/onionr/httpapi/__init__.py index ca9a2b7a..7f45cd5b 100755 --- a/onionr/httpapi/__init__.py +++ b/onionr/httpapi/__init__.py @@ -1,9 +1,9 @@ -''' +""" Onionr - Private P2P Communication This file registers plugin's flask blueprints for the client http server -''' -''' +""" +""" 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,13 +16,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -''' +""" import onionrplugins -def load_plugin_blueprints(flaskapp, blueprint='flask_blueprint'): - '''Iterate enabled plugins and load any http endpoints they have''' + +def load_plugin_blueprints(flaskapp, blueprint: str = 'flask_blueprint'): + """Iterate enabled plugins and load any http endpoints they have""" for plugin in onionrplugins.get_enabled_plugins(): plugin = onionrplugins.get_plugin(plugin) try: flaskapp.register_blueprint(getattr(plugin, blueprint)) except AttributeError: - pass \ No newline at end of file + pass diff --git a/onionr/httpapi/security/client.py b/onionr/httpapi/security/client.py index 0019c4e5..73a4af58 100644 --- a/onionr/httpapi/security/client.py +++ b/onionr/httpapi/security/client.py @@ -20,19 +20,18 @@ import hmac from flask import Blueprint, request, abort, g from onionrservices import httpheaders +from . import pluginwhitelist + # Be extremely mindful of this. These are endpoints available without a password -whitelist_endpoints = ('siteapi.site', 'www', 'staticfiles.onionrhome', 'staticfiles.homedata', -'staticfiles.board', 'staticfiles.profiles', -'staticfiles.profilesindex', -'staticfiles.boardContent', 'staticfiles.sharedContent', -'staticfiles.mail', 'staticfiles.mailindex', 'staticfiles.friends', 'staticfiles.friendsindex', -'staticfiles.chat', 'staticfiles.chatIndex') +whitelist_endpoints = ['www', 'staticfiles.homedata', 'staticfiles.sharedContent', +'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site', 'staticfiles.onionrhome'] 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) @client_api_security_bp.before_app_request def validate_request(): @@ -40,6 +39,13 @@ class ClientAPISecurity: # For the purpose of preventing DNS rebinding attacks if request.host != '%s:%s' % (client_api.host, client_api.bindPort): abort(403) + + # Add shared objects + try: + g.too_many = self.client_api._too_many + except KeyError: + g.too_many = None + if request.endpoint in whitelist_endpoints: return try: @@ -49,12 +55,6 @@ class ClientAPISecurity: except KeyError: if not hmac.compare_digest(request.form['token'], client_api.clientToken): abort(403) - - # Add shared objects - try: - g.too_many = self.client_api._too_many - except KeyError: - g.too_many = None @client_api_security_bp.after_app_request def after_req(resp): diff --git a/onionr/httpapi/security/pluginwhitelist.py b/onionr/httpapi/security/pluginwhitelist.py new file mode 100644 index 00000000..ca238b2e --- /dev/null +++ b/onionr/httpapi/security/pluginwhitelist.py @@ -0,0 +1,13 @@ +import onionrplugins +def load_plugin_security_whitelist_endpoints(whitelist: list): + """Accept a list reference of whitelist endpoints from security/client.py and + append plugin's specified endpoints to them by attribute""" + for plugin in onionrplugins.get_enabled_plugins(): + try: + plugin = onionrplugins.get_plugin(plugin) + except FileNotFoundError: + continue + try: + whitelist.extend(getattr(plugin, "security_whitelist")) + except AttributeError: + pass \ No newline at end of file diff --git a/onionr/static-data/default-plugins/chat/main.py b/onionr/static-data/default-plugins/chat/main.py index 484e79e0..2b8f7eb6 100755 --- a/onionr/static-data/default-plugins/chat/main.py +++ b/onionr/static-data/default-plugins/chat/main.py @@ -31,6 +31,7 @@ sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) import controlapi, peerserver flask_blueprint = controlapi.flask_blueprint direct_blueprint = peerserver.direct_blueprint +security_whitelist = ['staticfiles.chat', 'staticfiles.chatIndex'] def exit_with_error(text=''): if text != '': diff --git a/onionr/static-data/default-plugins/flow/main.py b/onionr/static-data/default-plugins/flow/main.py index 29e9a012..1c0cf974 100755 --- a/onionr/static-data/default-plugins/flow/main.py +++ b/onionr/static-data/default-plugins/flow/main.py @@ -30,6 +30,7 @@ import deadsimplekv as simplekv sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) import flowapi # import after path insert flask_blueprint = flowapi.flask_blueprint +security_whitelist = ['staticfiles.boardContent', 'staticfiles.board'] plugin_name = 'flow' PLUGIN_VERSION = '0.0.1' diff --git a/onionr/static-data/default-plugins/pms/main.py b/onionr/static-data/default-plugins/pms/main.py index b4c9e863..df26ad1e 100755 --- a/onionr/static-data/default-plugins/pms/main.py +++ b/onionr/static-data/default-plugins/pms/main.py @@ -36,6 +36,7 @@ PLUGIN_VERSION = '0.0.1' sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) import sentboxdb, mailapi, loadinbox # import after path insert flask_blueprint = mailapi.flask_blueprint +security_whitelist = ['staticfiles.mail', 'staticfiles.mailindex'] def add_deleted(keyStore, bHash): existing = keyStore.get('deleted_mail')