sftpd

package module
Version: v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 10, 2020 License: MIT Imports: 21 Imported by: 0

README

sftpd - SFTP server library in Go

基于 github.com/taruti/sftpd 截止 2020.04.02 的版本, 这个项目功能没有 github.com/pkg/sftp 全且更新慢, 但是可取的地方是使用了 FileSystem 接口来提供对目录的读写操作, 这样子就可以很方便的各种实现文件系统, 包括本地文件系统或者连接后端的 sftp server 的文件系统.

相对于原版做了以下修改:

  • 修正不支持 SSH_FXP_EXTENDED 请求的问题
  • 实现了一个本地可读写的文件系统接口 LocalFs,使用方法见 example/localfs
  • 实现了一个后端为 sftp 的可读写的文件系统接口 sftpFs,使用方法见 example/sftpfs
  • 添加软链接等特殊文件的支持(仅支持 liunx)
  • 添加重命名功能
  • 添加文件时间显示
  • 添加用户、组显示(仅支持 linux)
  • 添加中文兼容

开启 debug 显示

go build -tags debug -a

默认使用 log 输出

功能测试

sftp 客户端: sfx, xftp, winscp

文件系统: LocalFs

通过:

  • 显示列表
  • 下载文件
  • 下载目录
  • 上传文件
  • 上传目录
  • 删除文件
  • 删除目录
  • 重命名文件
  • 重命名目录
  • 修改文件属性
  • 修改目录属性
  • 显示文件时间
  • 显示文件大小
  • 显示软链接等特殊文件(仅支持 linux 服务端)
  • 显示宿主(用户和组)(仅支持 linux 服务端)

不通过:

  • 创建软链接
文件系统: sftpFs

通过:

  • 显示列表
  • 下载文件
  • 下载目录
  • 上传文件
  • 上传目录
  • 删除文件
  • 删除目录
  • 重命名文件
  • 重命名目录
  • 修改文件属性
  • 修改目录属性
  • 显示文件时间
  • 显示文件大小
  • 显示软链接等特殊文件(仅支持 linux 服务端)
  • 显示宿主(用户和组,只支持显示 uid 和 gid)(仅支持 linux 服务端)

不通过:

  • 创建软链接

TODO

  • 创建软链接

Documentation

Overview

Package sftpd is sftp (SSH File Transfer Protocol) server library.

windows 无 syscall.Stat_t

Index

Constants

View Source
const (
	SSH_FXP_INIT           = 1
	SSH_FXP_VERSION        = 2
	SSH_FXP_OPEN           = 3
	SSH_FXP_CLOSE          = 4
	SSH_FXP_READ           = 5
	SSH_FXP_WRITE          = 6
	SSH_FXP_LSTAT          = 7
	SSH_FXP_FSTAT          = 8
	SSH_FXP_SETSTAT        = 9
	SSH_FXP_FSETSTAT       = 10
	SSH_FXP_OPENDIR        = 11
	SSH_FXP_READDIR        = 12
	SSH_FXP_REMOVE         = 13
	SSH_FXP_MKDIR          = 14
	SSH_FXP_RMDIR          = 15
	SSH_FXP_REALPATH       = 16
	SSH_FXP_STAT           = 17
	SSH_FXP_RENAME         = 18
	SSH_FXP_READLINK       = 19
	SSH_FXP_SYMLINK        = 20
	SSH_FXP_STATUS         = 101
	SSH_FXP_HANDLE         = 102
	SSH_FXP_DATA           = 103
	SSH_FXP_NAME           = 104
	SSH_FXP_ATTRS          = 105
	SSH_FXP_EXTENDED       = 200
	SSH_FXP_EXTENDED_REPLY = 201
)
View Source
const (
	SSH_FX_OK                = 0
	SSH_FX_EOF               = 1
	SSH_FX_NO_SUCH_FILE      = 2
	SSH_FX_PERMISSION_DENIED = 3
	SSH_FX_FAILURE           = 4
	SSH_FX_BAD_MESSAGE       = 5
	SSH_FX_NO_CONNECTION     = 6
	SSH_FX_CONNECTION_LOST   = 7
	SSH_FX_OP_UNSUPPORTED    = 8
)
View Source
const (
	SSH_FILEXFER_ATTR_SIZE        = 0x00000001
	SSH_FILEXFER_ATTR_UIDGID      = 0x00000002
	SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004
	SSH_FILEXFER_ATTR_ACMODTIME   = 0x00000008
	SSH_FILEXFER_ATTR_EXTENDED    = 0x80000000
)
View Source
const (
	SSH_FXF_READ   = 0x00000001
	SSH_FXF_WRITE  = 0x00000002
	SSH_FXF_APPEND = 0x00000004
	SSH_FXF_CREAT  = 0x00000008
	SSH_FXF_TRUNC  = 0x00000010
	SSH_FXF_EXCL   = 0x00000020
)

sftp 协议中规定文件读写模式

View Source
const (
	ATTR_SIZE    = SSH_FILEXFER_ATTR_SIZE
	ATTR_UIDGID  = SSH_FILEXFER_ATTR_UIDGID
	ATTR_MODE    = SSH_FILEXFER_ATTR_PERMISSIONS
	ATTR_TIME    = SSH_FILEXFER_ATTR_ACMODTIME
	MODE_REGULAR = os.FileMode(0)
	MODE_DIR     = os.ModeDir
)
View Source
const S_IFMT = 0xf000

Variables

View Source
var Failure = errors.New("Failure")
View Source
var SSH_FXP_MAP = map[SSH_FXP]string{
	SSH_FXP_INIT:           `SSH_FXP_INIT`,
	SSH_FXP_VERSION:        `SSH_FXP_VERSION`,
	SSH_FXP_OPEN:           `SSH_FXP_OPEN`,
	SSH_FXP_CLOSE:          `SSH_FXP_CLOSE`,
	SSH_FXP_READ:           `SSH_FXP_READ`,
	SSH_FXP_WRITE:          `SSH_FXP_WRITE`,
	SSH_FXP_LSTAT:          `SSH_FXP_LSTAT`,
	SSH_FXP_FSTAT:          `SSH_FXP_FSTAT`,
	SSH_FXP_SETSTAT:        `SSH_FXP_SETSTAT`,
	SSH_FXP_FSETSTAT:       `SSH_FXP_FSETSTAT`,
	SSH_FXP_OPENDIR:        `SSH_FXP_OPENDIR`,
	SSH_FXP_READDIR:        `SSH_FXP_READDIR`,
	SSH_FXP_REMOVE:         `SSH_FXP_REMOVE`,
	SSH_FXP_MKDIR:          `SSH_FXP_MKDIR`,
	SSH_FXP_RMDIR:          `SSH_FXP_RMDIR`,
	SSH_FXP_REALPATH:       `SSH_FXP_REALPATH`,
	SSH_FXP_STAT:           `SSH_FXP_STAT`,
	SSH_FXP_RENAME:         `SSH_FXP_RENAME`,
	SSH_FXP_READLINK:       `SSH_FXP_READLINK`,
	SSH_FXP_SYMLINK:        `SSH_FXP_SYMLINK`,
	SSH_FXP_STATUS:         `SSH_FXP_STATUS`,
	SSH_FXP_HANDLE:         `SSH_FXP_HANDLE`,
	SSH_FXP_DATA:           `SSH_FXP_DATA`,
	SSH_FXP_NAME:           `SSH_FXP_NAME`,
	SSH_FXP_ATTRS:          `SSH_FXP_ATTRS`,
	SSH_FXP_EXTENDED:       `SSH_FXP_EXTENDED`,
	SSH_FXP_EXTENDED_REPLY: `SSH_FXP_EXTENDED_REPLY`,
}
View Source
var SSH_FX_MAP = map[SSH_FX]string{
	SSH_FX_OK:                `SSH_FX_OK`,
	SSH_FX_EOF:               `SSH_FX_EOF`,
	SSH_FX_NO_SUCH_FILE:      `SSH_FX_NO_SUCH_FILE`,
	SSH_FX_PERMISSION_DENIED: `SSH_FX_PERMISSION_DENIED`,
	SSH_FX_FAILURE:           `SSH_FX_FAILURE`,
	SSH_FX_BAD_MESSAGE:       `SSH_FX_BAD_MESSAGE`,
	SSH_FX_NO_CONNECTION:     `SSH_FX_NO_CONNECTION`,
	SSH_FX_CONNECTION_LOST:   `SSH_FX_CONNECTION_LOST`,
	SSH_FX_OP_UNSUPPORTED:    `SSH_FX_OP_UNSUPPORTED`,
}

Functions

func IsSftpRequest

func IsSftpRequest(req *ssh.Request) bool

IsSftpRequest checks whether a given ssh.Request is for sftp.

func NewSftpFs

func NewSftpFs(client *sftp.Client) *sftpFs

func NewSshClientConfig

func NewSshClientConfig(sshUser, sshPassword, sshType, sshKey, sshKeyPassword string, timeout time.Duration) (config *ssh.ClientConfig, err error)

func NewSshUpstream

func NewSshUpstream(host, username, password string, timeout time.Duration) (*ssh.Client, *ssh.Session, error)

func ServeChannel

func ServeChannel(c ssh.Channel, fs FileSystem, sysType int) error

ServeChannel serves a ssh.Channel with the given FileSystem.

Types

type Attr

type Attr struct {
	Flags        uint32
	Size         uint64
	Uid, Gid     uint32
	User, Group  string
	Mode         os.FileMode
	ModeString   string
	ATime, MTime time.Time
	Extended     []string
}

func (*Attr) FillFrom

func (a *Attr) FillFrom(fi os.FileInfo, sysType int)

FillFrom fills an Attr from a os.FileInfo

type Config

type Config struct {
	// ServerConfig should be initialized properly with
	// e.g. PasswordCallback and AddHostKey
	ssh.ServerConfig
	// HostPort specifies specifies [host]:port to listen on.
	// e.g. ":2022" or "127.0.0.1:2023".
	HostPort string
	// LogFunction is used to log errors.
	// e.g. log.Println has the right type.
	LogFunc func(v ...interface{})
	// FileSystem contains the FileSystem used for this server.
	FileSystem FileSystem
	// contains filtered or unexported fields
}

Config is the configuration struct for the high level API.

func (*Config) BlockTillReady

func (c *Config) BlockTillReady() error

BlockTillReady will block till the Config is ready to accept connections. Returns an error if listening failed. Can be called in a concurrent fashion. This is new API - make sure Init is called on the Config before using it.

func (*Config) Close

func (c *Config) Close() error

Close closes the server assosiated with this config. Can be called in a concurrent fashion. This is new API - make sure Init is called on the Config before using it.

func (*Config) Init

func (c *Config) Init()

Init inits a Config.

func (*Config) RunServer

func (c *Config) RunServer() error

RunServer runs the server using the high level API.

type Dir

type Dir interface {
	io.Closer
	Readdir(count int, handles Handles) ([]NamedAttr, error)
}

type EmptyDir

type EmptyDir struct{}

func (EmptyDir) Close

func (EmptyDir) Close() error

func (EmptyDir) Readdir

func (EmptyDir) Readdir(count int, handles Handles) ([]NamedAttr, error)

type EmptyFS

type EmptyFS struct{}
func (EmptyFS) CreateLink(p string, t string, f uint32) error

func (EmptyFS) Mkdir

func (EmptyFS) Mkdir(string, *Attr) error

func (EmptyFS) OpenDir

func (EmptyFS) OpenDir(string) (Dir, error)

func (EmptyFS) OpenFile

func (EmptyFS) OpenFile(string, uint32, *Attr) (File, error)
func (EmptyFS) ReadLink(p string) (string, error)

func (EmptyFS) RealPath

func (EmptyFS) RealPath(p string) (string, error)

func (EmptyFS) Remove

func (EmptyFS) Remove(string) error

func (EmptyFS) Rename

func (EmptyFS) Rename(string, string, uint32) error

func (EmptyFS) Rmdir

func (EmptyFS) Rmdir(string) error

func (EmptyFS) SetStat

func (EmptyFS) SetStat(string, *Attr) error

func (EmptyFS) Stat

func (EmptyFS) Stat(string, bool) (*Attr, error)

type EmptyFile

type EmptyFile struct{}

func (EmptyFile) Close

func (EmptyFile) Close() error

func (EmptyFile) FSetStat

func (EmptyFile) FSetStat(*Attr) error

func (EmptyFile) FStat

func (EmptyFile) FStat() (*Attr, error)

func (EmptyFile) ReadAt

func (EmptyFile) ReadAt([]byte, int64) (int, error)

func (EmptyFile) WriteAt

func (EmptyFile) WriteAt([]byte, int64) (int, error)

type File

type File interface {
	io.Closer
	io.ReaderAt
	io.WriterAt
	FStat() (*Attr, error)
	FSetStat(*Attr) error
}

type FileSystem

type FileSystem interface {
	OpenFile(name string, flags uint32, attr *Attr) (File, error)
	OpenDir(name string) (Dir, error)
	Remove(name string) error
	Rename(old string, new string, flags uint32) error
	Mkdir(name string, attr *Attr) error
	Rmdir(name string) error
	Stat(name string, islstat bool) (*Attr, error)
	SetStat(name string, attr *Attr) error
	ReadLink(path string) (string, error)
	CreateLink(path string, target string, flags uint32) error
	RealPath(path string) (string, error)
}

type Handles

type Handles struct {
	// contains filtered or unexported fields
}

func (*Handles) CloseAll

func (h *Handles) CloseAll()

func (*Handles) CloseHandle

func (h *Handles) CloseHandle(k string)

func (*Handles) GetDir

func (h *Handles) GetDir(n string) Dir

func (*Handles) GetFile

func (h *Handles) GetFile(n string) File

func (*Handles) Init

func (h *Handles) Init()

func (*Handles) Ndir

func (h *Handles) Ndir() int

func (*Handles) NewDir

func (h *Handles) NewDir(f Dir) string

func (*Handles) NewFile

func (h *Handles) NewFile(f File) string

func (*Handles) Nfiles

func (h *Handles) Nfiles() int

type LocalDir

type LocalDir struct {
	// contains filtered or unexported fields
}

func NewLocalDir

func NewLocalDir(dir *os.File) *LocalDir

func (*LocalDir) Close

func (d *LocalDir) Close() error

func (*LocalDir) Readdir

func (d *LocalDir) Readdir(count int, handles Handles) ([]NamedAttr, error)

type LocalFile

type LocalFile struct {
	// contains filtered or unexported fields
}

func NewLocalFile

func NewLocalFile(file *os.File) *LocalFile

func (*LocalFile) Close

func (rf *LocalFile) Close() error

func (*LocalFile) FSetStat

func (rf *LocalFile) FSetStat(a *Attr) error

func (*LocalFile) FStat

func (rf *LocalFile) FStat() (*Attr, error)

func (*LocalFile) ReadAt

func (rf *LocalFile) ReadAt(bs []byte, pos int64) (int, error)

func (*LocalFile) WriteAt

func (rf *LocalFile) WriteAt(bs []byte, pos int64) (int, error)

type LocalFs

type LocalFs struct {
	// contains filtered or unexported fields
}

func NewLocalFs

func NewLocalFs(root string) *LocalFs
func (fs *LocalFs) CreateLink(path string, target string, flags uint32) error

func (*LocalFs) Mkdir

func (fs *LocalFs) Mkdir(path string, attr *Attr) error

func (*LocalFs) OpenDir

func (fs *LocalFs) OpenDir(path string) (Dir, error)

func (*LocalFs) OpenFile

func (fs *LocalFs) OpenFile(path string, mode uint32, a *Attr) (File, error)
func (fs *LocalFs) ReadLink(path string) (string, error)

func (*LocalFs) RealPath

func (fs *LocalFs) RealPath(pathX string) (string, error)

func (*LocalFs) Remove

func (fs *LocalFs) Remove(path string) error

func (*LocalFs) Rename

func (fs *LocalFs) Rename(oldName, newName string, flag uint32) error

func (*LocalFs) Rmdir

func (fs *LocalFs) Rmdir(path string) error

func (*LocalFs) SetStat

func (fs *LocalFs) SetStat(path string, attr *Attr) error

func (*LocalFs) Stat

func (fs *LocalFs) Stat(path string, isLstat bool) (*Attr, error)

type NamedAttr

type NamedAttr struct {
	Name string
	Attr
}

type SSH_FX

type SSH_FX byte

func (SSH_FX) String

func (b SSH_FX) String() string

type SSH_FXP

type SSH_FXP byte

These are used to get more pretty debugging output.

func (SSH_FXP) String

func (b SSH_FXP) String() string

type SftpDir

type SftpDir struct {
	// contains filtered or unexported fields
}

func NewSftpDir

func NewSftpDir(client *sftp.Client, path string) *SftpDir

func (*SftpDir) Close

func (sd *SftpDir) Close() error

func (*SftpDir) Readdir

func (sd *SftpDir) Readdir(count int, handles Handles) ([]NamedAttr, error)

type SftpFile

type SftpFile struct {
	// contains filtered or unexported fields
}

func NewSftpFile

func NewSftpFile(file *sftp.File) *SftpFile

func (*SftpFile) Close

func (sf *SftpFile) Close() error

func (*SftpFile) FSetStat

func (sf *SftpFile) FSetStat(a *Attr) error

func (*SftpFile) FStat

func (sf *SftpFile) FStat() (*Attr, error)

func (*SftpFile) ReadAt

func (sf *SftpFile) ReadAt(bs []byte, pos int64) (int, error)

func (*SftpFile) WriteAt

func (sf *SftpFile) WriteAt(bs []byte, pos int64) (int, error)

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL