Description
Proposal Details
I propose a new ssh.Channel
function to read a single SSH packet.
This is required in to inter-opt with some channel types in use by OpenSSH.
For example to inter-opt with the tun@openssh.com
channel type defined in section 2.3 of the openssh protocol standard:
283: Once established the client and server may exchange packet or frames
284: over the tunnel channel by encapsulating them in SSH protocol strings
285: and sending them as channel data. This ensures that packet boundaries
286: are kept intact. Specifically, packets are transmitted using normal
287: SSH_MSG_CHANNEL_DATA packets:
It is required that you are able to read each individual SSH packet as it defines the length of each Network packet.
Currently the Read(...)
function defined by the ssh.Channel
interface reads all buffered SSH packets.
This requires the implementer of tun@openssh.com
and other similar channel types to attempt to determine SSH packet size (and thus network packet size) from the data that is returned from Read(...)
.
This is error prone and in some cases not feasible.
The following are two snippets to show how this may be implemented.
Example addition to ssh.buffer
:
func (b *buffer) ReadSingle() ([]byte, error) {
sb.Cond.L.Lock()
defer sb.Cond.L.Unlock()
if sb.closed {
return nil, io.EOF
}
if len(sb.head.buf) == 0 && sb.head == sb.tail {
// If we have no messages right now, just wait until we do
sb.Cond.Wait()
if sb.closed {
return nil, io.EOF
}
}
result := make([]byte, len(sb.head.buf))
n := copy(result, sb.head.buf)
sb.head.buf = sb.head.buf[n:]
if sb.head != sb.tail {
sb.head = sb.head.next
}
return result, nil
}
Example addition to ssh.channel
(and thus the ssh.Channel
interface):
func (c *channel) ReadSSHPacket() ([]byte, error) {
buff, err := m.pending.ReadSingle()
if err != nil {
return nil, err
}
if len(buff) > 0 {
err = c.adjustWindow(uint32(len(buff)))
if len(buff) > 0 && err == io.EOF {
err = nil
}
}
return buff, err
}
Additionally, here is a working example of how this must currently be done which uses incredibly brittle reflections.
Metadata
Metadata
Assignees
Type
Projects
Status