def test_lan_server(testmanager): if onionrvalues.IS_QUBES: logger.warn("Cannot test LAN on QubesOS", terminal=True) return start_time = get_epoch() for i in range(1337, 1340): try: if not best_ip or not best_ip.startswith(('192.168')): logger.warn( "lanservertest not running, not in standard 192.168 lan " + "run this test on a lan before release", terminal=True) return if requests.get(f"http://{best_ip}:{i}/ping").text == 'onionr!': bl = insert('test data') sleep(10) bl2 = insert('test data2') sleep(30) bl3 = insert('test data3') l = requests.get(f"http://{best_ip}:{i}/blist/0").text.split( '\n') if bl not in l or bl2 not in l or bl3 not in l: logger.error('blocks not in blist ' + '-'.join(l)) raise ValueError time = blockmetadb.get_block_date(bl3) - 1 l = requests.get( f"http://{best_ip}:{i}/blist/{time}").text.split('\n') if (bl in l and bl2 in l and bl3 in l) or len(l) == 0: logger.error('Failed to get appopriate time' + '-'.join(l)) raise ValueError if onionrblockapi.Block(bl).raw != requests.get( f"http://{best_ip}:{i}/get/{bl}", stream=True).raw.read(6000000): logger.error('Block doesn\'t match') raise ValueError break except requests.exceptions.ConnectionError: pass else: raise ValueError
def decrypt(self, encodedData=True): """ Decrypt a block, loading decrypted data into their vars """ if self.decrypted: return True retData = False # decrypt data if self.getHeader('encryptType') == 'asym': try: try: self.bcontent = encryption.pub_key_decrypt( self.bcontent, encodedData=encodedData) except (binascii.Error, ValueError) as e: self.bcontent = encryption.pub_key_decrypt( self.bcontent, encodedData=False) bmeta = encryption.pub_key_decrypt(self.bmetadata, encodedData=encodedData) try: bmeta = bmeta.decode() except AttributeError: # yet another bytes fix pass self.bmetadata = json.loads(bmeta) self.signature = encryption.pub_key_decrypt( self.signature, encodedData=encodedData) self.signer = encryption.pub_key_decrypt( self.signer, encodedData=encodedData) self.bheader['signer'] = self.signer.decode() self.signedData = json.dumps( self.bmetadata).encode() + self.bcontent if not self.signer is None: if not self.verifySig(): raise onionrexceptions.SignatureError( "Block has invalid signature") # Check for replay attacks try: if epoch.get_epoch() - blockmetadb.get_block_date( self.hash) > 60: if not cryptoutils.replay_validator( self.bmetadata['rply']): raise onionrexceptions.ReplayAttack except (AssertionError, KeyError, TypeError, onionrexceptions.ReplayAttack) as e: if not self.bypassReplayCheck: # Zero out variables to prevent reading of replays self.bmetadata = {} self.signer = '' self.bheader['signer'] = '' self.signedData = '' self.signature = '' raise onionrexceptions.ReplayAttack( 'Signature is too old. possible replay attack') try: if not self.bmetadata['forwardEnc']: raise KeyError except (AssertionError, KeyError) as e: pass else: try: self.bcontent = onionrusers.OnionrUser( self.signer).forwardDecrypt(self.bcontent) except (onionrexceptions.DecryptionError, nacl.exceptions.CryptoError) as e: #logger.error(str(e)) pass except nacl.exceptions.CryptoError: pass #logger.debug('Could not decrypt block. Either invalid key or corrupted data') except onionrexceptions.ReplayAttack: logger.warn('%s is possibly a replay attack' % (self.hash, )) else: retData = True self.decrypted = True return retData
def update(self, data=None, file=None): """ Loads data from a block in to the current object. Inputs: - data (str): - if None: will load from file by hash - else: will load from `data` string - file (str): - if None: will load from file specified in this parameter - else: will load from wherever block is stored by hash Outputs: - (bool): indicates whether or not the operation was successful """ try: # import from string blockdata = data # import from file if blockdata is None: try: blockdata = onionrstorage.getData( self.getHash()) #.decode() except AttributeError: raise onionrexceptions.NoDataAvailable( 'Block does not exist') else: self.blockFile = None # parse block self.raw = blockdata self.bheader = json.loads( self.getRaw()[:self.getRaw().index(b'\n')]) self.bcontent = self.getRaw()[self.getRaw().index(b'\n') + 1:] if ('encryptType' in self.bheader) and (self.bheader['encryptType'] in ('asym', 'sym')): self.bmetadata = self.getHeader('meta', None) self.isEncrypted = True else: self.bmetadata = json.loads(self.getHeader('meta', None)) self.btype = self.getMetadata('type', None) self.signed = ('sig' in self.getHeader() and self.getHeader('sig') != '') # TODO: detect if signer is hash of pubkey or not self.signer = self.getHeader('signer', None) self.signature = self.getHeader('sig', None) # signed data is jsonMeta + block content (no linebreak) self.signedData = (None if not self.isSigned() else self.getHeader('meta').encode() + self.getContent()) self.date = blockmetadb.get_block_date(self.getHash()) self.claimedTime = self.getHeader('time', None) if not self.getDate() is None: self.date = datetime.datetime.fromtimestamp(self.getDate()) self.valid = True if self.autoDecrypt: self.decrypt() return True except Exception as e: logger.warn('Failed to parse block %s' % self.getHash(), error=e, timestamp=False) # if block can't be parsed, it's a waste of precious space. Throw it away. if not self.delete(): logger.warn('Failed to delete invalid block %s.' % self.getHash(), error=e) else: logger.debug('Deleted invalid block %s.' % self.getHash(), timestamp=False) self.valid = False return False