From 30a4285b92fae9b704628d15bb14a0e9fb2eb7ba Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Sat, 21 Nov 2020 05:31:19 +0000 Subject: [PATCH] - Removed direct connections (will be a different project in the future) - removed chat for now - removed onionrcommunicatortimers --- .../private/register_private_blueprints.py | 3 - src/communicator/__init__.py | 57 ++------- src/communicatorutils/announcenode.py | 11 +- src/communicatorutils/housekeeping.py | 4 +- .../onionrcommunicatortimers.py | 99 --------------- src/communicatorutils/servicecreator.py | 47 ------- src/httpapi/directconnections/__init__.py | 78 ------------ .../httpheaders.py | 0 src/httpapi/miscpublicapi/getblocks.py | 6 +- src/httpapi/security/client.py | 2 +- src/httpapi/security/lan.py | 2 +- src/httpapi/security/public.py | 2 +- src/onionrservices/README.md | 13 -- src/onionrservices/__init__.py | 69 ----------- src/onionrservices/bootstrapservice.py | 116 ------------------ src/onionrservices/connectionserver.py | 89 -------------- src/onionrservices/pool.py | 29 ----- src/onionrservices/serverexists.py | 30 ----- src/setupkvvars/__init__.py | 2 +- .../default-plugins/chat/controlapi.py | 75 ----------- static-data/default-plugins/chat/info.json | 5 - static-data/default-plugins/chat/main.py | 39 ------ .../default-plugins/chat/peerserver.py | 65 ---------- static-data/default-plugins/chat/settings.py | 0 static-data/default_config.json | 1 - 25 files changed, 21 insertions(+), 823 deletions(-) delete mode 100755 src/communicatorutils/onionrcommunicatortimers.py delete mode 100755 src/communicatorutils/servicecreator.py delete mode 100644 src/httpapi/directconnections/__init__.py rename src/{onionrservices => httpapi}/httpheaders.py (100%) delete mode 100755 src/onionrservices/README.md delete mode 100755 src/onionrservices/__init__.py delete mode 100755 src/onionrservices/bootstrapservice.py delete mode 100755 src/onionrservices/connectionserver.py delete mode 100644 src/onionrservices/pool.py delete mode 100644 src/onionrservices/serverexists.py delete mode 100755 static-data/default-plugins/chat/controlapi.py delete mode 100755 static-data/default-plugins/chat/info.json delete mode 100755 static-data/default-plugins/chat/main.py delete mode 100755 static-data/default-plugins/chat/peerserver.py delete mode 100644 static-data/default-plugins/chat/settings.py diff --git a/src/apiservers/private/register_private_blueprints.py b/src/apiservers/private/register_private_blueprints.py index 4644f87d..0a33a8dd 100644 --- a/src/apiservers/private/register_private_blueprints.py +++ b/src/apiservers/private/register_private_blueprints.py @@ -7,7 +7,6 @@ from gevent import sleep from httpapi import security, friendsapi, configapi, insertblock from httpapi import miscclientapi, onionrsitesapi, apiutils -from httpapi import directconnections from httpapi import themeapi from httpapi import fileoffsetreader from httpapi.sse.private import private_sse_blueprint @@ -42,8 +41,6 @@ def register_private_blueprints(private_api, app): app.register_blueprint(onionrsitesapi.site_api) app.register_blueprint(apiutils.shutdown.shutdown_bp) app.register_blueprint(miscclientapi.staticfiles.static_files_bp) - app.register_blueprint(directconnections.DirectConnectionManagement( - private_api).direct_conn_management_bp) app.register_blueprint(themeapi.theme_blueprint) app.register_blueprint(private_sse_blueprint) app.register_blueprint(fileoffsetreader.offset_reader_api) diff --git a/src/communicator/__init__.py b/src/communicator/__init__.py index 89700d58..257822a3 100755 --- a/src/communicator/__init__.py +++ b/src/communicator/__init__.py @@ -12,8 +12,6 @@ import onionrpeers import onionrplugins as plugins from . import onlinepeers from . import uploadqueue -from communicatorutils import servicecreator -from communicatorutils import onionrcommunicatortimers from communicatorutils import downloadblocks from communicatorutils import lookupblocks from communicatorutils import lookupadders @@ -25,7 +23,6 @@ from communicatorutils import housekeeping from communicatorutils import netcheck from onionrthreads import add_onionr_thread from onionrcommands.openwebinterface import get_url -import onionrservices from netcontroller import NetController from . import bootstrappeers from . import daemoneventhooks @@ -44,8 +41,6 @@ from . import daemoneventhooks along with this program. If not, see . """ -OnionrCommunicatorTimers = onionrcommunicatortimers.OnionrCommunicatorTimers - config.reload() @@ -66,9 +61,6 @@ class OnionrCommunicatorDaemon: if config.get('general.offline_mode', False): self.kv.put('isOnline', False) - # list of timer instances - self.timers = [] - # initialize core with Tor socks port being 3rd argument self.proxyPort = shared_state.get(NetController).socksPort @@ -118,24 +110,11 @@ class OnionrCommunicatorDaemon: uploadblocks.upload_blocks_from_communicator, [self.shared_state], 5, 1) - # Setup direct connections - if config.get('general.ephemeral_tunnels', False): - self.services = onionrservices.OnionrServices() - self.active_services = [] - self.service_greenlets = [] - OnionrCommunicatorTimers( - self, servicecreator.service_creator, 5, - max_threads=50, my_args=[self]) - else: - self.services = None - - # {peer_pubkey: ephemeral_address}, the address to reach them - self.direct_connection_clients = {} - # This timer creates deniable blocks, # in an attempt to further obfuscate block insertion metadata if config.get('general.insert_deniable_blocks', True): - add_onionr_thread(deniableinserts.insert_deniable_block, [], 180, 10) + add_onionr_thread( + deniableinserts.insert_deniable_block, [], 180, 10) if config.get('transports.tor', True): # Timer to check for connectivity, @@ -147,24 +126,14 @@ class OnionrCommunicatorDaemon: if config.get('general.security_level', 1) == 0 \ and config.get('general.announce_node', True): # Default to high security level incase config breaks - announceTimer = OnionrCommunicatorTimers( - self, - announcenode.announce_node, - 3600, my_args=[self], requires_peer=True, max_threads=1) - announceTimer.count = (announceTimer.frequency - 60) + add_onionr_thread( + announcenode.announce_node, [self.shared_state], 600, 60) else: logger.debug('Will not announce node.') - # Timer to delete malfunctioning or long-dead peers - cleanupTimer = OnionrCommunicatorTimers( - self, self.peerCleanup, 300, requires_peer=True) + add_onionr_thread(onionrpeers.peer_cleanup, [], 300, 300) - # Timer to cleanup dead ephemeral forward secrecy keys - OnionrCommunicatorTimers( - self, housekeeping.clean_keys, 15, my_args=[self], max_threads=1) - - # Adjust initial timer triggers - cleanupTimer.count = (cleanupTimer.frequency - 60) + add_onionr_thread(housekeeping.clean_keys, [], 15, 1) if config.get('general.use_bootstrap_list', True): bootstrappeers.add_bootstrap_list_to_peer_list( @@ -192,11 +161,6 @@ class OnionrCommunicatorDaemon: try: while not self.shared_state.get_by_string( 'DeadSimpleKV').get('shutdown'): - for i in self.timers: - if self.shared_state.get_by_string( - 'DeadSimpleKV').get('shutdown'): - break - i.processTimer() time.sleep(self.delay) except KeyboardInterrupt: self.shared_state.get_by_string( @@ -204,14 +168,7 @@ class OnionrCommunicatorDaemon: logger.info( 'Goodbye. (Onionr is cleaning up, and will exit)', terminal=True) - try: - self.service_greenlets - except AttributeError: - pass - else: - # Stop onionr direct connection services - for server in self.service_greenlets: - server.stop() + try: time.sleep(0.5) except KeyboardInterrupt: diff --git a/src/communicatorutils/announcenode.py b/src/communicatorutils/announcenode.py index 2a4affd3..91caa987 100755 --- a/src/communicatorutils/announcenode.py +++ b/src/communicatorutils/announcenode.py @@ -32,16 +32,16 @@ if TYPE_CHECKING: """ -def announce_node(daemon): +def announce_node(shared_state): """Announce our node to our peers.""" ret_data = False - kv: "DeadSimpleKV" = daemon.shared_state.get_by_string("DeadSimpleKV") - + kv: "DeadSimpleKV" = shared_state.get_by_string("DeadSimpleKV") + config = shared_state.get_by_string("OnionrCommunicatorDaemon").config # Do not let announceCache get too large if len(kv.get('announceCache')) >= 10000: kv.get('announceCache').popitem() - if daemon.config.get('general.security_level', 0) == 0: + if config.get('general.security_level', 0) == 0: # Announce to random online peers for i in kv.get('onlinePeers'): if i not in kv.get('announceCache'): @@ -67,12 +67,11 @@ def announce_node(daemon): if basicrequests.do_post_request( url, data, - port=daemon.shared_state.get(NetController).socksPort)\ + port=shared_state.get(NetController).socksPort)\ == 'Success': logger.info('Successfully introduced node to ' + peer, terminal=True) ret_data = True keydb.transportinfo.set_address_info(peer, 'introduced', 1) - daemon.decrementThreadCount('announce_node') return ret_data diff --git a/src/communicatorutils/housekeeping.py b/src/communicatorutils/housekeeping.py index f87c28d3..97024663 100755 --- a/src/communicatorutils/housekeeping.py +++ b/src/communicatorutils/housekeeping.py @@ -68,7 +68,7 @@ def clean_old_blocks(shared_state): logger.info('Deleted block: %s' % (oldest,)) -def clean_keys(comm_inst): +def clean_keys(): """Delete expired forward secrecy keys""" conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=DATABASE_LOCK_TIMEOUT) @@ -88,5 +88,3 @@ def clean_keys(comm_inst): conn.close() onionrusers.deleteExpiredKeys() - - comm_inst.decrementThreadCount('clean_keys') diff --git a/src/communicatorutils/onionrcommunicatortimers.py b/src/communicatorutils/onionrcommunicatortimers.py deleted file mode 100755 index 9b91ac2f..00000000 --- a/src/communicatorutils/onionrcommunicatortimers.py +++ /dev/null @@ -1,99 +0,0 @@ -""" -Onionr - Private P2P Communication. - -This file contains timer control for the communicator -""" -from __future__ import annotations # thank you python, very cool -import uuid -import threading - -import onionrexceptions -import logger - -from typing import TYPE_CHECKING -from typing import Callable, NewType, Iterable -if TYPE_CHECKING: - from deadsimplekv import DeadSimpleKV - 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 - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - - -CallFreqSeconds = NewType('CallFreqSeconds', int) - - -class OnionrCommunicatorTimers: - def __init__(self, daemon_inst: OnionrCommunicatorDaemon, - timer_function: Callable, frequency: CallFreqSeconds, - make_thread: bool = True, - thread_amount: int = 1, max_threads: int = 5, - requires_peer: bool = False, my_args: Iterable = []): - self.timer_function = timer_function - self.frequency = frequency - self.thread_amount = thread_amount - self.make_thread = make_thread - self.requires_peer = requires_peer - self.daemon_inst = daemon_inst - self.max_threads = max_threads - self.args = my_args - self.kv: "DeadSimpleKV" = daemon_inst.shared_state.get_by_string( - "DeadSimpleKV") - - self.daemon_inst.timers.append(self) - self.count = 0 - - def processTimer(self): - - # mark # of instances of a thread we have (decremented at thread end) - try: - self.daemon_inst.threadCounts[self.timer_function.__name__] - except KeyError: - self.daemon_inst.threadCounts[self.timer_function.__name__] = 0 - - # execute timer's func, if we are not missing *required* online peer - if self.count == self.frequency and not self.kv.get('shutdown'): - try: - if self.requires_peer and \ - len(self.kv.get('onlinePeers')) == 0: - raise onionrexceptions.OnlinePeerNeeded - except onionrexceptions.OnlinePeerNeeded: - return - else: - if self.make_thread: - for i in range(self.thread_amount): - """ - Log if a timer has max num of active threads - If this logs frequently it is indicative of a bug - or need for optimization - """ - if self.daemon_inst.threadCounts[ - self.timer_function.__name__] >= \ - self.max_threads: - logger.debug( - f'{self.timer_function.__name__} is currently using the maximum number of threads, not starting another.') # noqa - # if active number of threads for timer not reached yet - else: - self.daemon_inst.threadCounts[ - self.timer_function.__name__] += 1 - newThread = threading.Thread( - target=self.timer_function, args=self.args, - daemon=True, - name=self.timer_function.__name__ + ' - ' + - str(uuid.uuid4())) - newThread.start() - else: - self.timer_function() - self.count = -1 # negative 1 because its incremented at bottom - self.count += 1 diff --git a/src/communicatorutils/servicecreator.py b/src/communicatorutils/servicecreator.py deleted file mode 100755 index 52228f5f..00000000 --- a/src/communicatorutils/servicecreator.py +++ /dev/null @@ -1,47 +0,0 @@ -""" -Onionr - Private P2P Communication. - -Creates an onionr direct connection service by scanning all connection blocks -""" -import communicator -from onionrblocks import onionrblockapi -from onionrutils import stringvalidators, bytesconverter -from coredb import blockmetadb -from onionrservices import server_exists -""" - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - - -def service_creator(daemon): - assert isinstance(daemon, communicator.OnionrCommunicatorDaemon) - - # Find socket connection blocks - # TODO cache blocks and only look at recently received ones - con_blocks = blockmetadb.get_blocks_by_type('con') - for b in con_blocks: - if b not in daemon.active_services: - bl = onionrblockapi.Block(b, decrypt=True) - bs = bytesconverter.bytes_to_str(bl.bcontent) + '.onion' - if server_exists(bl.signer): - continue - if stringvalidators.validate_pub_key(bl.signer) and \ - stringvalidators.validate_transport(bs): - signer = bytesconverter.bytes_to_str(bl.signer) - daemon.active_services.append(b) - daemon.active_services.append(signer) - if not daemon.services.create_server(signer, bs, daemon): - daemon.active_services.remove(b) - daemon.active_services.remove(signer) - daemon.decrementThreadCount('service_creator') diff --git a/src/httpapi/directconnections/__init__.py b/src/httpapi/directconnections/__init__.py deleted file mode 100644 index 9169abd8..00000000 --- a/src/httpapi/directconnections/__init__.py +++ /dev/null @@ -1,78 +0,0 @@ -"""Onionr - Private P2P Communication. - -Misc client API endpoints too small to need their own file and that need access to the client api inst -""" -# For the client creation thread -import threading - -# For direct connection management HTTP endpoints -from flask import Response -# To make the direct connection management blueprint in the webUI -from flask import Blueprint -# Mainly to access the shared toomanyobjs object -from flask import g -import deadsimplekv - -import filepaths -import onionrservices -from onionrservices import pool -""" - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - - -def _get_communicator(g): - while True: - try: - return g.too_many.get_by_string("OnionrCommunicatorDaemon") - except KeyError: - pass - - -class DirectConnectionManagement: - def __init__(self, client_api): - direct_conn_management_bp = Blueprint( - 'direct_conn_management', __name__) - self.direct_conn_management_bp = direct_conn_management_bp - - cache = deadsimplekv.DeadSimpleKV(filepaths.cached_storage) - - @direct_conn_management_bp.route('/dc-client/isconnected/') - def is_connected(pubkey): - communicator = _get_communicator(g) - resp = "" - if pubkey in communicator.direct_connection_clients: - resp = communicator.direct_connection_clients[pubkey] - return Response(resp) - - @direct_conn_management_bp.route('/dc-client/connect/') - def make_new_connection(pubkey): - communicator = _get_communicator(g) - resp = "pending" - if pubkey in communicator.shared_state.get( - pool.ServicePool).bootstrap_pending: - return Response(resp) - - if pubkey in communicator.direct_connection_clients: - resp = communicator.direct_connection_clients[pubkey] - else: - """Spawn a thread that will create the client and eventually add it to the - communicator.active_services - """ - threading.Thread( - target=onionrservices.OnionrServices().create_client, - args=[pubkey, communicator], daemon=True).start() - - return Response(resp) - \ No newline at end of file diff --git a/src/onionrservices/httpheaders.py b/src/httpapi/httpheaders.py similarity index 100% rename from src/onionrservices/httpheaders.py rename to src/httpapi/httpheaders.py diff --git a/src/httpapi/miscpublicapi/getblocks.py b/src/httpapi/miscpublicapi/getblocks.py index adaceb91..cc64e6c9 100755 --- a/src/httpapi/miscpublicapi/getblocks.py +++ b/src/httpapi/miscpublicapi/getblocks.py @@ -60,9 +60,11 @@ def get_block_data(public_API, b_hash): # Encode in case data is binary block = block.encode('utf-8') except AttributeError: - if len(block) == 0: + # 404 if no block data + if not block: + abort(404) + if not len(block): abort(404) - #block = bytesconverter.str_to_bytes(block) resp = block if len(resp) == 0: abort(404) diff --git a/src/httpapi/security/client.py b/src/httpapi/security/client.py index 5bf5d6cc..11ee4f99 100644 --- a/src/httpapi/security/client.py +++ b/src/httpapi/security/client.py @@ -7,7 +7,7 @@ import hmac from flask import Blueprint, request, abort, g -from onionrservices import httpheaders +from httpapi import httpheaders from . import pluginwhitelist import config import logger diff --git a/src/httpapi/security/lan.py b/src/httpapi/security/lan.py index baacfa00..a25dd767 100644 --- a/src/httpapi/security/lan.py +++ b/src/httpapi/security/lan.py @@ -3,7 +3,7 @@ Process incoming requests to the public api server for certain attacks """ from flask import Blueprint, request, abort, g -from onionrservices import httpheaders +from httpapi import httpheaders from onionrutils import epoch from lan import getip """ diff --git a/src/httpapi/security/public.py b/src/httpapi/security/public.py index 74d7e0cd..239160fc 100644 --- a/src/httpapi/security/public.py +++ b/src/httpapi/security/public.py @@ -3,7 +3,7 @@ Process incoming requests to the public api server for certain attacks """ from flask import Blueprint, request, abort, g -from onionrservices import httpheaders +from httpapi import httpheaders from onionrutils import epoch from utils import gettransports """ diff --git a/src/onionrservices/README.md b/src/onionrservices/README.md deleted file mode 100755 index 2022231c..00000000 --- a/src/onionrservices/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# onionrservices - -onionservices is a submodule to handle direct connections to Onionr peers, using the Onionr network to broker them. - -## Files - -__init__.py: Contains the OnionrServices class which can create direct connection servers or clients. - -bootstrapservice.py: Creates a bootstrap server for a peer and announces the connection by creating a block encrypted to the peer we want to connect to. - -connectionserver.py: Creates a direct connection server for a peer - -httpheaders.py: Modifies a Flask response object http response headers for security purposes. \ No newline at end of file diff --git a/src/onionrservices/__init__.py b/src/onionrservices/__init__.py deleted file mode 100755 index a9d81db0..00000000 --- a/src/onionrservices/__init__.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Onionr - Private P2P Communication. - -Onionr services provide the server component to direct connections -""" -import time -from . import connectionserver, bootstrapservice, serverexists -from onionrutils import stringvalidators, basicrequests -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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" - -server_exists = serverexists.server_exists - - -class OnionrServices: - """Create a client or server for connecting to peer interfaces.""" - def __init__(self): - self.servers = {} - self.clients = {} - self.shutdown = False - - def create_server(self, peer, address, comm_inst): - """ - Create a server for direct connections - - When a client wants to connect, contact their bootstrap address and tell them our ephemeral address for our service by creating a new ConnectionServer instance - """ - if not stringvalidators.validate_transport(address): - raise ValueError('address must be valid') - # How many times to attempt contacting the bootstrap server - BOOTSTRAP_TRIES = 10 - # Seconds to wait before trying bootstrap again - TRY_WAIT = 3 - # HTTP is fine because .onion/i2p is encrypted/authenticated - base_url = 'http://%s/' % (address,) - socks = config.get('tor.socksport') - for x in range(BOOTSTRAP_TRIES): - if basicrequests.do_get_request( - base_url + 'ping', port=socks, ignoreAPI=True) == 'pong!': - # if bootstrap sever is online, tell them our service address - connectionserver.ConnectionServer( - peer, address, comm_inst=comm_inst) - else: - time.sleep(TRY_WAIT) - else: - return False - - @staticmethod - def create_client(peer, comm_inst=None): - # Create ephemeral onion service to bootstrap connection to server - if comm_inst is not None: - try: - return comm_inst.direct_connection_clients[peer] - except KeyError: - pass - address = bootstrapservice.bootstrap_client_service(peer, comm_inst) - return address diff --git a/src/onionrservices/bootstrapservice.py b/src/onionrservices/bootstrapservice.py deleted file mode 100755 index c41295df..00000000 --- a/src/onionrservices/bootstrapservice.py +++ /dev/null @@ -1,116 +0,0 @@ -''' - Onionr - Private P2P Communication - - Bootstrap onion direct connections for the clients -''' -''' - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -''' -import time, threading, uuid, os -from gevent.pywsgi import WSGIServer, WSGIHandler -from stem.control import Controller -from flask import Flask, Response -from netcontroller import get_open_port -from . import httpheaders -from onionrutils import stringvalidators, epoch -import logger -import config, onionrblocks, filepaths -import onionrexceptions -import deadsimplekv as simplekv -from . import pool - -def __bootstrap_timeout(server: WSGIServer, timeout: int, signal_object): - time.sleep(timeout) - signal_object.timed_out = True - server.stop() - -def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300): - ''' - Bootstrap client services - ''' - if not stringvalidators.validate_pub_key(peer): - raise ValueError('Peer must be valid base32 ed25519 public key') - - connection_pool = None - - # here we use a lambda for the timeout thread to set to true - timed_out = lambda: None - timed_out.timed_out = False - - bootstrap_port = get_open_port() - bootstrap_app = Flask(__name__) - bootstrap_app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 - - http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None) - try: - if comm_inst is None: raise ValueError - except (AttributeError, ValueError) as e: - pass - else: - comm_inst.service_greenlets.append(http_server) - connection_pool = comm_inst.shared_state.get(pool.ServicePool) - - bootstrap_address = '' - shutdown = False - bs_id = str(uuid.uuid4()) - key_store = simplekv.DeadSimpleKV(filepaths.cached_storage) - - @bootstrap_app.route('/ping') - def get_ping(): - return "pong!" - - @bootstrap_app.after_request - def afterReq(resp): - # Security headers - resp = httpheaders.set_default_onionr_http_headers(resp) - return resp - - @bootstrap_app.route('/bs/
', methods=['POST']) - def get_bootstrap(address): - if stringvalidators.validate_transport(address + '.onion'): - # Set the bootstrap address then close the server - bootstrap_address = address + '.onion' - key_store.put(bs_id, bootstrap_address) - http_server.stop() - return Response("success") - else: - return Response("") - - with Controller.from_port(port=config.get('tor.controlPort')) as controller: - if not connection_pool is None: connection_pool.bootstrap_pending.append(peer) - # Connect to the Tor process for Onionr - controller.authenticate(config.get('tor.controlpassword')) - # Create the v3 onion service - response = controller.create_ephemeral_hidden_service({80: bootstrap_port}, key_type = 'NEW', key_content = 'ED25519-V3', await_publication = True) - onionrblocks.insert(response.service_id, header='con', sign=True, encryptType='asym', - asymPeer=peer, disableForward=True, expire=(epoch.get_epoch() + bootstrap_timeout)) - - threading.Thread(target=__bootstrap_timeout, args=[http_server, bootstrap_timeout, timed_out], daemon=True).start() - - # Run the bootstrap server - try: - http_server.serve_forever() - except TypeError: - pass - # This line reached when server is shutdown by being bootstrapped - # Add the address to the client pool - if not comm_inst is None: - connection_pool.bootstrap_pending.remove(peer) - if timed_out.timed_out: - logger.warn('Could not connect to %s due to timeout' % (peer,)) - return None - comm_inst.direct_connection_clients[peer] = response.service_id - - # Now that the bootstrap server has received a server, return the address - return key_store.get(bs_id) diff --git a/src/onionrservices/connectionserver.py b/src/onionrservices/connectionserver.py deleted file mode 100755 index a63e94b5..00000000 --- a/src/onionrservices/connectionserver.py +++ /dev/null @@ -1,89 +0,0 @@ -''' - Onionr - Private P2P Communication - - This module does the second part of the bootstrap block handshake and creates the API 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -''' -from gevent.pywsgi import WSGIServer -from stem.control import Controller -from flask import Flask -import logger, httpapi -import onionrexceptions, config, filepaths -from netcontroller import get_open_port -from httpapi import apiutils -from onionrutils import stringvalidators, basicrequests, bytesconverter -from . import httpheaders -import deadsimplekv as simplekv - -class ConnectionServer: - def __init__(self, peer, address, comm_inst=None): - - if not stringvalidators.validate_pub_key(peer): - raise ValueError('Peer must be valid base32 ed25519 public key') - - socks = config.get('tor.socksport') # Load config for Tor socks port for proxy - service_app = Flask(__name__) # Setup Flask app for server. - service_port = get_open_port() - service_ip = apiutils.setbindip.set_bind_IP() - http_server = WSGIServer(('127.0.0.1', service_port), service_app, log=None) - comm_inst.service_greenlets.append(http_server) - key_store = simplekv.DeadSimpleKV(filepaths.cached_storage) - - # TODO define basic endpoints useful for direct connections like stats - - httpapi.load_plugin_blueprints(service_app, blueprint='direct_blueprint') - - @service_app.route('/ping') - def get_ping(): - return "pong!" - - @service_app.route('/close') - def shutdown_server(): - comm_inst.service_greenlets.remove(http_server) - http_server.stop() - return Response('goodbye') - - @service_app.after_request - def afterReq(resp): - # Security headers - resp = httpheaders.set_default_onionr_http_headers(resp) - return resp - - with Controller.from_port(port=config.get('tor.controlPort')) as controller: - # Connect to the Tor process for Onionr - controller.authenticate(config.get('tor.controlpassword')) - # Create the v3 onion service for the peer to connect to - response = controller.create_ephemeral_hidden_service({80: service_port}, await_publication = True, key_type='NEW', key_content = 'ED25519-V3') - - try: - for x in range(3): - attempt = basicrequests.do_post_request('http://' + address + '/bs/' + response.service_id, port=socks) - if attempt == 'success': - break - else: - raise ConnectionError - except ConnectionError: - # Re-raise - raise ConnectionError('Could not reach %s bootstrap address %s' % (peer, address)) - else: - # If no connection error, create the service and save it to local global key store - peer = bytesconverter.bytes_to_str(peer) - key_store.put('dc-' + peer, response.service_id) - key_store.flush() - logger.info('hosting on %s with %s' % (response.service_id, peer)) - http_server.serve_forever() - http_server.stop() - key_store.delete('dc-' + peer) diff --git a/src/onionrservices/pool.py b/src/onionrservices/pool.py deleted file mode 100644 index 4f26029c..00000000 --- a/src/onionrservices/pool.py +++ /dev/null @@ -1,29 +0,0 @@ -''' - Onionr - Private P2P Communication - - Holds active onionrservices clients and servers -''' -''' - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -''' -from onionrutils import epoch -class ServicePool: - def __init__(self): - self.servers = [] - self.clients = [] - self.bootstrap_pending = [] - - def add_server(self, service): - self.servers.append((service, epoch.get_epoch())) - \ No newline at end of file diff --git a/src/onionrservices/serverexists.py b/src/onionrservices/serverexists.py deleted file mode 100644 index b7b049d8..00000000 --- a/src/onionrservices/serverexists.py +++ /dev/null @@ -1,30 +0,0 @@ -''' - Onionr - Private P2P Communication - - Function to check if an onion server is created for a peer or not -''' -''' - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -''' -import deadsimplekv - -import filepaths -from onionrutils import bytesconverter - -def server_exists(peer: str) -> bool: - '''checks if an onion server is created for a peer or not''' - peer = bytesconverter.bytes_to_str(peer) - kv = deadsimplekv.DeadSimpleKV(filepaths.cached_storage) - kv.refresh() - return not kv.get('dc-' + peer) is None \ No newline at end of file diff --git a/src/setupkvvars/__init__.py b/src/setupkvvars/__init__.py index af3b156a..e5774db3 100644 --- a/src/setupkvvars/__init__.py +++ b/src/setupkvvars/__init__.py @@ -26,7 +26,7 @@ if TYPE_CHECKING: def setup_kv(shared_vars: 'DeadSimpleKV'): - """Init initial pseudo-variables.""" + """Init initial pseudo-globals.""" shared_vars.put('plaintextDisabledPeers', {}) shared_vars.put('blockQueue', {}) shared_vars.put('shutdown', False) diff --git a/static-data/default-plugins/chat/controlapi.py b/static-data/default-plugins/chat/controlapi.py deleted file mode 100755 index 0cbac652..00000000 --- a/static-data/default-plugins/chat/controlapi.py +++ /dev/null @@ -1,75 +0,0 @@ -"""Onionr - Private P2P Communication. - -HTTP endpoints for controlling IMs -""" -import ujson as json - -from flask import Response, request, redirect, Blueprint, send_from_directory -import deadsimplekv as simplekv - -import filepaths -""" - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" -flask_blueprint = Blueprint('chat_control', __name__) -key_store = simplekv.DeadSimpleKV(filepaths.cached_storage, refresh_seconds=5) -@flask_blueprint.route('/chatapi/ping') -def ping(): - return 'pong!' - -@flask_blueprint.route('/chatapi/send/', methods=['POST']) -def send_message(peer): - """Send a message to the peer""" - data = request.get_json(force=True) - key_store.refresh() - existing = key_store.get('s' + peer) - if existing is None: - existing = [] - existing.append(data) - key_store.put('s' + peer, existing) - key_store.flush() - return Response('success') - -@flask_blueprint.route('/chatapi/gets/') -def get_sent(peer): - """Get messages sent to peer""" - sent = key_store.get('s' + peer) - if sent is None: - sent = [] - return Response(json.dumps(sent)) - -@flask_blueprint.route('/chatapi/addrec/', methods=['POST']) -def add_rec(peer): - """Add a received message from the peer""" - data = request.get_json(force=True) - key_store.refresh() - existing = key_store.get('r' + peer) - if existing is None: - existing = [] - existing.append(data) - key_store.put('r' + peer, existing) - key_store.flush() - return Response('success') - -@flask_blueprint.route('/chatapi/getrec/') -def get_messages(peer): - """Get received messages for the peer""" - key_store.refresh() - existing = key_store.get('r' + peer) - if existing is None: - existing = [] - else: - existing = list(existing) - key_store.delete('r' + peer) - return Response(json.dumps(existing)) diff --git a/static-data/default-plugins/chat/info.json b/static-data/default-plugins/chat/info.json deleted file mode 100755 index a35a28fc..00000000 --- a/static-data/default-plugins/chat/info.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name" : "chat", - "version" : "1.0", - "author" : "onionr" -} diff --git a/static-data/default-plugins/chat/main.py b/static-data/default-plugins/chat/main.py deleted file mode 100755 index a7d730d4..00000000 --- a/static-data/default-plugins/chat/main.py +++ /dev/null @@ -1,39 +0,0 @@ -''' - Onionr - Private P2P Communication - - Instant message conversations with Onionr peers -''' -''' - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -''' - -# Imports some useful libraries -import locale, sys, os, threading, ujson as json -locale.setlocale(locale.LC_ALL, '') -import onionrservices, logger, config -from onionrservices import bootstrapservice -from onionrutils import stringvalidators, epoch, basicrequests - -plugin_name = 'chat' -PLUGIN_VERSION = '0.0.0' -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 != '': - logger.error(text) - sys.exit(1) diff --git a/static-data/default-plugins/chat/peerserver.py b/static-data/default-plugins/chat/peerserver.py deleted file mode 100755 index a37bf4b0..00000000 --- a/static-data/default-plugins/chat/peerserver.py +++ /dev/null @@ -1,65 +0,0 @@ -"""Onionr - Private P2P Communication. - -HTTP endpoints for communicating with peers -""" -import sys -import os -from json import JSONDecodeError - -import deadsimplekv as simplekv -import ujson as json -from flask import Response, request, redirect, Blueprint, abort, g - -from utils import identifyhome -from onionrutils import localcommand -import filepaths -""" - 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -""" -sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) -direct_blueprint = Blueprint('chat', __name__) - -key_store = simplekv.DeadSimpleKV(filepaths.cached_storage, refresh_seconds=5) -storage_dir = identifyhome.identify_home() - -@direct_blueprint.before_request -def request_setup(): - key_store.refresh() - host = request.host - host = host.strip('.b32.i2p') - host = host.strip('.onion') - g.host = host - g.peer = key_store.get('dc-' + g.host) - -@direct_blueprint.route('/chat/ping') -def pingdirect(): - return 'pong!' - -@direct_blueprint.route('/chat/sendto', methods=['POST', 'GET']) -def sendto(): - """Endpoint peers send chat messages to""" - try: - msg = request.get_json(force=True) - except JSONDecodeError: - msg = '' - else: - msg = json.dumps(msg) - localcommand.local_command('/chat/addrec/%s' % (g.peer,), post=True, post_data=msg) - return Response('success') - -@direct_blueprint.route('/chat/poll') -def poll_chat(): - """Endpoints peers get new messages from""" - return Response(localcommand.local_command('/chat/gets/%s' % (g.peer,))) - \ No newline at end of file diff --git a/static-data/default-plugins/chat/settings.py b/static-data/default-plugins/chat/settings.py deleted file mode 100644 index e69de29b..00000000 diff --git a/static-data/default_config.json b/static-data/default_config.json index b20fe114..8cb8e486 100755 --- a/static-data/default_config.json +++ b/static-data/default_config.json @@ -46,7 +46,6 @@ }, "plugins": { "disabled": [ - "chat" ], "enabled": [] },