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 AnswerCommand
- type ClientContext
- type ClientDriver
- type ClientDriverExtensionAllocate
- type ClientDriverExtensionAvailableSpace
- type ClientDriverExtensionFileList
- type ClientDriverExtensionHasher
- type ClientDriverExtensionRemoveDir
- type ClientDriverExtensionSite
- type ClientDriverExtensionSymlink
- type ClientDriverExtentionFileTransfer
- type CommandDescription
- type DataChannel
- type DataConnectionRequirement
- type DriverError
- type FileAccessError
- type FileTransfer
- type FileTransferError
- type Flusher
- type FtpServer
- type HASHAlgo
- type MainDriver
- type MainDriverExtensionPassiveWrapper
- type MainDriverExtensionPostAuthMessage
- type MainDriverExtensionQuitMessage
- type MainDriverExtensionTLSVerifier
- type MainDriverExtensionUserVerifier
- type NetworkError
- type PasvPortGetter
- type PortMappingRange
- type PortRange
- type PublicIPResolver
- type Settings
- type TLSRequirement
- type TransferFinalizer
- type TransferMode
- 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 AnswerCommand ¶ added in v0.27.0
AnswerCommand is a struct to answer a command to the client
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 ¶ added in v0.12.0
type ClientDriverExtensionAvailableSpace interface {
GetAvailableSpace(dirName string) (int64, error)
}
ClientDriverExtensionAvailableSpace is an extension to implement to support the AVBL ftp command
type ClientDriverExtensionFileList ¶ added in v0.9.0
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 ¶ added in v0.12.0
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 ¶ added in v0.9.0
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 ClientDriverExtensionSite ¶ added in v0.27.0
type ClientDriverExtensionSite interface {
Site(param string) *AnswerCommand
}
ClientDriverExtensionSite is an extension to implement if you want to handle SITE command yourself. You have to set DisableSite to false for this extension to be called
type ClientDriverExtensionSymlink ¶ added in v0.9.0
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 ¶ added in v0.9.0
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 ¶ added in v0.15.0
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 ¶ added in v0.16.0
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 ¶ added in v0.24.0
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 ¶ added in v0.24.0
func (e DriverError) Error() string
func (DriverError) Unwrap ¶ added in v0.24.0
func (e DriverError) Unwrap() error
type FileAccessError ¶ added in v0.24.0
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 ¶ added in v0.24.0
func (e FileAccessError) Error() string
func (FileAccessError) Unwrap ¶ added in v0.24.0
func (e FileAccessError) Unwrap() error
type FileTransfer ¶ added in v0.9.0
FileTransfer defines the inferface for file transfers.
type FileTransferError ¶ added in v0.9.0
type FileTransferError interface {
TransferError(err error)
}
FileTransferError is a FileTransfer extension used to notify errors.
type Flusher ¶ added in v0.29.0
type Flusher interface {
Flush() error
}
Flusher is the interface that wraps the basic Flush method.
type FtpServer ¶
type FtpServer struct {
Logger *slog.Logger // Structured logger (log/slog)
// 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 ¶ added in v0.12.0
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 ¶ added in v0.16.0
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 ¶ added in v0.23.0
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 ¶ added in v0.23.0
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 ¶ added in v0.13.0
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 ¶ added in v0.19.0
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 ¶ added in v0.24.0
type NetworkError struct {
// contains filtered or unexported fields
}
NetworkError is a wrapper for any error that occur while contacting the network
func (NetworkError) Error ¶ added in v0.24.0
func (e NetworkError) Error() string
func (NetworkError) Unwrap ¶ added in v0.24.0
func (e NetworkError) Unwrap() error
type PasvPortGetter ¶ added in v0.27.0
type PasvPortGetter interface {
// FetchNext returns the exposed one, the listened one and whether succeeded
FetchNext() (int, int, bool)
// NumberAttempts returns maximum number of attempts on finding an available passive transfer port
NumberAttempts() int
}
PasvPortGetter defined how the driver fetch a pair of ports used in passive transfer
type PortMappingRange ¶ added in v0.27.0
PortMappingRange is a range of mapped ports
func (PortMappingRange) FetchNext ¶ added in v0.27.0
func (r PortMappingRange) FetchNext() (int, int, bool)
FetchNext returns the next port mapping to try for the range
func (PortMappingRange) NumberAttempts ¶ added in v0.27.0
func (r PortMappingRange) NumberAttempts() int
NumberAttempts returns the number of attempts for the range
type PortRange ¶
PortRange is a range of ports
func (PortRange) NumberAttempts ¶ added in v0.27.0
NumberAttempts returns the number of attempts for the range
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)
Banner string // Banner to use in server status response
PassiveTransferPortRange PasvPortGetter // (Optional) Port Mapping for data connections. Random if not specified
PublicIPResolver PublicIPResolver // (Optional) To fetch a public IP lookup
IdleTimeout int // Maximum inactivity time before disconnecting (#58)
ConnectionTimeout int // Maximum time to establish passive or active transfer connections
ActiveTransferPortNon20 bool // Do not impose the port 20 for active data transfer (#88, RFC 1579)
DisableMLSD bool // Disable MLSD support
DisableMLST bool // Disable MLST support
DisableMFMT bool // Disable MFMT support (modify file mtime)
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
DeflateCompressionLevel int // Deflate compression level (1-9)
DefaultTransferType TransferType // Transfer type to use if the client don't send the TYPE command
// 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 TLSRequirement ¶ added in v0.12.0
type TLSRequirement int8
TLSRequirement is the enumerable that represents the supported TLS mode
const ( ClearOrEncrypted TLSRequirement = iota MandatoryEncryption ImplicitEncryption )
TLS modes
type TransferFinalizer ¶ added in v0.29.0
type TransferFinalizer interface {
FinalizeTransfer() error
}
TransferFinalizer is the interface for transfer streams that need explicit finalization (e.g., deflate streams need to write end-of-stream markers). This is distinct from closing the underlying connection. We use FinalizeTransfer() instead of Close() to distinguish from io.Closer, since net.Conn already implements io.Closer and we don't want to accidentally close the underlying connection.
type TransferMode ¶ added in v0.29.0
type TransferMode int8
TransferMode is the enumerable that represents the transfer mode (stream, block, compressed, deflate)
const ( // TransferModeStream is the standard uncompressed transfer mode TransferModeStream TransferMode = iota // TransferModeDeflate is the compressed transfer mode using deflate algorithm TransferModeDeflate )
Transfer modes
type TransferType ¶ added in v0.12.0
type TransferType int8
TransferType is the enumerable that represents the supported transfer types.
const ( TransferTypeASCII TransferType = iota TransferTypeBinary )
Supported transfer type