Show / Hide Table of Contents
    • Overview
    • File system changes
    • Authorization/authentication as per RFC 2228
      • Account directories queryable
      • Membership provider changes
    • Connection
      • Connection data changes
      • Data connections
      • Connection checks
        • Idle check
        • Connection check
    • FTP middleware
      • FTP request middleware
      • FTP command execution middleware
    • Server commands
      • CloseConnectionServerCommand
      • SendResponseServerCommand
    • FTP command execution
      • FtpContext
      • Command handlers (and attributes)
      • Command extensions (and attributes)
      • FEAT support
    • Internals
      • FTP command collection changes
    • Changelog
      • What's new?
      • What's changed?
      • What's fixed?
    • A look into the future

    Overview

    After the upgrade 3.0, you'll see that the IFtpServer.Start and IFtpServer.Stop functions are deprecated. Please query the IFtpServerHost instead and use the StartAsync and StopAsync functions instead.

    You will notice breaking changes in the following areas:

    • File system
    • Membership provider
    • Command handlers (and attributes)
    • Command extensions (and attributes)
    • FEAT support
    • Connection
    • FTP command collection

    File system changes

    There are two important changes:

    • IFileSystemClassFactory.Create now requires an IAccountInformation parameter
    • The IUnixFileSystemEntry doesn't contain the FileSystem property anymore.

    Authorization/authentication as per RFC 2228

    The authorization/authentication stack is new and implemented as specified in the RFC 2228.

    This results in additional interfaces/extension points, like

    • IAuthorizationMechanism
    • IAuthenticationMechanism

    There is also a new extension point for actions to be called when the user is fully authorized: IAuthorizationAction. You can develop your own action, but you should only use an IAuthorizationAction.Level below 1000. The values from 1000 (incl.) to 2000 (incl.) are reserved by the FTP server and are used to initialize the FTP connection data.

    Account directories queryable

    A new interface has been introduced to get the root and home directories for a given user.

    Type name Description
    SingleRootWithoutHomeAccountDirectoryQuery Provides a single root for all users.
    RootPerUserAccountDirectoryQuery Gives every user its own root directory. Useful, when - for example - the file system root was set to /home.
    PamAccountDirectoryQuery Uses home directory information from PAM. The home directory can be configured to be the root instead.

    Membership provider changes

    The membership provider is now asynchronous which means that the ValidateUser function was renamed to ValidateUserAsync. Everything else is the same.

    Connection

    The IFtpConnection API was heavily overhauled to use a feature collection, where the features can be queried through the Features property. Using the WriteAsync function is obsolete. The FTP command handlers should use the CommandContexts ServerCommandWriter if they need to send out-of-band responses.

    Obsolete property Target feature
    Encoding IEncodingFeature
    OriginalStream ISecureConnectionFeature
    SocketStream ISecureConnectionFeature
    IsSecure ISecureConnectionFeature
    Obsolete method New home
    WriteAsync FtpCommandHandler.CommandContext.ResponseWriter or FtpCommandHandlerExtension.CommandContext.ResponseWriter

    Connection data changes

    The whole FtpConnectionData class is marked as obsolete.

    The connection datas IsAnonymous property is obsolete. An anonymous user is now detected by testing if the FtpConnectionData.User implements IAnonymousFtpUser.

    Most of the properties of IFtpConnection.Data were moved to a corresponding feature.

    Obsolete property Target feature
    NlstEncoding IEncodingFeature
    User IAuthorizationInformationFeature
    FileSystem IFileSystemFeature
    Path IFileSystemFeature
    CurrentDirectory IFileSystemFeature
    Language ILocalizationFeature
    Catalog ILocalizationFeature
    TransferMode ITransferConfigurationFeature
    PortAddress Removed
    TransferTypeCommandUsed Removed
    RestartPosition IRestCommandFeature
    RenameFrom IRenameCommandFeature
    ActiveMlstFacts IMlstFactsFeature
    PassiveSocketClient Removed
    BackgroundCommandHandler IBackgroundTaskLifetimeFeature
    CreateEncryptedStream ISecureConnectionFeature

    There's no direct replacement for the UserData property, but you can use the feature collection too.

    Data connections

    We're now using two factories to create data connections:

    • ActiveDataConnectionFeatureFactory for active data connections (PORT/EPRT commands)
    • PassiveDataConnectionFeatureFactory for passive data connections (PASV/EPSV commands)

    This factories create a IFtpDataConnectionFeature which is used to create IFtpDataConnection implementations. This allows us to abstract away the differences between active and passive data connections.

    The function IFtpConnection.CreateResponseSocket was replaced by DataConnectionServerCommand server command. The passed AsyncDataConnectionDelegate gets an IFtpDataConnection implementation and may return a response. This function also takes care of SSL/TLS encryption as it wraps the IFtpDataConnection implementation returned by the IFtpDataConnectionFeature into a new IFtpDataConnection implementation with the help of the SecureDataConnectionWrapper.

    The extension method SendResponseAsync on the IFtpConnection was replaced by the DataConnectionServerCommand server command and takes care of closing the IFtpDataConnection.

    Connection checks

    The FTP server allows to check if a connection is still active. It ensures that the server doesn't get filled with dead connections, where the server didn't recognize that the client is gone (e.g. client crash, aborted TCP connection, etc...).

    This was made possible by using the following two implementations for IFtpConnectionCheck:

    • FtpConnectionEstablishedCheck checks if the TCP connection is still established
    • FtpConnectionIdleCheck checks if the connection is idle for too long

    This checks are enabled by default and can be disabled and reenabled by the following extension methods for the IFtpServerBuilder:

    • DisableChecks disables all checks (the default ones and the ones manually enabled before)
    • EnableDefaultChecks enables all default checks (see above)
    • EnableIdleCheck enables the check for an idle connection
    • EnableConnectionCheck enables the check for an establised TCP connection
    • DisableIdleCheck enables the check for an idle connection
    • DisableConnectionCheck disables the check for an establised TCP connection

    The checks above are enabled by default.

    Idle check

    The idle check determines if the connection was idle for too long. The default timeout is 5 minutes, configured through FtpConnectionOptions.InactivityTimeout.

    Connection check

    This determines if the TCP connection is still established by sending an empty data packet to the client.

    FTP middleware

    There are two types of middlewares:

    • FTP request middleware (between FTP command collection and dispatch)
    • FTP command execution middleware (between FTP command dispatch and execution)

    FTP request middleware

    This middleware allows interception and modification of the received FTP commands. You must implement and register the IFtpMiddleware interface as service in your dependency injection container.

    FTP command execution middleware

    The difference between this and the former middleware is, that the FTP command handler for the FTP command is already selected and you can only intercept the FTP commands or do something special.

    You must implement and register the IFtpCommandMiddleware interface as service in your dependency injection container.

    An example is the FsIdChanger in the TestFtpServer project. This middleware sets - for every authenticated user - the UID/GID for file system access.

    Server commands

    We're now supporting custom FTP server commands. Those commands must implement IServerCommand and must have a corresponding handler (IServerCommandHandler<TCommand>).

    CloseConnectionServerCommand

    This command closes the FTP connection.

    SendResponseServerCommand

    This command sends a response to the client.

    FTP command execution

    Massive changes were done to the FTP command execution. The center of this changes is the new FtpContext which provides a new way to access all necessary information like the FTP connection, the command information and a channel to send server commands (which replaces IFtpConnection.WriteAsync).

    FtpContext

    The new FtpContext is the FTP servers equivalent of ASP.NET Core's HttpContext and provides access to all information required to execute the FTP commands.

    Command handlers (and attributes)

    The command handlers were overhauled in the following areas:

    • Lazy initialization
      • Removed commands from DI container
        • You can still add your FTP command handlers to the DI container, but those may (most likely) be ignored from version 4.0 and up.
        • Implement your own IFtpCommandHandlerScanner or reuse AssemblyFtpCommandHandlerScanner
      • New IFtpCommandHandlerScanner which scans for types that may implement FTP command handlers
      • New IFtpCommandHandlerProvider which returns information for all found FTP command handler types
    • Attributes for command information
      • FtpCommandHandlerAttribute which gives the FTP command handler a name and defines if it needs a successful login or if it's abortable
    • Simplified constructor due to CommandContext (type FtpCommandHandlerContext) property injection
    • Activated (read: instantiated with property injection) by command name using the IFtpCommandActivator service

    Command extensions (and attributes)

    The command extensions cannot be returned by IFtpCommandHandler.GetExtensions() anymore. The extensions were moved to their own file and the default extensions are automatically registered as service.

    • Lazy initialization
      • Removed command extensions from DI container
        • You can still add your FTP command handler extensions to the DI container, but those may (most likely) be ignored from version 4.0 and up.
        • Implement your own IFtpCommandHandlerExtensionScanner or reuse AssemblyFtpCommandHandlerExtensionScanner
      • New IFtpCommandHandlerExtensionScanner which scans for types that may implement FTP command handler extensions
      • New IFtpCommandHandlerExtensionProvider which returns information for all found FTP command handler extension types
    • Attributes for command extension information
      • FtpCommandHandlerExtensionAttribute which gives the FTP command handler extension a name and defines the command it extends and if it needs a successful login
    • Simplified constructor due to CommandContext (type FtpCommandHandlerContext) property injection
    • Automatic indirect activation (read: instantiation with property injection) for the command it belongs to through the IFtpCommandActivator service

    FEAT support

    There are two new attributes to get the string to be returned by a FEAT command:

    • FtpFeatureTextAttribute contains the feature text itself
    • FtpFeatureFunctionAttribute contains the name of the static function to be called to get the feature text

    Internals

    FTP command collection changes

    We're now using ReadOnlySpan for both TelnetInputParser and FtpCommandCollector.

    Changelog

    What's new?

    • In-memory file system
    • Unix file system
    • Passive data connection port range (contribution from 40three GmbH)
    • New IFtpServerHost interface
    • New IFtpService interface which allows easy integration into ASP.NET Core
    • New IAccountInformation interface
    • New IAnonymousFtpUser interface
    • New RFC 2228 compliant authentication/authorization
    • Root and home directories for an account can be queried
    • New IFtpMiddleware interface for custom request middleware
    • New IFtpCommandMiddleware interface for custom command execution middleware
    • New FTP connection checks

    What's changed?

    • Google drive upload without background uploader
    • The IFtpCommandHandler.GetExtensions() is now deprecated as all extensions that were previously returned here have their own implementation now
    • BREAKING: Usage of ReadOnlySpan in the FTP command collector
    • BREAKING: IFileSystemClassFactory.Create takes an IAccountInformation
    • BREAKING: The IMembershipProvider is now asynchronous
    • BREAKING: FtpConnectionData.IsAnonymous is obsolete, the anonymous user is now of type IAnonymousFtpUser
    • BREAKING: Moved PromiscuousPasv into PasvCommandOptions
    • BREAKING: Removed property PortAddress, TransferTypeCommandUsed, and PassiveSocketClient from FtpConnectionData, because we're using a new IFtpDataConnection abstraction

    What's fixed?

    • AUTH TLS fails gracefully when no SSL certificate is configured
    • SITE BLST works again
    • Fixed deadlock in MultiBindingTcpListener
    • Thread safe increment/decrement for connection counter (fixes #68)
    • The . directory will be returned again (fixes #56)

    A look into the future

    The 4.x version will drop support for .NET Standard 1.3 and - most likely - .NET 4.6.1 as the FTP Server will be reimplemented as ConnectionHandler which will result into the following improvements:

    • Easy hosting in an ASP.NET Core application
    • Using the ASP.NET Core connection state management
    • Improve this Doc
    Back to top
    Copyright © 2018 Fubar Development Junker
    Generated by DocFX
    Creative Commons License
    FluentMigrator Documentation by FluentMigrator Project is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.