From 30630e1d8e0b8af3a0f6b0e708b9d8869e151db3 Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Fri, 29 Mar 2019 12:37:51 -0500 Subject: [PATCH] work on clandestine --- onionr/communicatorutils/onionrdaemontools.py | 2 +- onionr/communicatorutils/servicecreator.py | 1 + onionr/core.py | 6 +-- onionr/etc/onionrvalues.py | 2 +- onionr/httpapi/__init__.py | 4 +- onionr/onionrcommands/pubkeymanager.py | 4 +- onionr/onionrservices/connectionserver.py | 8 +++- .../default-plugins/clandestine/controlapi.py | 2 +- .../default-plugins/clandestine/main.py | 9 ++-- .../default-plugins/clandestine/peerserver.py | 42 +++++++++++++++++++ 10 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 onionr/static-data/default-plugins/clandestine/peerserver.py diff --git a/onionr/communicatorutils/onionrdaemontools.py b/onionr/communicatorutils/onionrdaemontools.py index b68c693d..1c4e0220 100755 --- a/onionr/communicatorutils/onionrdaemontools.py +++ b/onionr/communicatorutils/onionrdaemontools.py @@ -98,7 +98,7 @@ class DaemonTools: if len(self.daemon.onlinePeers) == 0: if not netutils.checkNetwork(self.daemon._core._utils, torPort=self.daemon.proxyPort): if not self.daemon.shutdown: - logger.warn('Network check failed, are you connected to the internet?') + logger.warn('Network check failed, are you connected to the Internet, and is Tor working?') self.daemon.isOnline = False else: self.daemon.isOnline = True diff --git a/onionr/communicatorutils/servicecreator.py b/onionr/communicatorutils/servicecreator.py index 4914547a..ecd1543c 100644 --- a/onionr/communicatorutils/servicecreator.py +++ b/onionr/communicatorutils/servicecreator.py @@ -12,6 +12,7 @@ def service_creator(daemon): bs = utils.bytesToStr(bl.bcontent) + '.onion' if utils.validatePubKey(bl.signer) and utils.validateID(bs): daemon.active_services.append(b) + daemon.active_services.append(bl.signer) daemon.services.create_server(bl.signer, bs) daemon.decrementThreadCount('service_creator') \ No newline at end of file diff --git a/onionr/core.py b/onionr/core.py index ecbe2d73..48029555 100755 --- a/onionr/core.py +++ b/onionr/core.py @@ -794,11 +794,11 @@ class Core: retData = False else: # Tell the api server through localCommand to wait for the daemon to upload this block to make stastical analysis more difficult - self._utils.localCommand('/waitforshare/' + retData, post=True) + if self._utils.localCommand('/ping', maxWait=10) == 'pong!': + self._utils.localCommand('/waitforshare/' + retData, post=True, maxWait=5) + self.daemonQueueAdd('uploadBlock', retData) self.addToBlockDB(retData, selfInsert=True, dataSaved=True) - #self.setBlockType(retData, meta['type']) self._utils.processBlockMetadata(retData) - self.daemonQueueAdd('uploadBlock', retData) if retData != False: if plaintextPeer == 'OVPCZLOXD6DC5JHX4EQ3PSOGAZ3T24F75HQLIUZSDSMYPEOXCPFA====': diff --git a/onionr/etc/onionrvalues.py b/onionr/etc/onionrvalues.py index 338dc0d3..8627d246 100755 --- a/onionr/etc/onionrvalues.py +++ b/onionr/etc/onionrvalues.py @@ -22,4 +22,4 @@ class OnionrValues: def __init__(self): self.passwordLength = 20 self.blockMetadataLengths = {'meta': 1000, 'sig': 200, 'signer': 200, 'time': 10, 'powRandomToken': 1000, 'encryptType': 4, 'expire': 14} #TODO properly refine values to minimum needed - self.default_expire = 2678400 \ No newline at end of file + self.default_expire = 2592000 \ No newline at end of file diff --git a/onionr/httpapi/__init__.py b/onionr/httpapi/__init__.py index 018d3abb..f38d80bd 100755 --- a/onionr/httpapi/__init__.py +++ b/onionr/httpapi/__init__.py @@ -19,11 +19,11 @@ ''' import onionrplugins -def load_plugin_blueprints(flaskapp): +def load_plugin_blueprints(flaskapp, blueprint='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, 'flask_blueprint')) + flaskapp.register_blueprint(getattr(plugin, blueprint)) except AttributeError: pass \ No newline at end of file diff --git a/onionr/onionrcommands/pubkeymanager.py b/onionr/onionrcommands/pubkeymanager.py index ea55a3fe..00d17175 100644 --- a/onionr/onionrcommands/pubkeymanager.py +++ b/onionr/onionrcommands/pubkeymanager.py @@ -19,7 +19,7 @@ ''' import sys, getpass -import logger +import logger, onionrexceptions from onionrusers import onionrusers def add_ID(o_inst): try: @@ -38,7 +38,7 @@ def add_ID(o_inst): logger.info('Generating deterministic key. This can take a while.') newID, privKey = o_inst.onionrCore._crypto.generateDeterministic(pass1) except onionrexceptions.PasswordStrengthError: - logger.error('Must use at least 25 characters.') + logger.error('Passphrase must use at least %s characters.' % (o_inst.onionrCore._crypto.deterministicRequirement,)) sys.exit(1) else: logger.error('Passwords do not match.') diff --git a/onionr/onionrservices/connectionserver.py b/onionr/onionrservices/connectionserver.py index ee586e2b..ad34cae1 100644 --- a/onionr/onionrservices/connectionserver.py +++ b/onionr/onionrservices/connectionserver.py @@ -21,7 +21,7 @@ import threading, time from gevent.pywsgi import WSGIServer, WSGIHandler from stem.control import Controller from flask import Flask -import core, logger +import core, logger, httpapi from netcontroller import getOpenPort import api from . import httpheaders @@ -44,7 +44,9 @@ class ConnectionServer: core_inst.onionrInst.communicatorInst.service_greenlets.append(http_server) # TODO define basic endpoints useful for direct connections like stats - # TODO load endpoints from plugins + + httpapi.load_plugin_blueprints(service_app, blueprint='direct_blueprint') + @service_app.route('/ping') def get_ping(): return "pong!" @@ -60,7 +62,9 @@ class ConnectionServer: controller.authenticate(core_inst.config.get('tor.controlpassword')) # Create the v3 onion service response = controller.create_ephemeral_hidden_service({80: service_port}, await_publication = True, key_type='NEW', key_content = 'ED25519-V3') + self.core_inst.keyStore.put('dc-' + response.service_id, self.core_inst._utils.bytesToStr(peer)) self.core_inst._utils.doPostRequest('http://' + address + '/bs/' + response.service_id, port=socks) logger.info('hosting on %s with %s' % (response.service_id, peer)) http_server.serve_forever() + self.core_inst.keyStore.delete('dc-' + response.service_id) http_server.stop() \ No newline at end of file diff --git a/onionr/static-data/default-plugins/clandestine/controlapi.py b/onionr/static-data/default-plugins/clandestine/controlapi.py index ce341f82..5631a2a4 100644 --- a/onionr/static-data/default-plugins/clandestine/controlapi.py +++ b/onionr/static-data/default-plugins/clandestine/controlapi.py @@ -21,6 +21,6 @@ from flask import Response, request, redirect, Blueprint, abort flask_blueprint = Blueprint('clandenstine', __name__) -@flask_blueprint.route('/mail/ping') +@flask_blueprint.route('/clandenstine/ping') def ping(): return 'pong!' diff --git a/onionr/static-data/default-plugins/clandestine/main.py b/onionr/static-data/default-plugins/clandestine/main.py index 93bfd2d3..9a1e75a2 100755 --- a/onionr/static-data/default-plugins/clandestine/main.py +++ b/onionr/static-data/default-plugins/clandestine/main.py @@ -23,14 +23,15 @@ import locale, sys, os locale.setlocale(locale.LC_ALL, '') -plugin_name = 'clandenstine' +plugin_name = 'clandestine' PLUGIN_VERSION = '0.0.0' sys.path.insert(0, os.path.dirname(os.path.realpath(__file__))) -from . import controlapi +from . import controlapi, peerserver flask_blueprint = controlapi.flask_blueprint +direct_blueprint = peerserver.direct_blueprint -class Clandenstine: +class Clandestine: def __init__(self, pluginapi): self.myCore = pluginapi.get_core() @@ -42,5 +43,5 @@ def on_init(api, data = None): ''' pluginapi = api - chat = Clandenstine(pluginapi) + chat = Clandestine(pluginapi) return diff --git a/onionr/static-data/default-plugins/clandestine/peerserver.py b/onionr/static-data/default-plugins/clandestine/peerserver.py new file mode 100644 index 00000000..e10fa016 --- /dev/null +++ b/onionr/static-data/default-plugins/clandestine/peerserver.py @@ -0,0 +1,42 @@ +''' + Onionr - P2P Anonymous Storage Network + + HTTP endpoints for communicating with 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 . +''' +import core +from flask import Response, request, redirect, Blueprint, abort, g + +direct_blueprint = Blueprint('clandestine', __name__) +core_inst = core.Core() + +storage_dir = core_inst.dataDir + +@direct_blueprint.before_request +def request_setup(): + core_inst.keyStore.refresh() + host = request.host + host = host.strip('.b32.i2p') + host = host.strip('.onion') + g.host = host + g.peer = core_inst.keyStore.get('dc-' + g.host) + +@direct_blueprint.route('/clandestine/ping') +def pingdirect(): + return 'pong!' + g.peer + +@direct_blueprint.route('/clandestine/send') +def poll_chat \ No newline at end of file