Still confused about window adjust :-( - SSH

This is a discussion on Still confused about window adjust :-( - SSH ; If I read the standard correctly (RFC 4254, section 5.2) the only data that counts for windowing purposes is the data string in SSH_MSG_CHANNEL_DATA and SSH_MSG_CHANNEL_EXTENDED_DATA packets. However, the packet itself is of course bigger than that, for it includes ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: Still confused about window adjust :-(

  1. Still confused about window adjust :-(

    If I read the standard correctly (RFC 4254, section 5.2) the only
    data that counts for windowing purposes is the data string in
    SSH_MSG_CHANNEL_DATA and SSH_MSG_CHANNEL_EXTENDED_DATA packets. However,
    the packet itself is of course bigger than that, for it includes the
    header (packet length, padding length, packet id and recipient channel
    fields, for SSH_MSG_CHANNEL_DATA packets) plus padding and HMAC.

    So imagine that we have an SSH_MSG_CHANNEL_DATA packet whose
    total length is L, whereas the length of the data string that it carries
    is D, with D < L. Let's assume that the current window size is W, with W
    < D, and that the maximum packet size is P > L.

    What portion of this packet can be sent? Is it the whole of the
    header plus D - W bytes from the data string? Or D - W bytes from the
    start of the packet, including the header? Or something else?

    Or do we have to wait until the other party adjusts the window so
    we can send the whole packet? I would have thought that this is not the
    case, for the networking layer in general will not deliver data to the
    SSH layer as whole SSH packets; the SSH layer will have to be able to
    accumulate incomplete SSH packets anyway, while getting more data from
    the network until it has at least one complete packet.


  2. Re: Still confused about window adjust :-(

    H.K. Kingston-Smith wrote:
    > If I read the standard correctly (RFC 4254, section 5.2) the only
    > data that counts for windowing purposes is the data string in
    > SSH_MSG_CHANNEL_DATA and SSH_MSG_CHANNEL_EXTENDED_DATA packets.


    Yes.

    > So imagine that we have an SSH_MSG_CHANNEL_DATA packet whose total
    > length is L, whereas the length of the data string that it carries
    > is D, with D < L. Let's assume that the current window size is W,
    > with W < D


    If W < D, you should never have constructed a data packet in the
    first place which contained more than W bytes of data.

    > What portion of this packet can be sent?


    You can't send partial packets in an SSH data stream; how would the
    other end work out where a partial packet stopped and some other
    packet started? You must send either a whole packet or no packet at
    all.

    > Or do we have to wait until the other party adjusts the window so
    > we can send the whole packet?


    If you're absolutely determined to send a single packet containing D
    bytes of actual channel data, then you will indeed have to wait
    until the window size has grown to at least D before sending it.

    However, you shouldn't have such a packet in your possession at all.
    The part of your code which takes a stream of incoming data and
    divides it into SSH packets should have known the current window
    size when it constructed that packet, and so it should have
    constructed one containing at most W bytes, which it would then have
    been able to send immediately. The remaining D-W bytes would stay in
    its buffer, unpacketised as yet, until the window size expanded from
    zero and permitted them to be sent.
    --
    Simon Tatham "A cynic is a person who smells flowers and
    immediately looks around for a coffin."

  3. Re: Still confused about window adjust :-(

    On Fri, 13 Jul 2007 09:08:10 +0100, Simon Tatham wrote:

    > H.K. Kingston-Smith wrote:
    >> If I read the standard correctly (RFC 4254, section 5.2) the only data
    >> that counts for windowing purposes is the data string in
    >> SSH_MSG_CHANNEL_DATA and SSH_MSG_CHANNEL_EXTENDED_DATA packets.

    >
    > Yes.
    >
    >> So imagine that we have an SSH_MSG_CHANNEL_DATA packet whose total
    >> length is L, whereas the length of the data string that it carries is
    >> D, with D < L. Let's assume that the current window size is W, with W <
    >> D

    >
    > If W < D, you should never have constructed a data packet in the first
    > place which contained more than W bytes of data.
    >
    >> What portion of this packet can be sent?

    >
    > You can't send partial packets in an SSH data stream; how would the
    > other end work out where a partial packet stopped and some other packet
    > started? You must send either a whole packet or no packet at all.


    Thanks for your answers, which are most informative. However, I
    believe that you are not addressing my two core issues here. Forget about
    partial packets for a moment. Assuming that we have just sent a complete
    SSH_MSG_CHANNEL_DATA packet of total length L, containing a data string
    of length S, S < L, how does the window size change after this? Does it
    decrease by S bytes? By L bytes? Something else?

    About partial packets now. How can the SSH layer be sure that it
    will get at least one complete SSH packet when reading data from the
    network? I still think it can't. First, the network layer might not be
    able to deliver a whole SSH packet if, for instance, this is a very large
    one; several consecutive reads might be necessary. Second, the network
    layer does not know anything about the SSH protocol, and therefore cannot
    accumulate incoming data on that basis. Actually, once the data stream is
    encrypted, the networking layer can't tell what the heck the data
    represents.

    On the other hand, it is easy for the SSH layer to determine
    whether or not data it has received contains a complete SSH packet,
    taking into account the structure of an SSH-2 packet. According to the
    standard (RFC 4253, section 6) SSH-2 packets are structured as follows:

    uint32 packet_length
    byte padding_length
    byte[n1] payload; n1 = packet_length - padding_length - 1
    byte[n2] random padding; n2 = padding_length
    byte[m] mac (Message Authentication Code - MAC); m = mac_length

    Thus, when receiving data the information contained in packet_length and
    padding_length, together with the knowledge of mac_length, and the length
    of the data received, are enough to find out whether or not the data
    received in this read operation constitutes a complete SSH-2 packet.

    Or is there anything wrong with this analysis?

    >
    >> Or do we have to wait until the other party adjusts the window so we
    >> can send the whole packet?

    >
    > If you're absolutely determined to send a single packet containing D
    > bytes of actual channel data, then you will indeed have to wait until
    > the window size has grown to at least D before sending it.
    >
    > However, you shouldn't have such a packet in your possession at all. The
    > part of your code which takes a stream of incoming data and divides it
    > into SSH packets should have known the current window size when it
    > constructed that packet, and so it should have constructed one
    > containing at most W bytes, which it would then have been able to send
    > immediately. The remaining D-W bytes would stay in its buffer,
    > unpacketised as yet, until the window size expanded from zero and
    > permitted them to be sent.


    I agree that that strategy works, and it probably is the best
    one. However, I believe that the one I have outlined is also legal, as
    far as the SSH-2 standards are concerned.

  4. Re: Still confused about window adjust :-(

    H.K. Kingston-Smith wrote:
    > Thanks for your answers, which are most informative. However, I
    > believe that you are not addressing my two core issues here. Forget
    > about partial packets for a moment. Assuming that we have just sent
    > a complete SSH_MSG_CHANNEL_DATA packet of total length L, containing
    > a data string of length S, S < L, how does the window size change
    > after this? Does it decrease by S bytes? By L bytes? Something
    > else?


    Window size is entirely about the actual channel data, not about the
    SSH packets in which it is encapsulated, so it decreases by S bytes.
    (Was this not already obvious from our previous discussions?)

    > About partial packets now. How can the SSH layer be sure that it
    > will get at least one complete SSH packet when reading data from the
    > network?


    Indeed, it may not get a complete packet when doing a single network
    read. So it continues to do network reads until it has managed to
    put together a complete packet, and then it decrypts that packet,
    verifies the MAC, and acts on it.

    The receiving SSH layer doesn't need to look at network read
    boundaries. It works solely on the basis of the stream of _data_
    received. The first 8 bytes received (or more, depending on the
    cipher block size) are decrypted to find the packet length and
    padding values, which determines the total length of the current
    packet. Then the receiver continues to read more data from the
    network, waiting if necessary, until it has that much; it can then
    decrypt the rest of the packet and verify the MAC. Then the next 8
    bytes it receives are decrypted to find the next packet length, and
    so on. So the only criterion is that the entire stream of data sent
    down the SSH connection must be composed of complete packets
    concatenated end-to-end. Anything else will confuse the decoder.

    So if you really wanted to, you _could_ send part of a packet and
    deliberately hold back the rest of it to send later; but if you did
    that, then you would be committed to sending the rest of it before
    you sent _anything else at all_. Also, the receiver wouldn't be able
    to act on the partial packet, because it would be a security hazard
    for it to do so without verifying the MAC. So while it's technically
    _legal_, it's also totally pointless.
    --
    Simon Tatham "What a caterpillar calls the end of the
    world, a human calls a butterfly."

  5. Re: Still confused about window adjust :-(

    Simon Tatham wrote:
    > (Was this not already obvious from our previous discussions?)


    Sorry, my mistake; it was James H. Newman who had previously asked
    this one, not you.
    --
    Simon Tatham "Selfless? I'm so selfless I
    don't even know who I am."

  6. Re: Still confused about window adjust :-(

    On Fri, 13 Jul 2007 16:28:05 +0100, Simon Tatham wrote:

    > H.K. Kingston-Smith wrote:
    >> Thanks for your answers, which are most informative. However, I believe
    >> that you are not addressing my two core issues here. Forget about
    >> partial packets for a moment. Assuming that we have just sent a
    >> complete SSH_MSG_CHANNEL_DATA packet of total length L, containing a
    >> data string of length S, S < L, how does the window size change after
    >> this? Does it decrease by S bytes? By L bytes? Something else?

    >
    > Window size is entirely about the actual channel data, not about the SSH
    > packets in which it is encapsulated, so it decreases by S bytes. (Was
    > this not already obvious from our previous discussions?)


    Let me quote the standard again (RFC 4253, section 5.2):

    Data transfer is done with messages of the following type.

    byte SSH_MSG_CHANNEL_DATA
    uint32 recipient channel
    string data

    The maximum amount of data allowed is determined by the maximum
    packet size for the channel, and the current window size, whichever
    is smaller. The window size is decremented by the amount of data
    sent. Both parties MAY ignore all extra data sent after the allowed
    window is empty.

    The second sentence from the end is, in my view, ambiguous. What does
    "the amount of data sent" mean? The total length of the packet, or the
    length of the data field? I am happy to acknowledge your expertise and
    accept your interpretation - after all, that's what PuTTY must be doing,
    and I know that it works.


    >> About partial packets now. How can the SSH layer be sure that it will
    >> get at least one complete SSH packet when reading data from the
    >> network?

    >
    > Indeed, it may not get a complete packet when doing a single network
    > read. So it continues to do network reads until it has managed to put
    > together a complete packet, and then it decrypts that packet, verifies
    > the MAC, and acts on it.
    >
    > The receiving SSH layer doesn't need to look at network read boundaries.
    > It works solely on the basis of the stream of _data_ received. The first
    > 8 bytes received (or more, depending on the cipher block size) are
    > decrypted to find the packet length and padding values, which determines
    > the total length of the current packet. Then the receiver continues to
    > read more data from the network, waiting if necessary, until it has that
    > much; it can then decrypt the rest of the packet and verify the MAC.
    > Then the next 8 bytes it receives are decrypted to find the next packet
    > length, and so on. So the only criterion is that the entire stream of
    > data sent down the SSH connection must be composed of complete packets
    > concatenated end-to-end. Anything else will confuse the decoder.


    I violently agree.

    > So if you really wanted to, you _could_ send part of a packet and
    > deliberately hold back the rest of it to send later; but if you did
    > that, then you would be committed to sending the rest of it before you
    > sent _anything else at all_.


    Correct.

    > Also, the receiver wouldn't be able to act
    > on the partial packet, because it would be a security hazard for it to
    > do so without verifying the MAC.


    Absolutely. In the general case, it would not be able to anyway,
    for the partial packet would not be likely to end right at the beginning
    of the MAC.

    > So while it's technically _legal_, it's also totally pointless.


    Well, that's an implementation issue, I guess.





  7. Re: Still confused about window adjust :-(

    On Fri, 13 Jul 2007 16:42:37 +0100, Simon Tatham wrote:

    > Simon Tatham wrote:
    >> (Was this not already obvious from our previous discussions?)

    >
    > Sorry, my mistake; it was James H. Newman who had previously asked this
    > one, not you.


    Apologies are not at all necessary.

+ Reply to Thread