[Pkg-privacy-commits] [txtorcon] 69/96: Properly treat HiddenServiceAuthorizeClient as a list
Jérémy Bobbio
lunar at moszumanska.debian.org
Sun Sep 6 18:33:41 UTC 2015
This is an automated email from the git hooks/post-receive script.
lunar pushed a commit to branch master
in repository txtorcon.
commit 7429cd08331a45b1ff9c776dd0f77463dd51bdeb
Author: meejah <meejah at meejah.ca>
Date: Fri Feb 13 00:30:10 2015 -0700
Properly treat HiddenServiceAuthorizeClient as a list
Also parses client_keys into HiddenService properly (available
as .client_keys)
---
test/test_torconfig.py | 21 ++++++++--
txtorcon/torconfig.py | 106 +++++++++++++++++++++++++++----------------------
2 files changed, 77 insertions(+), 50 deletions(-)
diff --git a/test/test_torconfig.py b/test/test_torconfig.py
index 595d50c..ab9c34e 100644
--- a/test/test_torconfig.py
+++ b/test/test_torconfig.py
@@ -35,6 +35,7 @@ from txtorcon import torconfig
from txtorcon.torconfig import TorProcessProtocol
from txtorcon.util import delete_file_or_tree
+from txtorcon.torconfig import parse_client_keys
class FakeControlProtocol:
@@ -692,12 +693,18 @@ HiddenServiceAuthorizeClient Dependant''')
f.write('public')
with open(os.path.join(d, 'private_key'), 'w') as f:
f.write('private')
+ with open(os.path.join(d, 'client_keys'), 'w') as f:
+ f.write('client-name hungry\ndescriptor-cookie omnomnom\n')
conf = TorConfig(self.protocol)
hs = HiddenService(conf, d, [])
self.assertEqual(hs.hostname, 'public')
self.assertEqual(hs.private_key, 'private')
+ self.assertEqual(len(hs.client_keys), 1)
+ self.assertEqual(hs.client_keys[0].name, 'hungry')
+ self.assertEqual(hs.client_keys[0].cookie, 'omnomnom')
+ self.assertEqual(hs.client_keys[0].key, None)
finally:
shutil.rmtree(d, ignore_errors=True)
@@ -745,7 +752,8 @@ HiddenServicePort=90 127.0.0.1:2345''')
self.assertEqual(conf.hiddenservices[0].dir, '/fake/path')
self.assertEqual(conf.hiddenservices[0].version, 2)
- self.assertEqual(conf.hiddenservices[0].authorize_client, 'basic')
+ self.assertEqual(len(conf.hiddenservices[0].authorize_client), 1)
+ self.assertEqual(conf.hiddenservices[0].authorize_client[0], 'basic')
self.assertEqual(len(conf.hiddenservices[0].ports), 1)
self.assertEqual(conf.hiddenservices[0].ports[0], '80 127.0.0.1:1234')
@@ -794,7 +802,7 @@ HiddenServicePort=90 127.0.0.1:2345''')
self.assertEqual(len(conf.hiddenservices), 1)
self.assertEqual(conf.hiddenservices[0].dir, '/fake/path')
self.assertEqual(conf.hiddenservices[0].version, 3)
- self.assertEqual(conf.hiddenservices[0].authorize_client, '')
+ self.assertEqual(0, len(conf.hiddenservices[0].authorize_client))
conf.hiddenservices[0].ports = ['123 127.0.0.1:4321']
conf.save()
@@ -1504,7 +1512,6 @@ class HiddenServiceAuthTests(unittest.TestCase):
def test_parse_client_keys(self):
data = StringIO(keydata)
- from txtorcon.torconfig import parse_client_keys
clients = list(parse_client_keys(data))
@@ -1520,3 +1527,11 @@ class HiddenServiceAuthTests(unittest.TestCase):
self.assertEqual('quux', clients[2].name)
self.assertEqual('asdlkjasdlfkjalsdkfffj==', clients[2].cookie)
self.assertEqual(None, clients[2].key)
+
+ def test_parse_error(self):
+ data = StringIO('client-name foo\nclient-name xxx\n')
+
+ self.assertRaises(
+ RuntimeError,
+ parse_client_keys, data
+ )
diff --git a/txtorcon/torconfig.py b/txtorcon/torconfig.py
index b8d1f89..878f7b0 100644
--- a/txtorcon/torconfig.py
+++ b/txtorcon/torconfig.py
@@ -642,6 +642,23 @@ class _ListWrapper(list):
return '_ListWrapper' + super(_ListWrapper, self).__repr__()
+class HiddenServiceClientAuth(object):
+ """
+ Encapsulates a single client-authorization, as parsed from a
+ HiddenServiceDir's "client_keys" file if you have stealth or basic
+ authentication turned on.
+
+ :param name: the name you gave it in the HiddenServiceAuthorizeClient line
+ :param cookie: random password
+ :param key: RSA private key, or None if this was basic auth
+ """
+
+ def __init__(self, name, cookie, key=None):
+ self.name = name
+ self.cookie = cookie
+ self.key = parse_rsa_blob(key) if key else None
+
+
class HiddenService(object):
"""
Because hidden service configuration is handled specially by Tor,
@@ -659,31 +676,47 @@ class HiddenService(object):
"""
def __init__(self, config, thedir, ports,
- auth=None, ver=2, group_readable=0):
+ auth=[], ver=2, group_readable=0):
"""
- config is the TorConfig to which this will belong (FIXME,
- can't we make this automatic somehow?), thedir corresponds to
- 'HiddenServiceDir' and will ultimately contain a 'hostname'
- and 'private_key' file, ports is a list of lines corresponding
- to HiddenServicePort (like '80 127.0.0.1:1234' to advertise a
- hidden service at port 80 and redirect it internally on
- 127.0.0.1:1234). auth corresponds to
- HiddenServiceAuthenticateClient line (FIXME: is that lines?)
- and ver corresponds to HiddenServiceVersion and is always 2
- right now.
+ config is the TorConfig to which this will belong, thedir
+ corresponds to 'HiddenServiceDir' and will ultimately contain
+ a 'hostname' and 'private_key' file, ports is a list of lines
+ corresponding to HiddenServicePort (like '80 127.0.0.1:1234'
+ to advertise a hidden service at port 80 and redirect it
+ internally on 127.0.0.1:1234). auth corresponds to the
+ HiddenServiceAuthenticateClient lines and can be either a
+ string or a list of strings (like 'basic client0,client1' or
+ 'stealth client5,client6') and ver corresponds to
+ HiddenServiceVersion and is always 2 right now.
+
+ XXX FIXME can we avoid having to pass the config object
+ somehow? Like provide a factory-function on TorConfig for
+ users instead?
"""
self.conf = config
self.dir = thedir
self.version = ver
- self.authorize_client = auth
self.group_readable = group_readable
- # there are two magic attributes, "hostname" and "private_key"
- # these are gotten from the dir if they're still None when
- # accessed. Note that after a SETCONF has returned '250 OK'
- # it seems from tor code that the keys will always have been
- # created on disk by that point
+ # HiddenServiceAuthorizeClient is a list
+ # in case people are passing '' for the auth
+ if not auth:
+ auth = []
+ elif not isinstance(auth, types.ListType):
+ auth = [auth]
+ self.authorize_client = _ListWrapper(
+ auth, functools.partial(
+ self.conf.mark_unsaved, 'HiddenServices'
+ )
+ )
+
+ # there are three magic attributes, "hostname" and
+ # "private_key" are gotten from the dir if they're still None
+ # when accessed. "client_keys" parses out any client
+ # authorizations. Note that after a SETCONF has returned '250
+ # OK' it seems from tor code that the keys will always have
+ # been created on disk by that point
if not isinstance(ports, types.ListType):
ports = [ports]
@@ -708,6 +741,13 @@ class HiddenService(object):
if name in ('hostname', 'private_key'):
with open(os.path.join(self.dir, name)) as f:
self.__dict__[name] = f.read().strip()
+ elif name == 'client_keys':
+ fname = os.path.join(self.dir, name)
+ keys = []
+ if os.path.exists(fname):
+ with open(fname) as f:
+ keys = parse_client_keys(f)
+ self.__dict__[name] = keys
return self.__dict__[name]
def config_attributes(self):
@@ -728,38 +768,10 @@ class HiddenService(object):
return rtn
-'''
-client-name bar
-descriptor-cookie O4rQyZ+IJr2PNHUdeXi0nA==
-client-key
------BEGIN RSA PRIVATE KEY-----
-MIICXQIBAAKBgQC1R/bPGTWnpGJpNCfT1KIfFq1QEGHz4enKSEKUDkz1CSEPOMGS
-bV37dfqTuI4klsFvdUsR3NpYXLin9xRWvw1viKwAN0y8cv5totl4qMxO5i+zcfVh
-oBqwzxFD0JVZVLlZjNYfSlkNnkDPmb7btcluzNETBP4IDo8rb2p2zCQc1wIDAQAB
-AoGAWhgg7n5N7zpAep6kKKAlzqObkQ4DUIz3f0P4atLMpn9aAdGoSpi2O7I/zcjM
-RBz0l+tIWuFTVtUGJNwkLJSZHP3FDkoZtOv1JDRD0cbnVClHQ6cOW7Asn/VhOiud
-0yTMkytN2wMpi/vpcQTs28yQdNi1486xPEx8/WEQH2azLJECQQDmkQ18+2gp0eBS
-AdW+9WPsd9RhwKKmDKCJ2TUMN+/4u1WLMx2pARuHqKKOvrWP7vlv7epEoKqWFajc
-3M4B4oupAkEAyUckoM4SOi1YNky9DqFUXrZ1Bl2UVVv15J0BB4jMnYFoSjirVn+i
-4cYHwOBPsvUdkW6OQWvn3gc69Dj5ht60fwJABPFlJaHKKONb+MYbS/28x6wF/JaB
-pietJWdnsLxeQ6nYeqR85UulyHHAEmlaQRyxcknadOAw6AjM1vdQ3095CQJBAKGG
-LzXAyc3YL887nAiOnTd4sscN+AjcSKNS/819Eb9gZ0IQ4icDPMJ0eiplmG/j1vur
-vgtwPd3m7X+p7U03kZ8CQQCHS0lciMezXoDVoi7uljnsFFbbB0HMNXKxcsxym1eQ
-bJiNvVv2EjfEyQaZfAy2PUfp/tAPYZMsyfps2DptWyNR
------END RSA PRIVATE KEY-----
-'''
-
def parse_rsa_blob(lines):
return ''.join(lines[1:-1])
-class HiddenServiceClientAuth(object):
- def __init__(self, name, cookie, key=None):
- self.name = name
- self.cookie = cookie
- self.key = parse_rsa_blob(key) if key else None
-
-
def parse_client_keys(stream):
'''
This parses a hidden-service "client_keys" file, either stealth or
@@ -1232,7 +1244,7 @@ class TorConfig(object):
directory = v
ports = []
ver = None
- auth = None
+ auth = []
group_read = 0
elif k == 'HiddenServicePort':
@@ -1242,7 +1254,7 @@ class TorConfig(object):
ver = int(v)
elif k == 'HiddenServiceAuthorizeClient':
- auth = v
+ auth.append(v)
elif k == 'HiddenServiceDirGroupReadable':
group_read = int(v)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/txtorcon.git
More information about the Pkg-privacy-commits
mailing list