commit fbf16826124982add83312969e64ef6460571f2f Author: Damian Johnson atagar@torproject.org Date: Sat Aug 22 15:48:47 2020 -0700
Incorrect filesystem encoding broke latin-1 cookie path
When a PROTOCOLINFO's authentication cookie path mismatches our filesystem encoding falling back to a couple common encodings (unicode and latin-1).
https://github.com/torproject/stem/issues/57 --- docs/change_log.rst | 1 + stem/response/protocolinfo.py | 16 ++++++++++++++-- test/unit/response/protocolinfo.py | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst index 59319e3c..abdbb0c9 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -58,6 +58,7 @@ The following are only available within Stem's `git repository
* Socket based control connections often raised BrokenPipeError when closed * Added :func:`~stem.control.Controller.add_hidden_service_auth`, :func:`~stem.control.Controller.remove_hidden_service_auth`, and :func:`~stem.control.Controller.list_hidden_service_auth` to the :class:`~stem.control.Controller` + * Incorrect filesystem encoding broke latin-1 cookie path (:ticket:`57`)
* **Descriptors**
diff --git a/stem/response/protocolinfo.py b/stem/response/protocolinfo.py index c1387fab..65cb2d8c 100644 --- a/stem/response/protocolinfo.py +++ b/stem/response/protocolinfo.py @@ -108,8 +108,20 @@ class ProtocolInfoResponse(stem.response.ControlMessage): # parse optional COOKIEFILE mapping (quoted and can have escapes)
if line.is_next_mapping('COOKIEFILE', True, True): - self.cookie_path = line._pop_mapping_bytes(True, True)[1].decode(sys.getfilesystemencoding()) - self.cookie_path = stem.util.str_tools._to_unicode(self.cookie_path) # normalize back to str + path = line._pop_mapping_bytes(True, True)[1] + + # re-encode this path from our filesystem's encoding (with common + # fallbacks) to unicode + + for encoding in set([sys.getfilesystemencoding(), 'utf-8', 'latin-1']): + try: + self.cookie_path = stem.util.str_tools._to_unicode(path.decode(encoding)) + break + except ValueError: + pass + + if self.cookie_path is None: + raise stem.ProtocolError("Cookie path '%s' mismatches our filesystem encoding (%s)" % (repr(path), sys.getfilesystemencoding())) elif line_type == 'VERSION': # Line format: # VersionLine = "250-VERSION" SP "Tor=" TorVersion OptArguments CRLF diff --git a/test/unit/response/protocolinfo.py b/test/unit/response/protocolinfo.py index a71746c9..69c54413 100644 --- a/test/unit/response/protocolinfo.py +++ b/test/unit/response/protocolinfo.py @@ -56,6 +56,13 @@ RELATIVE_COOKIE_PATH = r"""250-PROTOCOLINFO 1
EXPECTED_UNICODE_PATH = b"/home/user/\346\226\207\346\241\243/tor-browser_en-US/Browser/TorBrowser/Data/Tor/control_auth_cookie".decode('utf-8')
+LATIN_COOKIE_PATH = r"""250-PROTOCOLINFO 1 +250-AUTH METHODS=COOKIE,SAFECOOKIE COOKIEFILE="c:\Drive-E\Web\Today\ZeroNet-win-dist-win64 \341rv\355zt\373r\365 t\374k\366rf\372r\363g\351p\ZeroNet-win-dist-win64\core\tools\tor\data\control_auth_cookie" +250-VERSION Tor="0.4.2.6" +250 OK""" + +EXPECTED_LATIN_PATH = b"c:\Drive-E\Web\Today\ZeroNet-win-dist-win64 \341rv\355zt\373r\365 t\374k\366rf\372r\363g\351p\ZeroNet-win-dist-win64\core\tools\tor\data\control_auth_cookie".decode('latin-1') +
class TestProtocolInfoResponse(unittest.TestCase): def test_convert(self): @@ -151,3 +158,13 @@ class TestProtocolInfoResponse(unittest.TestCase):
control_message = ControlMessage.from_str(UNICODE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True) self.assertEqual(EXPECTED_UNICODE_PATH, control_message.cookie_path) + + @patch('sys.getfilesystemencoding', Mock(return_value = 'UTF-8')) + def test_latin_cookie_path(self): + """ + Parse a latin-1 path when our filesystem is configured for unicode. + (:ticket:`57`) + """ + + control_message = ControlMessage.from_str(LATIN_COOKIE_PATH, 'PROTOCOLINFO', normalize = True) + self.assertEqual(EXPECTED_LATIN_PATH, control_message.cookie_path)
tor-commits@lists.torproject.org