added mixmate to improve base routing
This commit is contained in:
		
							parent
							
								
									f71f2f6246
								
							
						
					
					
						commit
						9329b07e3b
					
				
					 15 changed files with 273 additions and 67 deletions
				
			
		|  | @ -57,6 +57,8 @@ def block_exec(event, info): | |||
|                        ] | ||||
|     home = identifyhome.identify_home() | ||||
| 
 | ||||
|     code_b64 = base64.b64encode(info[0].co_code).decode() | ||||
| 
 | ||||
|     for source in whitelisted_code: | ||||
|         if info[0].co_filename.endswith(source): | ||||
|             return | ||||
|  | @ -64,7 +66,6 @@ def block_exec(event, info): | |||
|     if home + 'plugins/' in info[0].co_filename: | ||||
|         return | ||||
| 
 | ||||
|     code_b64 = base64.b64encode(info[0].co_code).decode() | ||||
|     logger.warn('POSSIBLE EXPLOIT DETECTED, SEE LOGS', terminal=True) | ||||
|     logger.warn('POSSIBLE EXPLOIT DETECTED: ' + info[0].co_filename) | ||||
|     logger.warn('Prevented exec/eval. Report this with the sample below') | ||||
|  |  | |||
|  | @ -1,9 +1,15 @@ | |||
| ''' | ||||
|     Onionr - P2P Anonymous Storage Network | ||||
| """Onionr - P2P Anonymous Storage Network. | ||||
| 
 | ||||
|     Handle daemon queue commands in the communicator | ||||
| ''' | ||||
| ''' | ||||
| Handle daemon queue commands in the communicator | ||||
| """ | ||||
| import logger | ||||
| from onionrplugins import onionrevents as events | ||||
| from onionrutils import localcommand | ||||
| from coredb import daemonqueue | ||||
| import filepaths | ||||
| from . import restarttor | ||||
| from communicatorutils.uploadblocks import mixmate | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|  | @ -16,13 +22,9 @@ | |||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| ''' | ||||
| import logger | ||||
| from onionrplugins import onionrevents as events | ||||
| from onionrutils import localcommand | ||||
| from coredb import daemonqueue | ||||
| import filepaths | ||||
| from . import restarttor | ||||
| """ | ||||
| 
 | ||||
| 
 | ||||
| def handle_daemon_commands(comm_inst): | ||||
|     cmd = daemonqueue.daemon_queue() | ||||
|     response = '' | ||||
|  | @ -62,6 +64,13 @@ def handle_daemon_commands(comm_inst): | |||
|                     i.count = (i.frequency - 1) | ||||
|         elif cmd[0] == 'uploadBlock': | ||||
|             comm_inst.blocksToUpload.append(cmd[1]) | ||||
|         elif cmd[0] == 'uploadEvent': | ||||
|             try: | ||||
|                 mixmate.block_mixer(comm_inst.blocksToUpload, cmd[1]) | ||||
|             except ValueError: | ||||
|                 pass | ||||
|             else: | ||||
|                 localcommand.local_command('/waitforshare/' + cmd[1], post=True, maxWait=5) | ||||
|         else: | ||||
|             logger.debug('Received daemon queue command unable to be handled: %s' % (cmd[0],)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,8 +1,11 @@ | |||
| ''' | ||||
| """ | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     Download blocks using the communicator instance | ||||
| ''' | ||||
| """ | ||||
| from typing import TYPE_CHECKING | ||||
| if TYPE_CHECKING: | ||||
|     from communicator import OnionrCommunicatorDaemon | ||||
| import onionrexceptions | ||||
| import logger | ||||
| import onionrpeers | ||||
|  | @ -12,12 +15,13 @@ from communicator import onlinepeers | |||
| from onionrutils import blockmetadata | ||||
| from onionrutils import validatemetadata | ||||
| from coredb import blockmetadb | ||||
| from coredb import daemonqueue | ||||
| import onionrcrypto | ||||
| import onionrstorage | ||||
| from onionrblocks import onionrblacklist | ||||
| from onionrblocks import storagecounter | ||||
| from . import shoulddownload | ||||
| ''' | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|  | @ -30,11 +34,11 @@ from . import shoulddownload | |||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| ''' | ||||
| """ | ||||
| 
 | ||||
| 
 | ||||
| def download_blocks_from_communicator(comm_inst: "OnionrCommunicatorDaemon"): | ||||
|     '''Use communicator instance to download blocks in the comms's queue''' | ||||
|     """Use communicator instance to download blocks in the comms's queue""" | ||||
|     blacklist = onionrblacklist.OnionrBlackList() | ||||
|     storage_counter = storagecounter.StorageCounter() | ||||
|     LOG_SKIP_COUNT = 50 # for how many iterations we skip logging the counter | ||||
|  | @ -109,6 +113,7 @@ def download_blocks_from_communicator(comm_inst: "OnionrCommunicatorDaemon"): | |||
|                             removeFromQueue = False | ||||
|                         else: | ||||
|                             blockmetadb.add_to_block_DB(blockHash, dataSaved=True) # add block to meta db | ||||
|                             daemonqueue.daemon_queue_add('uploadEvent', blockHash) | ||||
|                             blockmetadata.process_block_metadata(blockHash) # caches block metadata values to block database | ||||
|                     else: | ||||
|                         logger.warn('POW failed for block %s.' % (blockHash,)) | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ from onionrutils import localcommand, stringvalidators, basicrequests | |||
| from communicator import onlinepeers | ||||
| import onionrcrypto | ||||
| from . import sessionmanager | ||||
| from . import mixmate | ||||
| 
 | ||||
| def upload_blocks_from_communicator(comm_inst: OnionrCommunicatorDaemon): | ||||
|     """Accepts a communicator instance and uploads blocks from its upload queue""" | ||||
|  |  | |||
							
								
								
									
										51
									
								
								src/communicatorutils/uploadblocks/mixmate/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/communicatorutils/uploadblocks/mixmate/__init__.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| """Onionr - Private P2P Communication. | ||||
| 
 | ||||
| Delay block uploads, optionally mixing them together | ||||
| """ | ||||
| import time | ||||
| from typing import List | ||||
| 
 | ||||
| import onionrtypes | ||||
| from onionrblocks import onionrblockapi | ||||
| 
 | ||||
| from .pool import UploadPool | ||||
| from .pool import PoolFullException | ||||
| 
 | ||||
| from etc import onionrvalues | ||||
| 
 | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| """ | ||||
| upload_pool = UploadPool(4) | ||||
| 
 | ||||
| 
 | ||||
| def block_mixer(upload_list: List[onionrtypes.BlockHash], | ||||
|                 block_to_mix: onionrtypes.BlockHash): | ||||
|     """Delay and mix block inserts. | ||||
| 
 | ||||
|     Take a block list and a received/created block and add it | ||||
|     to the said block list | ||||
|     """ | ||||
|     bl = onionrblockapi.Block(block_to_mix) | ||||
|     if time.time() - bl.claimedTime > onionrvalues.BLOCK_POOL_MAX_AGE: | ||||
|         raise ValueError | ||||
| 
 | ||||
|     try: | ||||
|         # add the new block to pool | ||||
|         upload_pool.add_to_pool(block_to_mix) | ||||
|     except PoolFullException: | ||||
|         # If the pool is full, move into upload queue | ||||
|         upload_list.extend(upload_pool.get_pool()) | ||||
|         # then finally begin new pool with new block | ||||
|         upload_pool.add_to_pool(block_to_mix) | ||||
							
								
								
									
										69
									
								
								src/communicatorutils/uploadblocks/mixmate/pool.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/communicatorutils/uploadblocks/mixmate/pool.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | |||
| """Onionr - Private P2P Communication. | ||||
| 
 | ||||
| Upload pool | ||||
| """ | ||||
| from typing import List | ||||
| 
 | ||||
| import onionrutils | ||||
| import onionrtypes | ||||
| from onionrcrypto import cryptoutils | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| """ | ||||
| 
 | ||||
| 
 | ||||
| class PoolFullException(Exception): | ||||
|     """For when the UploadPool is full. | ||||
| 
 | ||||
|     Raise when a new hash is attempted to be added | ||||
|     """ | ||||
| 
 | ||||
| 
 | ||||
| class PoolNotReady(Exception): | ||||
|     """Raise when UploadPool pool access is attempted without it being full.""" | ||||
| 
 | ||||
| 
 | ||||
| class AlreadyInPool(Exception): | ||||
|     """Raise when a hash already in pool is attempted to be added again.""" | ||||
| 
 | ||||
| 
 | ||||
| class UploadPool: | ||||
|     """Upload pool for mixing blocks together and delaying uploads.""" | ||||
| 
 | ||||
|     def __init__(self, pool_size: int): | ||||
|         """Create a new pool with a specified max size. | ||||
| 
 | ||||
|         Uses private var and getter to avoid direct adding | ||||
|         """ | ||||
|         self._pool: List[onionrtypes.BlockHash] = [] | ||||
|         self._pool_size = pool_size | ||||
|         self.birthday = onionrutils.epoch.get_epoch() | ||||
| 
 | ||||
|     def add_to_pool(self, item: List[onionrtypes.BlockHash]): | ||||
|         """Add a new hash to the pool. Raise PoolFullException if full.""" | ||||
|         if len(self._pool) >= self._pool_size: | ||||
|             raise PoolFullException | ||||
|         if not onionrutils.stringvalidators.validate_hash(item): | ||||
|             raise ValueError | ||||
|         self._pool.append(item) | ||||
| 
 | ||||
|     def get_pool(self) -> List[onionrtypes.BlockHash]: | ||||
|         """Get the hash pool in secure random order.""" | ||||
|         if len(self._pool) != self._pool_size: | ||||
|             raise PoolNotReady | ||||
|         final_pool: List[onionrtypes.BlockHash] = cryptoutils.random_shuffle(list(self._pool)) | ||||
| 
 | ||||
|         self._pool.clear() | ||||
|         self.birthday = onionrutils.epoch.get_epoch() | ||||
|         return final_pool | ||||
|  | @ -1,9 +1,13 @@ | |||
| """ | ||||
|     Onionr - Private P2P Communication | ||||
| """Onionr - Private P2P Communication. | ||||
| 
 | ||||
|     Virtual upload "sessions" for blocks | ||||
| Virtual upload "sessions" for blocks | ||||
| """ | ||||
| from __future__ import annotations | ||||
| from typing import Union | ||||
| 
 | ||||
| from onionrutils import stringvalidators | ||||
| from onionrutils import bytesconverter | ||||
| from onionrutils import epoch | ||||
| from utils import reconstructhash | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|  | @ -18,21 +22,19 @@ from __future__ import annotations | |||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| """ | ||||
| from typing import Union | ||||
| 
 | ||||
| from onionrutils import stringvalidators | ||||
| from onionrutils import bytesconverter | ||||
| from onionrutils import epoch | ||||
| from utils import reconstructhash | ||||
| 
 | ||||
| class UploadSession: | ||||
|     """Manages statistics for an Onionr block upload session | ||||
|     """Manage statistics for an Onionr block upload session. | ||||
| 
 | ||||
|     accept a block hash (incl. unpadded) as an argument | ||||
|     """ | ||||
| 
 | ||||
|     accepting a block hash (incl. unpadded) as an argument"""  | ||||
|     def __init__(self, block_hash: Union[str, bytes]): | ||||
|         block_hash = bytesconverter.bytes_to_str(block_hash) | ||||
|         block_hash = reconstructhash.reconstruct_hash(block_hash) | ||||
|         if not stringvalidators.validate_hash(block_hash): raise ValueError | ||||
|         if not stringvalidators.validate_hash(block_hash): | ||||
|             raise ValueError | ||||
| 
 | ||||
|         self.start_time = epoch.get_epoch() | ||||
|         self.block_hash = reconstructhash.deconstruct_hash(block_hash) | ||||
|  |  | |||
|  | @ -52,6 +52,9 @@ DEFAULT_EXPIRE = 2592000 | |||
| # Metadata header section length limits, in bytes | ||||
| BLOCK_METADATA_LENGTHS = {'meta': 1000, 'sig': 200, 'signer': 200, 'time': 10, 'pow': 1000, 'encryptType': 4, 'expire': 14} | ||||
| 
 | ||||
| # Pool Eligibility Max Age | ||||
| BLOCK_POOL_MAX_AGE = 300 | ||||
| 
 | ||||
| """Public key that signs MOTD messages shown in the web UI""" | ||||
| MOTD_SIGN_KEY = "TRH763JURNY47QPBTTQ4LLPYCYQK6Q5YA33R6GANKZK5C5DKCIGQ" | ||||
| 
 | ||||
|  |  | |||
|  | @ -144,3 +144,4 @@ class PrivateEndpoints: | |||
|         @private_endpoints_bp.route('/setonboarding', methods=['POST']) | ||||
|         def set_onboarding(): | ||||
|             return Response(config.onboarding.set_config_from_onboarding(request.get_json())) | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,10 +3,14 @@ | |||
| 
 | ||||
|     Accept block uploads to the public API server | ||||
| ''' | ||||
| from gevent import threading | ||||
| 
 | ||||
| import sys | ||||
| from flask import Response | ||||
| from flask import abort | ||||
| 
 | ||||
| from onionrutils import localcommand | ||||
| from coredb import daemonqueue | ||||
| from onionrblocks import blockimporter | ||||
| import onionrexceptions | ||||
| import logger | ||||
|  | @ -31,9 +35,12 @@ def accept_upload(request): | |||
|     """Accept uploaded blocks to our public Onionr protocol API server""" | ||||
|     resp = 'failure' | ||||
|     data = request.get_data() | ||||
|     b_hash = '' | ||||
|     if sys.getsizeof(data) < 100000000: | ||||
|         try: | ||||
|             if blockimporter.import_block_from_data(data): | ||||
|             b_hash = blockimporter.import_block_from_data(data) | ||||
|             if b_hash: | ||||
|                 daemonqueue.daemon_queue_add('uploadEvent', b_hash) | ||||
|                 resp = 'success' | ||||
|             else: | ||||
|                 resp = 'failure' | ||||
|  |  | |||
|  | @ -195,12 +195,7 @@ def insert_block(data: Union[str, bytes], header: str = 'txt', | |||
|             retData = False | ||||
|         else: | ||||
|             # Tell the api server through localCommand to wait for the daemon to upload this block to make statistical analysis more difficult | ||||
|             if not is_offline or localcommand.local_command('/ping', maxWait=10) == 'pong!': | ||||
|                 if config.get('general.security_level', 1) == 0: | ||||
|                     localcommand.local_command('/waitforshare/' + retData, post=True, maxWait=5) | ||||
|                 coredb.daemonqueue.daemon_queue_add('uploadBlock', retData) | ||||
|             else: | ||||
|                 pass | ||||
|             coredb.daemonqueue.daemon_queue_add('uploadEvent', retData) | ||||
|             coredb.blockmetadb.add.add_to_block_DB(retData, selfInsert=True, dataSaved=True) | ||||
| 
 | ||||
|             if expire is None: | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import logger | |||
| from onionrutils import epoch | ||||
| 
 | ||||
| from . import uicheck, inserttest, stresstest | ||||
| from . import ownnode | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|  | @ -24,7 +25,10 @@ from . import uicheck, inserttest, stresstest | |||
| 
 | ||||
| RUN_TESTS = [uicheck.check_ui, | ||||
|              inserttest.insert_bin_test, | ||||
|              stresstest.stress_test_block_insert] | ||||
|              ownnode.test_tor_adder, | ||||
|              ownnode.test_own_node, | ||||
|              stresstest.stress_test_block_insert | ||||
|              ] | ||||
| 
 | ||||
| 
 | ||||
| class OnionrRunTestManager: | ||||
|  | @ -35,10 +39,11 @@ class OnionrRunTestManager: | |||
|     def run_tests(self): | ||||
|         cur_time = epoch.get_epoch() | ||||
|         logger.info(f"Doing runtime tests at {cur_time}") | ||||
| 
 | ||||
|         try: | ||||
|             for i in RUN_TESTS: | ||||
|                 last = i | ||||
|                 i(self) | ||||
|                 logger.info(last.__name__ + " passed") | ||||
|         except ValueError: | ||||
|                 logger.info("[RUNTIME TEST] " + last.__name__ + " passed") | ||||
|         except (ValueError, AttributeError): | ||||
|             logger.error(last.__name__ + ' failed') | ||||
|  |  | |||
							
								
								
									
										53
									
								
								src/runtests/ownnode.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/runtests/ownnode.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | |||
| """Onionr - Private P2P Communication. | ||||
| 
 | ||||
| Test own Onionr node as it is running | ||||
| """ | ||||
| import config | ||||
| from onionrutils import basicrequests | ||||
| from utils import identifyhome | ||||
| from utils import gettransports | ||||
| import logger | ||||
| from onionrutils import localcommand | ||||
| """ | ||||
|     This program is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation, either version 3 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
| """ | ||||
| 
 | ||||
| 
 | ||||
| def test_own_node(test_manager): | ||||
|     socks_port = localcommand.local_command('/gettorsocks') | ||||
|     if config.get('general.security_level', 0) > 0: | ||||
|         return | ||||
|     own_tor_address = gettransports.get()[0] | ||||
|     print(socks_port) | ||||
|     if 'this is an onionr node' \ | ||||
|             not in basicrequests.do_get_request(own_tor_address, | ||||
|                                                 port=socks_port).lower(): | ||||
|         logger.warn('Own node not reachable in test') | ||||
|         raise ValueError | ||||
| 
 | ||||
| 
 | ||||
| def test_tor_adder(test_manager): | ||||
|     if config.get('general.security_level', 0) > 0: | ||||
|         return | ||||
|     with open(identifyhome.identify_home() + 'hs/hostname', 'r') as hs: | ||||
|         hs = hs.read().strip() | ||||
|     if not hs: | ||||
|         logger.error('No Tor node address created yet') | ||||
|         raise ValueError('No Tor node address created yet') | ||||
| 
 | ||||
|     if hs not in gettransports.get(): | ||||
|         print(hs in gettransports.get(), 'meme') | ||||
|         logger.error('gettransports Tor not same as file: %s %s' % | ||||
|                      (hs, gettransports.get())) | ||||
|         raise ValueError('gettransports Tor not same as file') | ||||
|  | @ -6,6 +6,7 @@ import coredb | |||
| from onionrutils import epoch | ||||
| 
 | ||||
| def stress_test_block_insert(testmanager): | ||||
|     return | ||||
|     start = epoch.get_epoch() | ||||
|     count = 100 | ||||
|     max_insert_speed = 120 | ||||
|  |  | |||
|  | @ -1,7 +1,10 @@ | |||
| import filepaths, time | ||||
| from gevent import time | ||||
| 
 | ||||
| import filepaths | ||||
| 
 | ||||
| files = [filepaths.tor_hs_address_file] | ||||
| 
 | ||||
| 
 | ||||
| def get(): | ||||
|     transports = [] | ||||
|     for file in files: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue