send: stall the --verify input() long enough to send the Verifier

Specifically, this lets the `wormhole tx` side send the VERSIONS message
before input() happens, allowing the `wormhole rx` side to compute and
display the Verifier. This only matters when the receiver sends both PAKE and
VERSIONS in the same turn, which only happens when tab-completion allowed
them to learn the Nameplate early and thus receive the sender's PAKE early.
In the other cases, the receiver sends PAKE and VERSIONS on separate turns,
so the sender doesn't get into this situation.

The bug this fixes is when both sides use --verify, and the receiver uses
tab-completion, then the sender shows the Verifier and waits for
confirmation, but the receiver doesn't show the Verifier until *after* the
sender confirms. So the two users don't have enough information to compare.

Many thanks to Jacek Politowski (@jpolnetpl) for the catch and initial
investigation.

closes #349
This commit is contained in:
Brian Warner 2019-08-17 15:24:13 -07:00
parent ab5fe65c3b
commit fd867a9cd6

View File

@ -12,7 +12,7 @@ import six
from humanize import naturalsize
from tqdm import tqdm
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.internet.defer import inlineCallbacks, returnValue, Deferred
from twisted.protocols import basic
from twisted.python import log
from wormhole import __version__, create
@ -160,6 +160,20 @@ class Sender:
notify.cancel()
if args.verify:
# check_verifier() does a blocking call to input(), so stall for
# a moment to let any outbound messages get written into the
# kernel. At this point, we're sitting in a callback of
# get_verifier(), which is triggered by receipt of the other
# side's VERSION message. But we might have gotten both the PAKE
# and the VERSION message in the same turn, and our outbound
# VERSION message (triggered by receipt of their PAKE) is still
# in Twisted's transmit queue. If we don't wait a moment, it will
# be stuck there until `input()` returns, and the receiver won't
# be able to compute a Verifier for the users to compare. #349
# has more details
d = Deferred()
reactor.callLater(0.001, d.callback, None)
yield d
self._check_verifier(w,
verifier_bytes) # blocks, can TransferError