Add some error handling
parent
ded179bcad
commit
1332e9ee9e
|
@ -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=''):
|
||||||
|
|
|
@ -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())
|
||||||
|
|
Loading…
Reference in New Issue