issue #275: parent/ssh: centralize EC0_MARKER and change it for ssh.py.

Must maintain a minimum buffer length prior to deciding whether we have
an interesting token, and 'EC0' is too short for that.
pull/287/head
David Wilson 6 years ago
parent 84fa3ff024
commit d6126a9516

@ -51,7 +51,7 @@ can be recovered by the bootstrapped process later. It then forks into a new
process.
After fork, the parent half overwrites its ``stdin`` with the read end of the
pipe, and the child half writes the string ``EC0\n``, then begins reading the
pipe, and the child half writes the string ``MITOGEN0\n``, then begins reading the
:py:mod:`zlib`-compressed payload supplied on ``stdin`` by the master, and
writing the decompressed result to the write-end of the UNIX pipe.
@ -112,12 +112,17 @@ fetched from the master a second time.
Signalling Success
##################
Once the first stage has signalled ``EC0\n``, the master knows it is ready to
receive the compressed bootstrap. After decompressing and writing the bootstrap
source to its parent Python interpreter, the first stage writes the string
``EC1\n`` to ``stdout`` before exiting. The master process waits for this
string before considering bootstrap successful and the child's ``stdio`` ready
to receive messages.
Once the first stage has signalled ``MITO000\n``, the master knows it is ready
to receive the compressed bootstrap. After decompressing and writing the
bootstrap source to its parent Python interpreter, the first stage writes the
string ``MITO001\n`` to ``stdout`` before exiting. The master process waits for
this string before considering bootstrap successful and the child's ``stdio``
ready to receive messages.
The signal value is 8 bytes to match the minimum chunk size required to
disambiguate between lines containing an interesting token during SSH password
authentication, a debug message from the SSH client itself, or a message from
the first stage.
ExternalContext.main()

@ -790,11 +790,11 @@ class Stream(mitogen.core.Stream):
sys.executable += sys.version[:3]
os.environ['ARGV0']=sys.executable
os.execl(sys.executable,sys.executable+'(mitogen:CONTEXT_NAME)')
os.write(1,'EC0\n')
os.write(1,'MITO000\n')
C=_(os.fdopen(0,'rb').read(PREAMBLE_COMPRESSED_LEN),'zip')
os.fdopen(W,'w',0).write(C)
os.fdopen(w,'w',0).write('PREAMBLE_LEN\n'+C)
os.write(1,'EC1\n')
os.write(1,'MITO001\n')
def get_boot_command(self):
source = inspect.getsource(self._first_stage)
@ -870,13 +870,17 @@ class Stream(mitogen.core.Stream):
self._reap_child()
raise
#: For ssh.py, this must be at least max(len('password'), len('debug1:'))
EC0_MARKER = 'MITO000\n'
EC1_MARKER = 'MITO001\n'
def _ec0_received(self):
LOG.debug('%r._ec0_received()', self)
write_all(self.transmit_side.fd, self.get_preamble())
discard_until(self.receive_side.fd, 'EC1\n', self.connect_deadline)
discard_until(self.receive_side.fd, 'MITO001\n', self.connect_deadline)
def _connect_bootstrap(self, extra_fd):
discard_until(self.receive_side.fd, 'EC0\n', self.connect_deadline)
discard_until(self.receive_side.fd, 'MITO000\n', self.connect_deadline)
self._ec0_received()

@ -68,10 +68,10 @@ def filter_debug(stream, it):
while buf:
if state == 'start_of_line':
if len(buf) < 8:
# short read near the buffer limit, block waiting for at
# least 8 bytes so we can discern either a debug line, or
# the minimum desired interesting token from above
# ('password').
# short read near buffer limit, block awaiting at least 8
# bytes so we can discern a debug line, or the minimum
# interesting token from above or the bootstrap
# ('password', 'MITO000\n').
break
elif buf.startswith(DEBUG_PREFIXES):
state = 'in_debug'
@ -229,7 +229,7 @@ class Stream(mitogen.parent.Stream):
for buf in filter_debug(self, it):
LOG.debug('%r: received %r', self, buf)
if buf.endswith('EC0\n'):
if buf.endswith(self.EC0_MARKER):
self._router.broker.start_receive(self.tty_stream)
self._ec0_received()
return

@ -97,7 +97,7 @@ class Stream(mitogen.parent.Stream):
for buf in it:
LOG.debug('%r: received %r', self, buf)
if buf.endswith('EC0\n'):
if buf.endswith(self.EC0_MARKER):
self._ec0_received()
return
if any(s in buf.lower() for s in self.incorrect_prompts):

@ -168,7 +168,7 @@ class Stream(mitogen.parent.Stream):
for buf in it:
LOG.debug('%r: received %r', self, buf)
if buf.endswith('EC0\n'):
if buf.endswith(self.EC0_MARKER):
self._ec0_received()
return
elif PASSWORD_PROMPT in buf.lower():

Loading…
Cancel
Save