diff --git a/onionr/onionrservices/bootstrapservice.py b/onionr/onionrservices/bootstrapservice.py
index 292df4ed..a2952563 100644
--- a/onionr/onionrservices/bootstrapservice.py
+++ b/onionr/onionrservices/bootstrapservice.py
@@ -23,6 +23,7 @@ from stem.control import Controller
from flask import Flask, Response
import core
from netcontroller import getOpenPort
+from . import httpheaders
def bootstrap_client_service(peer, core_inst=None, bootstrap_timeout=300):
'''
@@ -52,6 +53,12 @@ def bootstrap_client_service(peer, core_inst=None, bootstrap_timeout=300):
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 core_inst._utils.validateID(address + '.onion'):
diff --git a/onionr/onionrservices/connectionserver.py b/onionr/onionrservices/connectionserver.py
index 6b04645c..ee586e2b 100644
--- a/onionr/onionrservices/connectionserver.py
+++ b/onionr/onionrservices/connectionserver.py
@@ -24,6 +24,7 @@ from flask import Flask
import core, logger
from netcontroller import getOpenPort
import api
+from . import httpheaders
class ConnectionServer:
def __init__(self, peer, address, core_inst=None):
@@ -48,6 +49,12 @@ class ConnectionServer:
def get_ping():
return "pong!"
+ @service_app.after_request
+ def afterReq(resp):
+ # Security headers
+ resp = httpheaders.set_default_onionr_http_headers(resp)
+ return resp
+
with Controller.from_port(port=core_inst.config.get('tor.controlPort')) as controller:
# Connect to the Tor process for Onionr
controller.authenticate(core_inst.config.get('tor.controlpassword'))
diff --git a/onionr/onionrsockets.py b/onionr/onionrsockets.py
deleted file mode 100755
index aa02c3db..00000000
--- a/onionr/onionrsockets.py
+++ /dev/null
@@ -1,172 +0,0 @@
-'''
- Onionr - P2P Anonymous Storage Network
-
- Onionr Socket interface
-'''
-'''
- 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 stem.control
-import threading
-import socks, config, uuid
-import onionrexceptions, time, requests, onionrblockapi, logger
-from dependencies import secrets
-from gevent.pywsgi import WSGIServer
-from flask import request, Response, abort
-import flask
-class OnionrSocketServer:
- def __init__(self, coreInst):
- self._core = coreInst
- app = flask.Flask(__name__)
- self._core.socketServerConnData = {}
- self.bindPort = 0
-
- self.sockets = {}
-
- while self.bindPort < 1024:
- self.bindPort = secrets.randbelow(65535)
-
- self.responseData = {}
-
- threading.Thread(target=self.detectShutdown).start()
- threading.Thread(target=self.socketStarter).start()
- app = flask.Flask(__name__)
- self.http_server = WSGIServer(('127.0.0.1', self.bindPort), app)
- self.http_server.serve_forever()
-
- @app.route('/dc/', methods=['POST'])
- def acceptConn(self):
- data = request.form['data']
- data = self._core._utils.bytesTorStr(data)
- data = {'date': self._core._utils.getEpoch(), 'data': data}
- myPeer = ''
- retData = ''
- for peer in self.sockets:
- if self.sockets[peer] == request.host:
- myPeer = peer
- break
- else:
- return ""
-
- if request.host in self.sockets:
- self._core.socketServerConnData[myPeer].append(data)
- else:
- self._core.socketServerConnData[myPeer] = [data]
-
- try:
- retData = self._core.socketServerResponseData[myPeer]
- except KeyError:
- pass
- else:
- self._core.socketServerResponseData[myPeer] = ''
-
- return retData
-
- def socketStarter(self):
- while not self._core.killSockets:
- try:
- self.addSocket(self._core.startSocket['peer'], reason=self._core.startSocket['reason'])
- except KeyError:
- pass
- else:
- logger.info('%s socket started with %s' % (self._core.startSocket['reason'], self._core.startSocket['peer']))
- self._core.startSocket = {}
- time.sleep(1)
-
- def detectShutdown(self):
- while not self._core.killSockets:
- time.sleep(5)
-
- logger.debug('Killing socket server...')
- self.http_server.stop()
-
- def addSocket(self, peer, reason=''):
- bindPort = 1337
-
- assert len(reason) <= 12
-
- with stem.control.Controller.from_port(port=config.get('tor.controlPort')) as controller:
- controller.authenticate(config.get('tor.controlpassword'))
-
- socket = controller.create_ephemeral_hidden_service({80: bindPort}, await_publication = True)
- self.sockets[peer] = socket.service_id + '.onion'
-
- self.responseData[socket.service_id + '.onion'] = ''
-
- self._core.insertBlock(str(uuid.uuid4()), header='socket', sign=True, encryptType='asym', asymPeer=peer, meta={'reason': reason, 'address': socket.service_id + '.onion'})
- self._core.socketReasons[peer] = reason
- return
-
-class OnionrSocketClient:
- def __init__(self, coreInst):
- self.sockets = {} # pubkey: tor address
- self.connPool = {}
- self.sendData = {}
- self._core = coreInst
- self.response = ''
- self.request = ''
- self.connected = False
- self.killSocket = False
-
- def startSocket(self, peer, reason):
- address = ''
- logger.info('Trying to find socket server for %s' % (peer,))
- # Find the newest open socket for a given peer
- for block in self._core.getBlocksByType('socket'):
- block = onionrblockapi.Block(block, core=self._core)
- if block.decrypt():
- theSigner = block.signer
- try:
- theSigner = theSigner.decode()
- except AttributeError:
- pass
- if block.verifySig() and theSigner == peer:
- address = block.getMetadata('address')
- if self._core._utils.validateID(address):
- # If we got their address, it is valid, and verified, we can break out
- if block.getMetadata('reason') == reason:
- break
- else:
- logger.error('The socket the peer opened is not for %s' % (reason,))
- else:
- logger.error('Peer transport id is invalid for socket: %s' % (address,))
- address = ''
- else:
- logger.warn('Block has invalid sig or id, was for %s' % (theSigner,))
- if address != '':
- logger.info('%s socket client started with %s' % (reason, peer))
- self.sockets[peer] = address
- data = 'hey'
- while not self.killSocket:
- try:
- data = self.sendData[peer]
- logger.info('Sending %s to %s' % (data, peer))
- except KeyError:
- pass
- else:
- self.sendData[peer] = ''
- postData = {'data': data}
- self.connPool[peer] = {'date': self._core._utils.getEpoch(), 'data': self._core._utils.doPostRequest('http://' + address + '/dc/', data=postData)}
- time.sleep(2)
-
- def getResponse(self, peer):
- retData = ''
- try:
- retData = self.connPool[peer]
- except KeyError:
- pass
- return
-
- def sendData(self, peer, data):
- self.sendData[peer] = data
diff --git a/onionr/static-data/default-plugins/clandestine/controlapi.py b/onionr/static-data/default-plugins/clandestine/controlapi.py
new file mode 100644
index 00000000..ce341f82
--- /dev/null
+++ b/onionr/static-data/default-plugins/clandestine/controlapi.py
@@ -0,0 +1,26 @@
+'''
+ Onionr - P2P Anonymous Storage Network
+
+ HTTP endpoints for controlling IMs
+'''
+'''
+ 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 flask import Response, request, redirect, Blueprint, abort
+
+flask_blueprint = Blueprint('clandenstine', __name__)
+
+@flask_blueprint.route('/mail/ping')
+def ping():
+ return 'pong!'
diff --git a/onionr/static-data/default-plugins/clandestine/info.json b/onionr/static-data/default-plugins/clandestine/info.json
new file mode 100755
index 00000000..7c5a143c
--- /dev/null
+++ b/onionr/static-data/default-plugins/clandestine/info.json
@@ -0,0 +1,5 @@
+{
+ "name" : "clandestine",
+ "version" : "1.0",
+ "author" : "onionr"
+}
diff --git a/onionr/static-data/default-plugins/clandestine/main.py b/onionr/static-data/default-plugins/clandestine/main.py
new file mode 100755
index 00000000..bc7ca112
--- /dev/null
+++ b/onionr/static-data/default-plugins/clandestine/main.py
@@ -0,0 +1,46 @@
+'''
+ Onionr - P2P Anonymous Storage Network
+
+ 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
+
+locale.setlocale(locale.LC_ALL, '')
+
+plugin_name = 'clandenstine'
+PLUGIN_VERSION = '0.0.0'
+
+sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
+from . import controlapi
+flask_blueprint = controlapi.flask_blueprint
+
+class Clandenstine:
+ def __init__(self, pluginapi):
+ self.myCore = pluginapi.get_core()
+
+def on_init(api, data = None):
+ '''
+ This event is called after Onionr is initialized, but before the command
+ inputted is executed. Could be called when daemon is starting or when
+ just the client is running.
+ '''
+
+ pluginapi = api
+ chat = Clandenstine(pluginapi)
+ return