fixed broken random IP binding, work on improving code safety

This commit is contained in:
Kevin Froman 2019-09-08 17:39:51 -05:00
parent 8191854a2f
commit bd24b54bef
11 changed files with 39 additions and 20 deletions

1
.gitignore vendored
View File

@ -19,6 +19,7 @@ core
.vscode/* .vscode/*
venv/* venv/*
onionr/fs* onionr/fs*
onionr/tmp/*
*.dll *.dll
*.exe *.exe

View File

@ -110,7 +110,7 @@ Everyone is welcome to contribute. Help is wanted for the following:
* Creation of a shared lib for use from other languages and faster proof-of-work * Creation of a shared lib for use from other languages and faster proof-of-work
* Android and IOS development * Android and IOS development
* Windows and Mac support (already partially supported, testers needed) * Windows and Mac support (already partially supported, testers needed)
* General bug fixes and development of new features * Bug fixes and development of new features
* Testing * Testing
* Translations/localizations * Translations/localizations
* UI/UX design * UI/UX design

View File

@ -20,6 +20,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
''' '''
# Set the user's locale for encoding reasons # Set the user's locale for encoding reasons
import locale import locale
locale.setlocale(locale.LC_ALL, '') locale.setlocale(locale.LC_ALL, '')

View File

@ -118,7 +118,7 @@ def reload():
try: try:
with open(get_config_file(), 'r', encoding="utf8") as configfile: with open(get_config_file(), 'r', encoding="utf8") as configfile:
set_config(json.loads(configfile.read())) set_config(json.loads(configfile.read()))
except: except (FileNotFoundError, json.JSONDecodeError) as e:
pass pass
#logger.debug('Failed to parse configuration file.') #logger.debug('Failed to parse configuration file.')

View File

@ -26,10 +26,11 @@ def get_expired_blocks():
c = conn.cursor() c = conn.cursor()
date = int(epoch.get_epoch()) date = int(epoch.get_epoch())
execute = 'SELECT hash FROM hashes WHERE expire <= %s ORDER BY dateReceived;' % (date,) compiled = (date,)
execute = 'SELECT hash FROM hashes WHERE expire <= ? ORDER BY dateReceived;'
rows = list() rows = list()
for row in c.execute(execute): for row in c.execute(execute, compiled):
for i in row: for i in row:
rows.append(i) rows.append(i)
conn.close() conn.close()

View File

@ -34,12 +34,14 @@ def update_block_info(hash, key, data):
dateClaimed - timestamp claimed inside the block, only as trustworthy as the block author is dateClaimed - timestamp claimed inside the block, only as trustworthy as the block author is
expire - expire date for a block expire - expire date for a block
''' '''
if key not in ('dateReceived', 'decrypted', 'dataType', 'dataFound', 'dataSaved', 'sig', 'author', 'dateClaimed', 'expire'): if key not in ('dateReceived', 'decrypted', 'dataType', 'dataFound',
return False 'dataSaved', 'sig', 'author', 'dateClaimed', 'expire'):
raise ValueError('Key must be in the allowed list')
conn = sqlite3.connect(dbfiles.block_meta_db, timeout=30) conn = sqlite3.connect(dbfiles.block_meta_db, timeout=30)
c = conn.cursor() c = conn.cursor()
args = (data, hash) args = (data, hash)
# Unfortunately, not really possible
c.execute("UPDATE hashes SET " + key + " = ? where hash = ?;", args) c.execute("UPDATE hashes SET " + key + " = ? where hash = ?;", args)
conn.commit() conn.commit()
conn.close() conn.close()

View File

@ -86,10 +86,7 @@ def clear_daemon_queue():
conn = sqlite3.connect(dbfiles.daemon_queue_db, timeout=30) conn = sqlite3.connect(dbfiles.daemon_queue_db, timeout=30)
c = conn.cursor() c = conn.cursor()
try: c.execute('DELETE FROM commands;')
c.execute('DELETE FROM commands;') conn.commit()
conn.commit()
except:
pass
conn.close() conn.close()

View File

@ -66,7 +66,7 @@ def set_address_info(address, key, data):
command = (data, address) command = (data, address)
if key not in ('address', 'type', 'knownPeer', 'speed', 'success', 'failure', 'powValue', 'lastConnect', 'lastConnectAttempt', 'trust', 'introduced'): if key not in ('address', 'type', 'knownPeer', 'speed', 'success', 'failure', 'powValue', 'lastConnect', 'lastConnectAttempt', 'trust', 'introduced'):
raise Exception("Got invalid database key when setting address info") raise ValueError("Got invalid database key when setting address info, must be in whitelist")
else: else:
c.execute('UPDATE adders SET ' + key + ' = ? WHERE address=?', command) c.execute('UPDATE adders SET ' + key + ' = ? WHERE address=?', command)
conn.commit() conn.commit()

View File

@ -61,9 +61,8 @@ def set_peer_info(peer, key, data):
command = (data, peer) command = (data, peer)
# TODO: validate key on whitelist
if key not in ('id', 'name', 'pubkey', 'forwardKey', 'dateSeen', 'trust'): if key not in ('id', 'name', 'pubkey', 'forwardKey', 'dateSeen', 'trust'):
raise Exception("Got invalid database key when setting peer info") raise ValueError("Got invalid database key when setting peer info")
c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command) c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command)
conn.commit() conn.commit()

View File

@ -1,12 +1,13 @@
import json import json
import onionrblockapi import onionrblockapi
from onionrutils import bytesconverter, stringvalidators from onionrutils import bytesconverter, stringvalidators
import onionrexceptions
class GetBlockData: class GetBlockData:
def __init__(self, client_api_inst=None): def __init__(self, client_api_inst=None):
return return
def get_block_data(self, bHash, decrypt=False, raw=False, headerOnly=False): def get_block_data(self, bHash, decrypt=False, raw=False, headerOnly=False):
assert stringvalidators.validate_hash(bHash) if not stringvalidators.validate_hash(bHash): raise onionrexceptions.InvalidHexHash("block hash not valid hash format")
bl = onionrblockapi.Block(bHash) bl = onionrblockapi.Block(bHash)
if decrypt: if decrypt:
bl.decrypt() bl.decrypt()

View File

@ -1,11 +1,28 @@
import random, socket import gevent
from gevent import socket, sleep
import secrets, random
import config, logger import config, logger
import os
# Hacky monkey patch so we can bind random localhosts without gevent trying to switch with an empty hub
socket.getfqdn = lambda n: n
def _get_acceptable_random_number()->int:
"""Return a cryptographically random number in the inclusive range (1, 255)"""
number = 0
while number == 0:
number = secrets.randbelow(0xFF)
return number
def set_bind_IP(filePath=''): def set_bind_IP(filePath=''):
'''Set a random localhost IP to a specified file (intended for private or public API localhost IPs)''' '''Set a random localhost IP to a specified file (intended for private or public API localhost IPs)'''
if config.get('general.random_bind_ip', True): if config.get('general.random_bind_ip', True):
hostOctets = [str(127), str(random.randint(0x02, 0xFF)), str(random.randint(0x02, 0xFF)), str(random.randint(0x02, 0xFF))] hostOctets = []
for i in range(3):
hostOctets.append(str(_get_acceptable_random_number()))
hostOctets = ['127'] + hostOctets
data = '.'.join(hostOctets) data = '.'.join(hostOctets)
# Try to bind IP. Some platforms like Mac block non normal 127.x.x.x # Try to bind IP. Some platforms like Mac block non normal 127.x.x.x
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: try: