Vendor packages and add Makefile
* Vendors packages * Adds a Makefile that uses docker to build a static binary against musl using alpine linux. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
0a17578798
commit
bbbe67bf7c
1763 changed files with 755342 additions and 5 deletions
326
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/attrs.go
generated
vendored
Normal file
326
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/attrs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
package filexfer
|
||||
|
||||
// Attributes related flags.
|
||||
const (
|
||||
AttrSize = 1 << iota // SSH_FILEXFER_ATTR_SIZE
|
||||
AttrUIDGID // SSH_FILEXFER_ATTR_UIDGID
|
||||
AttrPermissions // SSH_FILEXFER_ATTR_PERMISSIONS
|
||||
AttrACModTime // SSH_FILEXFER_ACMODTIME
|
||||
|
||||
AttrExtended = 1 << 31 // SSH_FILEXFER_ATTR_EXTENDED
|
||||
)
|
||||
|
||||
// Attributes defines the file attributes type defined in draft-ietf-secsh-filexfer-02
|
||||
//
|
||||
// Defined in: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5
|
||||
type Attributes struct {
|
||||
Flags uint32
|
||||
|
||||
// AttrSize
|
||||
Size uint64
|
||||
|
||||
// AttrUIDGID
|
||||
UID uint32
|
||||
GID uint32
|
||||
|
||||
// AttrPermissions
|
||||
Permissions FileMode
|
||||
|
||||
// AttrACmodTime
|
||||
ATime uint32
|
||||
MTime uint32
|
||||
|
||||
// AttrExtended
|
||||
ExtendedAttributes []ExtendedAttribute
|
||||
}
|
||||
|
||||
// GetSize returns the Size field and a bool that is true if and only if the value is valid/defined.
|
||||
func (a *Attributes) GetSize() (size uint64, ok bool) {
|
||||
return a.Size, a.Flags&AttrSize != 0
|
||||
}
|
||||
|
||||
// SetSize is a convenience function that sets the Size field,
|
||||
// and marks the field as valid/defined in Flags.
|
||||
func (a *Attributes) SetSize(size uint64) {
|
||||
a.Flags |= AttrSize
|
||||
a.Size = size
|
||||
}
|
||||
|
||||
// GetUIDGID returns the UID and GID fields and a bool that is true if and only if the values are valid/defined.
|
||||
func (a *Attributes) GetUIDGID() (uid, gid uint32, ok bool) {
|
||||
return a.UID, a.GID, a.Flags&AttrUIDGID != 0
|
||||
}
|
||||
|
||||
// SetUIDGID is a convenience function that sets the UID and GID fields,
|
||||
// and marks the fields as valid/defined in Flags.
|
||||
func (a *Attributes) SetUIDGID(uid, gid uint32) {
|
||||
a.Flags |= AttrUIDGID
|
||||
a.UID = uid
|
||||
a.GID = gid
|
||||
}
|
||||
|
||||
// GetPermissions returns the Permissions field and a bool that is true if and only if the value is valid/defined.
|
||||
func (a *Attributes) GetPermissions() (perms FileMode, ok bool) {
|
||||
return a.Permissions, a.Flags&AttrPermissions != 0
|
||||
}
|
||||
|
||||
// SetPermissions is a convenience function that sets the Permissions field,
|
||||
// and marks the field as valid/defined in Flags.
|
||||
func (a *Attributes) SetPermissions(perms FileMode) {
|
||||
a.Flags |= AttrPermissions
|
||||
a.Permissions = perms
|
||||
}
|
||||
|
||||
// GetACModTime returns the ATime and MTime fields and a bool that is true if and only if the values are valid/defined.
|
||||
func (a *Attributes) GetACModTime() (atime, mtime uint32, ok bool) {
|
||||
return a.ATime, a.MTime, a.Flags&AttrACModTime != 0
|
||||
return a.ATime, a.MTime, a.Flags&AttrACModTime != 0
|
||||
}
|
||||
|
||||
// SetACModTime is a convenience function that sets the ATime and MTime fields,
|
||||
// and marks the fields as valid/defined in Flags.
|
||||
func (a *Attributes) SetACModTime(atime, mtime uint32) {
|
||||
a.Flags |= AttrACModTime
|
||||
a.ATime = atime
|
||||
a.MTime = mtime
|
||||
}
|
||||
|
||||
// Len returns the number of bytes a would marshal into.
|
||||
func (a *Attributes) Len() int {
|
||||
length := 4
|
||||
|
||||
if a.Flags&AttrSize != 0 {
|
||||
length += 8
|
||||
}
|
||||
|
||||
if a.Flags&AttrUIDGID != 0 {
|
||||
length += 4 + 4
|
||||
}
|
||||
|
||||
if a.Flags&AttrPermissions != 0 {
|
||||
length += 4
|
||||
}
|
||||
|
||||
if a.Flags&AttrACModTime != 0 {
|
||||
length += 4 + 4
|
||||
}
|
||||
|
||||
if a.Flags&AttrExtended != 0 {
|
||||
length += 4
|
||||
|
||||
for _, ext := range a.ExtendedAttributes {
|
||||
length += ext.Len()
|
||||
}
|
||||
}
|
||||
|
||||
return length
|
||||
}
|
||||
|
||||
// MarshalInto marshals e onto the end of the given Buffer.
|
||||
func (a *Attributes) MarshalInto(b *Buffer) {
|
||||
b.AppendUint32(a.Flags)
|
||||
|
||||
if a.Flags&AttrSize != 0 {
|
||||
b.AppendUint64(a.Size)
|
||||
}
|
||||
|
||||
if a.Flags&AttrUIDGID != 0 {
|
||||
b.AppendUint32(a.UID)
|
||||
b.AppendUint32(a.GID)
|
||||
}
|
||||
|
||||
if a.Flags&AttrPermissions != 0 {
|
||||
b.AppendUint32(uint32(a.Permissions))
|
||||
}
|
||||
|
||||
if a.Flags&AttrACModTime != 0 {
|
||||
b.AppendUint32(a.ATime)
|
||||
b.AppendUint32(a.MTime)
|
||||
}
|
||||
|
||||
if a.Flags&AttrExtended != 0 {
|
||||
b.AppendUint32(uint32(len(a.ExtendedAttributes)))
|
||||
|
||||
for _, ext := range a.ExtendedAttributes {
|
||||
ext.MarshalInto(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalBinary returns a as the binary encoding of a.
|
||||
func (a *Attributes) MarshalBinary() ([]byte, error) {
|
||||
buf := NewBuffer(make([]byte, 0, a.Len()))
|
||||
a.MarshalInto(buf)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalFrom unmarshals an Attributes from the given Buffer into e.
|
||||
//
|
||||
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
||||
func (a *Attributes) UnmarshalFrom(b *Buffer) (err error) {
|
||||
flags, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.XXX_UnmarshalByFlags(flags, b)
|
||||
}
|
||||
|
||||
// XXX_UnmarshalByFlags uses the pre-existing a.Flags field to determine which fields to decode.
|
||||
// DO NOT USE THIS: it is an anti-corruption function to implement existing internal usage in pkg/sftp.
|
||||
// This function is not a part of any compatibility promise.
|
||||
func (a *Attributes) XXX_UnmarshalByFlags(flags uint32, b *Buffer) (err error) {
|
||||
a.Flags = flags
|
||||
|
||||
// Short-circuit dummy attributes.
|
||||
if a.Flags == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if a.Flags&AttrSize != 0 {
|
||||
if a.Size, err = b.ConsumeUint64(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if a.Flags&AttrUIDGID != 0 {
|
||||
if a.UID, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.GID, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if a.Flags&AttrPermissions != 0 {
|
||||
m, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Permissions = FileMode(m)
|
||||
}
|
||||
|
||||
if a.Flags&AttrACModTime != 0 {
|
||||
if a.ATime, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.MTime, err = b.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if a.Flags&AttrExtended != 0 {
|
||||
count, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.ExtendedAttributes = make([]ExtendedAttribute, count)
|
||||
for i := range a.ExtendedAttributes {
|
||||
a.ExtendedAttributes[i].UnmarshalFrom(b)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes the binary encoding of Attributes into e.
|
||||
func (a *Attributes) UnmarshalBinary(data []byte) error {
|
||||
return a.UnmarshalFrom(NewBuffer(data))
|
||||
}
|
||||
|
||||
// ExtendedAttribute defines the extended file attribute type defined in draft-ietf-secsh-filexfer-02
|
||||
//
|
||||
// Defined in: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5
|
||||
type ExtendedAttribute struct {
|
||||
Type string
|
||||
Data string
|
||||
}
|
||||
|
||||
// Len returns the number of bytes e would marshal into.
|
||||
func (e *ExtendedAttribute) Len() int {
|
||||
return 4 + len(e.Type) + 4 + len(e.Data)
|
||||
}
|
||||
|
||||
// MarshalInto marshals e onto the end of the given Buffer.
|
||||
func (e *ExtendedAttribute) MarshalInto(b *Buffer) {
|
||||
b.AppendString(e.Type)
|
||||
b.AppendString(e.Data)
|
||||
}
|
||||
|
||||
// MarshalBinary returns e as the binary encoding of e.
|
||||
func (e *ExtendedAttribute) MarshalBinary() ([]byte, error) {
|
||||
buf := NewBuffer(make([]byte, 0, e.Len()))
|
||||
e.MarshalInto(buf)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalFrom unmarshals an ExtendedAattribute from the given Buffer into e.
|
||||
func (e *ExtendedAttribute) UnmarshalFrom(b *Buffer) (err error) {
|
||||
if e.Type, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Data, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes the binary encoding of ExtendedAttribute into e.
|
||||
func (e *ExtendedAttribute) UnmarshalBinary(data []byte) error {
|
||||
return e.UnmarshalFrom(NewBuffer(data))
|
||||
}
|
||||
|
||||
// NameEntry implements the SSH_FXP_NAME repeated data type from draft-ietf-secsh-filexfer-02
|
||||
//
|
||||
// This type is incompatible with versions 4 or higher.
|
||||
type NameEntry struct {
|
||||
Filename string
|
||||
Longname string
|
||||
Attrs Attributes
|
||||
}
|
||||
|
||||
// Len returns the number of bytes e would marshal into.
|
||||
func (e *NameEntry) Len() int {
|
||||
return 4 + len(e.Filename) + 4 + len(e.Longname) + e.Attrs.Len()
|
||||
}
|
||||
|
||||
// MarshalInto marshals e onto the end of the given Buffer.
|
||||
func (e *NameEntry) MarshalInto(b *Buffer) {
|
||||
b.AppendString(e.Filename)
|
||||
b.AppendString(e.Longname)
|
||||
|
||||
e.Attrs.MarshalInto(b)
|
||||
}
|
||||
|
||||
// MarshalBinary returns e as the binary encoding of e.
|
||||
func (e *NameEntry) MarshalBinary() ([]byte, error) {
|
||||
buf := NewBuffer(make([]byte, 0, e.Len()))
|
||||
e.MarshalInto(buf)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalFrom unmarshals an NameEntry from the given Buffer into e.
|
||||
//
|
||||
// NOTE: The values of fields not covered in the a.Flags are explicitly undefined.
|
||||
func (e *NameEntry) UnmarshalFrom(b *Buffer) (err error) {
|
||||
if e.Filename, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Longname, err = b.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.Attrs.UnmarshalFrom(b)
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes the binary encoding of NameEntry into e.
|
||||
func (e *NameEntry) UnmarshalBinary(data []byte) error {
|
||||
return e.UnmarshalFrom(NewBuffer(data))
|
||||
}
|
||||
293
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/buffer.go
generated
vendored
Normal file
293
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/buffer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
package filexfer
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Various encoding errors.
|
||||
var (
|
||||
ErrShortPacket = errors.New("packet too short")
|
||||
ErrLongPacket = errors.New("packet too long")
|
||||
)
|
||||
|
||||
// Buffer wraps up the various encoding details of the SSH format.
|
||||
//
|
||||
// Data types are encoded as per section 4 from https://tools.ietf.org/html/draft-ietf-secsh-architecture-09#page-8
|
||||
type Buffer struct {
|
||||
b []byte
|
||||
off int
|
||||
}
|
||||
|
||||
// NewBuffer creates and initializes a new buffer using buf as its initial contents.
|
||||
// The new buffer takes ownership of buf, and the caller should not use buf after this call.
|
||||
//
|
||||
// In most cases, new(Buffer) (or just declaring a Buffer variable) is sufficient to initialize a Buffer.
|
||||
func NewBuffer(buf []byte) *Buffer {
|
||||
return &Buffer{
|
||||
b: buf,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMarshalBuffer creates a new Buffer ready to start marshaling a Packet into.
|
||||
// It preallocates enough space for uint32(length), uint8(type), uint32(request-id) and size more bytes.
|
||||
func NewMarshalBuffer(size int) *Buffer {
|
||||
return NewBuffer(make([]byte, 4+1+4+size))
|
||||
}
|
||||
|
||||
// Bytes returns a slice of length b.Len() holding the unconsumed bytes in the Buffer.
|
||||
// The slice is valid for use only until the next buffer modification
|
||||
// (that is, only until the next call to an Append or Consume method).
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
return b.b[b.off:]
|
||||
}
|
||||
|
||||
// Len returns the number of unconsumed bytes in the buffer.
|
||||
func (b *Buffer) Len() int { return len(b.b) - b.off }
|
||||
|
||||
// Cap returns the capacity of the buffer’s underlying byte slice,
|
||||
// that is, the total space allocated for the buffer’s data.
|
||||
func (b *Buffer) Cap() int { return cap(b.b) }
|
||||
|
||||
// Reset resets the buffer to be empty, but it retains the underlying storage for use by future Appends.
|
||||
func (b *Buffer) Reset() {
|
||||
b.b = b.b[:0]
|
||||
b.off = 0
|
||||
}
|
||||
|
||||
// StartPacket resets and initializes the buffer to be ready to start marshaling a packet into.
|
||||
// It truncates the buffer, reserves space for uint32(length), then appends the given packetType and requestID.
|
||||
func (b *Buffer) StartPacket(packetType PacketType, requestID uint32) {
|
||||
b.b, b.off = append(b.b[:0], make([]byte, 4)...), 0
|
||||
|
||||
b.AppendUint8(uint8(packetType))
|
||||
b.AppendUint32(requestID)
|
||||
}
|
||||
|
||||
// Packet finalizes the packet started from StartPacket.
|
||||
// It is expected that this will end the ownership of the underlying byte-slice,
|
||||
// and so the returned byte-slices may be reused the same as any other byte-slice,
|
||||
// the caller should not use this buffer after this call.
|
||||
//
|
||||
// It writes the packet body length into the first four bytes of the buffer in network byte order (big endian).
|
||||
// The packet body length is the length of this buffer less the 4-byte length itself, plus the length of payload.
|
||||
//
|
||||
// It is assumed that no Consume methods have been called on this buffer,
|
||||
// and so it returns the whole underlying slice.
|
||||
func (b *Buffer) Packet(payload []byte) (header, payloadPassThru []byte, err error) {
|
||||
b.PutLength(len(b.b) - 4 + len(payload))
|
||||
|
||||
return b.b, payload, nil
|
||||
}
|
||||
|
||||
// ConsumeUint8 consumes a single byte from the buffer.
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint8() (uint8, error) {
|
||||
if b.Len() < 1 {
|
||||
return 0, ErrShortPacket
|
||||
}
|
||||
|
||||
var v uint8
|
||||
v, b.off = b.b[b.off], b.off+1
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AppendUint8 appends a single byte into the buffer.
|
||||
func (b *Buffer) AppendUint8(v uint8) {
|
||||
b.b = append(b.b, v)
|
||||
}
|
||||
|
||||
// ConsumeBool consumes a single byte from the buffer, and returns true if that byte is non-zero.
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeBool() (bool, error) {
|
||||
v, err := b.ConsumeUint8()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return v != 0, nil
|
||||
}
|
||||
|
||||
// AppendBool appends a single bool into the buffer.
|
||||
// It encodes it as a single byte, with false as 0, and true as 1.
|
||||
func (b *Buffer) AppendBool(v bool) {
|
||||
if v {
|
||||
b.AppendUint8(1)
|
||||
} else {
|
||||
b.AppendUint8(0)
|
||||
}
|
||||
}
|
||||
|
||||
// ConsumeUint16 consumes a single uint16 from the buffer, in network byte order (big-endian).
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint16() (uint16, error) {
|
||||
if b.Len() < 2 {
|
||||
return 0, ErrShortPacket
|
||||
}
|
||||
|
||||
v := binary.BigEndian.Uint16(b.b[b.off:])
|
||||
b.off += 2
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AppendUint16 appends single uint16 into the buffer, in network byte order (big-endian).
|
||||
func (b *Buffer) AppendUint16(v uint16) {
|
||||
b.b = append(b.b,
|
||||
byte(v>>8),
|
||||
byte(v>>0),
|
||||
)
|
||||
}
|
||||
|
||||
// unmarshalUint32 is used internally to read the packet length.
|
||||
// It is unsafe, and so not exported.
|
||||
// Even within this package, its use should be avoided.
|
||||
func unmarshalUint32(b []byte) uint32 {
|
||||
return binary.BigEndian.Uint32(b[:4])
|
||||
}
|
||||
|
||||
// ConsumeUint32 consumes a single uint32 from the buffer, in network byte order (big-endian).
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint32() (uint32, error) {
|
||||
if b.Len() < 4 {
|
||||
return 0, ErrShortPacket
|
||||
}
|
||||
|
||||
v := binary.BigEndian.Uint32(b.b[b.off:])
|
||||
b.off += 4
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AppendUint32 appends a single uint32 into the buffer, in network byte order (big-endian).
|
||||
func (b *Buffer) AppendUint32(v uint32) {
|
||||
b.b = append(b.b,
|
||||
byte(v>>24),
|
||||
byte(v>>16),
|
||||
byte(v>>8),
|
||||
byte(v>>0),
|
||||
)
|
||||
}
|
||||
|
||||
// ConsumeUint64 consumes a single uint64 from the buffer, in network byte order (big-endian).
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeUint64() (uint64, error) {
|
||||
if b.Len() < 8 {
|
||||
return 0, ErrShortPacket
|
||||
}
|
||||
|
||||
v := binary.BigEndian.Uint64(b.b[b.off:])
|
||||
b.off += 8
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AppendUint64 appends a single uint64 into the buffer, in network byte order (big-endian).
|
||||
func (b *Buffer) AppendUint64(v uint64) {
|
||||
b.b = append(b.b,
|
||||
byte(v>>56),
|
||||
byte(v>>48),
|
||||
byte(v>>40),
|
||||
byte(v>>32),
|
||||
byte(v>>24),
|
||||
byte(v>>16),
|
||||
byte(v>>8),
|
||||
byte(v>>0),
|
||||
)
|
||||
}
|
||||
|
||||
// ConsumeInt64 consumes a single int64 from the buffer, in network byte order (big-endian) with two’s complement.
|
||||
// If the buffer does not have enough data, it will return ErrShortPacket.
|
||||
func (b *Buffer) ConsumeInt64() (int64, error) {
|
||||
u, err := b.ConsumeUint64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int64(u), err
|
||||
}
|
||||
|
||||
// AppendInt64 appends a single int64 into the buffer, in network byte order (big-endian) with two’s complement.
|
||||
func (b *Buffer) AppendInt64(v int64) {
|
||||
b.AppendUint64(uint64(v))
|
||||
}
|
||||
|
||||
// ConsumeByteSlice consumes a single string of raw binary data from the buffer.
|
||||
// A string is a uint32 length, followed by that number of raw bytes.
|
||||
// If the buffer does not have enough data, or defines a length larger than available, it will return ErrShortPacket.
|
||||
//
|
||||
// The returned slice aliases the buffer contents, and is valid only as long as the buffer is not reused
|
||||
// (that is, only until the next call to Reset, PutLength, StartPacket, or UnmarshalBinary).
|
||||
//
|
||||
// In no case will any Consume calls return overlapping slice aliases,
|
||||
// and Append calls are guaranteed to not disturb this slice alias.
|
||||
func (b *Buffer) ConsumeByteSlice() ([]byte, error) {
|
||||
length, err := b.ConsumeUint32()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if b.Len() < int(length) {
|
||||
return nil, ErrShortPacket
|
||||
}
|
||||
|
||||
v := b.b[b.off:]
|
||||
if len(v) > int(length) {
|
||||
v = v[:length:length]
|
||||
}
|
||||
b.off += int(length)
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// AppendByteSlice appends a single string of raw binary data into the buffer.
|
||||
// A string is a uint32 length, followed by that number of raw bytes.
|
||||
func (b *Buffer) AppendByteSlice(v []byte) {
|
||||
b.AppendUint32(uint32(len(v)))
|
||||
b.b = append(b.b, v...)
|
||||
}
|
||||
|
||||
// ConsumeString consumes a single string of binary data from the buffer.
|
||||
// A string is a uint32 length, followed by that number of raw bytes.
|
||||
// If the buffer does not have enough data, or defines a length larger than available, it will return ErrShortPacket.
|
||||
//
|
||||
// NOTE: Go implicitly assumes that strings contain UTF-8 encoded data.
|
||||
// All caveats on using arbitrary binary data in Go strings applies.
|
||||
func (b *Buffer) ConsumeString() (string, error) {
|
||||
v, err := b.ConsumeByteSlice()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(v), nil
|
||||
}
|
||||
|
||||
// AppendString appends a single string of binary data into the buffer.
|
||||
// A string is a uint32 length, followed by that number of raw bytes.
|
||||
func (b *Buffer) AppendString(v string) {
|
||||
b.AppendByteSlice([]byte(v))
|
||||
}
|
||||
|
||||
// PutLength writes the given size into the first four bytes of the buffer in network byte order (big endian).
|
||||
func (b *Buffer) PutLength(size int) {
|
||||
if len(b.b) < 4 {
|
||||
b.b = append(b.b, make([]byte, 4-len(b.b))...)
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint32(b.b, uint32(size))
|
||||
}
|
||||
|
||||
// MarshalBinary returns a clone of the full internal buffer.
|
||||
func (b *Buffer) MarshalBinary() ([]byte, error) {
|
||||
clone := make([]byte, len(b.b))
|
||||
n := copy(clone, b.b)
|
||||
return clone[:n], nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary sets the internal buffer of b to be a clone of data, and zeros the internal offset.
|
||||
func (b *Buffer) UnmarshalBinary(data []byte) error {
|
||||
if grow := len(data) - len(b.b); grow > 0 {
|
||||
b.b = append(b.b, make([]byte, grow)...)
|
||||
}
|
||||
|
||||
n := copy(b.b, data)
|
||||
b.b = b.b[:n]
|
||||
b.off = 0
|
||||
return nil
|
||||
}
|
||||
142
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extended_packets.go
generated
vendored
Normal file
142
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extended_packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
package filexfer
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ExtendedData aliases the untyped interface composition of encoding.BinaryMarshaler and encoding.BinaryUnmarshaler.
|
||||
type ExtendedData = interface {
|
||||
encoding.BinaryMarshaler
|
||||
encoding.BinaryUnmarshaler
|
||||
}
|
||||
|
||||
// ExtendedDataConstructor defines a function that returns a new(ArbitraryExtendedPacket).
|
||||
type ExtendedDataConstructor func() ExtendedData
|
||||
|
||||
var extendedPacketTypes = struct {
|
||||
mu sync.RWMutex
|
||||
constructors map[string]ExtendedDataConstructor
|
||||
}{
|
||||
constructors: make(map[string]ExtendedDataConstructor),
|
||||
}
|
||||
|
||||
// RegisterExtendedPacketType defines a specific ExtendedDataConstructor for the given extension string.
|
||||
func RegisterExtendedPacketType(extension string, constructor ExtendedDataConstructor) {
|
||||
extendedPacketTypes.mu.Lock()
|
||||
defer extendedPacketTypes.mu.Unlock()
|
||||
|
||||
if _, exist := extendedPacketTypes.constructors[extension]; exist {
|
||||
panic("encoding/ssh/filexfer: multiple registration of extended packet type " + extension)
|
||||
}
|
||||
|
||||
extendedPacketTypes.constructors[extension] = constructor
|
||||
}
|
||||
|
||||
func newExtendedPacket(extension string) ExtendedData {
|
||||
extendedPacketTypes.mu.RLock()
|
||||
defer extendedPacketTypes.mu.RUnlock()
|
||||
|
||||
if f := extendedPacketTypes.constructors[extension]; f != nil {
|
||||
return f()
|
||||
}
|
||||
|
||||
return new(Buffer)
|
||||
}
|
||||
|
||||
// ExtendedPacket defines the SSH_FXP_CLOSE packet.
|
||||
type ExtendedPacket struct {
|
||||
ExtendedRequest string
|
||||
|
||||
Data ExtendedData
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *ExtendedPacket) Type() PacketType {
|
||||
return PacketTypeExtended
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
//
|
||||
// The Data is marshaled into binary, and returned as the payload.
|
||||
func (p *ExtendedPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.ExtendedRequest) // string(extended-request)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeExtended, reqid)
|
||||
buf.AppendString(p.ExtendedRequest)
|
||||
|
||||
if p.Data != nil {
|
||||
payload, err = p.Data.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
//
|
||||
// If p.Data is nil, and the extension has been registered, a new type will be made from the registration.
|
||||
// If the extension has not been registered, then a new Buffer will be allocated.
|
||||
// Then the request-specific-data will be unmarshaled from the rest of the buffer.
|
||||
func (p *ExtendedPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.ExtendedRequest, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Data == nil {
|
||||
p.Data = newExtendedPacket(p.ExtendedRequest)
|
||||
}
|
||||
|
||||
return p.Data.UnmarshalBinary(buf.Bytes())
|
||||
}
|
||||
|
||||
// ExtendedReplyPacket defines the SSH_FXP_CLOSE packet.
|
||||
type ExtendedReplyPacket struct {
|
||||
Data ExtendedData
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *ExtendedReplyPacket) Type() PacketType {
|
||||
return PacketTypeExtendedReply
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
//
|
||||
// The Data is marshaled into binary, and returned as the payload.
|
||||
func (p *ExtendedReplyPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
buf = NewMarshalBuffer(0)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeExtendedReply, reqid)
|
||||
|
||||
if p.Data != nil {
|
||||
payload, err = p.Data.MarshalBinary()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
//
|
||||
// If p.Data is nil, and there is request-specific-data,
|
||||
// then the request-specific-data will be wrapped in a Buffer and assigned to p.Data.
|
||||
func (p *ExtendedReplyPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Data == nil {
|
||||
p.Data = new(Buffer)
|
||||
}
|
||||
|
||||
return p.Data.UnmarshalBinary(buf.Bytes())
|
||||
}
|
||||
46
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extensions.go
generated
vendored
Normal file
46
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/extensions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package filexfer
|
||||
|
||||
// ExtensionPair defines the extension-pair type defined in draft-ietf-secsh-filexfer-13.
|
||||
// This type is backwards-compatible with how draft-ietf-secsh-filexfer-02 defines extensions.
|
||||
//
|
||||
// Defined in: https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-4.2
|
||||
type ExtensionPair struct {
|
||||
Name string
|
||||
Data string
|
||||
}
|
||||
|
||||
// Len returns the number of bytes e would marshal into.
|
||||
func (e *ExtensionPair) Len() int {
|
||||
return 4 + len(e.Name) + 4 + len(e.Data)
|
||||
}
|
||||
|
||||
// MarshalInto marshals e onto the end of the given Buffer.
|
||||
func (e *ExtensionPair) MarshalInto(buf *Buffer) {
|
||||
buf.AppendString(e.Name)
|
||||
buf.AppendString(e.Data)
|
||||
}
|
||||
|
||||
// MarshalBinary returns e as the binary encoding of e.
|
||||
func (e *ExtensionPair) MarshalBinary() ([]byte, error) {
|
||||
buf := NewBuffer(make([]byte, 0, e.Len()))
|
||||
e.MarshalInto(buf)
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalFrom unmarshals an ExtensionPair from the given Buffer into e.
|
||||
func (e *ExtensionPair) UnmarshalFrom(buf *Buffer) (err error) {
|
||||
if e.Name, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Data, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes the binary encoding of ExtensionPair into e.
|
||||
func (e *ExtensionPair) UnmarshalBinary(data []byte) error {
|
||||
return e.UnmarshalFrom(NewBuffer(data))
|
||||
}
|
||||
54
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/filexfer.go
generated
vendored
Normal file
54
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/filexfer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// Package filexfer implements the wire encoding for secsh-filexfer as described in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02
|
||||
package filexfer
|
||||
|
||||
// PacketMarshaller narrowly defines packets that will only be transmitted.
|
||||
//
|
||||
// ExtendedPacket types will often only implement this interface,
|
||||
// since decoding the whole packet body of an ExtendedPacket can only be done dependent on the ExtendedRequest field.
|
||||
type PacketMarshaller interface {
|
||||
// MarshalPacket is the primary intended way to encode a packet.
|
||||
// The request-id for the packet is set from reqid.
|
||||
//
|
||||
// An optional buffer may be given in b.
|
||||
// If the buffer has a minimum capacity, it shall be truncated and used to marshal the header into.
|
||||
// The minimum capacity for the packet must be a constant expression, and should be at least 9.
|
||||
//
|
||||
// It shall return the main body of the encoded packet in header,
|
||||
// and may optionally return an additional payload to be written immediately after the header.
|
||||
//
|
||||
// It shall encode in the first 4-bytes of the header the proper length of the rest of the header+payload.
|
||||
MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error)
|
||||
}
|
||||
|
||||
// Packet defines the behavior of a full generic SFTP packet.
|
||||
//
|
||||
// InitPacket, and VersionPacket are not generic SFTP packets, and instead implement (Un)MarshalBinary.
|
||||
//
|
||||
// ExtendedPacket types should not iplement this interface,
|
||||
// since decoding the whole packet body of an ExtendedPacket can only be done dependent on the ExtendedRequest field.
|
||||
type Packet interface {
|
||||
PacketMarshaller
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with the specific packet.
|
||||
Type() PacketType
|
||||
|
||||
// UnmarshalPacketBody decodes a packet body from the given Buffer.
|
||||
// It is assumed that the common header values of the length, type and request-id have already been consumed.
|
||||
//
|
||||
// Implementations should not alias the given Buffer,
|
||||
// instead they can consider prepopulating an internal buffer as a hint,
|
||||
// and copying into that buffer if it has sufficient length.
|
||||
UnmarshalPacketBody(buf *Buffer) error
|
||||
}
|
||||
|
||||
// ComposePacket converts returns from MarshalPacket into an equivalent call to MarshalBinary.
|
||||
func ComposePacket(header, payload []byte, err error) ([]byte, error) {
|
||||
return append(header, payload...), err
|
||||
}
|
||||
|
||||
// Default length values,
|
||||
// Defined in draft-ietf-secsh-filexfer-02 section 3.
|
||||
const (
|
||||
DefaultMaxPacketLength = 34000
|
||||
DefaultMaxDataLength = 32768
|
||||
)
|
||||
147
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fx.go
generated
vendored
Normal file
147
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fx.go
generated
vendored
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
package filexfer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Status defines the SFTP error codes used in SSH_FXP_STATUS response packets.
|
||||
type Status uint32
|
||||
|
||||
// Defines the various SSH_FX_* values.
|
||||
const (
|
||||
// see draft-ietf-secsh-filexfer-02
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7
|
||||
StatusOK = Status(iota)
|
||||
StatusEOF
|
||||
StatusNoSuchFile
|
||||
StatusPermissionDenied
|
||||
StatusFailure
|
||||
StatusBadMessage
|
||||
StatusNoConnection
|
||||
StatusConnectionLost
|
||||
StatusOPUnsupported
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-03#section-7
|
||||
StatusV4InvalidHandle
|
||||
StatusV4NoSuchPath
|
||||
StatusV4FileAlreadyExists
|
||||
StatusV4WriteProtect
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-7
|
||||
StatusV4NoMedia
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-7
|
||||
StatusV5NoSpaceOnFilesystem
|
||||
StatusV5QuotaExceeded
|
||||
StatusV5UnknownPrincipal
|
||||
StatusV5LockConflict
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-06#section-8
|
||||
StatusV6DirNotEmpty
|
||||
StatusV6NotADirectory
|
||||
StatusV6InvalidFilename
|
||||
StatusV6LinkLoop
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-07#section-8
|
||||
StatusV6CannotDelete
|
||||
StatusV6InvalidParameter
|
||||
StatusV6FileIsADirectory
|
||||
StatusV6ByteRangeLockConflict
|
||||
StatusV6ByteRangeLockRefused
|
||||
StatusV6DeletePending
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-08#section-8.1
|
||||
StatusV6FileCorrupt
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-10#section-9.1
|
||||
StatusV6OwnerInvalid
|
||||
StatusV6GroupInvalid
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.1
|
||||
StatusV6NoMatchingByteRangeLock
|
||||
)
|
||||
|
||||
func (s Status) Error() string {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
// Is returns true if the target is the same Status code,
|
||||
// or target is a StatusPacket with the same Status code.
|
||||
func (s Status) Is(target error) bool {
|
||||
if target, ok := target.(*StatusPacket); ok {
|
||||
return target.StatusCode == s
|
||||
}
|
||||
|
||||
return s == target
|
||||
}
|
||||
|
||||
func (s Status) String() string {
|
||||
switch s {
|
||||
case StatusOK:
|
||||
return "SSH_FX_OK"
|
||||
case StatusEOF:
|
||||
return "SSH_FX_EOF"
|
||||
case StatusNoSuchFile:
|
||||
return "SSH_FX_NO_SUCH_FILE"
|
||||
case StatusPermissionDenied:
|
||||
return "SSH_FX_PERMISSION_DENIED"
|
||||
case StatusFailure:
|
||||
return "SSH_FX_FAILURE"
|
||||
case StatusBadMessage:
|
||||
return "SSH_FX_BAD_MESSAGE"
|
||||
case StatusNoConnection:
|
||||
return "SSH_FX_NO_CONNECTION"
|
||||
case StatusConnectionLost:
|
||||
return "SSH_FX_CONNECTION_LOST"
|
||||
case StatusOPUnsupported:
|
||||
return "SSH_FX_OP_UNSUPPORTED"
|
||||
case StatusV4InvalidHandle:
|
||||
return "SSH_FX_INVALID_HANDLE"
|
||||
case StatusV4NoSuchPath:
|
||||
return "SSH_FX_NO_SUCH_PATH"
|
||||
case StatusV4FileAlreadyExists:
|
||||
return "SSH_FX_FILE_ALREADY_EXISTS"
|
||||
case StatusV4WriteProtect:
|
||||
return "SSH_FX_WRITE_PROTECT"
|
||||
case StatusV4NoMedia:
|
||||
return "SSH_FX_NO_MEDIA"
|
||||
case StatusV5NoSpaceOnFilesystem:
|
||||
return "SSH_FX_NO_SPACE_ON_FILESYSTEM"
|
||||
case StatusV5QuotaExceeded:
|
||||
return "SSH_FX_QUOTA_EXCEEDED"
|
||||
case StatusV5UnknownPrincipal:
|
||||
return "SSH_FX_UNKNOWN_PRINCIPAL"
|
||||
case StatusV5LockConflict:
|
||||
return "SSH_FX_LOCK_CONFLICT"
|
||||
case StatusV6DirNotEmpty:
|
||||
return "SSH_FX_DIR_NOT_EMPTY"
|
||||
case StatusV6NotADirectory:
|
||||
return "SSH_FX_NOT_A_DIRECTORY"
|
||||
case StatusV6InvalidFilename:
|
||||
return "SSH_FX_INVALID_FILENAME"
|
||||
case StatusV6LinkLoop:
|
||||
return "SSH_FX_LINK_LOOP"
|
||||
case StatusV6CannotDelete:
|
||||
return "SSH_FX_CANNOT_DELETE"
|
||||
case StatusV6InvalidParameter:
|
||||
return "SSH_FX_INVALID_PARAMETER"
|
||||
case StatusV6FileIsADirectory:
|
||||
return "SSH_FX_FILE_IS_A_DIRECTORY"
|
||||
case StatusV6ByteRangeLockConflict:
|
||||
return "SSH_FX_BYTE_RANGE_LOCK_CONFLICT"
|
||||
case StatusV6ByteRangeLockRefused:
|
||||
return "SSH_FX_BYTE_RANGE_LOCK_REFUSED"
|
||||
case StatusV6DeletePending:
|
||||
return "SSH_FX_DELETE_PENDING"
|
||||
case StatusV6FileCorrupt:
|
||||
return "SSH_FX_FILE_CORRUPT"
|
||||
case StatusV6OwnerInvalid:
|
||||
return "SSH_FX_OWNER_INVALID"
|
||||
case StatusV6GroupInvalid:
|
||||
return "SSH_FX_GROUP_INVALID"
|
||||
case StatusV6NoMatchingByteRangeLock:
|
||||
return "SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK"
|
||||
default:
|
||||
return fmt.Sprintf("SSH_FX_UNKNOWN(%d)", s)
|
||||
}
|
||||
}
|
||||
124
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fxp.go
generated
vendored
Normal file
124
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/fxp.go
generated
vendored
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
package filexfer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// PacketType defines the various SFTP packet types.
|
||||
type PacketType uint8
|
||||
|
||||
// Request packet types.
|
||||
const (
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
||||
PacketTypeInit = PacketType(iota + 1)
|
||||
PacketTypeVersion
|
||||
PacketTypeOpen
|
||||
PacketTypeClose
|
||||
PacketTypeRead
|
||||
PacketTypeWrite
|
||||
PacketTypeLStat
|
||||
PacketTypeFStat
|
||||
PacketTypeSetstat
|
||||
PacketTypeFSetstat
|
||||
PacketTypeOpenDir
|
||||
PacketTypeReadDir
|
||||
PacketTypeRemove
|
||||
PacketTypeMkdir
|
||||
PacketTypeRmdir
|
||||
PacketTypeRealPath
|
||||
PacketTypeStat
|
||||
PacketTypeRename
|
||||
PacketTypeReadLink
|
||||
PacketTypeSymlink
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-07#section-3.3
|
||||
PacketTypeV6Link
|
||||
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-08#section-3.3
|
||||
PacketTypeV6Block
|
||||
PacketTypeV6Unblock
|
||||
)
|
||||
|
||||
// Response packet types.
|
||||
const (
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
||||
PacketTypeStatus = PacketType(iota + 101)
|
||||
PacketTypeHandle
|
||||
PacketTypeData
|
||||
PacketTypeName
|
||||
PacketTypeAttrs
|
||||
)
|
||||
|
||||
// Extended packet types.
|
||||
const (
|
||||
// https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
||||
PacketTypeExtended = PacketType(iota + 200)
|
||||
PacketTypeExtendedReply
|
||||
)
|
||||
|
||||
func (f PacketType) String() string {
|
||||
switch f {
|
||||
case PacketTypeInit:
|
||||
return "SSH_FXP_INIT"
|
||||
case PacketTypeVersion:
|
||||
return "SSH_FXP_VERSION"
|
||||
case PacketTypeOpen:
|
||||
return "SSH_FXP_OPEN"
|
||||
case PacketTypeClose:
|
||||
return "SSH_FXP_CLOSE"
|
||||
case PacketTypeRead:
|
||||
return "SSH_FXP_READ"
|
||||
case PacketTypeWrite:
|
||||
return "SSH_FXP_WRITE"
|
||||
case PacketTypeLStat:
|
||||
return "SSH_FXP_LSTAT"
|
||||
case PacketTypeFStat:
|
||||
return "SSH_FXP_FSTAT"
|
||||
case PacketTypeSetstat:
|
||||
return "SSH_FXP_SETSTAT"
|
||||
case PacketTypeFSetstat:
|
||||
return "SSH_FXP_FSETSTAT"
|
||||
case PacketTypeOpenDir:
|
||||
return "SSH_FXP_OPENDIR"
|
||||
case PacketTypeReadDir:
|
||||
return "SSH_FXP_READDIR"
|
||||
case PacketTypeRemove:
|
||||
return "SSH_FXP_REMOVE"
|
||||
case PacketTypeMkdir:
|
||||
return "SSH_FXP_MKDIR"
|
||||
case PacketTypeRmdir:
|
||||
return "SSH_FXP_RMDIR"
|
||||
case PacketTypeRealPath:
|
||||
return "SSH_FXP_REALPATH"
|
||||
case PacketTypeStat:
|
||||
return "SSH_FXP_STAT"
|
||||
case PacketTypeRename:
|
||||
return "SSH_FXP_RENAME"
|
||||
case PacketTypeReadLink:
|
||||
return "SSH_FXP_READLINK"
|
||||
case PacketTypeSymlink:
|
||||
return "SSH_FXP_SYMLINK"
|
||||
case PacketTypeV6Link:
|
||||
return "SSH_FXP_LINK"
|
||||
case PacketTypeV6Block:
|
||||
return "SSH_FXP_BLOCK"
|
||||
case PacketTypeV6Unblock:
|
||||
return "SSH_FXP_UNBLOCK"
|
||||
case PacketTypeStatus:
|
||||
return "SSH_FXP_STATUS"
|
||||
case PacketTypeHandle:
|
||||
return "SSH_FXP_HANDLE"
|
||||
case PacketTypeData:
|
||||
return "SSH_FXP_DATA"
|
||||
case PacketTypeName:
|
||||
return "SSH_FXP_NAME"
|
||||
case PacketTypeAttrs:
|
||||
return "SSH_FXP_ATTRS"
|
||||
case PacketTypeExtended:
|
||||
return "SSH_FXP_EXTENDED"
|
||||
case PacketTypeExtendedReply:
|
||||
return "SSH_FXP_EXTENDED_REPLY"
|
||||
default:
|
||||
return fmt.Sprintf("SSH_FXP_UNKNOWN(%d)", f)
|
||||
}
|
||||
}
|
||||
249
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/handle_packets.go
generated
vendored
Normal file
249
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/handle_packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
package filexfer
|
||||
|
||||
// ClosePacket defines the SSH_FXP_CLOSE packet.
|
||||
type ClosePacket struct {
|
||||
Handle string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *ClosePacket) Type() PacketType {
|
||||
return PacketTypeClose
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *ClosePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Handle) // string(handle)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeClose, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ClosePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadPacket defines the SSH_FXP_READ packet.
|
||||
type ReadPacket struct {
|
||||
Handle string
|
||||
Offset uint64
|
||||
Len uint32
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *ReadPacket) Type() PacketType {
|
||||
return PacketTypeRead
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *ReadPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
// string(handle) + uint64(offset) + uint32(len)
|
||||
size := 4 + len(p.Handle) + 8 + 4
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeRead, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
buf.AppendUint64(p.Offset)
|
||||
buf.AppendUint32(p.Len)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ReadPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Offset, err = buf.ConsumeUint64(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Len, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WritePacket defines the SSH_FXP_WRITE packet.
|
||||
type WritePacket struct {
|
||||
Handle string
|
||||
Offset uint64
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *WritePacket) Type() PacketType {
|
||||
return PacketTypeWrite
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *WritePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
// string(handle) + uint64(offset) + uint32(len(data)); data content in payload
|
||||
size := 4 + len(p.Handle) + 8 + 4
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeWrite, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
buf.AppendUint64(p.Offset)
|
||||
buf.AppendUint32(uint32(len(p.Data)))
|
||||
|
||||
return buf.Packet(p.Data)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
//
|
||||
// If p.Data is already populated, and of sufficient length to hold the data,
|
||||
// then this will copy the data into that byte slice.
|
||||
//
|
||||
// If p.Data has a length insufficient to hold the data,
|
||||
// then this will make a new slice of sufficient length, and copy the data into that.
|
||||
//
|
||||
// This means this _does not_ alias any of the data buffer that is passed in.
|
||||
func (p *WritePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.Offset, err = buf.ConsumeUint64(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := buf.ConsumeByteSlice()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(p.Data) < len(data) {
|
||||
p.Data = make([]byte, len(data))
|
||||
}
|
||||
|
||||
n := copy(p.Data, data)
|
||||
p.Data = p.Data[:n]
|
||||
return nil
|
||||
}
|
||||
|
||||
// FStatPacket defines the SSH_FXP_FSTAT packet.
|
||||
type FStatPacket struct {
|
||||
Handle string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *FStatPacket) Type() PacketType {
|
||||
return PacketTypeFStat
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *FStatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Handle) // string(handle)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeFStat, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *FStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FSetstatPacket defines the SSH_FXP_FSETSTAT packet.
|
||||
type FSetstatPacket struct {
|
||||
Handle string
|
||||
Attrs Attributes
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *FSetstatPacket) Type() PacketType {
|
||||
return PacketTypeFSetstat
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *FSetstatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Handle) + p.Attrs.Len() // string(handle) + ATTRS(attrs)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeFSetstat, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
|
||||
p.Attrs.MarshalInto(buf)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *FSetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Attrs.UnmarshalFrom(buf)
|
||||
}
|
||||
|
||||
// ReadDirPacket defines the SSH_FXP_READDIR packet.
|
||||
type ReadDirPacket struct {
|
||||
Handle string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *ReadDirPacket) Type() PacketType {
|
||||
return PacketTypeReadDir
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *ReadDirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Handle) // string(handle)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeReadDir, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ReadDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
99
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/init_packets.go
generated
vendored
Normal file
99
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/init_packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package filexfer
|
||||
|
||||
// InitPacket defines the SSH_FXP_INIT packet.
|
||||
type InitPacket struct {
|
||||
Version uint32
|
||||
Extensions []*ExtensionPair
|
||||
}
|
||||
|
||||
// MarshalBinary returns p as the binary encoding of p.
|
||||
func (p *InitPacket) MarshalBinary() ([]byte, error) {
|
||||
size := 1 + 4 // byte(type) + uint32(version)
|
||||
|
||||
for _, ext := range p.Extensions {
|
||||
size += ext.Len()
|
||||
}
|
||||
|
||||
b := NewBuffer(make([]byte, 4, 4+size))
|
||||
b.AppendUint8(uint8(PacketTypeInit))
|
||||
b.AppendUint32(p.Version)
|
||||
|
||||
for _, ext := range p.Extensions {
|
||||
ext.MarshalInto(b)
|
||||
}
|
||||
|
||||
b.PutLength(size)
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary unmarshals a full raw packet out of the given data.
|
||||
// It is assumed that the uint32(length) has already been consumed to receive the data.
|
||||
// It is also assumed that the uint8(type) has already been consumed to which packet to unmarshal into.
|
||||
func (p *InitPacket) UnmarshalBinary(data []byte) (err error) {
|
||||
buf := NewBuffer(data)
|
||||
|
||||
if p.Version, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for buf.Len() > 0 {
|
||||
var ext ExtensionPair
|
||||
if err := ext.UnmarshalFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Extensions = append(p.Extensions, &ext)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VersionPacket defines the SSH_FXP_VERSION packet.
|
||||
type VersionPacket struct {
|
||||
Version uint32
|
||||
Extensions []*ExtensionPair
|
||||
}
|
||||
|
||||
// MarshalBinary returns p as the binary encoding of p.
|
||||
func (p *VersionPacket) MarshalBinary() ([]byte, error) {
|
||||
size := 1 + 4 // byte(type) + uint32(version)
|
||||
|
||||
for _, ext := range p.Extensions {
|
||||
size += ext.Len()
|
||||
}
|
||||
|
||||
b := NewBuffer(make([]byte, 4, 4+size))
|
||||
b.AppendUint8(uint8(PacketTypeVersion))
|
||||
b.AppendUint32(p.Version)
|
||||
|
||||
for _, ext := range p.Extensions {
|
||||
ext.MarshalInto(b)
|
||||
}
|
||||
|
||||
b.PutLength(size)
|
||||
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary unmarshals a full raw packet out of the given data.
|
||||
// It is assumed that the uint32(length) has already been consumed to receive the data.
|
||||
// It is also assumed that the uint8(type) has already been consumed to which packet to unmarshal into.
|
||||
func (p *VersionPacket) UnmarshalBinary(data []byte) (err error) {
|
||||
buf := NewBuffer(data)
|
||||
|
||||
if p.Version, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for buf.Len() > 0 {
|
||||
var ext ExtensionPair
|
||||
if err := ext.UnmarshalFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Extensions = append(p.Extensions, &ext)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
89
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/open_packets.go
generated
vendored
Normal file
89
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/open_packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package filexfer
|
||||
|
||||
// SSH_FXF_* flags.
|
||||
const (
|
||||
FlagRead = 1 << iota // SSH_FXF_READ
|
||||
FlagWrite // SSH_FXF_WRITE
|
||||
FlagAppend // SSH_FXF_APPEND
|
||||
FlagCreate // SSH_FXF_CREAT
|
||||
FlagTruncate // SSH_FXF_TRUNC
|
||||
FlagExclusive // SSH_FXF_EXCL
|
||||
)
|
||||
|
||||
// OpenPacket defines the SSH_FXP_OPEN packet.
|
||||
type OpenPacket struct {
|
||||
Filename string
|
||||
PFlags uint32
|
||||
Attrs Attributes
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *OpenPacket) Type() PacketType {
|
||||
return PacketTypeOpen
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *OpenPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
// string(filename) + uint32(pflags) + ATTRS(attrs)
|
||||
size := 4 + len(p.Filename) + 4 + p.Attrs.Len()
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeOpen, reqid)
|
||||
buf.AppendString(p.Filename)
|
||||
buf.AppendUint32(p.PFlags)
|
||||
|
||||
p.Attrs.MarshalInto(buf)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *OpenPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Filename, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.PFlags, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Attrs.UnmarshalFrom(buf)
|
||||
}
|
||||
|
||||
// OpenDirPacket defines the SSH_FXP_OPENDIR packet.
|
||||
type OpenDirPacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *OpenDirPacket) Type() PacketType {
|
||||
return PacketTypeOpenDir
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *OpenDirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeOpenDir, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *OpenDirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
323
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/packets.go
generated
vendored
Normal file
323
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,323 @@
|
|||
package filexfer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// smallBufferSize is an initial allocation minimal capacity.
|
||||
const smallBufferSize = 64
|
||||
|
||||
func newPacketFromType(typ PacketType) (Packet, error) {
|
||||
switch typ {
|
||||
case PacketTypeOpen:
|
||||
return new(OpenPacket), nil
|
||||
case PacketTypeClose:
|
||||
return new(ClosePacket), nil
|
||||
case PacketTypeRead:
|
||||
return new(ReadPacket), nil
|
||||
case PacketTypeWrite:
|
||||
return new(WritePacket), nil
|
||||
case PacketTypeLStat:
|
||||
return new(LStatPacket), nil
|
||||
case PacketTypeFStat:
|
||||
return new(FStatPacket), nil
|
||||
case PacketTypeSetstat:
|
||||
return new(SetstatPacket), nil
|
||||
case PacketTypeFSetstat:
|
||||
return new(FSetstatPacket), nil
|
||||
case PacketTypeOpenDir:
|
||||
return new(OpenDirPacket), nil
|
||||
case PacketTypeReadDir:
|
||||
return new(ReadDirPacket), nil
|
||||
case PacketTypeRemove:
|
||||
return new(RemovePacket), nil
|
||||
case PacketTypeMkdir:
|
||||
return new(MkdirPacket), nil
|
||||
case PacketTypeRmdir:
|
||||
return new(RmdirPacket), nil
|
||||
case PacketTypeRealPath:
|
||||
return new(RealPathPacket), nil
|
||||
case PacketTypeStat:
|
||||
return new(StatPacket), nil
|
||||
case PacketTypeRename:
|
||||
return new(RenamePacket), nil
|
||||
case PacketTypeReadLink:
|
||||
return new(ReadLinkPacket), nil
|
||||
case PacketTypeSymlink:
|
||||
return new(SymlinkPacket), nil
|
||||
case PacketTypeExtended:
|
||||
return new(ExtendedPacket), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected request packet type: %v", typ)
|
||||
}
|
||||
}
|
||||
|
||||
// RawPacket implements the general packet format from draft-ietf-secsh-filexfer-02
|
||||
//
|
||||
// RawPacket is intended for use in clients receiving responses,
|
||||
// where a response will be expected to be of a limited number of types,
|
||||
// and unmarshaling unknown/unexpected response packets is unnecessary.
|
||||
//
|
||||
// For servers expecting to receive arbitrary request packet types,
|
||||
// use RequestPacket.
|
||||
//
|
||||
// Defined in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
||||
type RawPacket struct {
|
||||
PacketType PacketType
|
||||
RequestID uint32
|
||||
|
||||
Data Buffer
|
||||
}
|
||||
|
||||
// Type returns the Type field defining the SSH_FXP_xy type for this packet.
|
||||
func (p *RawPacket) Type() PacketType {
|
||||
return p.PacketType
|
||||
}
|
||||
|
||||
// Reset clears the pointers and reference-semantic variables of RawPacket,
|
||||
// releasing underlying resources, and making them and the RawPacket suitable to be reused,
|
||||
// so long as no other references have been kept.
|
||||
func (p *RawPacket) Reset() {
|
||||
p.Data = Buffer{}
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
//
|
||||
// The internal p.RequestID is overridden by the reqid argument.
|
||||
func (p *RawPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
buf = NewMarshalBuffer(0)
|
||||
}
|
||||
|
||||
buf.StartPacket(p.PacketType, reqid)
|
||||
|
||||
return buf.Packet(p.Data.Bytes())
|
||||
}
|
||||
|
||||
// MarshalBinary returns p as the binary encoding of p.
|
||||
//
|
||||
// This is a convenience implementation primarily intended for tests,
|
||||
// because it is inefficient with allocations.
|
||||
func (p *RawPacket) MarshalBinary() ([]byte, error) {
|
||||
return ComposePacket(p.MarshalPacket(p.RequestID, nil))
|
||||
}
|
||||
|
||||
// UnmarshalFrom decodes a RawPacket from the given Buffer into p.
|
||||
//
|
||||
// The Data field will alias the passed in Buffer,
|
||||
// so the buffer passed in should not be reused before RawPacket.Reset().
|
||||
func (p *RawPacket) UnmarshalFrom(buf *Buffer) error {
|
||||
typ, err := buf.ConsumeUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.PacketType = PacketType(typ)
|
||||
|
||||
if p.RequestID, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Data = *buf
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a full raw packet out of the given data.
|
||||
// It is assumed that the uint32(length) has already been consumed to receive the data.
|
||||
//
|
||||
// This is a convenience implementation primarily intended for tests,
|
||||
// because this must clone the given data byte slice,
|
||||
// as Data is not allowed to alias any part of the data byte slice.
|
||||
func (p *RawPacket) UnmarshalBinary(data []byte) error {
|
||||
clone := make([]byte, len(data))
|
||||
n := copy(clone, data)
|
||||
return p.UnmarshalFrom(NewBuffer(clone[:n]))
|
||||
}
|
||||
|
||||
// readPacket reads a uint32 length-prefixed binary data packet from r.
|
||||
// using the given byte slice as a backing array.
|
||||
//
|
||||
// If the packet length read from r is bigger than maxPacketLength,
|
||||
// or greater than math.MaxInt32 on a 32-bit implementation,
|
||||
// then a `ErrLongPacket` error will be returned.
|
||||
//
|
||||
// If the given byte slice is insufficient to hold the packet,
|
||||
// then it will be extended to fill the packet size.
|
||||
func readPacket(r io.Reader, b []byte, maxPacketLength uint32) ([]byte, error) {
|
||||
if cap(b) < 4 {
|
||||
// We will need allocate our own buffer just for reading the packet length.
|
||||
|
||||
// However, we don’t really want to allocate an extremely narrow buffer (4-bytes),
|
||||
// and cause unnecessary allocation churn from both length reads and small packet reads,
|
||||
// so we use smallBufferSize from the bytes package as a reasonable guess.
|
||||
|
||||
// But if callers really do want to force narrow throw-away allocation of every packet body,
|
||||
// they can do so with a buffer of capacity 4.
|
||||
b = make([]byte, smallBufferSize)
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(r, b[:4]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
length := unmarshalUint32(b)
|
||||
if int(length) < 5 {
|
||||
// Must have at least uint8(type) and uint32(request-id)
|
||||
|
||||
if int(length) < 0 {
|
||||
// Only possible when strconv.IntSize == 32,
|
||||
// the packet length is longer than math.MaxInt32,
|
||||
// and thus longer than any possible slice.
|
||||
return nil, ErrLongPacket
|
||||
}
|
||||
|
||||
return nil, ErrShortPacket
|
||||
}
|
||||
if length > maxPacketLength {
|
||||
return nil, ErrLongPacket
|
||||
}
|
||||
|
||||
if int(length) > cap(b) {
|
||||
// We know int(length) must be positive, because of tests above.
|
||||
b = make([]byte, length)
|
||||
}
|
||||
|
||||
n, err := io.ReadFull(r, b[:length])
|
||||
return b[:n], err
|
||||
}
|
||||
|
||||
// ReadFrom provides a simple functional packet reader,
|
||||
// using the given byte slice as a backing array.
|
||||
//
|
||||
// To protect against potential denial of service attacks,
|
||||
// if the read packet length is longer than maxPacketLength,
|
||||
// then no packet data will be read, and ErrLongPacket will be returned.
|
||||
// (On 32-bit int architectures, all packets >= 2^31 in length
|
||||
// will return ErrLongPacket regardless of maxPacketLength.)
|
||||
//
|
||||
// If the read packet length is longer than cap(b),
|
||||
// then a throw-away slice will allocated to meet the exact packet length.
|
||||
// This can be used to limit the length of reused buffers,
|
||||
// while still allowing reception of occasional large packets.
|
||||
//
|
||||
// The Data field may alias the passed in byte slice,
|
||||
// so the byte slice passed in should not be reused before RawPacket.Reset().
|
||||
func (p *RawPacket) ReadFrom(r io.Reader, b []byte, maxPacketLength uint32) error {
|
||||
b, err := readPacket(r, b, maxPacketLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.UnmarshalFrom(NewBuffer(b))
|
||||
}
|
||||
|
||||
// RequestPacket implements the general packet format from draft-ietf-secsh-filexfer-02
|
||||
// but also automatically decode/encodes valid request packets (2 < type < 100 || type == 200).
|
||||
//
|
||||
// RequestPacket is intended for use in servers receiving requests,
|
||||
// where any arbitrary request may be received, and so decoding them automatically
|
||||
// is useful.
|
||||
//
|
||||
// For clients expecting to receive specific response packet types,
|
||||
// where automatic unmarshaling of the packet body does not make sense,
|
||||
// use RawPacket.
|
||||
//
|
||||
// Defined in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-3
|
||||
type RequestPacket struct {
|
||||
RequestID uint32
|
||||
|
||||
Request Packet
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with the underlying packet.
|
||||
func (p *RequestPacket) Type() PacketType {
|
||||
return p.Request.Type()
|
||||
}
|
||||
|
||||
// Reset clears the pointers and reference-semantic variables in RequestPacket,
|
||||
// releasing underlying resources, and making them and the RequestPacket suitable to be reused,
|
||||
// so long as no other references have been kept.
|
||||
func (p *RequestPacket) Reset() {
|
||||
p.Request = nil
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
//
|
||||
// The internal p.RequestID is overridden by the reqid argument.
|
||||
func (p *RequestPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
if p.Request == nil {
|
||||
return nil, nil, errors.New("empty request packet")
|
||||
}
|
||||
|
||||
return p.Request.MarshalPacket(reqid, b)
|
||||
}
|
||||
|
||||
// MarshalBinary returns p as the binary encoding of p.
|
||||
//
|
||||
// This is a convenience implementation primarily intended for tests,
|
||||
// because it is inefficient with allocations.
|
||||
func (p *RequestPacket) MarshalBinary() ([]byte, error) {
|
||||
return ComposePacket(p.MarshalPacket(p.RequestID, nil))
|
||||
}
|
||||
|
||||
// UnmarshalFrom decodes a RequestPacket from the given Buffer into p.
|
||||
//
|
||||
// The Request field may alias the passed in Buffer, (e.g. SSH_FXP_WRITE),
|
||||
// so the buffer passed in should not be reused before RequestPacket.Reset().
|
||||
func (p *RequestPacket) UnmarshalFrom(buf *Buffer) error {
|
||||
typ, err := buf.ConsumeUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Request, err = newPacketFromType(PacketType(typ))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.RequestID, err = buf.ConsumeUint32(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Request.UnmarshalPacketBody(buf)
|
||||
}
|
||||
|
||||
// UnmarshalBinary decodes a full request packet out of the given data.
|
||||
// It is assumed that the uint32(length) has already been consumed to receive the data.
|
||||
//
|
||||
// This is a convenience implementation primarily intended for tests,
|
||||
// because this must clone the given data byte slice,
|
||||
// as Request is not allowed to alias any part of the data byte slice.
|
||||
func (p *RequestPacket) UnmarshalBinary(data []byte) error {
|
||||
clone := make([]byte, len(data))
|
||||
n := copy(clone, data)
|
||||
return p.UnmarshalFrom(NewBuffer(clone[:n]))
|
||||
}
|
||||
|
||||
// ReadFrom provides a simple functional packet reader,
|
||||
// using the given byte slice as a backing array.
|
||||
//
|
||||
// To protect against potential denial of service attacks,
|
||||
// if the read packet length is longer than maxPacketLength,
|
||||
// then no packet data will be read, and ErrLongPacket will be returned.
|
||||
// (On 32-bit int architectures, all packets >= 2^31 in length
|
||||
// will return ErrLongPacket regardless of maxPacketLength.)
|
||||
//
|
||||
// If the read packet length is longer than cap(b),
|
||||
// then a throw-away slice will allocated to meet the exact packet length.
|
||||
// This can be used to limit the length of reused buffers,
|
||||
// while still allowing reception of occasional large packets.
|
||||
//
|
||||
// The Request field may alias the passed in byte slice,
|
||||
// so the byte slice passed in should not be reused before RawPacket.Reset().
|
||||
func (p *RequestPacket) ReadFrom(r io.Reader, b []byte, maxPacketLength uint32) error {
|
||||
b, err := readPacket(r, b, maxPacketLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.UnmarshalFrom(NewBuffer(b))
|
||||
}
|
||||
368
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/path_packets.go
generated
vendored
Normal file
368
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/path_packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
package filexfer
|
||||
|
||||
// LStatPacket defines the SSH_FXP_LSTAT packet.
|
||||
type LStatPacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *LStatPacket) Type() PacketType {
|
||||
return PacketTypeLStat
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *LStatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeLStat, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *LStatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetstatPacket defines the SSH_FXP_SETSTAT packet.
|
||||
type SetstatPacket struct {
|
||||
Path string
|
||||
Attrs Attributes
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *SetstatPacket) Type() PacketType {
|
||||
return PacketTypeSetstat
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *SetstatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) + p.Attrs.Len() // string(path) + ATTRS(attrs)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeSetstat, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
p.Attrs.MarshalInto(buf)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *SetstatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Attrs.UnmarshalFrom(buf)
|
||||
}
|
||||
|
||||
// RemovePacket defines the SSH_FXP_REMOVE packet.
|
||||
type RemovePacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *RemovePacket) Type() PacketType {
|
||||
return PacketTypeRemove
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *RemovePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeRemove, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RemovePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MkdirPacket defines the SSH_FXP_MKDIR packet.
|
||||
type MkdirPacket struct {
|
||||
Path string
|
||||
Attrs Attributes
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *MkdirPacket) Type() PacketType {
|
||||
return PacketTypeMkdir
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *MkdirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) + p.Attrs.Len() // string(path) + ATTRS(attrs)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeMkdir, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
p.Attrs.MarshalInto(buf)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *MkdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Attrs.UnmarshalFrom(buf)
|
||||
}
|
||||
|
||||
// RmdirPacket defines the SSH_FXP_RMDIR packet.
|
||||
type RmdirPacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *RmdirPacket) Type() PacketType {
|
||||
return PacketTypeRmdir
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *RmdirPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeRmdir, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RmdirPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RealPathPacket defines the SSH_FXP_REALPATH packet.
|
||||
type RealPathPacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *RealPathPacket) Type() PacketType {
|
||||
return PacketTypeRealPath
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *RealPathPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeRealPath, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RealPathPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StatPacket defines the SSH_FXP_STAT packet.
|
||||
type StatPacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *StatPacket) Type() PacketType {
|
||||
return PacketTypeStat
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *StatPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeStat, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *StatPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenamePacket defines the SSH_FXP_RENAME packet.
|
||||
type RenamePacket struct {
|
||||
OldPath string
|
||||
NewPath string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *RenamePacket) Type() PacketType {
|
||||
return PacketTypeRename
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *RenamePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
// string(oldpath) + string(newpath)
|
||||
size := 4 + len(p.OldPath) + 4 + len(p.NewPath)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeRename, reqid)
|
||||
buf.AppendString(p.OldPath)
|
||||
buf.AppendString(p.NewPath)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *RenamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.OldPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.NewPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadLinkPacket defines the SSH_FXP_READLINK packet.
|
||||
type ReadLinkPacket struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *ReadLinkPacket) Type() PacketType {
|
||||
return PacketTypeReadLink
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *ReadLinkPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Path) // string(path)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeReadLink, reqid)
|
||||
buf.AppendString(p.Path)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *ReadLinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Path, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SymlinkPacket defines the SSH_FXP_SYMLINK packet.
|
||||
//
|
||||
// The order of the arguments to the SSH_FXP_SYMLINK method was inadvertently reversed.
|
||||
// Unfortunately, the reversal was not noticed until the server was widely deployed.
|
||||
// Covered in Section 3.1 of https://github.com/openssh/openssh-portable/blob/master/PROTOCOL
|
||||
type SymlinkPacket struct {
|
||||
LinkPath string
|
||||
TargetPath string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *SymlinkPacket) Type() PacketType {
|
||||
return PacketTypeSymlink
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *SymlinkPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
// string(targetpath) + string(linkpath)
|
||||
size := 4 + len(p.TargetPath) + 4 + len(p.LinkPath)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeSymlink, reqid)
|
||||
|
||||
// Arguments were inadvertently reversed.
|
||||
buf.AppendString(p.TargetPath)
|
||||
buf.AppendString(p.LinkPath)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *SymlinkPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
// Arguments were inadvertently reversed.
|
||||
if p.TargetPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.LinkPath, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
114
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/permissions.go
generated
vendored
Normal file
114
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/permissions.go
generated
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package filexfer
|
||||
|
||||
// FileMode represents a file’s mode and permission bits.
|
||||
// The bits are defined according to POSIX standards,
|
||||
// and may not apply to the OS being built for.
|
||||
type FileMode uint32
|
||||
|
||||
// Permission flags, defined here to avoid potential inconsistencies in individual OS implementations.
|
||||
const (
|
||||
ModePerm FileMode = 0o0777 // S_IRWXU | S_IRWXG | S_IRWXO
|
||||
ModeUserRead FileMode = 0o0400 // S_IRUSR
|
||||
ModeUserWrite FileMode = 0o0200 // S_IWUSR
|
||||
ModeUserExec FileMode = 0o0100 // S_IXUSR
|
||||
ModeGroupRead FileMode = 0o0040 // S_IRGRP
|
||||
ModeGroupWrite FileMode = 0o0020 // S_IWGRP
|
||||
ModeGroupExec FileMode = 0o0010 // S_IXGRP
|
||||
ModeOtherRead FileMode = 0o0004 // S_IROTH
|
||||
ModeOtherWrite FileMode = 0o0002 // S_IWOTH
|
||||
ModeOtherExec FileMode = 0o0001 // S_IXOTH
|
||||
|
||||
ModeSetUID FileMode = 0o4000 // S_ISUID
|
||||
ModeSetGID FileMode = 0o2000 // S_ISGID
|
||||
ModeSticky FileMode = 0o1000 // S_ISVTX
|
||||
|
||||
ModeType FileMode = 0xF000 // S_IFMT
|
||||
ModeNamedPipe FileMode = 0x1000 // S_IFIFO
|
||||
ModeCharDevice FileMode = 0x2000 // S_IFCHR
|
||||
ModeDir FileMode = 0x4000 // S_IFDIR
|
||||
ModeDevice FileMode = 0x6000 // S_IFBLK
|
||||
ModeRegular FileMode = 0x8000 // S_IFREG
|
||||
ModeSymlink FileMode = 0xA000 // S_IFLNK
|
||||
ModeSocket FileMode = 0xC000 // S_IFSOCK
|
||||
)
|
||||
|
||||
// IsDir reports whether m describes a directory.
|
||||
// That is, it tests for m.Type() == ModeDir.
|
||||
func (m FileMode) IsDir() bool {
|
||||
return (m & ModeType) == ModeDir
|
||||
}
|
||||
|
||||
// IsRegular reports whether m describes a regular file.
|
||||
// That is, it tests for m.Type() == ModeRegular
|
||||
func (m FileMode) IsRegular() bool {
|
||||
return (m & ModeType) == ModeRegular
|
||||
}
|
||||
|
||||
// Perm returns the POSIX permission bits in m (m & ModePerm).
|
||||
func (m FileMode) Perm() FileMode {
|
||||
return (m & ModePerm)
|
||||
}
|
||||
|
||||
// Type returns the type bits in m (m & ModeType).
|
||||
func (m FileMode) Type() FileMode {
|
||||
return (m & ModeType)
|
||||
}
|
||||
|
||||
// String returns a `-rwxrwxrwx` style string representing the `ls -l` POSIX permissions string.
|
||||
func (m FileMode) String() string {
|
||||
var buf [10]byte
|
||||
|
||||
switch m.Type() {
|
||||
case ModeRegular:
|
||||
buf[0] = '-'
|
||||
case ModeDir:
|
||||
buf[0] = 'd'
|
||||
case ModeSymlink:
|
||||
buf[0] = 'l'
|
||||
case ModeDevice:
|
||||
buf[0] = 'b'
|
||||
case ModeCharDevice:
|
||||
buf[0] = 'c'
|
||||
case ModeNamedPipe:
|
||||
buf[0] = 'p'
|
||||
case ModeSocket:
|
||||
buf[0] = 's'
|
||||
default:
|
||||
buf[0] = '?'
|
||||
}
|
||||
|
||||
const rwx = "rwxrwxrwx"
|
||||
for i, c := range rwx {
|
||||
if m&(1<<uint(9-1-i)) != 0 {
|
||||
buf[i+1] = byte(c)
|
||||
} else {
|
||||
buf[i+1] = '-'
|
||||
}
|
||||
}
|
||||
|
||||
if m&ModeSetUID != 0 {
|
||||
if buf[3] == 'x' {
|
||||
buf[3] = 's'
|
||||
} else {
|
||||
buf[3] = 'S'
|
||||
}
|
||||
}
|
||||
|
||||
if m&ModeSetGID != 0 {
|
||||
if buf[6] == 'x' {
|
||||
buf[6] = 's'
|
||||
} else {
|
||||
buf[6] = 'S'
|
||||
}
|
||||
}
|
||||
|
||||
if m&ModeSticky != 0 {
|
||||
if buf[9] == 'x' {
|
||||
buf[9] = 't'
|
||||
} else {
|
||||
buf[9] = 'T'
|
||||
}
|
||||
}
|
||||
|
||||
return string(buf[:])
|
||||
}
|
||||
243
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/response_packets.go
generated
vendored
Normal file
243
vendor/github.com/pkg/sftp/internal/encoding/ssh/filexfer/response_packets.go
generated
vendored
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
package filexfer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// StatusPacket defines the SSH_FXP_STATUS packet.
|
||||
//
|
||||
// Specified in https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7
|
||||
type StatusPacket struct {
|
||||
StatusCode Status
|
||||
ErrorMessage string
|
||||
LanguageTag string
|
||||
}
|
||||
|
||||
// Error makes StatusPacket an error type.
|
||||
func (p *StatusPacket) Error() string {
|
||||
if p.ErrorMessage == "" {
|
||||
return "sftp: " + p.StatusCode.String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("sftp: %q (%s)", p.ErrorMessage, p.StatusCode)
|
||||
}
|
||||
|
||||
// Is returns true if target is a StatusPacket with the same StatusCode,
|
||||
// or target is a Status code which is the same as SatusCode.
|
||||
func (p *StatusPacket) Is(target error) bool {
|
||||
if target, ok := target.(*StatusPacket); ok {
|
||||
return p.StatusCode == target.StatusCode
|
||||
}
|
||||
|
||||
return p.StatusCode == target
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *StatusPacket) Type() PacketType {
|
||||
return PacketTypeStatus
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *StatusPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
// uint32(error/status code) + string(error message) + string(language tag)
|
||||
size := 4 + 4 + len(p.ErrorMessage) + 4 + len(p.LanguageTag)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeStatus, reqid)
|
||||
buf.AppendUint32(uint32(p.StatusCode))
|
||||
buf.AppendString(p.ErrorMessage)
|
||||
buf.AppendString(p.LanguageTag)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *StatusPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
statusCode, err := buf.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.StatusCode = Status(statusCode)
|
||||
|
||||
if p.ErrorMessage, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.LanguageTag, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandlePacket defines the SSH_FXP_HANDLE packet.
|
||||
type HandlePacket struct {
|
||||
Handle string
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *HandlePacket) Type() PacketType {
|
||||
return PacketTypeHandle
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *HandlePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 + len(p.Handle) // string(handle)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeHandle, reqid)
|
||||
buf.AppendString(p.Handle)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *HandlePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
if p.Handle, err = buf.ConsumeString(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DataPacket defines the SSH_FXP_DATA packet.
|
||||
type DataPacket struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *DataPacket) Type() PacketType {
|
||||
return PacketTypeData
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *DataPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 // uint32(len(data)); data content in payload
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeData, reqid)
|
||||
buf.AppendUint32(uint32(len(p.Data)))
|
||||
|
||||
return buf.Packet(p.Data)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
//
|
||||
// If p.Data is already populated, and of sufficient length to hold the data,
|
||||
// then this will copy the data into that byte slice.
|
||||
//
|
||||
// If p.Data has a length insufficient to hold the data,
|
||||
// then this will make a new slice of sufficient length, and copy the data into that.
|
||||
//
|
||||
// This means this _does not_ alias any of the data buffer that is passed in.
|
||||
func (p *DataPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
data, err := buf.ConsumeByteSlice()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(p.Data) < len(data) {
|
||||
p.Data = make([]byte, len(data))
|
||||
}
|
||||
|
||||
n := copy(p.Data, data)
|
||||
p.Data = p.Data[:n]
|
||||
return nil
|
||||
}
|
||||
|
||||
// NamePacket defines the SSH_FXP_NAME packet.
|
||||
type NamePacket struct {
|
||||
Entries []*NameEntry
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *NamePacket) Type() PacketType {
|
||||
return PacketTypeName
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *NamePacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := 4 // uint32(len(entries))
|
||||
|
||||
for _, e := range p.Entries {
|
||||
size += e.Len()
|
||||
}
|
||||
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeName, reqid)
|
||||
buf.AppendUint32(uint32(len(p.Entries)))
|
||||
|
||||
for _, e := range p.Entries {
|
||||
e.MarshalInto(buf)
|
||||
}
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *NamePacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
count, err := buf.ConsumeUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Entries = make([]*NameEntry, 0, count)
|
||||
|
||||
for i := uint32(0); i < count; i++ {
|
||||
var e NameEntry
|
||||
if err := e.UnmarshalFrom(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.Entries = append(p.Entries, &e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttrsPacket defines the SSH_FXP_ATTRS packet.
|
||||
type AttrsPacket struct {
|
||||
Attrs Attributes
|
||||
}
|
||||
|
||||
// Type returns the SSH_FXP_xy value associated with this packet type.
|
||||
func (p *AttrsPacket) Type() PacketType {
|
||||
return PacketTypeAttrs
|
||||
}
|
||||
|
||||
// MarshalPacket returns p as a two-part binary encoding of p.
|
||||
func (p *AttrsPacket) MarshalPacket(reqid uint32, b []byte) (header, payload []byte, err error) {
|
||||
buf := NewBuffer(b)
|
||||
if buf.Cap() < 9 {
|
||||
size := p.Attrs.Len() // ATTRS(attrs)
|
||||
buf = NewMarshalBuffer(size)
|
||||
}
|
||||
|
||||
buf.StartPacket(PacketTypeAttrs, reqid)
|
||||
p.Attrs.MarshalInto(buf)
|
||||
|
||||
return buf.Packet(payload)
|
||||
}
|
||||
|
||||
// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
|
||||
// It is assumed that the uint32(request-id) has already been consumed.
|
||||
func (p *AttrsPacket) UnmarshalPacketBody(buf *Buffer) (err error) {
|
||||
return p.Attrs.UnmarshalFrom(buf)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue