Subject: Re: SFTP v6?

From: [email-masked] (Niels Möller)
Date: 01 Nov 2004 10:32:59 +0100

Joseph Galbraith <[email-masked]> writes:

> This is almost the way it works, but not quite.
> 
> V_C = max { version numbers supported by the client }
> V_U = highest version supported by server <= V_C
> 
> (V_S doesn't actually exist on the wire.)

Thanks for the correction. Let's see if I understand what this implies
for interoperability. The failure, for traditional version exchange,
seems to be

  * Client supporting version 3 and 6.
  * Server supporting version 3 and 4.

  =>  V_U = 4  =>  communication failure.

Is this correct?

> So I'll make an alternate proposal:

[...]

> Therefore, I suggest that we change the name of the subsystem
> to 'file-share'
> 
> The 'file-share' protocol supports all versions of the 'sftp'
> protocol, with the minor exception that version exchange
> consists of:
> 
> Server and client both send (without waiting to receive):
> 
> FXP_INIT2
> string version-list
> <extension-data>
> 
> version-list is comma separated string of versions,
> in order of preference.  For example.  "6,2,1"

I agree this is a clean solution, in line with how the rest of the ssh
protocol works. However, let's compare how it will work in practice
during the transition period (next few years), with particular focus
on our failure case: a client supporting versions 3 and 6, and an old
server supporting versions 3 and 4.

  1. Client asks SSH server for subsystem "file-share".

  2. SSH server replies failure.

  3. Client asks for subsystem "sftp".

  4. SSH server replies success, and starts the subsystem.

  5. Client sends V_C = 3 (servers supporting version 6 are supposed
     to support "file-share", so there's no point of asking for
     version 6 at this point).

  6. The sftp server selects V_U = 3.

  7. Handshaking is finished and sftp version 3 is used for the rest
     of the session.

Do I understand your proposal correctly? Now compare this to the
"kludge" that can be used without any changes to the current protocol:

  1. Client asks SSH server for subsystem "sftp"

  2. SSH server replies success, and starts the subsystem.

  3. Client sends V_C = 6.

  4. Server replies V_U = 4.

  5. Client terminates session, since it doesn't support version 4.

  6. Client asks SSH server for subsystem "sftp"

  7. SSH server replies success, and starts the subsystem.

  8. Client sends V_C = 3.

  9. Server replies V_U = 3.

 10. Handshaking is finished and sftp version 3 is used for the rest
     of the session.

In this case (which I think is the most central problematic case which
we're trying to address) I don't see a big win in introducing
"file-share". It makes things only slightly easier for the client, and
slightly more complex for the server.

And when having this choice, I usually prefer putting the complexity
in the client. The reason is that complexity always increases the risk
for bugs, and bugs usually have a much worse security impact in the
server than in the client.

Best regards,
/Niels

---

From: Joseph Galbraith <[email-masked]>
Date: Mon, 01 Nov 2004 09:38:56 -0700

>   =>  V_U = 4  =>  communication failure.

Yes, I believe this is the case.

[...]

> server supporting versions 3 and 4.

[...description omitted for brevitty...]

> 
> Do I understand your proposal correctly?

Yes, I think you do.

 > Now compare this to the

[...description omitted for brevitty...]

I suppose that the kludge isn't that bad.

> server than in the client.

In general I agree, I'd rather have complexity in the client than the
server, however, in this case, I think the additional complexity in
the server is pretty small for 'file-share' and the additional
complexity in the client for 'kludge-mode' is significantly higher
degree than increased complexity for 'file-share'.

In fact, 'kludge-mode' requires the entire channel to go down and
be reopened.  'file-share' experiences a failure to start a subsystem,
and so requests a different one, but shouldn't require the channel
to go down.

Put another way, I have a lower layer (connection) that starts an
upper layer protocol (sftp).  In kludge mode, that upper layer now
has to:

  a. pass back private data to the lower, connection, layer (the server
     sftp version) and a request the connection layer to restart
     the sftp layer with the version as a parameter.

     --or--

  b. Emulate the lower layer itself to start a new channel.

With file-share, this complexity occurs along a more natural border
(at least in my software), because the channel doesn't have to go
down.

In addition, their are several reasons I feel strongly about the
'file-share' proposal.

1. I believe it is the better version negotiation protocol.

2. It works the way you thought it did :-), with client and
    server both announcing their versions to the other.

    As you noted, this is the way many protocols work,
    and I think it is more intuitive.

3. It is familiar to SSH implementors in it's specific
    algorithm (choose first item on client list also on
    servers.)

4. When a version negotiation failure occurs, both sides
    know why, because they both have the same information.

    This leads to better error messages and easier trouble
    shooting for sys admins and tech support.

    In fact, with the current draft, if the server doesn't
    support the clients version at all (v2-4 client, v6
    only server), the server has to close the connection,
    there is no way to communicate to the client why it
    did so.

    Until we had this discussion, I would have assumed, as
    a tech support, admin, or implementor, that the server
    had a bug and crashed, not that there was a version
    problem.

5. It allows extension of the startup protocol on both
    sides, not just the server.

6. For a brand new latest-version-only implementation,
    it reduces complexity.  There is one less packet type, one
    less error condition on each side (the server sent me a client
    init packet, or visa versa.)

    So, it reduces burden on new implementations while only adding
    a little complexity to existing implemenations.

    This is important because one presumes there will be more
    implementations after we get to RFC, that don't want / need
    to be burden with all of our intermediate baggage.

7. It is faster (saves half a round trip.)

    Even in compatibility mode, when the client has to fall back
    to 'sftp', it is only one extra round trip, as compared
    to kludge mode which requires a channel open, subsystem
    request, sftp-init, and sftp-version, and channel close
    (5 round trips) before it can fall back to the version
    that will inter-operate.

    [Note this is least significant to me, but still a property
     of the proposal.]

In other words, outside of the fact that it solves the
version problem we've been discussing, I think it is
just plain a better way to go.

Thanks,

- Joseph

---

From: Joseph Galbraith <[email-masked]>
Date: Mon, 01 Nov 2004 11:18:14 -0700

>   =>  V_U = 4  =>  communication failure.

Let me call out one additional failure-- I mention
it in my other message but I think it is worth
calling out seperately.

It is more a failure to fail gracefully.

* Client supporting versions < n
* Server supporting versions >= n+1

These two can't interoperate, but the server can't
communicate why.

The client sees a channel close as the failure mode,
which could mean many different things.

Today, in fact, a channel close probably means that
the server crashed.

Or had some other fatal startup bug/failure.

Version negotiation failure is probably a small
percentage of such cases.  (Today anyway-- next year
may be different.)

I'd like an unambigous failure when the versions are
incompatible.

Thanks,

- Joseph

---

From: [email-masked] (Niels Möller)
Date: 01 Nov 2004 22:37:58 +0100

> and so requests a different one, but shouldn't require the channel

At least conceptually, ssh channels are farily lightweight. Ok, a
typical implementation with sftp as a separate process will spawn one
process for each channel, which wastes some resources, but I'm not
sure optimal resource usage is important for the backwards compatibility
case.

>   b. Emulate the lower layer itself to start a new channel.

I'm not sure if you're thinking about the server or client now, but as
far as I can see, the interface is clean in both cases.

The sftp client asks the lower layer (ssh connection) for a session
channel, and asks it to start the sftp subsystem. And it sometimes
does that twice. But it's identical both times, no "private data"
involved. Then, the request for a session channel may or may not imply
a new ssh connection, but that's an implementation issue. One case
that I expect to be common when efficiency matters, is to keep an ssh
connection in the background, like the lsh gateway mode, or the
corresponding feature in recent openssh. Then *all* sftp sessions
channels to the same host will reuse an existing connection, no matter
which versions they want to use.

> 1. I believe it is the better version negotiation protocol.

It's more complete than version negotiation in most protocols. Most
protocols seem to work fine without completeness, though.

I think the reason we seem to be getting into trouble is the rapid
increments to the version number, with corresponding changes that
aren't backwards compatible at all. Development of most other internet
protocols (including ssh!) pays more attention to backwards
compatibility, and bumps the protocol version number very rarely.

>     algorithm (choose first item on client list also on

Just some tangential comments: If we go this way, then the "version
numbers" need not be numbers at all, they can be arbitrary names, with
no ordering attached by the protocol. Then an alternative approach
(which I'm not advocating) is to delete version negotiation from the
sftp protocol completely, just have different subsystem names, sftp1,
sftp3, sftp6, .... The client asks for the subsystem type it wants, in
can make multiple requests in any order of its choice.

>     shooting for sys admins and tech support.

I think this is one of the stronger arguments for your proposal.

I tend to be somewhat negative to all general protocol changes (as I'm
sure you've noticed ;-), but I guess I ought to be less conservative
with sftp than with ssh proper.

Regards,
/Niels

---

From: Joseph Galbraith <[email-masked]>
Date: Mon, 01 Nov 2004 15:49:22 -0700

> far as I can see, the interface is clean in both cases.

Client...

> involved. 

But in order for kludge mode to work, the second time
it starts the sftp subsystem, it has to pass down
the server version it got from the first attempt.  (So
that the second time around the client can send the
version that will have the server pick the right version.)

(In our software, it is all one process, but different objects.)

The problem is that kludge mode requires me to either
reset an an object (complex) and give that object a
way to ask the lower layer to restart it's underlying
transport, or to persist some state from the object (the
version from the sftp server) and provide a way to restart.

'file-share', at least for my implementation, works the way
you are describing, because I don't have to get into the
middle of the sftp protocol before finding out it doesn't
work.  The lower layer starts one, and if it doesn't work,
it starts the other.

> compatibility, and bumps the protocol version number very rarely.

On the other hand, it seems like there were several
occasions were we punted on a problem or choose a
sub-optimal solution because we had to maintain
backwards compatibility.

So it does swing both ways.

> no ordering attached by the protocol.

Yes; that had occurred to me.  I'm not sure we'd ever take
advantage of it, but it is possible.

> Then an alternative approach

Yes, this is a very significant point.

I tried to change the version negotiation back when
I first started editing sftp so that the server sent
back it's version (V_S rather than V_U)... which
at least gives the server something valid to send
when version negation fails, but we had to back
it out because of backwards compatibility.

The other argument that is strong to me is that
the new proposal works better than what we have
for someone implementing only the latest version.

I.e., the protocol we go to RFC with will be simpler,
not more complex, because of it.  (Even if clients and
servers doing backwards compatibility do get a little
more complex.)

> with sftp than with ssh proper.

I tend to be quite negative towards protocol changes in SSH proper...
however, sftp hasn't gone to last call yet (for good reason...) and
so isn't in the same semi-frozen state as the SSH proper.

(I hope to get there soon though :-)

Joseph

---

From: [email-masked] (Niels Möller)
Date: 02 Nov 2004 06:46:35 +0100

> version that will have the server pick the right version.)

I'd tend to include the sftp version negotiation in the sftp "layer".
The lower layer, connection, provides a way for the upper layer (sftp)
to open a channel and request a subsystem. But all data transmission
on the channel, including the sftp version exchange, is the upper
layer's (i.e. sftp's) job. The lower layer doesn't know *anything*
about the protocol used on the channel, not even the version used.

From this point of view, I see no problem with the interface.

> it out because of backwards compatibility.

One simple idea: In this failure case, server version 6, client
version 4 (say), is there any good reason the server can't send
version 6 in its SSH_FXP_VERSION, before disconnecting? That would
give the client at least some clue. It could reasonably interprete
this response as "This server doesn't seem to support versions below
6", and tell that to the user.

Regards,
/Niels

---

From: Joseph Galbraith <[email-masked]>
Date: Tue, 02 Nov 2004 09:23:33 -0700

> 6", and tell that to the user.

Yes; unfortunately, it is hard to say waht a version 4 client
would do with that, since it isn't legal in the protocol
v4 protocol... if we'd spec'd it that way for 4 it could
work :-)

We could make the change for v6... and the implementation
would have to decide whether to take the risk that a v4
implemenation would behave better with an invalid version
packet or behave better with a silent channel close.

I think I'd prefer to solve the whole ball of wax at
one go... this is an area where we've been bandaging
the protocol for a while for backwards compatibilities
sake.

I'd like to just bite the bullet and get it over with.

- Joseph

---

From: "denis bider" <[email-masked]>
Date: Tue, 2 Nov 2004 20:24:11 +0100

> I'd like to just bite the bullet and get it over with.

I support that and I'd like to see whatever real solution in place, just not
the kludge. It seems to me like this has already been discussed enough.