From d4d33202775811ebd2a5be55e5fdded02b091491 Mon Sep 17 00:00:00 2001 From: Chris Wolfe Date: Thu, 2 Jun 2016 14:07:27 -0700 Subject: [PATCH 1/5] add failing test, error --- src/wormhole/errors.py | 6 ++++++ src/wormhole/test/test_wormhole.py | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/wormhole/errors.py b/src/wormhole/errors.py index 08ebae7..2a271c6 100644 --- a/src/wormhole/errors.py +++ b/src/wormhole/errors.py @@ -36,6 +36,12 @@ class WrongPasswordError(Exception): # or the data blob was corrupted, and that's why decrypt failed pass +class KeyFormatError(Exception): + """ + The key you entered contains spaces. Magic-wormhole expects keys to be + separated by dashes. + """ + class ReflectionAttack(Exception): """An attacker (or bug) reflected our outgoing message back to us.""" diff --git a/src/wormhole/test/test_wormhole.py b/src/wormhole/test/test_wormhole.py index ba54123..eae68af 100644 --- a/src/wormhole/test/test_wormhole.py +++ b/src/wormhole/test/test_wormhole.py @@ -7,7 +7,8 @@ from twisted.internet import reactor from twisted.internet.defer import Deferred, gatherResults, inlineCallbacks from .common import ServerBase from .. import wormhole -from ..errors import WrongPasswordError, WelcomeError, UsageError +from ..errors import (WrongPasswordError, WelcomeError, UsageError, + KeyFormatError) from spake2 import SPAKE2_Symmetric from ..timing import DebugTiming from ..util import (bytes_to_dict, dict_to_bytes, @@ -818,6 +819,20 @@ class Wormholes(ServerBase, unittest.TestCase): yield w2.close() self.flushLoggedErrors(WrongPasswordError) + @inlineCallbacks + def test_wrong_password_with_spaces(self): + w1 = wormhole.wormhole(APPID, self.relayurl, reactor) + w2 = wormhole.wormhole(APPID, self.relayurl, reactor) + code = yield w1.get_code() + code_no_dashes = code.replace('-', ' ') + + with self.assertRaises(KeyFormatError): + w2.set_code(code_no_dashes) + + yield w1.close() + yield w2.close() + self.flushLoggedErrors(ValueError) + @inlineCallbacks def test_verifier(self): w1 = wormhole.wormhole(APPID, self.relayurl, reactor) @@ -875,4 +890,3 @@ class Errors(ServerBase, unittest.TestCase): yield self.assertFailure(w.get_code(), UsageError) yield self.assertFailure(w.input_code(), UsageError) yield w.close() - From 5be436b81d796f81134d39fe4b541a623e005cda Mon Sep 17 00:00:00 2001 From: Chris Wolfe Date: Thu, 2 Jun 2016 14:12:54 -0700 Subject: [PATCH 2/5] raise a specific error when spaces are detected, pass along the docstring to the user --- src/wormhole/cli/runner.py | 6 ++++-- src/wormhole/wormhole.py | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/wormhole/cli/runner.py b/src/wormhole/cli/runner.py index ac984c1..a15a50e 100644 --- a/src/wormhole/cli/runner.py +++ b/src/wormhole/cli/runner.py @@ -4,7 +4,8 @@ start = time.time() import os, sys, textwrap from twisted.internet.defer import maybeDeferred from twisted.internet.task import react -from ..errors import TransferError, WrongPasswordError, WelcomeError, Timeout +from ..errors import (TransferError, WrongPasswordError, WelcomeError, Timeout, + KeyFormatError) from ..timing import DebugTiming from .cli_args import parser top_import_finish = time.time() @@ -49,7 +50,8 @@ def run(reactor, argv, cwd, stdout, stderr, executable=None): d.addBoth(_maybe_dump_timing) def _explain_error(f): # these errors don't print a traceback, just an explanation - f.trap(TransferError, WrongPasswordError, WelcomeError, Timeout) + f.trap(TransferError, WrongPasswordError, WelcomeError, Timeout, + KeyFormatError) if f.check(WrongPasswordError): msg = textwrap.fill("ERROR: " + textwrap.dedent(f.value.__doc__)) print(msg, file=stderr) diff --git a/src/wormhole/wormhole.py b/src/wormhole/wormhole.py index fafb966..1607413 100644 --- a/src/wormhole/wormhole.py +++ b/src/wormhole/wormhole.py @@ -15,7 +15,7 @@ from . import __version__ from . import codes #from .errors import ServerError, Timeout from .errors import (WrongPasswordError, UsageError, WelcomeError, - WormholeClosedError) + WormholeClosedError, KeyFormatError) from .timing import DebugTiming from .util import (to_bytes, bytes_to_hexstr, hexstr_to_bytes, dict_to_bytes, bytes_to_dict) @@ -476,6 +476,13 @@ class _Wormhole: def _event_learned_code(self, code): self._timing.add("code established") + # bail out early if the password contains spaces... + # this should raise a useful error + if ' ' in code: + raise KeyFormatError( + "code (%s) contains spaces. Words must be separated by dashes" + % code + ) self._code = code mo = re.search(r'^(\d+)-', code) if not mo: From bc7dea8bab43ff548f809b772dae91c321186580 Mon Sep 17 00:00:00 2001 From: Chris Wolfe Date: Thu, 2 Jun 2016 14:21:29 -0700 Subject: [PATCH 3/5] add simpler exception message, assert that it is being used --- src/wormhole/test/test_wormhole.py | 5 ++++- src/wormhole/wormhole.py | 5 +---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/wormhole/test/test_wormhole.py b/src/wormhole/test/test_wormhole.py index eae68af..68d5679 100644 --- a/src/wormhole/test/test_wormhole.py +++ b/src/wormhole/test/test_wormhole.py @@ -826,9 +826,12 @@ class Wormholes(ServerBase, unittest.TestCase): code = yield w1.get_code() code_no_dashes = code.replace('-', ' ') - with self.assertRaises(KeyFormatError): + with self.assertRaises(KeyFormatError) as ex: w2.set_code(code_no_dashes) + expected_msg = "code (%s) contains spaces." % (code_no_dashes,) + self.assertEqual(expected_msg, str(ex.exception)) + yield w1.close() yield w2.close() self.flushLoggedErrors(ValueError) diff --git a/src/wormhole/wormhole.py b/src/wormhole/wormhole.py index 1607413..7392433 100644 --- a/src/wormhole/wormhole.py +++ b/src/wormhole/wormhole.py @@ -479,10 +479,7 @@ class _Wormhole: # bail out early if the password contains spaces... # this should raise a useful error if ' ' in code: - raise KeyFormatError( - "code (%s) contains spaces. Words must be separated by dashes" - % code - ) + raise KeyFormatError("code (%s) contains spaces." % code) self._code = code mo = re.search(r'^(\d+)-', code) if not mo: From 65713d865203744fc89b062c5f803c06e8b26397 Mon Sep 17 00:00:00 2001 From: Chris Wolfe Date: Thu, 2 Jun 2016 14:27:14 -0700 Subject: [PATCH 4/5] make the error message for the cli a bit more specific --- src/wormhole/cli/runner.py | 3 +++ src/wormhole/errors.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/wormhole/cli/runner.py b/src/wormhole/cli/runner.py index a15a50e..8c373b1 100644 --- a/src/wormhole/cli/runner.py +++ b/src/wormhole/cli/runner.py @@ -60,6 +60,9 @@ def run(reactor, argv, cwd, stdout, stderr, executable=None): print(msg, file=stderr) print(file=stderr) print(str(f.value), file=stderr) + elif f.check(KeyFormatError): + msg = textwrap.fill("ERROR: " + textwrap.dedent(f.value.__doc__)) + print(msg, file=stderr) else: print("ERROR:", f.value, file=stderr) raise SystemExit(1) diff --git a/src/wormhole/errors.py b/src/wormhole/errors.py index 2a271c6..47b9c2e 100644 --- a/src/wormhole/errors.py +++ b/src/wormhole/errors.py @@ -39,7 +39,8 @@ class WrongPasswordError(Exception): class KeyFormatError(Exception): """ The key you entered contains spaces. Magic-wormhole expects keys to be - separated by dashes. + separated by dashes. Please reenter the key you were given separating the + words with dashes. """ class ReflectionAttack(Exception): From 0ad8df375071d31e9d052f7b4fb05547b30e5290 Mon Sep 17 00:00:00 2001 From: Chris Wolfe Date: Thu, 2 Jun 2016 14:27:51 -0700 Subject: [PATCH 5/5] flush the correct error --- src/wormhole/test/test_wormhole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wormhole/test/test_wormhole.py b/src/wormhole/test/test_wormhole.py index 68d5679..795b6b6 100644 --- a/src/wormhole/test/test_wormhole.py +++ b/src/wormhole/test/test_wormhole.py @@ -834,7 +834,7 @@ class Wormholes(ServerBase, unittest.TestCase): yield w1.close() yield w2.close() - self.flushLoggedErrors(ValueError) + self.flushLoggedErrors(KeyFormatError) @inlineCallbacks def test_verifier(self):