Work on torgossip client

Use stems HS validator instead of custom logic
This commit is contained in:
Kevin Froman 2021-02-05 22:16:10 +00:00
parent bae7f745ee
commit b720f2f1d5
9 changed files with 100 additions and 98 deletions

View File

@ -77,10 +77,10 @@ def block_exec(event, info):
if code_b64 in whitelisted_source:
return
# uncomment when you want to build on the whitelist
else:
with open("../static-data/base64-code-whitelist.txt", "a") as f:
f.write(code_b64 + "\n")
return
#else:
# with open("../static-data/base64-code-whitelist.txt", "a") as f:
# f.write(code_b64 + "\n")
# return
for source in whitelisted_code:
if info[0].co_filename.endswith(source):

View File

@ -1,31 +1,37 @@
'''
Onionr - Private P2P Communication
"""
Onionr - Private P2P Communication
validate various string data types
'''
'''
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.
validate various string data types
"""
import base64
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.
import unpaddedbase32
import nacl.signing
import nacl.encoding
from stem.util import tor_tools
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 base64, string
import unpaddedbase32, nacl.signing, nacl.encoding
from onionrutils import bytesconverter
def validate_hash(data, length=64):
'''
Validate if a string is a valid hash hex digest (does not compare, just checks length and charset)
"""
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.
Length is only invalid if its *more* than the specified
'''
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 validate_hash(data, length=64):
"""Validate if a string is a valid hash hex digest (does not compare, checks length and charset)
Length is only invalid if its *more* than the specified
"""
retVal = True
if data == False or data == True:
return False
@ -40,10 +46,9 @@ def validate_hash(data, length=64):
return retVal
def validate_pub_key(key):
'''
Validate if a string is a valid base32 encoded Ed25519 key
'''
"""Validate if a string is a valid base32 encoded Ed25519 key"""
if type(key) is type(None):
return False
# Accept keys that have no = padding
@ -60,57 +65,15 @@ def validate_pub_key(key):
retVal = True
return retVal
def validate_transport(id):
try:
idLength = len(id)
retVal = True
idNoDomain = ''
peerType = ''
# i2p b32 addresses are 60 characters long (including .b32.i2p)
if idLength == 60:
peerType = 'i2p'
if not id.endswith('.b32.i2p'):
retVal = False
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 IndexError:
pass
else:
retVal = False
elif peerType == 'onion':
try:
id.split('.onion')[2]
except IndexError:
pass
else:
retVal = False
if not idNoDomain.isalnum():
retVal = False
# Validate address is valid base32 (when capitalized and minus extension); v2/v3 onions and .b32.i2p use base32
for x in idNoDomain.upper():
if x not in string.ascii_uppercase and x not in '234567':
retVal = False
def validate_transport(id: str):
id = id.replace('.onion', '')
return tor_tools.is_valid_hidden_service_address(
id, version=3) and id.endswith('d')
return retVal
except Exception as e:
return False
def is_integer_string(data):
'''Check if a string is a valid base10 integer (also returns true if already an int)'''
"""Check if a string is a valid base10 integer (also returns true if already an int)"""
try:
int(data)
except (ValueError, TypeError) as e:

View File

@ -18,6 +18,7 @@ from .housekeeping import test_inserted_housekeeping
from .lanservertest import test_lan_server
from .sneakernettest import test_sneakernet_import
from .dnsrebindingtest import test_dns_rebinding
from .serviceonlinetest import test_service_online
"""
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
@ -43,8 +44,9 @@ RUN_TESTS = [uicheck.check_ui,
test_clearnet_tor_request,
test_inserted_housekeeping,
test_lan_server,
sneakernettest.test_sneakernet_import,
test_dns_rebinding
test_sneakernet_import,
test_dns_rebinding,
test_service_online
]
SUCCESS_FILE = os.path.dirname(os.path.realpath(__file__)) + '/../../tests/runtime-result.txt'

View File

@ -15,6 +15,8 @@ from gevent import sleep
def test_sneakernet_import(test_manager):
if not config.get('transports.lan', False):
return
if config.get('runtests.skip_slow', False):
return
in_db = lambda b: b in get_block_list()
bl = insert(os.urandom(10))
assert in_db(bl)

View File

@ -4,6 +4,15 @@ Torgossip client
Create streams to random peers
"""
from os import path
from typing import TYPE_CHECKING
from random import SystemRandom
from netcontroller.torcontrol.onionserviceonline import service_online_recently
from netcontroller.torcontrol import torcontroller
if TYPE_CHECKING:
from .peerdb import TorGossipPeers
"""
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
@ -20,7 +29,35 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
def _add_bootstrap_peers(peer_db: 'TorGossipPeers'):
bootstap_peers = path.dirname(path.realpath(__file__)) + "/bootstrap.txt"
with open(bootstap_peers, 'r') as bs_peers:
peers = bs_peers.split(',')
for peer in peers:
if peer:
peer_db.add_peer(peer)
def _client_pool(shared_state, controller):
peer_db: 'TorGossipPeers' = shared_state.get_by_string('TorGossipPeers')
socket_pool = {}
peers = peer_db.get_highest_score_peers(20)
SystemRandom().shuffle(peers)
for peer in peers:
if not service_online_recently(controller, peer):
continue
def client_pool(shared_state):
return
controller = torcontroller.get_controller()
# Pass the stem Controller and then close it even if an exception raises
try:
_client_pool(shared_state, controller)
except Exception:
raise
finally:
# Calls before the above raise no matter what
controller.close()

View File

@ -5,6 +5,7 @@ Torgossip peer safedb interface
from base64 import b32decode
from struct import unpack, pack
from time import time
from typing import List
from utils.identifyhome import identify_home
import safedb
@ -54,7 +55,7 @@ class TorGossipPeers: # name it this way to avoid collisions in SharedState
self.db.put(peer, pack(self.PACK_FORMAT, score, seen))
def get_highest_score_peers(self, max):
def get_highest_score_peers(self, max) -> List:
assert max >= 1
peer = self.db.db_conn.firstkey()
if peer == b'enc':

View File

@ -112,5 +112,3 @@ def torgossip_runtest(test_manager):
s.sendall(b'9')
assert s.recv(64) == b"BYE"

View File

@ -17,7 +17,7 @@ from coredb import keydb
class OnionrTests(unittest.TestCase):
def test_address_add(self):
testAddresses = ['facebookcorewwwi.onion', '56kmnycrvepfarolhnx6t2dvmldfeyg7jdymwgjb7jjzg47u2lqw2sad.onion', '5bvb5ncnfr4dlsfriwczpzcvo65kn7fnnlnt2ln7qvhzna2xaldq.b32.i2p']
testAddresses = ['56kmnycrvepfarolhnx6t2dvmldfeyg7jdymwgjb7jjzg47u2lqw2sad.onion', 'ao34zusas5oocjllkh6uounorhtujyep4ffwz4k4r7qkxie5otdiwqad.onion']
for address in testAddresses:
keydb.addkeys.add_address(address)
dbAddresses = keydb.listkeys.list_adders()
@ -35,7 +35,7 @@ class OnionrTests(unittest.TestCase):
self.assertNotIn(address, dbAddresses)
def test_address_info(self):
adder = 'nytimes3xbfgragh.onion'
adder = 'ao34zusas5oocjllkh6uounorhtujyep4ffwz4k4r7qkxie5otdiwqad.onion'
keydb.addkeys.add_address(adder)
self.assertNotEqual(keydb.transportinfo.get_address_info(adder, 'success'), 1000)
keydb.transportinfo.set_address_info(adder, 'success', 1000)

View File

@ -9,28 +9,27 @@ os.environ["ONIONR_HOME"] = TEST_DIR
from onionrutils import stringvalidators
class OnionrValidations(unittest.TestCase):
def test_peer_validator(self):
# Test hidden service domain validities
valid = ['facebookcorewwwi.onion', 'vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion',
'5bvb5ncnfr4dlsfriwczpzcvo65kn7fnnlnt2ln7qvhzna2xaldq.b32.i2p']
valid = ['ao34zusas5oocjllkh6uounorhtujyep4ffwz4k4r7qkxie5otdiwqad.onion', 'vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd.onion']
invalid = [None, 'dsfewjirji0ejipdfs', '', ' ', '\n', '\r\n', 'f$ce%^okc+rewwwi.onion', 'facebookc0rewwi.onion']
invalid = [None, 'dsfewjirji0ejipdfs', '', ' ', '\n', '\r\n', 'f$ce%^okc+rewwwi.onion', 'facebookc0rewwi.onion', 'facebookcorewwwi.onion']
for x in valid:
print('testing', x)
self.assertTrue(stringvalidators.validate_transport(x))
for x in invalid:
print('testing', x)
self.assertFalse(stringvalidators.validate_transport(x))
def test_hash_validator(self):
valid = ['00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00c96\n', '00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00c96', b'00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00c96',
'00003b3813a166e706e490238e9515633cc36', b'00003b3813a166e706e490238e9515633cc3d083']
invalid = [None, 0, 1, True, False, '%#W483242#', '00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00c9666', '', b'',
invalid = [None, 0, 1, True, False, '%#W483242#', '00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00c9666', '', b'',
b'00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00c9666666', b' ', '\n', '00003b3813a166e706e490238e9515633cc3d083efe982a67753d50d87a00ccccc\n']
for x in valid:
self.assertTrue(stringvalidators.validate_hash(x))
for x in invalid:
@ -43,7 +42,7 @@ class OnionrValidations(unittest.TestCase):
self.assertFalse(result)
except AssertionError:
raise AssertionError("%s returned true" % (x,))
def test_pubkey_validator(self):
# Test ed25519 public key validity
valids = ['JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ====', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ']
@ -56,17 +55,17 @@ class OnionrValidations(unittest.TestCase):
for x in invalid:
#print('testing', x)
self.assertFalse(stringvalidators.validate_pub_key(x))
def test_integer_string(self):
valid = ["1", "100", 100, "-5", -5]
invalid = ['test', "1d3434", "1e100", None]
for x in valid:
#print('testing', x)
self.assertTrue(stringvalidators.is_integer_string(x))
self.assertTrue(stringvalidators.is_integer_string(x))
for x in invalid:
#print('testing', x)
self.assertFalse(stringvalidators.is_integer_string(x))
unittest.main()