Documentation
¶
Overview ¶
Package ftpserver provides all the tools to build your own FTP server: The core library and the driver.
Index ¶
- Constants
- Variables
- func Control(_, _ string, c syscall.RawConn) error
- type ClientContext
- type ClientDriver
- type ClientDriverExtensionAllocate
- type ClientDriverExtensionAvailableSpace
- type ClientDriverExtensionFileList
- type ClientDriverExtensionHasher
- type ClientDriverExtensionRemoveDir
- type ClientDriverExtensionSymlink
- type ClientDriverExtentionFileTransfer
- type CommandDescription
- type DataChannel
- type DataConnectionRequirement
- type DriverError
- type FileAccessError
- type FileTransfer
- type FileTransferError
- type FtpServer
- type HASHAlgo
- type MainDriver
- type MainDriverExtensionPassiveWrapper
- type MainDriverExtensionPostAuthMessage
- type MainDriverExtensionQuitMessage
- type MainDriverExtensionTLSVerifier
- type MainDriverExtensionUserVerifier
- type NetworkError
- type PasvPortGetter
- type PublicIPResolver
- type Settings
- type SiteHandler
- type TLSRequirement
- type TransferType
Constants ¶
const ( // 100 Series - The requested action is being initiated, expect another reply before // proceeding with a new command. StatusFileStatusOK = 150 // RFC 959, 4.2.1 // 200 Series - The requested action has been successfully completed. StatusOK = 200 // RFC 959, 4.2.1 StatusNotImplemented = 202 // RFC 959, 4.2.1 StatusSystemStatus = 211 // RFC 959, 4.2.1 StatusDirectoryStatus = 212 // RFC 959, 4.2.1 StatusFileStatus = 213 // RFC 959, 4.2.1 StatusHelpMessage = 214 // RFC 959, 4.2.1 StatusSystemType = 215 // RFC 959, 4.2.1 StatusServiceReady = 220 // RFC 959, 4.2.1 StatusClosingControlConn = 221 // RFC 959, 4.2.1 StatusClosingDataConn = 226 // RFC 959, 4.2.1 StatusEnteringPASV = 227 // RFC 959, 4.2.1 StatusEnteringEPSV = 229 // RFC 2428, 3 StatusUserLoggedIn = 230 // RFC 959, 4.2.1 StatusAuthAccepted = 234 // RFC 2228, 3 StatusFileOK = 250 // RFC 959, 4.2.1 StatusPathCreated = 257 // RFC 959, 4.2.1 // 300 Series - The command has been accepted, but the requested action is on hold, // pending receipt of further information. StatusUserOK = 331 // RFC 959, 4.2.1 StatusFileActionPending = 350 // RFC 959, 4.2.1 // 400 Series - The command was not accepted and the requested action did not take place, // but the error condition is temporary and the action may be requested again. StatusServiceNotAvailable = 421 // RFC 959, 4.2.1 StatusCannotOpenDataConnection = 425 // RFC 959, 4.2.1 StatusTransferAborted = 426 // RFC 959, 4.2.1 StatusFileActionNotTaken = 450 // RFC 959, 4.2.1 // 500 Series - Syntax error, command unrecognized and the requested action did not take // place. This may include errors such as command line too long. StatusSyntaxErrorNotRecognised = 500 // RFC 959, 4.2.1 StatusSyntaxErrorParameters = 501 // RFC 959, 4.2.1 StatusCommandNotImplemented = 502 // RFC 959, 4.2.1 StatusBadCommandSequence = 503 // RFC 959, 4.2.1 StatusNotImplementedParam = 504 // RFC 959, 4.2.1 StatusNotLoggedIn = 530 // RFC 959, 4.2.1 StatusActionNotTaken = 550 // RFC 959, 4.2.1 StatusActionAborted = 552 // RFC 959, 4.2.1 StatusActionNotTakenNoFile = 553 // RFC 959, 4.2.1 )
Status codes as documented by: https://tools.ietf.org/html/rfc959 https://tools.ietf.org/html/rfc2428 https://tools.ietf.org/html/rfc2228
Variables ¶
var ( // ErrStorageExceeded defines the error mapped to the FTP 552 reply code. // As for RFC 959 this error is checked for STOR, APPE ErrStorageExceeded = errors.New("storage limit exceeded") // ErrFileNameNotAllowed defines the error mapped to the FTP 553 reply code. // As for RFC 959 this error is checked for STOR, APPE, RNTO ErrFileNameNotAllowed = errors.New("filename not allowed") )
var ErrNoAvailableListeningPort = errors.New("could not find any port to listen to")
ErrNoAvailableListeningPort is returned when no port could be found to accept incoming connection
var ErrNotListening = errors.New("we aren't listening")
ErrNotListening is returned when we are performing an action that is only valid while listening
var ErrRemoteAddrFormat = errors.New("remote address has a bad format")
ErrRemoteAddrFormat is returned when the remote address has a bad format
Functions ¶
Types ¶
type ClientContext ¶
type ClientContext interface {
// Path provides the path of the current connection
Path() string
// SetPath sets the path of the current connection.
// This method is useful to set a start directory, you should use it before returning a successful
// authentication response from your driver implementation.
// Calling this method after the authentication step could lead to undefined behavior
SetPath(value string)
// SetListPath allows to change the path for the last LIST/NLST request.
// This method is useful if the driver expands wildcards and so the returned results
// refer to a path different from the requested one.
// The value must be cleaned using path.Clean
SetListPath(value string)
// SetDebug activates the debugging of this connection commands
SetDebug(debug bool)
// Debug returns the current debugging status of this connection commands
Debug() bool
// Client's ID on the server
ID() uint32
// Client's address
RemoteAddr() net.Addr
// Servers's address
LocalAddr() net.Addr
// Client's version can be empty
GetClientVersion() string
// Close closes the connection and disconnects the client.
Close() error
// HasTLSForControl returns true if the control connection is over TLS
HasTLSForControl() bool
// HasTLSForTransfers returns true if the transfer connection is over TLS
HasTLSForTransfers() bool
// GetLastCommand returns the last received command
GetLastCommand() string
// GetLastDataChannel returns the last data channel mode
GetLastDataChannel() DataChannel
// SetTLSRequirement sets the TLS requirement to respect on a per-client basis.
// The requirement is checked when the client issues the "USER" command,
// after executing the MainDriverExtensionUserVerifier extension, and
// before opening transfer connections.
// Supported values: ClearOrEncrypted, MandatoryEncryption.
// If you want to enforce the same requirement for all
// clients, use the TLSRequired parameter defined in server settings instead
SetTLSRequirement(requirement TLSRequirement) error
// SetExtra allows to set application specific data
SetExtra(extra any)
// Extra returns application specific data set using SetExtra
Extra() any
}
ClientContext is implemented on the server side to provide some access to few data around the client
type ClientDriver ¶
ClientDriver is the base FS implementation that allows to manipulate files
type ClientDriverExtensionAllocate ¶
type ClientDriverExtensionAllocate interface {
// AllocateSpace reserves the space necessary to upload files
AllocateSpace(size int) error
}
ClientDriverExtensionAllocate is an extension to support the "ALLO" - file allocation - command
type ClientDriverExtensionAvailableSpace ¶
type ClientDriverExtensionAvailableSpace interface {
GetAvailableSpace(dirName string) (int64, error)
}
ClientDriverExtensionAvailableSpace is an extension to implement to support the AVBL ftp command
type ClientDriverExtensionFileList ¶
type ClientDriverExtensionFileList interface {
// ReadDir reads the directory named by name and return a list of directory entries.
ReadDir(name string) ([]os.FileInfo, error)
}
ClientDriverExtensionFileList is a convenience extension to allow to return file listing without requiring to implement the methods Open/Readdir for your custom afero.File
type ClientDriverExtensionHasher ¶
type ClientDriverExtensionHasher interface {
ComputeHash(name string, algo HASHAlgo, startOffset, endOffset int64) (string, error)
}
ClientDriverExtensionHasher is an extension to implement if you want to handle file digests yourself. You have to set EnableHASH to true for this extension to be called
type ClientDriverExtensionRemoveDir ¶
ClientDriverExtensionRemoveDir is an extension to implement if you need to distinguish between the FTP command DELE (remove a file) and RMD (remove a dir). If you don't implement this extension they will be both mapped to the Remove method defined in your afero.Fs implementation
type ClientDriverExtensionSymlink ¶
type ClientDriverExtensionSymlink interface {
// Symlink creates a symlink
Symlink(oldname, newname string) error
}
ClientDriverExtensionSymlink is an extension to support the "SITE SYMLINK" - symbolic link creation - command
type ClientDriverExtentionFileTransfer ¶
type ClientDriverExtentionFileTransfer interface {
// GetHandle return an handle to upload or download a file based on flags:
// os.O_RDONLY indicates a download
// os.O_WRONLY indicates an upload and can be combined with os.O_APPEND (resume) or
// os.O_CREATE (upload to new file/truncate)
//
// offset is the argument of a previous REST command, if any, or 0
GetHandle(name string, flags int, offset int64) (FileTransfer, error)
}
ClientDriverExtentionFileTransfer is a convenience extension to allow to transfer files without requiring to implement the methods Create/Open/OpenFile for your custom afero.File.
type CommandDescription ¶
type CommandDescription struct {
Open bool // Open to clients without auth
TransferRelated bool // This is a command that can open a transfer connection
SpecialAction bool // Command to handle even if there is a transfer in progress
Fn func(*clientHandler, string) error // Function to handle it
}
CommandDescription defines which function should be used and if it should be open to anyone or only logged in users
type DataChannel ¶
type DataChannel int8
DataChannel is the enumerable that represents the data channel (active or passive)
const ( DataChannelPassive DataChannel = iota + 1 DataChannelActive )
Supported data channel types
type DataConnectionRequirement ¶
type DataConnectionRequirement int8
DataConnectionRequirement is the enumerable that represents the supported protection mode for data channels
const ( // IPMatchRequired requires matching peer IP addresses of control and data connection IPMatchRequired DataConnectionRequirement = iota // IPMatchDisabled disables checking peer IP addresses of control and data connection IPMatchDisabled )
Supported data connection requirements
type DriverError ¶
type DriverError struct {
// contains filtered or unexported fields
}
DriverError is a wrapper is for any error that occur while contacting the drivers
func (DriverError) Error ¶
func (e DriverError) Error() string
func (DriverError) Unwrap ¶
func (e DriverError) Unwrap() error
type FileAccessError ¶
type FileAccessError struct {
// contains filtered or unexported fields
}
FileAccessError is a wrapper for any error that occur while accessing the file system
func (FileAccessError) Error ¶
func (e FileAccessError) Error() string
func (FileAccessError) Unwrap ¶
func (e FileAccessError) Unwrap() error
type FileTransfer ¶
FileTransfer defines the inferface for file transfers.
type FileTransferError ¶
type FileTransferError interface {
TransferError(err error)
}
FileTransferError is a FileTransfer extension used to notify errors.
type FtpServer ¶
type FtpServer struct {
Logger log.Logger // fclairamb/go-log generic logger
// contains filtered or unexported fields
}
FtpServer is where everything is stored We want to keep it as simple as possible
func NewFtpServer ¶
func NewFtpServer(driver MainDriver) *FtpServer
NewFtpServer creates a new FtpServer instance
func (*FtpServer) ListenAndServe ¶
ListenAndServe simply chains the Listen and Serve method calls
type HASHAlgo ¶
type HASHAlgo int8
HASHAlgo is the enumerable that represents the supported HASH algorithms.
type MainDriver ¶
type MainDriver interface {
// GetSettings returns some general settings around the server setup
GetSettings() (*Settings, error)
// ClientConnected is called to send the very first welcome message
ClientConnected(cc ClientContext) (string, error)
// ClientDisconnected is called when the user disconnects, even if he never authenticated
ClientDisconnected(cc ClientContext)
// AuthUser authenticates the user and selects an handling driver
AuthUser(cc ClientContext, user, pass string) (ClientDriver, error)
// GetTLSConfig returns a TLS Certificate to use
// The certificate could frequently change if we use something like "let's encrypt"
GetTLSConfig() (*tls.Config, error)
}
MainDriver handles the authentication and ClientHandlingDriver selection
type MainDriverExtensionPassiveWrapper ¶
type MainDriverExtensionPassiveWrapper interface {
// WrapPassiveListener is called after creating the listener for passive
// data connections.
// You can wrap the passed listener or just return it unmodified.
// Returning an error will cause the passive connection to fail
WrapPassiveListener(listener net.Listener) (net.Listener, error)
}
MainDriverExtensionPassiveWrapper is an extension that allows to wrap the listener used for passive connection
type MainDriverExtensionPostAuthMessage ¶
type MainDriverExtensionPostAuthMessage interface {
// PostAuthMessage is called after the authentication
PostAuthMessage(cc ClientContext, user string, authErr error) string
}
MainDriverExtensionPostAuthMessage is an extension that allows to send a message after the authentication
type MainDriverExtensionQuitMessage ¶
type MainDriverExtensionQuitMessage interface {
// QuitMessage returns the message to display when the user quits the server
QuitMessage() string
}
MainDriverExtensionQuitMessage is an extension that allows to control the quit message
type MainDriverExtensionTLSVerifier ¶
type MainDriverExtensionTLSVerifier interface {
// VerifyConnection is called when receiving the "USER" command.
// If it returns a non-nil error, the client will receive a 530 error and it will be disconnected.
// If it returns a non-nil ClientDriver and a nil error the client will be authenticated.
// If it returns a nil ClientDriver and a nil error the user password is required
VerifyConnection(cc ClientContext, user string, tlsConn *tls.Conn) (ClientDriver, error)
}
MainDriverExtensionTLSVerifier is an extension that allows to verify the TLS connection estabilished on the control channel
type MainDriverExtensionUserVerifier ¶
type MainDriverExtensionUserVerifier interface {
// PreAuthUser is called when receiving the "USER" command before proceeding with any other checks
// If it returns a non-nil error, the client will receive a 530 error and be disconnected.
PreAuthUser(cc ClientContext, user string) error
}
MainDriverExtensionUserVerifier is an extension that allows to control user access once username is known, before the authentication
type NetworkError ¶
type NetworkError struct {
// contains filtered or unexported fields
}
NetworkError is a wrapper for any error that occur while contacting the network
func (NetworkError) Error ¶
func (e NetworkError) Error() string
func (NetworkError) Unwrap ¶
func (e NetworkError) Unwrap() error
type PasvPortGetter ¶
PasvPortGetter is called when a passive transfer is booting and provides a pair of ports. The first will be exposed to the client, the second will be listened on
func PortMapper ¶
func PortMapper(exposedStart, exposedEnd, listenedStart int) PasvPortGetter
PortMapper generates a PasvPortGetter from a map of ports
func PortRange ¶
func PortRange(start, end int) PasvPortGetter
PortRange generates a PasvPortGetter from a range of ports
type PublicIPResolver ¶
type PublicIPResolver func(ClientContext) (string, error)
PublicIPResolver takes a ClientContext for a connection and returns the public IP to use in the response to the PASV command, or an error if a public IP cannot be determined.
type Settings ¶
type Settings struct {
Listener net.Listener // (Optional) To provide an already initialized listener
ListenAddr string // Listening address
PublicHost string // Public IP to expose (only an IP address is accepted at this stage)
PublicIPResolver PublicIPResolver // (Optional) To fetch a public IP lookup
PassiveTransferPortGetter PasvPortGetter // (Optional) Port Range for data connections. Random if not specified
FindPasvPortAttempts int // Maximum number of attempt on finding available passive transfer port
ActiveTransferPortNon20 bool // Do not impose the port 20 for active data transfer (#88, RFC 1579)
IdleTimeout int // Maximum inactivity time before disconnecting (#58)
ConnectionTimeout int // Maximum time to establish passive or active transfer connections
DisableMLSD bool // Disable MLSD support
DisableMLST bool // Disable MLST support
DisableMFMT bool // Disable MFMT support (modify file mtime)
Banner string // Banner to use in server status response
TLSRequired TLSRequirement // defines the TLS mode
DisableLISTArgs bool // Disable ls like options (-a,-la etc.) for directory listing
DisableSite bool // Disable SITE command
DisableActiveMode bool // Disable Active FTP
EnableHASH bool // Enable support for calculating hash value of files
DisableSTAT bool // Disable Server STATUS, STAT on files and directories will still work
DisableSYST bool // Disable SYST
EnableCOMB bool // Enable COMB support
DefaultTransferType TransferType // Transfer type to use if the client don't send the TYPE command
// SiteHandlers defines custom SITE command handler
SiteHandlers map[string]SiteHandler
// ActiveConnectionsCheck defines the security requirements for active connections
ActiveConnectionsCheck DataConnectionRequirement
// PasvConnectionsCheck defines the security requirements for passive connections
PasvConnectionsCheck DataConnectionRequirement
}
Settings defines all the server settings
type SiteHandler ¶
type SiteHandler func(string, ClientDriver) (int, string)
SiteHandler defines how a SITE command works
type TLSRequirement ¶
type TLSRequirement int8
TLSRequirement is the enumerable that represents the supported TLS mode
const ( ClearOrEncrypted TLSRequirement = iota MandatoryEncryption ImplicitEncryption )
TLS modes
type TransferType ¶
type TransferType int8
TransferType is the enumerable that represents the supported transfer types.
const ( TransferTypeASCII TransferType = iota TransferTypeBinary )
Supported transfer type