diff --git a/onionr/api.py b/onionr/api.py index d3d86d9f..27b7cc1b 100755 --- a/onionr/api.py +++ b/onionr/api.py @@ -69,6 +69,8 @@ class API: self.clientToken = config.get('client')['client_hmac'] self.timeBypassToken = base64.b16encode(os.urandom(32)).decode() + self.i2pEnabled = config.get('i2p')['host'] + self.mimeType = 'text/plain' with open('data/time-bypass.txt', 'w') as bypass: @@ -197,7 +199,7 @@ class API: elif action == 'getDBHash': resp = Response(self._utils.getBlockDBHash()) elif action == 'getBlockHashes': - resp = Response(self._core.getBlockList()) + resp = Response('\n'.join(self._core.getBlockList())) elif action == 'directMessage': resp = Response(self._core.handle_direct_connection(data)) elif action == 'announce': @@ -289,6 +291,10 @@ class API: if not request.host.endswith('onion') and not request.host.endswith('i2p'): abort(403) # Validate x-requested-with, to protect against CSRF/metadata leaks + + if not self.i2pEnabled and request.host.endswith('i2p'): + abort(403) + if not self._developmentMode: try: request.headers['X-Requested-With'] diff --git a/onionr/communicator.py b/onionr/communicator.py index 777660ad..defe4c0a 100755 --- a/onionr/communicator.py +++ b/onionr/communicator.py @@ -490,7 +490,7 @@ class OnionrCommunicate: if lastDB != currentDB: logger.debug('Fetching hash from %s - %s current hash.' % (str(i), currentDB)) try: - blockList.append(self.performGet('getBlockHashes', i)) + blockList.extend(self.performGet('getBlockHashes', i).split('\n')) except TypeError: logger.warn('Failed to get data hash from %s' % str(i)) self.peerData[i]['failCount'] -= 1 @@ -616,7 +616,13 @@ class OnionrCommunicate: return def removeBlockFromProcessingList(self, block): - return block in blocksProcessing + '''Remove a block from the processing list''' + try: + self.blocksProcessing.remove(block) + except ValueError: + return False + else: + return True def downloadBlock(self, hash, peerTries=3): ''' @@ -672,13 +678,13 @@ class OnionrCommunicate: ''' return urllib.parse.quote_plus(data) - def performGet(self, action, peer, data=None, skipHighFailureAddress=False, peerType='tor', selfCheck=True): + def performGet(self, action, peer, data=None, skipHighFailureAddress=False, selfCheck=True): ''' Performs a request to a peer through Tor or i2p (currently only Tor) ''' - if not peer.endswith('.onion') and not peer.endswith('.onion/'): - raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion') + if not peer.endswith('.onion') and not peer.endswith('.onion/') and not peer.endswith('.b32.i2p'): + raise PeerError('Currently only Tor/i2p .onion/.b32.i2p peers are supported. You must manually specify .onion/.b32.i2p') if len(self._core.hsAdder.strip()) == 0: raise Exception("Could not perform self address check in performGet due to not knowing our address") @@ -692,9 +698,15 @@ class OnionrCommunicate: self.peerData[peer] = {'connectCount': 0, 'failCount': 0, 'lastConnectTime': self._utils.getEpoch()} socksPort = sys.argv[2] '''We use socks5h to use tor as DNS''' - proxies = {'http': 'socks5://127.0.0.1:' + str(socksPort), 'https': 'socks5://127.0.0.1:' + str(socksPort)} + + if peer.endswith('onion'): + proxies = {'http': 'socks5h://127.0.0.1:' + str(socksPort), 'https': 'socks5h://127.0.0.1:' + str(socksPort)} + + elif peer.endswith('b32.i2p'): + proxies = {'http': 'http://127.0.0.1:4444'} headers = {'user-agent': 'PyOnionr'} url = 'http://' + peer + '/public/?action=' + self.urlencode(action) + if data != None: url = url + '&data=' + self.urlencode(data) try: @@ -704,7 +716,11 @@ class OnionrCommunicate: else: self.peerStatus[peer] = action logger.debug('Contacting %s on port %s' % (peer, str(socksPort))) - r = requests.get(url, headers=headers, proxies=proxies, timeout=(15, 30)) + try: + r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30)) + except ValueError: + proxies = {'http': 'socks5://127.0.0.1:' + str(socksPort), 'https': 'socks5://127.0.0.1:' + str(socksPort)} + r = requests.get(url, headers=headers, proxies=proxies, allow_redirects=False, timeout=(15, 30)) retData = r.text except requests.exceptions.RequestException as e: logger.debug("%s failed with peer %s" % (action, peer)) diff --git a/onionr/core.py b/onionr/core.py index 502ea8f0..9b78ee1a 100644 --- a/onionr/core.py +++ b/onionr/core.py @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . ''' -import sqlite3, os, sys, time, math, base64, tarfile, getpass, simplecrypt, hashlib, nacl, logger, json, netcontroller, math +import sqlite3, os, sys, time, math, base64, tarfile, getpass, simplecrypt, hashlib, nacl, logger, json, netcontroller, math, config #from Crypto.Cipher import AES #from Crypto import Random @@ -111,6 +111,8 @@ class Core: ''' Add an address to the address database (only tor currently) ''' + if address == config.get('i2p')['ownAddr']: + return False if self._utils.validateID(address): conn = sqlite3.connect(self.addressDB) c = conn.cursor() diff --git a/onionr/onionr.py b/onionr/onionr.py index d55664a8..bc33e8fb 100755 --- a/onionr/onionr.py +++ b/onionr/onionr.py @@ -575,7 +575,7 @@ class Onionr: # count stats 'div2' : True, - 'Known Peers Count' : str(len(self.onionrCore.listPeers())), + 'Known Peers Count' : str(len(self.onionrCore.listPeers()) - 1), 'Enabled Plugins Count' : str(len(config.get('plugins')['enabled'])) + ' / ' + str(len(os.listdir('data/plugins/'))) } diff --git a/onionr/onionrproofs.py b/onionr/onionrproofs.py index 7001d1d6..bf749ad6 100644 --- a/onionr/onionrproofs.py +++ b/onionr/onionrproofs.py @@ -18,7 +18,7 @@ along with this program. If not, see . ''' -import nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, logger, sys +import nacl.encoding, nacl.hash, nacl.utils, time, math, threading, binascii, logger, sys, base64 import core class POW: @@ -45,6 +45,7 @@ class POW: endTime = math.floor(time.time()) if self.reporting: logger.info('Found token ' + token, timestamp=True) + logger.info('rand value: ' + base64.b64encode(rand).decode()) logger.info('took ' + str(endTime - startTime) + ' seconds', timestamp=True) self.result = (token, rand) diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py index 457960e0..e96cabee 100644 --- a/onionr/onionrutils.py +++ b/onionr/onionrutils.py @@ -109,7 +109,10 @@ class OnionrUtils: except IndexError: logger.warn('No pow token') continue - powHash = self._core._crypto.blake2bHash(base64.b64decode(key[1]) + self._core._crypto.blake2bHash(key[0].encode())) + #powHash = self._core._crypto.blake2bHash(base64.b64decode(key[1]) + self._core._crypto.blake2bHash(key[0].encode())) + value = base64.b64decode(key[1]) + hashedKey = self._core._crypto.blake2bHash(key[0]) + powHash = self._core._crypto.blake2bHash(value + hashedKey) try: powHash = powHash.encode() except AttributeError: diff --git a/onionr/static-data/default_config.json b/onionr/static-data/default_config.json index ccafd7a4..1dae4f12 100644 --- a/onionr/static-data/default_config.json +++ b/onionr/static-data/default_config.json @@ -13,6 +13,11 @@ "color": true } }, + "i2p":{ + "host": false, + "connect": true, + "ownAddr": "" + }, "allocations":{ "disk": 1000000000, "netTotal": 1000000000 diff --git a/onionr/static-data/index.html b/onionr/static-data/index.html index 6cd0c558..f9df9eb7 100644 --- a/onionr/static-data/index.html +++ b/onionr/static-data/index.html @@ -1,5 +1,5 @@

This is an Onionr Node

-

The content on this server is not necessarily created or intentionally stored by the owner of the software.

+

The content on this server is not necessarily created or intentionally stored by the owner of the server.

To learn more about Onionr, see the website at https://Onionr.VoidNet.tech/