def start(self): logger.warn("Please note: everything said here is public, even if a random channel name is used.", terminal=True) message = "" self.flowRunning = True try: self.channel = logger.readline("Enter a channel name or none for default:").strip() except (KeyboardInterrupt, EOFError) as e: self.flowRunning = False newThread = threading.Thread(target=self.showOutput, daemon=True) newThread.start() while self.flowRunning: if self.channel == "": self.channel = "global" try: message = logger.readline('\nInsert message into flow:').strip().replace('\n', '\\n').replace('\r', '\\r') except EOFError: pass except KeyboardInterrupt: self.flowRunning = False else: if message == "q": self.flowRunning = False expireTime = epoch.get_epoch() + 43200 if len(message) > 0: logger.info('Inserting message as block...', terminal=True) onionrblocks.insert(message, header='brd', expire=expireTime, meta={'ch': self.channel}) logger.info("Flow is exiting, goodbye", terminal=True) return
def test_block_list(self): block_list = BlockList() self.assertEqual(len(block_list.get()), 0) bl = insert('test') bettersleep.better_sleep(0.8) self.assertIn(bl, block_list.get()) bl2 = insert('test2') bettersleep.better_sleep(0.8) self.assertIn(bl2, block_list.get()) self.assertIn(bl, block_list.get())
def stress_test_block_insert(testmanager): start = epoch.get_epoch() count = 100 max_insert_speed = 120 for x in range(count): onionrblocks.insert(os.urandom(32)) speed = epoch.get_epoch() - start if speed < max_insert_speed: raise ValueError( f'{count} blocks inserted too fast, {max_insert_speed}, got {speed}' ) logger.info( f'runtest stress block insertion: {count} blocks inserted in {speed}s')
def insert_deniable_block(): """Insert a fake block to make it more difficult to track real blocks.""" fakePeer = '' chance = 10 if secrets.randbelow(chance) == (chance - 1): # This assumes on the libsodium primitives to have key-privacy fakePeer = onionrvalues.DENIABLE_PEER_ADDRESS data = secrets.token_hex(secrets.randbelow(5120) + 1) onionrblocks.insert(data, header='pm', encryptType='asym', asymPeer=fakePeer, disableForward=True, meta={'subject': 'foo'})
def insert_bin_test(testmanager): data = os.urandom(32) b_hash = onionrblocks.insert(data, ) if not b_hash in coredb.blockmetadb.get_block_list(): logger.error(str(b_hash) + 'is not in bl') raise ValueError
def test_plaintext_insert(self): setup_test() message = 'hello world' bl = onionrblocks.insert(message) self.assertTrue(bl.startswith('0')) self.assertIn(bytesconverter.str_to_bytes(message), onionrstorage.getData(bl))
def add_file(blockType='bin'): """Add a file to the onionr network.""" if len(sys.argv) >= 3: filename = sys.argv[2] if not os.path.exists(_get_dir(filename)): logger.error( 'That file does not exist. Improper path (specify full path)?', terminal=True) return logger.info('Adding file, this might take a long time.', terminal=True) try: with open(_get_dir(filename), 'rb') as single_file: blockhash = insert(single_file.read(), header=blockType) if len(blockhash) > 0: logger.info('File %s saved in block %s' % (filename, blockhash), terminal=True) except Exception as err: # pylint: disable=W0703 logger.error('Failed to save file in block ' + str(err), timestamp=False, terminal=True) else: logger.error('%s add-file <filename>' % sys.argv[0], timestamp=False, terminal=True)
def save(self, sign=False, recreate=True): """ Saves a block to file and imports it into Onionr Inputs: - sign (bool): whether or not to sign the block before saving - recreate (bool): if the block already exists, whether or not to recreate the block and save under a new hash Outputs: - (bool): whether or not the operation was successful """ try: if self.isValid() is True: self.hash = onionrblocks.insert(self.getRaw(), header=self.getType(), sign=sign, meta=self.getMetadata(), expire=self.getExpire()) if self.hash != False: self.update() return self.getHash() else: logger.warn('Not writing block; it is invalid.') except Exception as e: logger.error('Failed to save block.', error=e, timestamp=False) return False
def test_count(self): _test_setup() counter = storagecounter.StorageCounter() start_value = counter.get_amount() b_hash = onionrblocks.insert("test") self.assertGreater(counter.get_amount(), start_value) onionrstorage.removeblock.remove_block(b_hash) self.assertEqual(counter.get_amount(), start_value)
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 motd_creator(): """Create a new MOTD message for the Onionr network""" motd = '' new = '' print('Enter a new MOTD, quit on a new line:') while new != 'quit': new = input() if new != 'quit': motd += new bl = onionrblocks.insert(motd, header='motd', sign=True) print(f"inserted in {bl}")
def insert_bin_test(testmanager): data = os.urandom(32) b_hash = onionrblocks.insert(data) time.sleep(0.3) if b_hash not in testmanager._too_many.get_by_string( "PublicAPI").hideBlocks: raise ValueError("Block not hidden") if b_hash not in coredb.blockmetadb.get_block_list(): logger.error(str(b_hash) + 'is not in bl') raise ValueError
def test_sneakernet_import(test_manager): in_db = lambda b: b in get_block_list() bl = insert(os.urandom(10)) assert in_db(bl) export_block(bl) assert os.path.exists(export_location + bl + BLOCK_EXPORT_FILE_EXT) remove_block(bl) deleteBlock(bl) assert not in_db(bl) os.remove(data_nonce_file) move(export_location + bl + BLOCK_EXPORT_FILE_EXT, block_data_location) sleep(1) assert in_db(bl)
def create_site(admin_pass: DeterministicKeyPassphrase, directory:str='.')->Tuple[UserID, BlockHash]: public_key, private_key = generate_deterministic(admin_pass) raw_tar = io.BytesIO() tar = tarfile.open(mode='x:gz', fileobj=raw_tar) tar.add(directory) tar.close() raw_tar.seek(0) block_hash = insert(raw_tar.read(), header='osite', signing_key=private_key, sign=True) return (public_key, block_hash)
def on_circlesend_cmd(api, data=None): err_msg = "Second arg is board name, third is quoted message" try: sys.argv[2] except IndexError: logger.error(err_msg, terminal=True) try: sys.argv[3] except IndexError: logger.error(err_msg, terminal=True) bl = onionrblocks.insert(sys.argv[3], header='brd', expire=(EXPIRE_TIME + epoch.get_epoch()), meta={'ch': sys.argv[2]}) print(bl)
def test_inserted_housekeeping(testmanager): """Tests that inserted blocks are proprely deleted""" bl = insert('testdata', expire=12) wait_seconds = 132 # Wait two minutes plus expire time count = 0 if bl in get_block_list(): while count < wait_seconds: if bl in get_block_list(): sleep(0.8) count += 1 else: return raise ValueError('Inserted block with expiry not erased') else: raise ValueError('Inserted block in expiry test not present in list')
#!/usr/bin/env python3 import sys import os if not os.path.exists('onionr.sh'): os.chdir('../') sys.path.append("src/") import onionrblocks expire = 600 print(onionrblocks.insert(data=os.urandom(32), expire=expire))
def test_encrypted_insert(self): setup_test() message = 'hello world2' bl = onionrblocks.insert(message, asymPeer=onionrcrypto.pub_key) self.assertIn(bytesconverter.str_to_bytes(message), onionrblockapi.Block(bl, decrypt=True).bcontent)
def bootstrap_client_service(peer, comm_inst=None, bootstrap_timeout=300): ''' Bootstrap client services ''' if not stringvalidators.validate_pub_key(peer): raise ValueError('Peer must be valid base32 ed25519 public key') connection_pool = None # here we use a lambda for the timeout thread to set to true timed_out = lambda: None timed_out.timed_out = False bootstrap_port = get_open_port() bootstrap_app = Flask(__name__) bootstrap_app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 http_server = WSGIServer(('127.0.0.1', bootstrap_port), bootstrap_app, log=None) try: if comm_inst is None: raise ValueError except (AttributeError, ValueError) as e: pass else: comm_inst.service_greenlets.append(http_server) connection_pool = comm_inst.shared_state.get(pool.ServicePool) bootstrap_address = '' shutdown = False bs_id = str(uuid.uuid4()) key_store = simplekv.DeadSimpleKV(filepaths.cached_storage) @bootstrap_app.route('/ping') def get_ping(): return "pong!" @bootstrap_app.after_request def afterReq(resp): # Security headers resp = httpheaders.set_default_onionr_http_headers(resp) return resp @bootstrap_app.route('/bs/<address>', methods=['POST']) def get_bootstrap(address): if stringvalidators.validate_transport(address + '.onion'): # Set the bootstrap address then close the server bootstrap_address = address + '.onion' key_store.put(bs_id, bootstrap_address) http_server.stop() return Response("success") else: return Response("") with Controller.from_port( port=config.get('tor.controlPort')) as controller: if not connection_pool is None: connection_pool.bootstrap_pending.append(peer) # Connect to the Tor process for Onionr controller.authenticate(config.get('tor.controlpassword')) # Create the v3 onion service response = controller.create_ephemeral_hidden_service( {80: bootstrap_port}, key_type='NEW', key_content='ED25519-V3', await_publication=True) onionrblocks.insert(response.service_id, header='con', sign=True, encryptType='asym', asymPeer=peer, disableForward=True, expire=(epoch.get_epoch() + bootstrap_timeout)) threading.Thread(target=__bootstrap_timeout, args=[http_server, bootstrap_timeout, timed_out], daemon=True).start() # Run the bootstrap server try: http_server.serve_forever() except TypeError: pass # This line reached when server is shutdown by being bootstrapped # Add the address to the client pool if not comm_inst is None: connection_pool.bootstrap_pending.remove(peer) if timed_out.timed_out: logger.warn('Could not connect to %s due to timeout' % (peer, )) return None comm_inst.direct_connection_clients[peer] = response.service_id # Now that the bootstrap server has received a server, return the address return key_store.get(bs_id)