Mercurial > hg
comparison mercurial/help/internals/wireprotocol.txt @ 35976:48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
The existing SSH protocol has several design flaws. Future commits
will elaborate on these flaws as new features are introduced
to combat these flaws. For now, hopefully you can take me for my
word that a ground up rewrite of the SSH protocol is needed.
This commit lays the foundation for a new SSH protocol by defining
a mechanism to upgrade the SSH transport channel away from the
default (version 1) protocol to something modern (which we'll call
"version 2" for now).
This upgrade process is detailed in the internals documentation
for the wire protocol. The gist of it is the client sends a
request line preceding the "hello" command/line which basically
says "I'm requesting an upgrade: here's what I support." If the
server recognizes that line, it processes the upgrade request and
the transport channel is switched to use the new version of the
protocol. If not, it sends an empty response, which is how all
Mercurial SSH servers from the beginning of time reacted to unknown
commands. The upgrade request is effectively ignored and the client
continues to use the existing version of the protocol as if nothing
happened.
The new version of the SSH protocol is completely identical to
version 1 aside from the upgrade dance and the bytes that follow.
The immediate bytes that follow the protocol switch are defined to
be a length framed "capabilities: " line containing the remote's
advertised capabilities. In reality, this looks very similar to
what the "hello" response would look like. But it will evolve
quickly.
The methodology by which the protocol will evolve is important.
I'm not going to introduce the new protocol all at once. That would
likely lead to endless bike shedding and forward progress would
stall. Instead, I intend to tricle out new features and diversions
from the existing protocol in small, incremental changes.
To support the gradual evolution of the protocol, the on-the-wire
advertised protocol name contains an "exp" to denote "experimental"
and a 4 digit field to capture the sub-version of the protocol.
Whenever we make a BC change to the wire protocol, we can increment
this version and lock out all older clients because it will appear
as a completely different protocol version. This means we can incur
as many breaking changes as we want. We don't have to commit to
supporting any one feature or idea for a long period of time. We
can even evolve the handshake mechanism, because that is defined
as being an implementation detail of the negotiated protocol version!
Hopefully this lowers the barrier to accepting changes to the
protocol and for experimenting with "radical" ideas during its
development.
In core, sshpeer received most of the attention. We haven't even
implemented the server bits for the new protocol in core yet.
Instead, we add very primitive support to our test server, mainly
just to exercise the added code paths in sshpeer.
Differential Revision: https://phab.mercurial-scm.org/D2061
# no-check-commit because of required foo_bar naming
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 06 Feb 2018 11:08:36 -0800 |
parents | 40d94ea51402 |
children | fddcb51b5084 |
comparison
equal
deleted
inserted
replaced
35975:40d94ea51402 | 35976:48a3a9283f09 |
---|---|
216 Note that output from the ``hello`` command is terminated by a ``\n``. This is | 216 Note that output from the ``hello`` command is terminated by a ``\n``. This is |
217 part of the response payload and not part of the wire protocol adding a newline | 217 part of the response payload and not part of the wire protocol adding a newline |
218 after responses. In other words, the length of the response contains the | 218 after responses. In other words, the length of the response contains the |
219 trailing ``\n``. | 219 trailing ``\n``. |
220 | 220 |
221 Clients supporting version 2 of the SSH transport send a line beginning | |
222 with ``upgrade`` before the ``hello`` and ``between`` commands. The line | |
223 (which isn't a well-formed command line because it doesn't consist of a | |
224 single command name) serves to both communicate the client's intent to | |
225 switch to transport version 2 (transports are version 1 by default) as | |
226 well as to advertise the client's transport-level capabilities so the | |
227 server may satisfy that request immediately. | |
228 | |
229 The upgrade line has the form: | |
230 | |
231 upgrade <token> <transport capabilities> | |
232 | |
233 That is the literal string ``upgrade`` followed by a space, followed by | |
234 a randomly generated string, followed by a space, followed by a string | |
235 denoting the client's transport capabilities. | |
236 | |
237 The token can be anything. However, a random UUID is recommended. (Use | |
238 of version 4 UUIDs is recommended because version 1 UUIDs can leak the | |
239 client's MAC address.) | |
240 | |
241 The transport capabilities string is a URL/percent encoded string | |
242 containing key-value pairs defining the client's transport-level | |
243 capabilities. The following capabilities are defined: | |
244 | |
245 proto | |
246 A comma-delimited list of transport protocol versions the client | |
247 supports. e.g. ``ssh-v2``. | |
248 | |
249 If the server does not recognize the ``upgrade`` line, it should issue | |
250 an empty response and continue processing the ``hello`` and ``between`` | |
251 commands. Here is an example handshake between a version 2 aware client | |
252 and a non version 2 aware server: | |
253 | |
254 c: upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=ssh-v2 | |
255 c: hello\n | |
256 c: between\n | |
257 c: pairs 81\n | |
258 c: 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000 | |
259 s: 0\n | |
260 s: 324\n | |
261 s: capabilities: lookup changegroupsubset branchmap pushkey known getbundle ...\n | |
262 s: 1\n | |
263 s: \n | |
264 | |
265 (The initial ``0\n`` line from the server indicates an empty response to | |
266 the unknown ``upgrade ..`` command/line.) | |
267 | |
268 If the server recognizes the ``upgrade`` line and is willing to satisfy that | |
269 upgrade request, it replies to with a payload of the following form: | |
270 | |
271 upgraded <token> <transport name>\n | |
272 | |
273 This line is the literal string ``upgraded``, a space, the token that was | |
274 specified by the client in its ``upgrade ...`` request line, a space, and the | |
275 name of the transport protocol that was chosen by the server. The transport | |
276 name MUST match one of the names the client specified in the ``proto`` field | |
277 of its ``upgrade ...`` request line. | |
278 | |
279 If a server issues an ``upgraded`` response, it MUST also read and ignore | |
280 the lines associated with the ``hello`` and ``between`` command requests | |
281 that were issued by the server. It is assumed that the negotiated transport | |
282 will respond with equivalent requested information following the transport | |
283 handshake. | |
284 | |
285 All data following the ``\n`` terminating the ``upgraded`` line is the | |
286 domain of the negotiated transport. It is common for the data immediately | |
287 following to contain additional metadata about the state of the transport and | |
288 the server. However, this isn't strictly speaking part of the transport | |
289 handshake and isn't covered by this section. | |
290 | |
291 Here is an example handshake between a version 2 aware client and a version | |
292 2 aware server: | |
293 | |
294 c: upgrade 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a proto=ssh-v2 | |
295 c: hello\n | |
296 c: between\n | |
297 c: pairs 81\n | |
298 c: 0000000000000000000000000000000000000000-0000000000000000000000000000000000000000 | |
299 s: upgraded 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a ssh-v2\n | |
300 s: <additional transport specific data> | |
301 | |
302 The client-issued token that is echoed in the response provides a more | |
303 resilient mechanism for differentiating *banner* output from Mercurial | |
304 output. In version 1, properly formatted banner output could get confused | |
305 for Mercurial server output. By submitting a randomly generated token | |
306 that is then present in the response, the client can look for that token | |
307 in response lines and have reasonable certainty that the line did not | |
308 originate from a *banner* message. | |
309 | |
221 SSH Version 1 Transport | 310 SSH Version 1 Transport |
222 ----------------------- | 311 ----------------------- |
223 | 312 |
224 The SSH transport (version 1) is a custom text-based protocol suitable for | 313 The SSH transport (version 1) is a custom text-based protocol suitable for |
225 use over any bi-directional stream transport. It is most commonly used with | 314 use over any bi-directional stream transport. It is most commonly used with |
278 | 367 |
279 If the server receives an unknown command, it will send an empty ``string`` | 368 If the server receives an unknown command, it will send an empty ``string`` |
280 response. | 369 response. |
281 | 370 |
282 The server terminates if it receives an empty command (a ``\n`` character). | 371 The server terminates if it receives an empty command (a ``\n`` character). |
372 | |
373 SSH Version 2 Transport | |
374 ----------------------- | |
375 | |
376 **Experimental** | |
377 | |
378 Version 2 of the SSH transport behaves identically to version 1 of the SSH | |
379 transport with the exception of handshake semantics. See above for how | |
380 version 2 of the SSH transport is negotiated. | |
381 | |
382 Immediately following the ``upgraded`` line signaling a switch to version | |
383 2 of the SSH protocol, the server automatically sends additional details | |
384 about the capabilities of the remote server. This has the form: | |
385 | |
386 <integer length of value>\n | |
387 capabilities: ...\n | |
388 | |
389 e.g. | |
390 | |
391 s: upgraded 2e82ab3f-9ce3-4b4e-8f8c-6fd1c0e9e23a ssh-v2\n | |
392 s: 240\n | |
393 s: capabilities: known getbundle batch ...\n | |
394 | |
395 Following capabilities advertisement, the peers communicate using version | |
396 1 of the SSH transport. | |
283 | 397 |
284 Capabilities | 398 Capabilities |
285 ============ | 399 ============ |
286 | 400 |
287 Servers advertise supported wire protocol features. This allows clients to | 401 Servers advertise supported wire protocol features. This allows clients to |