|
|
|
|
||||||
| comp.security.ssh SSH secure remote login and tunneling tools. |
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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 |
|
Messages: n/a
Hébergeur: |
H.K. Kingston-Smith <HKK-S@yahoo.com> 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 <anakin@pobox.com> immediately looks around for a coffin." |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Fri, 13 Jul 2007 09:08:10 +0100, Simon Tatham wrote:
> H.K. Kingston-Smith <HKK-S@yahoo.com> 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 |
|
Messages: n/a
Hébergeur: |
H.K. Kingston-Smith <HKK-S@yahoo.com> 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 <anakin@pobox.com> world, a human calls a butterfly." |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Simon Tatham <anakin@pobox.com> 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 <anakin@pobox.com> don't even know who I am." |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On Fri, 13 Jul 2007 16:28:05 +0100, Simon Tatham wrote:
> H.K. Kingston-Smith <HKK-S@yahoo.com> 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 |
|
Messages: n/a
Hébergeur: |
On Fri, 13 Jul 2007 16:42:37 +0100, Simon Tatham wrote:
> Simon Tatham <anakin@pobox.com> 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. |
|
![]() |
| Outils de la discussion | |
|
|