[Pkg-privacy-commits] [txtorcon] 31/96: HiddenServiceDirGroupReadable support

Jérémy Bobbio lunar at moszumanska.debian.org
Sun Sep 6 18:33:36 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 94b0e30aec8e37ecf80e9bf740efb22e9d23eedc
Author: meejah <meejah at meejah.ca>
Date:   Sat Jan 17 01:10:56 2015 -0700

    HiddenServiceDirGroupReadable support
---
 test/test_torconfig.py | 60 ++++++++++++++++++++++++---------------
 txtorcon/endpoints.py  |  6 ++--
 txtorcon/stream.py     |  7 ++---
 txtorcon/torconfig.py  | 76 ++++++++++++++++++++++++++++----------------------
 4 files changed, 86 insertions(+), 63 deletions(-)

diff --git a/test/test_torconfig.py b/test/test_torconfig.py
index be4c294..4d7bae3 100644
--- a/test/test_torconfig.py
+++ b/test/test_torconfig.py
@@ -3,6 +3,7 @@ import shutil
 import tempfile
 import functools
 from getpass import getuser
+from mock import patch
 from StringIO import StringIO
 
 from mock import Mock, patch
@@ -267,12 +268,13 @@ class ConfigTests(unittest.TestCase):
         conf.save()
 
     def test_get_type(self):
-        self.protocol.answers.append('config/names=\nSomethingExciting CommaList')
+        self.protocol.answers.append('config/names=\nSomethingExciting CommaList\nHiddenServices Dependant')
         self.protocol.answers.append({'SomethingExciting': 'a,b'})
         conf = TorConfig(self.protocol)
 
-        from txtorcon.torconfig import CommaList
+        from txtorcon.torconfig import CommaList, HiddenService
         self.assertEqual(conf.get_type('SomethingExciting'), CommaList)
+        self.assertEqual(conf.get_type('HiddenServices'), HiddenService)
 
     def foo(self, *args):
         print "FOOO", args
@@ -531,7 +533,7 @@ class CreateTorrcTests(unittest.TestCase):
         config = TorConfig()
         config.SocksPort = 1234
         config.hiddenservices = [HiddenService(config, '/some/dir', '80 127.0.0.1:1234',
-                                               'auth', 2)]
+                                               'auth', 2, True)]
         config.Log = ['80 127.0.0.1:80', '90 127.0.0.1:90']
         config.save()
         torrc = config.create_torrc()
@@ -554,30 +556,36 @@ class HiddenServiceTests(unittest.TestCase):
         self.protocol.answers.append('''config/names=
 HiddenServiceOptions Virtual
 HiddenServiceVersion Dependant
+HiddenServiceDirGroupReadable Dependant
 HiddenServiceAuthorizeClient Dependant''')
 
+    @defer.inlineCallbacks
     def test_options_hidden(self):
-        self.protocol.answers.append('HiddenServiceDir=/fake/path\nHiddenServicePort=80 127.0.0.1:1234\n')
+        self.protocol.answers.append('HiddenServiceDir=/fake/path\nHiddenServicePort=80 127.0.0.1:1234\nHiddenServiceDirGroupReadable=1\n')
 
         conf = TorConfig(self.protocol)
+        yield conf.post_bootstrap
+        self.assertTrue(conf.post_bootstrap.called)
         self.assertTrue('HiddenServiceOptions' not in conf.config)
+        self.assertTrue('HiddenServices' in conf.config)
         self.assertEqual(len(conf.HiddenServices), 1)
 
         self.assertTrue(not conf.needs_save())
-        conf.hiddenservices.append(HiddenService(conf, '/some/dir', '80 127.0.0.1:2345', 'auth', 2))
+        conf.hiddenservices.append(HiddenService(conf, '/some/dir', '80 127.0.0.1:2345', 'auth', 2, True))
         conf.hiddenservices[0].ports.append('443 127.0.0.1:443')
         self.assertTrue(conf.needs_save())
         conf.save()
-        self.assertEqual(conf.get_type('HiddenServices'), HiddenService)
 
-        self.assertEqual(len(self.protocol.sets), 7)
+        self.assertEqual(len(self.protocol.sets), 9)
         self.assertEqual(self.protocol.sets[0], ('HiddenServiceDir', '/fake/path'))
-        self.assertEqual(self.protocol.sets[1], ('HiddenServicePort', '80 127.0.0.1:1234'))
-        self.assertEqual(self.protocol.sets[2], ('HiddenServicePort', '443 127.0.0.1:443'))
-        self.assertEqual(self.protocol.sets[3], ('HiddenServiceDir', '/some/dir'))
-        self.assertEqual(self.protocol.sets[4], ('HiddenServicePort', '80 127.0.0.1:2345'))
-        self.assertEqual(self.protocol.sets[5], ('HiddenServiceVersion', '2'))
-        self.assertEqual(self.protocol.sets[6], ('HiddenServiceAuthorizeClient', 'auth'))
+        self.assertEqual(self.protocol.sets[1], ('HiddenServiceDirGroupReadable', '1'))
+        self.assertEqual(self.protocol.sets[2], ('HiddenServicePort', '80 127.0.0.1:1234'))
+        self.assertEqual(self.protocol.sets[3], ('HiddenServicePort', '443 127.0.0.1:443'))
+        self.assertEqual(self.protocol.sets[4], ('HiddenServiceDir', '/some/dir'))
+        self.assertEqual(self.protocol.sets[5], ('HiddenServiceDirGroupReadable', '1'))
+        self.assertEqual(self.protocol.sets[6], ('HiddenServicePort', '80 127.0.0.1:2345'))
+        self.assertEqual(self.protocol.sets[7], ('HiddenServiceVersion', '2'))
+        self.assertEqual(self.protocol.sets[8], ('HiddenServiceAuthorizeClient', 'auth'))
 
     def test_save_no_protocol(self):
         conf = TorConfig()
@@ -592,6 +600,7 @@ HiddenServiceAuthorizeClient Dependant''')
         self.assertEqual(2, len(conf.HiddenServices))
 
     def test_onion_keys(self):
+        # FIXME test without crapping on filesystem
         self.protocol.answers.append('HiddenServiceDir=/fake/path\n')
         d = tempfile.mkdtemp()
 
@@ -629,11 +638,14 @@ HiddenServiceAuthorizeClient Dependant''')
         conf = TorConfig()
         h0 = HiddenService(conf, '/fake/path', ['80 127.0.0.1:1234'], '', 3)
         h1 = HiddenService(conf, '/fake/path', ['90 127.0.0.1:4321'], '', 3)
-        conf.hiddenservices.append(h0)
+        h2 = HiddenService(conf, '/fake/path', ['90 127.0.0.1:5432'], '', 3, True)
+        conf.hiddenservices = [h0]
         conf.hiddenservices.append(h1)
-        self.assertEqual(len(conf.hiddenservices), 2)
+        conf.hiddenservices.append(h2)
+        self.assertEqual(len(conf.hiddenservices), 3)
         self.assertEqual(h0, conf.hiddenservices[0])
         self.assertEqual(h1, conf.hiddenservices[1])
+        self.assertEqual(h2, conf.hiddenservices[2])
         self.assertTrue(conf.needs_save())
 
     def test_multiple_startup_services(self):
@@ -707,7 +719,6 @@ HiddenServicePort=90 127.0.0.1:2345''')
         conf.hiddenservices[0].ports.append('90 127.0.0.1:2345')
         self.assertTrue(conf.needs_save())
 
-
 class FakeReactor(task.Clock):
     implements(IReactorCore)
 
@@ -882,13 +893,18 @@ class LaunchTorTests(unittest.TestCase):
         return self.assertRaises(RuntimeError,
             launch_tor, config, None, timeout=5, tor_binary='/bin/echo')
 
-    def test_launch_root_changes_tmpdir_ownership(self):
+    @patch('txtorcon.torconfig.sys')
+    @patch('txtorcon.torconfig.pwd')
+    @patch('txtorcon.torconfig.os.geteuid')
+    @patch('txtorcon.torconfig.os.chown')
+    def test_launch_root_changes_tmpdir_ownership(self, chown, euid, _pwd, _sys):
+        _pwd.return_value = 1000
+        _sys.platform = 'linux2'
+        euid.return_value = 0
         config = TorConfig()
-        try:
-            launch_tor(config, None, timeout=5, tor_binary='/bin/echo')
-            self.fail("Should have thrown an error")
-        except RuntimeError:
-            pass
+        config.User = 'chuffington'
+        d = launch_tor(config, Mock(), tor_binary='/bin/echo')
+        self.assertEqual(1, chown.call_count)
 
     @defer.inlineCallbacks
     def test_launch_timeout_exception(self):
diff --git a/txtorcon/endpoints.py b/txtorcon/endpoints.py
index bcae171..ef3c93c 100644
--- a/txtorcon/endpoints.py
+++ b/txtorcon/endpoints.py
@@ -169,7 +169,6 @@ class TCPHiddenServiceEndpoint(object):
         """
         This returns a TCPHiddenServiceEndpoint connected to the
         endpoint you specify in `control_endpoint`. After connecting, a
-
         single hidden service is added. The endpoint can be a Unix
         socket if Tor's `ControlSocket` option was used (instead of
         `ControlPort`).
@@ -177,7 +176,7 @@ class TCPHiddenServiceEndpoint(object):
         .. note::
 
             If Tor bug #11291 is not yet fixed, this won't work if you
-            only have Group access.
+            only have Group access. XXX FIXME re-test
         """
 
         @defer.inlineCallbacks
@@ -333,8 +332,7 @@ class TCPHiddenServiceEndpoint(object):
 
     @defer.inlineCallbacks
     def listen(self, protocolfactory):
-        """
-        Implement :api:`twisted.internet.interfaces.IStreamServerEndpoint
+        """Implement :api:`twisted.internet.interfaces.IStreamServerEndpoint
         <IStreamServerEndpoint>`.
 
         Returns a Deferred that delivers an
diff --git a/txtorcon/stream.py b/txtorcon/stream.py
index ea3ab85..3cc8ec5 100644
--- a/txtorcon/stream.py
+++ b/txtorcon/stream.py
@@ -228,10 +228,9 @@ class Stream(object):
         else:
             raise RuntimeError("Unknown state: %s" % self.state)
 
-        ## see if we attached to a circuit. I believe this only
-        ## happens on a SENTCONNECT or REMAP. DETACHED is excluded so
-        ## we don't immediately re-add the circuit we just detached
-        ## from
+        # see if we attached to a circuit. I believe this only happens
+        # on a SENTCONNECT or REMAP. DETACHED is excluded so we don't
+        # immediately re-add the circuit we just detached from
         if self.state not in ['CLOSED', 'FAILED', 'DETACHED']:
             cid = int(args[2])
             if cid == 0:
diff --git a/txtorcon/torconfig.py b/txtorcon/torconfig.py
index 577446f..b715383 100644
--- a/txtorcon/torconfig.py
+++ b/txtorcon/torconfig.py
@@ -130,12 +130,12 @@ class TorProcessProtocol(protocol.ProcessProtocol):
         if self.stdout:
             self.stdout.write(data)
 
-        ## minor hack: we can't try this in connectionMade because
-        ## that's when the process first starts up so Tor hasn't
-        ## opened any ports properly yet. So, we presume that after
-        ## its first output we're good-to-go. If this fails, we'll
-        ## reset and try again at the next output (see this class'
-        ## tor_connection_failed)
+        # minor hack: we can't try this in connectionMade because
+        # that's when the process first starts up so Tor hasn't
+        # opened any ports properly yet. So, we presume that after
+        # its first output we're good-to-go. If this fails, we'll
+        # reset and try again at the next output (see this class'
+        # tor_connection_failed)
 
         txtorlog.msg(data)
         if not self.attempted_connect and self.connection_creator \
@@ -174,7 +174,7 @@ class TorProcessProtocol(protocol.ProcessProtocol):
         Clean up my temporary files.
         """
 
-        [delete_file_or_tree(f) for f in self.to_delete]
+        all([delete_file_or_tree(f) for f in self.to_delete])
         self.to_delete = []
 
     def processEnded(self, status):
@@ -215,10 +215,10 @@ class TorProcessProtocol(protocol.ProcessProtocol):
     ## the below are all callbacks
 
     def tor_connection_failed(self, failure):
-        ## FIXME more robust error-handling please, like a timeout so
-        ## we don't just wait forever after 100% bootstrapped (that
-        ## is, we're ignoring these errors, but shouldn't do so after
-        ## we'll stop trying)
+        # FIXME more robust error-handling please, like a timeout so
+        # we don't just wait forever after 100% bootstrapped (that
+        # is, we're ignoring these errors, but shouldn't do so after
+        # we'll stop trying)
         self.attempted_connect = False
 
     def status_client(self, arg):
@@ -666,12 +666,13 @@ class HiddenService(object):
         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
+        # 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
 
         if not isinstance(ports, types.ListType):
             ports = [ports]
@@ -703,13 +704,15 @@ class HiddenService(object):
         Helper method used by TorConfig when generating a torrc file.
         """
 
-        rtn = [('HiddenServiceDir', self.dir)]
+        rtn = [('HiddenServiceDir', str(self.dir))]
+        if self.conf._supports['HiddenServiceDirGroupReadable'] and self.group_readable:
+            rtn.append(('HiddenServiceDirGroupReadable', str(1)))
         for x in self.ports:
-            rtn.append(('HiddenServicePort', x))
+            rtn.append(('HiddenServicePort', str(x)))
         if self.version:
-            rtn.append(('HiddenServiceVersion', self.version))
+            rtn.append(('HiddenServiceVersion', str(self.version)))
         if self.authorize_client:
-            rtn.append(('HiddenServiceAuthorizeClient', self.authorize_client))
+            rtn.append(('HiddenServiceAuthorizeClient', str(self.authorize_client)))
         return rtn
 
 
@@ -783,6 +786,14 @@ class TorConfig(object):
         self.list_parsers = set(['hiddenservices'])
         '''All the names (keys from .parsers) that are a List of something.'''
 
+        # during bootstrapping we decide whether we support the
+        # following features. A thing goes in here if TorConfig
+        # behaves differently depending upon whether it shows up in
+        # "GETINFO config/names"
+        self._supports = dict(
+            HiddenServiceDirGroupReadable=False
+        )
+
         self.post_bootstrap = defer.Deferred()
         if self.protocol:
             if self.protocol.post_bootstrap:
@@ -977,17 +988,9 @@ class TorConfig(object):
             if key == 'HiddenServices':
                 self.config['HiddenServices'] = value
                 for hs in value:
-                    args.append('HiddenServiceDir')
-                    args.append(hs.dir)
-                    for p in hs.ports:
-                        args.append('HiddenServicePort')
-                        args.append(str(p))
-                    if hs.version:
-                        args.append('HiddenServiceVersion')
-                        args.append(str(hs.version))
-                    if hs.authorize_client:
-                        args.append('HiddenServiceAuthorizeClient')
-                        args.append(hs.authorize_client)
+                    for (k, v) in hs.config_attributes():
+                        args.append(k)
+                        args.append(v)
                 continue
 
             if isinstance(value, types.ListType):
@@ -1033,6 +1036,9 @@ class TorConfig(object):
                 continue
 
             (name, value) = line.split()
+            if name in self._supports:
+                self._supports[name] = True
+
             if name == 'HiddenServiceOptions':
                 ## set up the "special-case" hidden service stuff
                 servicelines = yield self.protocol.get_conf_raw(
@@ -1087,11 +1093,12 @@ class TorConfig(object):
             k, v = line.split('=')
             if k == 'HiddenServiceDir':
                 if directory is not None:
-                    hs.append(HiddenService(self, directory, ports, auth, ver))
+                    hs.append(HiddenService(self, directory, ports, auth, ver, group_read))
                 directory = v
                 ports = []
                 ver = None
                 auth = None
+                group_read = 0
 
             elif k == 'HiddenServicePort':
                 ports.append(v)
@@ -1102,11 +1109,14 @@ class TorConfig(object):
             elif k == 'HiddenServiceAuthorizeClient':
                 auth = v
 
+            elif k == 'HiddenServiceDirGroupReadable':
+                group_read = int(v)
+
             else:
                 raise RuntimeError("Can't parse HiddenServiceOptions: " + k)
 
         if directory is not None:
-            hs.append(HiddenService(self, directory, ports, auth, ver))
+            hs.append(HiddenService(self, directory, ports, auth, ver, group_read))
 
         name = 'HiddenServices'
         self.config[name] = _ListWrapper(

-- 
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