Add some error handling

master
Arinerron 2018-04-18 19:16:10 -07:00
parent ded179bcad
commit 1332e9ee9e
No known key found for this signature in database
GPG Key ID: 99383627861C62F0
2 changed files with 130 additions and 99 deletions

View File

@ -36,28 +36,32 @@ class Core:
''' '''
Initialize Core Onionr library Initialize Core Onionr library
''' '''
self.queueDB = 'data/queue.db' try:
self.peerDB = 'data/peers.db' self.queueDB = 'data/queue.db'
self.blockDB = 'data/blocks.db' self.peerDB = 'data/peers.db'
self.blockDataLocation = 'data/blocks/' self.blockDB = 'data/blocks.db'
self.addressDB = 'data/address.db' self.blockDataLocation = 'data/blocks/'
self.hsAdder = '' self.addressDB = 'data/address.db'
self.hsAdder = ''
if not os.path.exists('data/'): if not os.path.exists('data/'):
os.mkdir('data/') os.mkdir('data/')
if not os.path.exists('data/blocks/'): if not os.path.exists('data/blocks/'):
os.mkdir('data/blocks/') os.mkdir('data/blocks/')
if not os.path.exists(self.blockDB): if not os.path.exists(self.blockDB):
self.createBlockDB() self.createBlockDB()
if os.path.exists('data/hs/hostname'): if os.path.exists('data/hs/hostname'):
with open('data/hs/hostname', 'r') as hs: with open('data/hs/hostname', 'r') as hs:
self.hsAdder = hs.read() self.hsAdder = hs.read()
self._utils = onionrutils.OnionrUtils(self)
# Initialize the crypto object
self._crypto = onionrcrypto.OnionrCrypto(self)
self._utils = onionrutils.OnionrUtils(self)
# Initialize the crypto object
self._crypto = onionrcrypto.OnionrCrypto(self)
except Exception as error:
logger.error('Failed to initialize core Onionr library.', error=error)
logger.fatal('Cannot recover from error.')
exit(1)
return return
def addPeer(self, peerID, name=''): def addPeer(self, peerID, name=''):

View File

@ -41,22 +41,28 @@ class OnionrUtils:
return return
def getTimeBypassToken(self): def getTimeBypassToken(self):
if os.path.exists('data/time-bypass.txt'): try:
with open('data/time-bypass.txt', 'r') as bypass: if os.path.exists('data/time-bypass.txt'):
self.timingToken = bypass.read() with open('data/time-bypass.txt', 'r') as bypass:
self.timingToken = bypass.read()
except Exception as error:
logger.error('Failed to fetch time bypass token.', error=error)
def sendPM(self, pubkey, message): def sendPM(self, pubkey, message):
''' '''
High level function to encrypt a message to a peer and insert it as a block High level function to encrypt a message to a peer and insert it as a block
''' '''
encrypted = self._core._crypto.pubKeyEncrypt(message, pubkey, anonymous=True, encodedData=True).decode() try:
block = self._core.insertBlock(encrypted, header='pm') encrypted = self._core._crypto.pubKeyEncrypt(message, pubkey, anonymous=True, encodedData=True).decode()
block = self._core.insertBlock(encrypted, header='pm')
if block == '': if block == '':
logger.error('Could not send PM') logger.error('Could not send PM')
else: else:
logger.info('Sent PM, hash: ' + block) logger.info('Sent PM, hash: ' + block)
except Exception as error:
logger.error('Failed to send PM.', error=error)
return return
@ -80,36 +86,49 @@ class OnionrUtils:
''' '''
Merge ed25519 key list to our database Merge ed25519 key list to our database
''' '''
retVal = False try:
if newKeyList != False: retVal = False
for key in newKeyList.split(','): if newKeyList != False:
if not key in self._core.listPeers(randomOrder=False) and type(key) != None and key != self._core._crypto.pubKey: for key in newKeyList.split(','):
if self._core.addPeer(key): if not key in self._core.listPeers(randomOrder=False) and type(key) != None and key != self._core._crypto.pubKey:
retVal = True if self._core.addPeer(key):
return retVal retVal = True
return retVal
except Exception as error:
logger.error('Failed to merge keys.', error=error)
return False
def mergeAdders(self, newAdderList): def mergeAdders(self, newAdderList):
''' '''
Merge peer adders list to our database Merge peer adders list to our database
''' '''
retVal = False try:
if newAdderList != False: retVal = False
for adder in newAdderList.split(','): if newAdderList != False:
if not adder in self._core.listAdders(randomOrder=False) and adder.strip() != self.getMyAddress(): for adder in newAdderList.split(','):
if self._core.addAddress(adder): if not adder in self._core.listAdders(randomOrder=False) and adder.strip() != self.getMyAddress():
logger.info('Added ' + adder + ' to db.', timestamp=True) if self._core.addAddress(adder):
input() logger.info('Added ' + adder + ' to db.', timestamp=True)
retVal = True input()
else: retVal = True
logger.debug(adder + " is either our address or already in our DB") else:
return retVal logger.debug(adder + " is either our address or already in our DB")
return retVal
except Exception as error:
logger.error('Failed to merge adders.', error=error)
return False
def getMyAddress(self): def getMyAddress(self):
myAddressFile = open("data/hs/hostname", 'r') try:
myAddress = myAddressFile.read() myAddressFile = open("data/hs/hostname", 'r')
myAddressFile.close() myAddress = myAddressFile.read()
return myAddress.strip() myAddressFile.close()
return myAddress.strip()
except Exception as error:
logger.error('Failed to read my address.', error=error)
return ''
def localCommand(self, command): def localCommand(self, command):
''' '''
@ -121,7 +140,8 @@ class OnionrUtils:
# TODO: URL encode parameters, just as an extra measure. May not be needed, but should be added regardless. # TODO: URL encode parameters, just as an extra measure. May not be needed, but should be added regardless.
try: try:
retData = requests.get('http://' + open('data/host.txt', 'r').read() + ':' + str(config.get('client')['port']) + '/client/?action=' + command + '&token=' + str(config.get('client')['client_hmac']) + '&timingToken=' + self.timingToken).text retData = requests.get('http://' + open('data/host.txt', 'r').read() + ':' + str(config.get('client')['port']) + '/client/?action=' + command + '&token=' + str(config.get('client')['client_hmac']) + '&timingToken=' + self.timingToken).text
except requests.ConnectionError: except Exception as error:
logger.error('Failed to make local request (command: ' + str(command) + ').', error=error)
retData = False retData = False
return retData return retData
@ -179,13 +199,16 @@ class OnionrUtils:
''' '''
Return a sha3_256 hash of the blocks DB Return a sha3_256 hash of the blocks DB
''' '''
with open(self._core.blockDB, 'rb') as data: try:
data = data.read() with open(self._core.blockDB, 'rb') as data:
hasher = hashlib.sha3_256() data = data.read()
hasher.update(data) hasher = hashlib.sha3_256()
dataHash = hasher.hexdigest() hasher.update(data)
dataHash = hasher.hexdigest()
return dataHash return dataHash
except Exception as error:
logger.error('Failed to get block DB hash.', error=error)
def hasBlock(self, hash): def hasBlock(self, hash):
''' '''
@ -224,7 +247,9 @@ class OnionrUtils:
return retVal return retVal
def validatePubKey(self, key): def validatePubKey(self, key):
'''Validate if a string is a valid base32 encoded Ed25519 key''' '''
Validate if a string is a valid base32 encoded Ed25519 key
'''
retVal = False retVal = False
try: try:
nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder) nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
@ -241,45 +266,48 @@ class OnionrUtils:
''' '''
Validate if an address is a valid tor or i2p hidden service Validate if an address is a valid tor or i2p hidden service
''' '''
idLength = len(id) try:
retVal = True idLength = len(id)
idNoDomain = '' retVal = True
peerType = '' idNoDomain = ''
# i2p b32 addresses are 60 characters long (including .b32.i2p) peerType = ''
if idLength == 60: # i2p b32 addresses are 60 characters long (including .b32.i2p)
peerType = 'i2p' if idLength == 60:
if not id.endswith('.b32.i2p'): peerType = 'i2p'
retVal = False if not id.endswith('.b32.i2p'):
else:
idNoDomain = id.split('.b32.i2p')[0]
# Onion v2's are 22 (including .onion), v3's are 62 with .onion
elif idLength == 22 or idLength == 62:
peerType = 'onion'
if not id.endswith('.onion'):
retVal = False
else:
idNoDomain = id.split('.onion')[0]
else:
retVal = False
if retVal:
if peerType == 'i2p':
try:
id.split('.b32.i2p')[2]
except:
pass
else:
retVal = False retVal = False
elif peerType == 'onion':
try:
id.split('.onion')[2]
except:
pass
else: else:
idNoDomain = id.split('.b32.i2p')[0]
# Onion v2's are 22 (including .onion), v3's are 62 with .onion
elif idLength == 22 or idLength == 62:
peerType = 'onion'
if not id.endswith('.onion'):
retVal = False retVal = False
if not idNoDomain.isalnum(): else:
idNoDomain = id.split('.onion')[0]
else:
retVal = False retVal = False
if retVal:
if peerType == 'i2p':
try:
id.split('.b32.i2p')[2]
except:
pass
else:
retVal = False
elif peerType == 'onion':
try:
id.split('.onion')[2]
except:
pass
else:
retVal = False
if not idNoDomain.isalnum():
retVal = False
return retVal return retVal
except:
return False
def loadPMs(self): def loadPMs(self):
''' '''
@ -298,8 +326,7 @@ class OnionrUtils:
try: try:
message = self._core._crypto.pubKeyDecrypt(message.replace('-pm-', ''), encodedData=True, anonymous=True) message = self._core._crypto.pubKeyDecrypt(message.replace('-pm-', ''), encodedData=True, anonymous=True)
except nacl.exceptions.CryptoError as e: except nacl.exceptions.CryptoError as e:
#logger.debug('Unable to decrypt ' + i) logger.debug('Unable to decrypt ' + i, error=e)
#logger.debug(str(e))
pass pass
else: else:
logger.info('Recieved message: ' + message.decode()) logger.info('Recieved message: ' + message.decode())