diff --git a/onionr/communicator2.py b/onionr/communicator2.py old mode 100644 new mode 100755 index d6313630..9bcb0d97 --- a/onionr/communicator2.py +++ b/onionr/communicator2.py @@ -19,32 +19,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import core, config, onionrblockapi as block, requests, xml +import sys, core, config, onionrblockapi as block, requests +from defusedxml import minidom + class OnionrCommunicatorDaemon: def __init__(self, debug, developmentMode): self.timers = [] # list of tuples, function, time in seconds self._core = core.Core() - self.nistSalt = 0 + self.nistSaltTimestamp = 0 + self.powSalt = 0 return - def getNistTimeStamp(self): - curTime = self._core._utils.getCurrentHourEpoch - data = doGetRequest('https://beacon.nist.gov/rest/record/' + str(curTime)) - - def doGetRequest(self, url, port=sys.argv[2], proxyType='tor'): - ''' - Do a get request through a local tor or i2p instance - ''' - if proxyType == 'tor': - proxies = {'http': 'socks5://127.0.0.1:' + str(port), 'https': 'socks5://127.0.0.1:' + str(port)} - elif proxyType == 'i2p': - proxies = {'http': 'http://127.0.0.1:4444'} - else: - return - headers = {'user-agent': 'PyOnionr'} - r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30)) shouldRun = False debug = True diff --git a/onionr/onionr.py b/onionr/onionr.py index 15bada6f..f64aba17 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -549,7 +549,7 @@ class Onionr: ''' Starts the Onionr communication daemon ''' - + communicatorDaemon = './communicator.py' if not os.environ.get("WERKZEUG_RUN_MAIN") == "true": if self._developmentMode: logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)', timestamp = False) @@ -560,7 +560,13 @@ class Onionr: logger.info('Started .onion service: ' + logger.colors.underline + net.myID) logger.info('Our Public key: ' + self.onionrCore._crypto.pubKey) time.sleep(1) - subprocess.Popen(["./communicator.py", "run", str(net.socksPort)]) + try: + if config.get('newCommunicator'): + communicatorDaemon = './communicator2.py' + logger.info('Using new communicator') + except NameError: + pass + subprocess.Popen([communicatorDaemon, "run", str(net.socksPort)]) logger.debug('Started communicator') events.event('daemon_start', onionr = self) api.API(self.debug) diff --git a/onionr/onionrexceptions.py b/onionr/onionrexceptions.py new file mode 100644 index 00000000..c3975e63 --- /dev/null +++ b/onionr/onionrexceptions.py @@ -0,0 +1,22 @@ +''' + Onionr - P2P Microblogging Platform & Social network. + + This file contains exceptions for onionr +''' +''' + 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 . +''' + +class MissingPort(Exception): + pass \ No newline at end of file diff --git a/onionr/onionrpeers.py b/onionr/onionrpeers.py new file mode 100644 index 00000000..b6ed72ec --- /dev/null +++ b/onionr/onionrpeers.py @@ -0,0 +1,19 @@ +''' + Onionr - P2P Microblogging Platform & Social network. + + This file contains both the OnionrCommunicate class for communcating 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 . +''' \ No newline at end of file diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index b0bd941d..e43e9ad6 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -21,6 +21,8 @@ import getpass, sys, requests, os, socket, hashlib, logger, sqlite3, config, binascii, time, base64, json, glob, shutil, math import nacl.signing, nacl.encoding from onionrblockapi import Block +import onionrexceptions +from defusedxml import minidom if sys.version_info < (3, 6): try: @@ -483,6 +485,44 @@ class OnionrUtils: '''returns epoch''' return math.floor(time.time()) + def doGetRequest(self, url, port=0, proxyType='tor'): + ''' + Do a get request through a local tor or i2p instance + ''' + if proxyType == 'tor': + if port == 0: + raise onionrexceptions.MissingPort('Socks port required for Tor HTTP get request') + proxies = {'http': 'socks5://127.0.0.1:' + str(port), 'https': 'socks5://127.0.0.1:' + str(port)} + elif proxyType == 'i2p': + proxies = {'http': 'http://127.0.0.1:4444'} + else: + return + headers = {'user-agent': 'PyOnionr'} + r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30)) + return r.text + + def getNistBeaconSalt(self, torPort=0): + ''' + Get the token for the current hour from the NIST randomness beacon + ''' + if torPort == 0: + try: + sys.argv[2] + except IndexError: + raise onionrexceptions.MissingPort('Missing Tor socks port') + retData = '' + curTime = self._core._utils.getCurrentHourEpoch + self.nistSaltTimestamp = curTime + data = self.doGetRequest('https://beacon.nist.gov/rest/record/' + str(curTime), port=torPort) + dataXML = minidom.parseString(data, forbid_dtd=True, forbid_entities=True, forbid_external=True) + try: + retData = dataXML.getElementsByTagName('outputValue')[0].childNodes[0].data + except ValueError: + logger.warn('Could not get NIST beacon value') + else: + self.powSalt = retData + return retData + def size(path='.'): ''' Returns the size of a folder's contents in bytes diff --git a/onionr/static-data/default_config.json b/onionr/static-data/default_config.json index 58df1019..a4fc7c9d 100644 --- a/onionr/static-data/default_config.json +++ b/onionr/static-data/default_config.json @@ -23,5 +23,6 @@ "allocations":{ "disk": 1000000000, "netTotal": 1000000000 - } + }, + "newCommunicator": false } diff --git a/onionr/timedhmac.py b/onionr/timedhmac.py deleted file mode 100644 index a6163ead..00000000 --- a/onionr/timedhmac.py +++ /dev/null @@ -1,50 +0,0 @@ -''' - Onionr - P2P Microblogging Platform & Social network. Run with 'help' for usage. - 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 hmac, base64, time, math - -class TimedHMAC: - def __init__(self, base64Key, data, hashAlgo): - ''' - base64Key = base64 encoded key - data = data to hash - expire = time expiry in epoch - hashAlgo = string in hashlib.algorithms_available - - Maximum of 10 seconds grace period - ''' - - self.data = data - self.expire = math.floor(time.time()) - self.hashAlgo = hashAlgo - self.b64Key = base64Key - generatedHMAC = hmac.HMAC(base64.b64decode(base64Key).decode(), digestmod=self.hashAlgo) - generatedHMAC.update(data + expire) - self.HMACResult = generatedHMAC.hexdigest() - - return - - def check(self, data): - ''' - Check a hash (and verify time is sane) - ''' - - testHash = hmac.HMAC(base64.b64decode(base64Key).decode(), digestmod=self.hashAlgo) - testHash.update(data + math.floor(time.time())) - testHash = testHash.hexdigest() - if hmac.compare_digest(testHash, self.HMACResult): - return true - - return false diff --git a/requirements.txt b/requirements.txt index ffdcdf77..e6bad4ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,5 +7,6 @@ sha3==0.2.1 simple_crypt==4.1.7 ecdsa==0.13 requests==2.12.4 +defusedxml==0.5.0 SocksiPy_branch==1.01 sphinx_rtd_theme==0.3.0