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
|
'prctl': ['python_prctl'], # Named threads
|
||||||
'qrcode': ['qrcode'],
|
'qrcode': ['qrcode'],
|
||||||
'sound;platform_system=="Windows"': ['winsound'],
|
'sound;platform_system=="Windows"': ['winsound'],
|
||||||
|
'tor': ['stem'],
|
||||||
'docs': [
|
'docs': [
|
||||||
'sphinx', # fab build_docs
|
'sphinx', # fab build_docs
|
||||||
'graphviz', # fab build_docs
|
'graphviz', # fab build_docs
|
||||||
|
@ -129,6 +130,9 @@ if __name__ == "__main__":
|
||||||
ext_modules=[bitmsghash],
|
ext_modules=[bitmsghash],
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
entry_points={
|
entry_points={
|
||||||
|
'bitmessage.nodes.validator': [
|
||||||
|
'onion = pybitmessage.plugins.validator_onion [tor]'
|
||||||
|
],
|
||||||
'bitmessage.gui.menu': [
|
'bitmessage.gui.menu': [
|
||||||
'address.qrcode = pybitmessage.plugins.menu_qrcode [qrcode]'
|
'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