OnionValidator: a dumb plugin for validating onion peers
This commit is contained in:
parent
d20486df0c
commit
5e11a04e9a
4
setup.py
4
setup.py
|
@ -16,6 +16,7 @@ EXTRAS_REQUIRE = {
|
|||
'prctl': ['python_prctl'], # Named threads
|
||||
'qrcode': ['qrcode'],
|
||||
'sound;platform_system=="Windows"': ['winsound'],
|
||||
'tor': ['stem'],
|
||||
'docs': [
|
||||
'sphinx', # fab build_docs
|
||||
'graphviz', # fab build_docs
|
||||
|
@ -129,6 +130,9 @@ if __name__ == "__main__":
|
|||
ext_modules=[bitmsghash],
|
||||
zip_safe=False,
|
||||
entry_points={
|
||||
'bitmessage.nodes.validator': [
|
||||
'onion = pybitmessage.plugins.validator_onion [tor]'
|
||||
],
|
||||
'bitmessage.gui.menu': [
|
||||
'address.qrcode = pybitmessage.plugins.menu_qrcode [qrcode]'
|
||||
],
|
||||
|
|
31
src/plugins/test_validator_onion.py
Normal file
31
src/plugins/test_validator_onion.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
import unittest
|
||||
|
||||
from pybitmessage.state import Peer
|
||||
|
||||
try:
|
||||
from validator_onion import OnionValidator
|
||||
validator_onion = True
|
||||
except ImportError:
|
||||
validator_onion = False
|
||||
|
||||
|
||||
@unittest.skipIf(not validator_onion, 'OnionValidator is not available')
|
||||
class TestOnionValidator(unittest.TestCase):
|
||||
"""Test case for OnionValidator"""
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.check = OnionValidator()
|
||||
|
||||
def test_valid(self):
|
||||
"""Ensure validator returns True for valid nodes"""
|
||||
# not onion node
|
||||
self.assertTrue(self.check(Peer('5.45.99.75', 8444)))
|
||||
# default onion node
|
||||
self.assertTrue(self.check(Peer('quzwelsuziwqgpt2.onion', 8444)))
|
||||
|
||||
def test_invalid(self):
|
||||
"""Ensure validator returns False for invalid hostnames"""
|
||||
# is not base32
|
||||
self.assertFalse(self.check(Peer('test.onion', 8444)))
|
||||
# no descriptor
|
||||
self.assertFalse(self.check(Peer('aaaaaaaaaaaaaaaa.onion', 8444)))
|
45
src/plugins/validator_onion.py
Normal file
45
src/plugins/validator_onion.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import base64
|
||||
|
||||
import stem
|
||||
from stem.control import Controller
|
||||
|
||||
|
||||
class OnionValidator(object):
|
||||
"""Validation plugin for onion nodes"""
|
||||
def __init__(self):
|
||||
try: # TODO: deal with authentication
|
||||
self.controller = Controller.from_port()
|
||||
self.controller.authenticate()
|
||||
except (stem.SocketError, stem.connection.AuthenticationFailure):
|
||||
raise ValueError # do not load this if controller is not available
|
||||
|
||||
def _validate_onion(self, addr):
|
||||
"""Check the .onion address validity"""
|
||||
try:
|
||||
base64.b32decode(addr, True)
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
if not self.controller:
|
||||
return True
|
||||
|
||||
try:
|
||||
self.controller.get_hidden_service_descriptor(addr)
|
||||
except stem.DescriptorUnavailable:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __call__(self, node):
|
||||
"""Filter check for .onion addresses validation"""
|
||||
addr = node.host
|
||||
try:
|
||||
addr, dom = addr.split('.')
|
||||
except ValueError:
|
||||
return True
|
||||
return self._validate_onion(addr) if dom == 'onion' else True
|
||||
|
||||
|
||||
connect_plugin = OnionValidator()
|
Reference in New Issue
Block a user