Gumdrop

Gumdrop FTP Server

Gumdrop provides a complete FTP server implementation following RFC 959 and its security extensions (RFC 4217 for FTP-TLS). Like all Gumdrop protocol implementations, the FTP server uses the event-driven, non-blocking architecture that enables high concurrency with minimal resource consumption.

Contents

Protocol Support

The FTP server implements the File Transfer Protocol as defined in RFC 959, with modern extensions for security and IPv6.

Supported Commands

All standard FTP commands are implemented:

Extended Commands

Data Connection Modes

Both active and passive modes are supported:

Security Extensions

The server implements RFC 4217 (Securing FTP with TLS):

AUTH TLS

Upgrades the control connection to TLS. After successful AUTH TLS, credentials and commands are encrypted:

C: AUTH TLS
S: 234 AUTH TLS successful
[TLS negotiation]
C: USER alice
...

Implicit FTPS

When configured with secure="true", the server expects TLS from connection establishment. The listening port automatically defaults to 990 (per RFC 4217) unless an explicit port is set.

Data Connection Protection

Use requireTLSForData="true" to mandate encrypted data transfers.

Data Connection Security (RFC 4217 section 10)

In passive mode, the server verifies that the IP address of each incoming data connection matches the control connection’s client IP. Connections from mismatched addresses are rejected to prevent data connection hijacking.

Authentication

Authentication uses Gumdrop's centralised Realm interface. The FTP server supports traditional USER/PASS authentication:

C: USER alice
S: 331 User name okay, need password
C: PASS secret123
S: 230 User logged in

The Realm Interface

A Realm represents a collection of authenticatable principals. The built-in BasicRealm reads users from an XML file:

<realm>
  <group id="readers" name="ftp-read"/>
  <group id="writers" name="ftp-read ftp-write"/>
  <group id="admins" name="ftp-admin"/>
  
  <user name="alice" password="secret" groups="#writers"/>
  <user name="bob" password="password123" groups="#readers"/>
  <user name="admin" password="admin123" groups="#admins"/>
</realm>

Custom realm implementations can integrate with LDAP, databases, or external identity providers.

File System Handler

File operations are delegated to an FTPConnectionHandler, which provides access to the underlying storage:

FTPConnectionHandler Interface

The handler interface defines methods for all file operations:

Built-in Handlers

Role-Based Access Control

The RoleBasedFTPHandler enforces fine-grained access control based on user roles defined in the realm.

FTP Roles

Operation Mapping

CommandsRequired Role
RETR, LIST, NLST, STATftp-read
STOR, STOU, APPE, MKDftp-write
DELE, RMDftp-delete
RNFR, RNTOftp-write (source) + ftp-delete (if replacing)
SITE commandsftp-admin

Configuration Example

<realm id="ftpRealm" class="org.bluezoo.gumdrop.auth.BasicRealm">
    <property name="href">ftp-users.xml</property>
</realm>

<service id="ftp" class="org.bluezoo.gumdrop.ftp.file.RoleBasedFTPService">
    <property name="realm" ref="#ftpRealm"/>
    <property name="root-directory">/srv/ftp</property>
    <listener class="org.bluezoo.gumdrop.ftp.FTPListener">
        <property name="port">21</property>
        <property name="keystore-file">keystore.p12</property>
        <property name="keystore-pass">secret</property>
    </listener>
</service>

Filesystem-Level Enforcement

When filesystem-enforcement is true on RoleBasedFTPService, each handler's file system is wrapped in RoleAwareFTPFileSystem. This enforces read/write/delete roles at the filesystem operation level as a defence-in-depth layer, complementing the command-level checks in RoleBasedFTPHandler.

Configuration

FTPListener Properties

org.bluezoo.gumdrop.ftp.FTPListener (transport configuration):

RoleBasedFTPService Properties

org.bluezoo.gumdrop.ftp.file.RoleBasedFTPService (service logic):

Passive Mode Configuration

Timeouts

Example Configuration

<!-- FTP with explicit TLS (port 21 + AUTH TLS) -->
<service id="ftp" class="org.bluezoo.gumdrop.ftp.file.RoleBasedFTPService">
    <property name="realm" ref="#ftpRealm"/>
    <property name="root-directory">/srv/ftp</property>
    <listener class="org.bluezoo.gumdrop.ftp.FTPListener">
        <property name="port">21</property>
        <property name="keystore-file">keystore.p12</property>
        <property name="keystore-pass">secret</property>
        <property name="passive-port-min">50000</property>
        <property name="passive-port-max">50100</property>
        <property name="require-tls-for-data">true</property>
    </listener>
</service>

<!-- FTPS with implicit TLS (port defaults to 990 when secure) -->
<service id="ftps" class="org.bluezoo.gumdrop.ftp.file.RoleBasedFTPService">
    <property name="realm" ref="#ftpRealm"/>
    <property name="root-directory">/srv/ftp</property>
    <listener class="org.bluezoo.gumdrop.ftp.FTPListener">
        <property name="secure">true</property>
        <property name="keystore-file">keystore.p12</property>
        <property name="keystore-pass">secret</property>
    </listener>
</service>

Quota Management

The FTP server supports storage quotas to limit disk usage per user. Quotas are enforced on upload operations and can be queried via SITE commands.

SITE QUOTA Command

Users can query their current quota status:

ftp> quote SITE QUOTA
211-Quota Status for user 'alice'
211-Source: Role-based quota (premium)
211-Storage: 2.5 GB used of 10 GB (25%)
211 End

Administrators with the ftp-admin role can check other users:

ftp> quote SITE QUOTA bob
211-Quota Status for user 'bob'
211-Source: System default quota
211-Storage: 45 MB used of 100 MB (45%)
211 End

SITE SETQUOTA Command

Administrators can set per-user quotas:

ftp> quote SITE SETQUOTA alice 20GB
200 Quota set for user 'alice': 20 GB

Sizes accept standard suffixes: KB, MB, GB, TB. Use unlimited for no limit.

Upload Quota Enforcement

When a user attempts to upload a file that would exceed their quota, the server returns a 552 error:

ftp> put largefile.zip
552 Quota exceeded: 98 MB used of 100 MB

QuotaManager Configuration

Quotas are managed through a QuotaManager configured on the handler factory:

<component id="ftpQuota"
              class="org.bluezoo.gumdrop.quota.RoleBasedQuotaManager">
    <property name="realm" ref="#ftpRealm"/>
    <property name="storage-dir">/var/ftp/quota</property>
    <property name="default-quota">100MB</property>
    <property name="role-quota.premium">10GB</property>
    <property name="role-quota.enterprise">unlimited</property>
</component>

<service id="ftp" class="org.bluezoo.gumdrop.ftp.file.RoleBasedFTPService">
    <property name="realm" ref="#ftpRealm"/>
    <property name="root-directory">/srv/ftp</property>
    <property name="quota-manager" ref="#ftpQuota"/>
    <listener class="org.bluezoo.gumdrop.ftp.FTPListener" port="21"/>
</service>

Quota Policy Hierarchy

The RoleBasedQuotaManager determines a user's quota by checking:

  1. User-specific quota - set via SITE SETQUOTA
  2. Role-based quota - from roleQuota.{rolename} properties
  3. System default - from defaultQuota property

Telemetry

Quota operations integrate with Gumdrop's telemetry:


← Back to Main Page | HTTP Server & Client | SMTP Server & Client | IMAP Server | POP3 Server | Telemetry

Gumdrop FTP Server