comparison tests/sshprotoext.py @ 36215:464bedc0fdb4

wireprotoserver: handle SSH protocol version 2 upgrade requests This commit teaches the SSH server to recognize the "upgrade" request line that clients send when they wish to switch the channel to version 2 of the SSH protocol. Servers don't honor upgrade requests unless an experimental config option is set. Since the built-in server now supports upgrade requests, our test server to test the handshake has been deleted. Existing tests use the built-in server and their output doesn't change. The upgrade is handled in our state machine. The end result is a bit wonky, as the server transitions back to version 1 state immediately after upgrading. But this will change as soon as version 2 has an actual protocol that differs from version 1. Tests demonstrating that the new server is a bit more strict about the upgrade handshake have been added. Differential Revision: https://phab.mercurial-scm.org/D2204
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 12 Feb 2018 16:33:54 -0800
parents 3b3a987bbbaa
children b4d85bc122bd
comparison
equal deleted inserted replaced
36214:3b3a987bbbaa 36215:464bedc0fdb4
53 rsp = wireproto.dispatch(self._repo, proto, b'between') 53 rsp = wireproto.dispatch(self._repo, proto, b'between')
54 wireprotoserver._sshv1respondbytes(self._fout, rsp.data) 54 wireprotoserver._sshv1respondbytes(self._fout, rsp.data)
55 55
56 super(prehelloserver, self).serve_forever() 56 super(prehelloserver, self).serve_forever()
57 57
58 class upgradev2server(wireprotoserver.sshserver):
59 """Tests behavior for clients that issue upgrade to version 2."""
60 def serve_forever(self):
61 name = wireprotoserver.SSHV2
62 l = self._fin.readline()
63 assert l.startswith(b'upgrade ')
64 token, caps = l[:-1].split(b' ')[1:]
65 assert caps == b'proto=%s' % name
66
67 # Filter hello and between requests.
68 l = self._fin.readline()
69 assert l == b'hello\n'
70 l = self._fin.readline()
71 assert l == b'between\n'
72 l = self._fin.readline()
73 assert l == b'pairs 81\n'
74 self._fin.read(81)
75
76 # Send the upgrade response.
77 proto = wireprotoserver.sshv1protocolhandler(self._ui, self._fin,
78 self._fout)
79 self._fout.write(b'upgraded %s %s\n' % (token, name))
80 servercaps = wireproto.capabilities(self._repo, proto)
81 rsp = b'capabilities: %s' % servercaps.data
82 self._fout.write(b'%d\n' % len(rsp))
83 self._fout.write(rsp)
84 self._fout.write(b'\n')
85 self._fout.flush()
86
87 super(upgradev2server, self).serve_forever()
88
89 def performhandshake(orig, ui, stdin, stdout, stderr): 58 def performhandshake(orig, ui, stdin, stdout, stderr):
90 """Wrapped version of sshpeer._performhandshake to send extra commands.""" 59 """Wrapped version of sshpeer._performhandshake to send extra commands."""
91 mode = ui.config(b'sshpeer', b'handshake-mode') 60 mode = ui.config(b'sshpeer', b'handshake-mode')
92 if mode == b'pre-no-args': 61 if mode == b'pre-no-args':
93 ui.debug(b'sending no-args command\n') 62 ui.debug(b'sending no-args command\n')
116 85
117 if servermode == b'banner': 86 if servermode == b'banner':
118 wireprotoserver.sshserver = bannerserver 87 wireprotoserver.sshserver = bannerserver
119 elif servermode == b'no-hello': 88 elif servermode == b'no-hello':
120 wireprotoserver.sshserver = prehelloserver 89 wireprotoserver.sshserver = prehelloserver
121 elif servermode == b'upgradev2':
122 wireprotoserver.sshserver = upgradev2server
123 elif servermode: 90 elif servermode:
124 raise error.ProgrammingError(b'unknown server mode: %s' % servermode) 91 raise error.ProgrammingError(b'unknown server mode: %s' % servermode)
125 92
126 peermode = ui.config(b'sshpeer', b'mode') 93 peermode = ui.config(b'sshpeer', b'mode')
127 94