[tor-commits] [stem/master] Having create_hidden_service() return the *.onion address

atagar at torproject.org atagar at torproject.org
Sat Dec 20 21:41:07 UTC 2014


commit 260a73ca78a6ffbd6e8b781c3c4558df0f40204e
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Dec 13 16:11:41 2014 -0800

    Having create_hidden_service() return the *.onion address
    
    This isn't reliable since tor restricts the hidden service directory to only be
    readable by the tor user. This sucks, since it's handy to have the hidden
    service address and this is the only way to get it. But oh well, more useful
    than returning a boolean as we did before.
---
 stem/control.py                  |   35 +++++++++++++++++++++++++++++++----
 test/integ/control/controller.py |   18 +++++++++++-------
 2 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/stem/control.py b/stem/control.py
index a90dfcb..77a5e3b 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -2237,6 +2237,10 @@ class Controller(BaseController):
     Create a new hidden service. If the directory is already present, a
     new port is added.
 
+    This method returns our *.onion address by reading the hidden service
+    directory. However, this directory is only readable by the tor user, so if
+    unavailable this method returns None.
+
     .. versionadded:: 1.3.0
 
     :param str path: path for the hidden service's data directory
@@ -2245,8 +2249,8 @@ class Controller(BaseController):
     :param int target_port: port of the service, by default this is the same as
       **port**
 
-    :returns: **True** if the hidden service is created, **False** if the
-      hidden service port is already in use
+    :returns: **str** of the onion address for the hidden service if it can be
+      retrieved, **None** otherwise
 
     :raises: :class:`stem.ControllerError` if the call fails
     """
@@ -2268,14 +2272,37 @@ class Controller(BaseController):
       ports = conf[path]['HiddenServicePort']
 
       if (port, target_address, target_port) in ports:
-        return False
+        return
     else:
       conf[path] = {'HiddenServicePort': []}
 
     conf[path]['HiddenServicePort'].append((port, target_address, target_port))
     self.set_hidden_service_conf(conf)
 
-    return True
+    if self.is_localhost():
+      if not os.path.isabs(path):
+        cwd = stem.util.system.cwd(self.get_pid(None))
+
+        if cwd:
+          path = stem.util.system.expand_path(path, cwd)
+
+      if os.path.isabs(path):
+        start_time = time.time()
+        hostname_path = os.path.join(path, 'hostname')
+
+        while not os.path.exists(hostname_path):
+          wait_time = time.time() - start_time
+
+          if wait_time >= 3:
+            return
+          else:
+            time.sleep(0.05)
+
+        try:
+          with open(hostname_path) as hostname_file:
+            return hostname_file.read().strip()
+        except:
+          pass
 
   def remove_hidden_service(self, path, port = None):
     """
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 386eb8e..8b9759c 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -505,27 +505,31 @@ class TestController(unittest.TestCase):
 
         # add already existing services, with/without explicit target
 
-        self.assertFalse(controller.create_hidden_service('test_hidden_service1/', 8020))
-        self.assertFalse(controller.create_hidden_service('test_hidden_service1/', 8021, target_port = 8021))
+        self.assertEqual(None, controller.create_hidden_service('test_hidden_service1/', 8020))
+        self.assertEqual(None, controller.create_hidden_service('test_hidden_service1/', 8021, target_port = 8021))
         self.assertDictEqual(initialconf, controller.get_hidden_service_conf())
 
         # add a new service, with/without explicit target
 
-        self.assertTrue(controller.create_hidden_service('test_hidden_serviceX/', 8888))
-        self.assertTrue(controller.create_hidden_service('test_hidden_serviceX/', 8989, target_port = 8021))
+        hs_path = os.path.join(os.getcwd(), 'test_hidden_serviceX')
+        hs_address1 = controller.create_hidden_service(hs_path, 8888)
+        hs_address2 = controller.create_hidden_service(hs_path, 8989, target_port = 8021)
+
+        self.assertEqual(hs_address1, hs_address2)
+        self.assertTrue(hs_address1.endswith('.onion'))
 
         conf = controller.get_hidden_service_conf()
         self.assertEqual(4, len(conf))
-        self.assertEqual(2, len(conf['test_hidden_serviceX/']['HiddenServicePort']))
+        self.assertEqual(2, len(conf[hs_path]['HiddenServicePort']))
 
         # remove a hidden service, the service dir should still be there
 
-        controller.remove_hidden_service('test_hidden_serviceX/', 8888)
+        controller.remove_hidden_service(hs_path, 8888)
         self.assertEqual(4, len(controller.get_hidden_service_conf()))
 
         # remove a service completely, it should now be gone
 
-        controller.remove_hidden_service('test_hidden_serviceX/', 8989)
+        controller.remove_hidden_service(hs_path, 8989)
         self.assertEqual(3, len(controller.get_hidden_service_conf()))
       finally:
         controller.set_hidden_service_conf({})  # drop hidden services created during the test





More information about the tor-commits mailing list