RFC 7151

File Transfer Protocol HOST Command for Virtual Hosts

πŸ“… published March 2014, from ietf

RFC 7151 πŸ’– File Transfer Protocol HOST Command for Virtual Hosts

okay bestie, this is RFC 7151 and it's about a new FTP command called HOST πŸŽ€ Here's the title block tea: it's by P. Hethmon (Hethmon Brothers) and R. McMurray (Microsoft Corporation). It's a Standards Track doc, published March 2014, with ISSN 2070-1721. It updates RFC 959 (that's the original FTP spec), and the header doesn't list anything it obsoletes. ✨

Abstract 🌸

Okay so, RFC 959 (the original FTP spec) has no way for FTP clients and servers to tell apart multiple DNS names that are all registered to one IP address. This doc adds a new FTP command that lets clients and servers identify individual virtual hosts on an FTP server. Main character energy πŸ‘‘

Status of This Memo πŸ“œ

This is an Internet Standards Track document. πŸ¦‹

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 5741.

Info about the current status of this doc, any errata, and how to give feedback is at http://www.rfc-editor.org/info/rfc7151. πŸ’…

Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved. 🫢

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License. πŸ™ˆ

Table of Contents πŸ—ΊοΈ

1. Introduction ....................................................2
2. Document Conventions ............................................3
   2.1. Basic Tokens ...............................................3
   2.2. Server Replies .............................................4
3. The HOST Command ................................................4
   3.1. Syntax of the HOST Command .................................5
   3.2. HOST Command Semantics .....................................7
        3.2.1. REIN Command Semantics ..............................8
        3.2.2. User-PI Usage of HOST ...............................9
        3.2.3. State Diagrams .....................................11
   3.3. HOST Command Errors .......................................16
   3.4. FEAT Response for HOST Command ............................17
4. Security Considerations ........................................17
5. IANA Considerations ............................................19
6. References .....................................................19
   6.1. Normative References ......................................19
   6.2. Informative References ....................................20
Appendix A. Unworkable Alternatives ...............................21
  A.1. Overloading the CWD Command ................................21
  A.2. Overloading the ACCT Command ...............................21
  A.3. Overloading the USER Command ...............................22
  A.4. Conclusion .................................................23
Appendix B. Acknowledgements ......................................23

1. Introduction 🧚

It's super common on the Internet for lots of DNS names to resolve to a single IP address. This practice gave us the idea of a "virtual host", where a host appears to be an independent entity but actually shares its physical resources with one or more similar hosts. 🌈

This setup causes some problems for FTP servers, because an FTP server tells incoming FTP connections apart by IP address rather than by DNS name. So all DNS names that share an IP address get handled by the same FTP server and share the same Network Virtual File System (NVFS). 😭

That means different virtual hosts can't offer clients different virtual file systems, and they can't offer different authentication systems either. Any fix for this has to indicate not only the destination IP address but also the virtual hostname that goes with the virtual FTP server the client wants. Right now, typical user-FTP processes use hostnames to resolve the IP address and then ignore the hostname for the rest of the FTP session. So any fix would need changes to the user protocol interpreter (user-PI) and the server protocol interpreter (server-PI). πŸ”₯

Worth noting: this same problem existed for HTTP/1.0 as defined in [RFC1945], and it was solved in HTTP/1.1 as defined in [RFC2616] by adding the Host request header field. The goal of this document is to give FTP that same level of feature parity by introducing a new HOST command. It lets a user-FTP process say which virtual host it wants to connect to, on a server-FTP process that handles requests for multiple virtual hosts on a single IP address. ✨

2. Document Conventions πŸŽ€

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. πŸ’œ

In examples, "C>" and "S>" indicate lines sent by the client and server, respectively. πŸ“

This document also uses notation defined in [RFC959] and [RFC1123]. Specifically, the terms "reply", "user", "NVFS", "NVT", "file", "pathname", "FTP commands", "DTP", "user-FTP process", "user-PI", "user-DTP", "server-FTP process", "server-PI", "server-DTP", "mode", "type", "control connection", "data connection", and "ASCII" all mean exactly what they mean there. πŸ“–

The required syntax is written in the Augmented BNF from [RFC5234]. Some general ABNF definitions are needed throughout the document, and they'll be defined in later sections. 🧁

With virtualization tech being used so much these days, there might be several possible definitions for "virtual host". This document follows the definition from Section 4.1.14 of [RFC3875], where several virtual hosts share the same IP address, and hostnames are how the server-FTP process routes user-PI sessions to the right virtual host. πŸ¦‹

2.1. Basic Tokens πŸ’…

This document imports the core definitions from Appendix B of [RFC5234]. That's where you'll find basic ABNF elements like ALPHA, DIGIT, SP, and so on. On top of those, this document adds the following term. 🌸

   TCHAR = VCHAR / SP / HTAB    ; visible plus white space

The VCHAR rule (from [RFC5234]) and the TCHAR rule give basic character types from different subsets of the ASCII character set, for use in various commands and responses. πŸ”₯

Quick heads-up: in ABNF, string literals are case insensitive. That convention is kept in this document, which means the FTP commands and parameters added by this spec can be written in any case. So "HOST" is the same as "host", "Host", "HoSt", and so on. Domain names are also case insensitive, so "ftp.example.com" is the same as "Ftp.Example.Com", "fTp.eXample.cOm", and so on. πŸ’–

2.2. Server Replies πŸ—¨οΈ

Section 4.2 of [RFC959] defines the format and meaning of replies from the server-PI to FTP commands from the user-PI. This document uses those reply conventions without any changes. ✨

   error-response = error-code SP *TCHAR CRLF
   error-code     = ("4" / "5") 2DIGIT

Implementers should know that the ABNF syntax in this document and other FTP-related documents (but not the syntax in [RFC959]) sometimes shows replies in the one-line format. Unless it's explicitly stated otherwise, multi-line responses are also allowed. Implementers should assume that, unless stated to the contrary, any reply to any FTP command (including QUIT) can be in the multi-line format described in [RFC959]. 🫢

Throughout this document, replies are identified by the three-digit code that comes first in them. So the term "500 reply" means a reply from the server-PI using the three-digit code "500". πŸ“

3. The HOST Command 🌈

A new command, "HOST", is added to the FTP command set so that a server-FTP process can work out which of possibly many virtual hosts the client wants to connect to. If a HOST command is sent, it MUST be issued before the user is authenticated, because that lets the authentication scheme and the set of authorized users depend on the virtual host that gets chosen. πŸ‘‘

Server-FTP processes MUST treat a situation in which the HOST command is issued more than once before the user has been authenticated as though only the last HOST command had been sent. They then return the appropriate reply for that last HOST command. Server-FTP processes MUST treat a situation in which the HOST command is issued after the user has been authenticated as an erroneous sequence of commands, and return a 503 reply. πŸ™ˆ

Servers should note that the response to the HOST command is a good moment to send their "welcome" message. That lets the message be personalized for any virtual hosts that are supported. It also lets the client use the FEAT response to see which languages or representations the server supports, and pick one with the LANG command. See [RFC2640] for more information. 🧚

Also, user-PI implementations created before the HOST command was introduced won't support this new command. A similar problem came up when the Host header was introduced for HTTP in [RFC2616]. HTTP server implementations had to figure out how best to handle HTTP requests from down-level clients that didn't support the Host header. With that in mind, server-FTP processes will need to figure out how best to handle FTP requests from down-level FTP clients that don't support the HOST command. Those considerations are outside the scope of this document, though. πŸ¦‹

3.1. Syntax of the HOST Command πŸ’–

okay so here's the grammar for the HOST command 🧐 bestie, one thing first: [RFC3986] is still the source of truth for how IPv4 and IPv6 address literals are written. That keeps the presentation identical in 'ftp' URI hostname parts and in the protocol element here πŸŽ€

host-command  = "HOST" SP hostname CRLF
hostname      = domain / IP-literal

domain        = sub-domain *("." sub-domain)
sub-domain    = let-dig [ldh-str]
let-dig       = ALPHA / DIGIT
ldh-str       = *( ALPHA / DIGIT / "-" ) let-dig

IP-literal    = ( "[" IPv6address "]" ) / IPv4address

IPv6address   = <see [RFC3986] Section 3.2.2>
IPv4address   = <see [RFC3986] Section 3.2.2>

host-response = host-ok / error-response
host-ok       = "220" [ SP *TCHAR ] CRLF

The "hostname" rule is a tighter version of the "host" rule from [RFC3986] 🌸 This doc adds extra restrictions, and you'll see the details in the syntax talk later in this section. The whole point is to make implementers' lives easier by only allowing stuff that's precisely specified and actually used on the Internet. Iconic, honestly ✨

As with every FTP command, the "HOST" command word is case independent. You can type it in whatever case you want πŸ’…

The "hostname" parameter is the virtual host you want to access πŸ¦‹ It SHOULD be the same hostname that was used to get the IP address the FTP control connection was made to. This counts after any client conversions that turn an abbreviated or local alias into a full (fully qualified) domain name, but it's before you resolve a DNS alias (the owner of a CNAME resource record) to its canonical name. Main character sequencing, no cap πŸ‘‘

Internationalized domain names are only supported through Internationalized Domain Names for Applications (IDNA) "A-labels" for <sub-domain>, as described in [RFC5890]. For example, this HOST command specifies an internationalized domain name 🌈

HOST xn--e1afmkfd.com

Now, if the user was handed an IPv4 or IPv6 literal address, and so never had to derive it from a hostname, the client MAY send the HOST command with the IPv4 or IPv6 literal address exactly as it was given 🧚 Lowkey weird to send a literal address with HOST after you already connected using one, I know πŸ™ˆ But this is expected behaviour, because a user-FTP process shouldn't have to tell the difference between a fully qualified domain name and an IPv4 or IPv6 network literal address. That said, if the literal address the client specifies doesn't match the server's literal address, the server MUST respond with a 504 reply to say the IPv4 or IPv6 literal address isn't valid πŸ’€

When the hostname parameter has a literal address, square brackets are there to tell IPv6 address syntax apart from port number syntax πŸ“ So if the literal address is an IPv6 address, it is required to be enclosed in square brackets. (This is after getting rid of any syntax that might also be enclosed in brackets but doesn't have to be, and that the server used to work out a literal address was specified.) Here are some examples that MAY be sent if the client was told to connect to "192.0.2.1", "2001:db8::c000:201", or "::192.0.2.1", respectively, with IPv6 syntax preferred 🫢

HOST 192.0.2.1
HOST [2001:db8::c000:201]
HOST [::192.0.2.1]

The client MUST NOT send the port number as part of the HOST command, even if it was told to connect to a non-standard port πŸ™… The reason is that the user-PI has already set up a connection to the server-PI before the HOST command gets sent, so giving a different port with HOST means absolutely nothing 😭 For example, the server-PI MUST respond with a 501 reply if the client sends a HOST command that looks like either of these:

HOST 192.0.2.1:2112
HOST [2001:db8::c000:201]:2112

Otherwise, the hostname parameter is treated as a fully qualified domain name or a relative name, as those terms are defined in Section 3.1 of [RFC1034] πŸ“š That means the name is a case-independent string: uppercase ASCII characters count as the same as their lowercase ASCII versions, but otherwise they're kept exactly as given. It also means there are limits on the length of the parameter and of the parts that make up its internal structure. Those limits aren't changed in any way here 🌸

Neither [RFC1034] nor [RFC1035] puts any other restrictions on what names can be stored in the DNS. This spec, though, only allows names that can be inferred from the ABNF grammar given for "hostname" πŸ’… Similarly, this spec only allows address literals from the IPv4 and IPv6 address families that are well established on the Internet ✨


3.2. HOST Command Semantics πŸŽ€

When a server gets the HOST command, before it authenticates the user-PI, a server-FTP process SHOULD check that the hostname given is a valid virtual host for that server. If it is, the server-FTP process sets up the right environment for that virtual host πŸ¦‹ This doc doesn't specify what actions create that environment. They could be anything from doing nothing at all, to a simple change of working directory, to changing authentication schemes and/or username and password lists, or even much more elaborate state changes like creating isolated environments for each FTP session 🀯

The 220 reply code for the HOST command is the same code used in the initial "welcome" message that gets sent after the connection is established πŸ‘‘

If the hostname specified would normally be acceptable but is temporarily unavailable, the server-FTP process SHOULD respond to the HOST command with a 421 reply and close the connection 😭

Example: The server-FTP process is shutting down, so it responds to the HOST command with a 421 reply and closes the connection. In this scenario, the 421 reply tells the client it can retry at another time.

If the hostname specified is unknown to the server, or if the server is otherwise unwilling to treat this particular connection as a connection to the hostname specified, the server SHOULD respond with a 504 reply πŸ™ˆ

Examples: The particular virtual host that the HOST command specified is disabled at the server. The server responds with a 504 reply and keeps the connection open, so the user-PI gets a chance to name another virtual host with a later HOST command. Alternatively, the server-FTP process might choose to route all connections with unknown hostnames to a different virtual host, so no connection attempts end up failing. This design would be implementation specific and is outside the scope of this specification 🧚

3.2.1. REIN Command Semantics 🌈

As [RFC959] specifies, the REIN command returns the state of the connection to what it was right after the transport connection was opened. This spec makes no changes to that behaviour πŸ’– The effect of a HOST command MUST be reset if a REIN command is performed, and a new HOST command MUST be issued afterwards to connect to a virtual host. Non-negotiable, bestie 😀

3.2.2. User-PI Usage of HOST πŸ¦‹

A user-PI MUST send the HOST command after opening the transport connection, or after any REIN command, and before it tries to authenticate the user with the USER command. Here's what a typical login sequence might look like when HOST is used πŸŽ€

C> HOST ftp.example.com
S> 220 Host accepted
C> USER foo
S> 331 Password required
C> PASS bar
S> 230 User logged in

If a user-PI sends another HOST command before trying to authenticate the user, a server-FTP process MUST treat the additional HOST command as though no previous HOST command had been sent, and return the appropriate reply for the new HOST command. This is so useful, ngl. For example, if a user accidentally types the wrong virtual hostname, sending a subsequent HOST command fixes the mistake πŸ™Œ Here's what the login sequence might look like when HOST is sent twice before the user is authenticated:

C> HOST foo.example.com
S> 220 Host accepted
C> HOST bar.example.com
S> 220 Host accepted
C> USER foo
S> 331 Password required
C> PASS bar
S> 230 User logged in

The HOST command can be combined with the ACCT command to tell apart a user's various accounts on a specific virtual host πŸ’… In this scenario, the user-PI sends a HOST command, which the server-PI uses to route activity to the correct virtual host. The user-PI then sends credentials using the USER and PASS commands, which the server-PI validates. Then, the user-PI sends an ACCT command to specify any extra account information for the server-PI implementation. Here's a sequential series of client commands that send both HOST and ACCT, with the server responses left out for brevity:

C> HOST ftp.example.com
C> USER foo
C> PASS bar
C> ACCT project1

This is also true when HOST is used with the AUTH and ADAT commands discussed in [RFC2228] and [RFC4217] 🫢 In this scenario, the user-PI sends a HOST command, which the server-PI uses to route activity to the correct virtual host. Then the user-PI uses the AUTH and ADAT commands to negotiate the security mechanism and the relevant authentication token(s) with the server-PI. Next, the user-PI sends user credentials using the USER and PASS commands, which the server-PI validates. After that, the user-PI MAY send an ACCT command to specify any extra account information for the server-PI implementation. Here's a sequential series of client commands that send both HOST and ACCT alongside the security commands discussed in [RFC2228] and [RFC4217], with server responses omitted for brevity:

C> HOST ftp.example.com
C> AUTH <mechanism-name>
C> ADAT <base64data>
C> USER foo
C> PASS bar
C> ACCT project1

There's one exception to the above scenario 🚨 It happens when the user-PI provides the hostname in the "server_name" extension of a Transport Layer Security (TLS) extended client hello, as discussed in [RFC6066]. When the user-PI specifies the hostname in the "server_name" extension of a TLS extended client hello, the server-PI MUST verify that the hostname in the HOST command matches the value of the "server_name" extension. Here's a sequential series of client commands that use HOST alongside the TLS extensions discussed in [RFC6066], with server responses omitted for brevity:

C> AUTH TLS
C> HOST ftp.example.com
C> USER foo
C> PASS bar

Additional security information about using the HOST command with the security extensions discussed in [RFC2228], [RFC4217], and [RFC6066] is in Section 4 of this document πŸ”

3.2.3. State Diagrams ✨

okay so this section is the visual part of the RFC πŸŽ€ and honestly the diagrams are giving main character energy πŸ’… they show the typical back-and-forth between the user-PI and the server-PI, and they're modeled on the similar diagrams in Section 6 of [RFC959] 🧚

quick setup before we dive in 🫢 in every diagram, the (B) "begin" state is assumed to happen after the transport connection has opened, or after a REIN command has succeeded 🌸 and other commands that don't need authentication, like FEAT [RFC2389], may have slipped in before that πŸ’œ

some decoder rings for reading the diagrams πŸ”₯ a three-digit reply means a precise server reply code 🎯 but a single digit on a reply path means ANY reply starting with that digit, unless a precise code is already defined on another path πŸ™ˆ so a single "5" covers "500", "501", "502", and so on, when those codes aren't explicitly drawn in the diagram πŸ’€ every command has three possible outcomes: success (S), failure (F), or error (E) ✨ and in the diagrams we use "B" for "begin" and "W" for "wait for reply" πŸ¦‹

one more thing that's lowkey important πŸ‘‘ for each of these diagrams, even when no state transitions are shown, a REIN command will send the diagram from ANY wait state back to the (B) "begin" state 🌈

Figure 1 is the typical login sequence when HOST is used with USER and PASS to log in to a particular FTP virtual host πŸŽ€
          +---+   HOST    +---+ 1,3,5
          | B |---------->| W |-----------------
          +---+           +---+                 |
                           | |                  |
                 2,500,502 | | 4,501,503,504    |
             --------------   -----------       |
            |                            |      V
            V                   1        |    +---+
          +---+   USER    +---+-------------->| E |
          |   |---------->| W | 2        |    +---+
          +---+           +---+-------   |      ^
                           | |        |  |      |
                         3 | | 4,5    |  |      |
             --------------   -----   |  |      |
            |                      |  |  |      |
            |                -------------------
            |              1|      |  |  |
            V               |      |   ------>+---+
          +---+   PASS    +---+ 2  |     |    | S |
          |   |---------->| W |-------------->+---+
          +---+           +---+    |     |
                            |      |     |
                            |4,5   |     |
                            |      |      --->+---+
                            |       --------->| F |
                             ---------------->+---+

Figure 1: Typical Login Sequence with HOST Command 🌸

after a user has logged in, the server might want an extra account too 🏦 and the client can specify it using the ACCT command πŸ’– so Figure 2 shows the typical flow when HOST is used with USER and PASS to log in to an FTP virtual host AND ACCT is used to specify an account 🫢

          +---+   HOST    +---+ 1,3,5
          | B |---------->| W |-----------------
          +---+           +---+                 |
                           | |                  |
                 2,500,502 | | 4,501,503,504    |
             --------------   -------------     |
            |                              |    |
            V                   1          |    V
          +---+   USER    +---+-------------->+---+
          |   |---------->| W | 2       ----->| E |
          +---+           +---+------  |  --->+---+
                           | |       | | | |
                         3 | | 4,5   | | | |
             --------------   -----  | | | |
            |                      | | | | |
            |                      | | | | |
            |                ----------  | |
            |              1|      | |   | |
            V               |      | |   | |
          +---+   PASS    +---+ 2  |  ------->+---+
          |   |---------->| W |-------------->| S |
          +---+           +---+   ----------->+---+
                           | |   | |     | |
                         3 | |4,5| |     | |
             --------------   --------   |  ----
            |                    | |  |  |      |
            |                    | |  |  |      |
            |                ------------       |
            |            1,3|    | |  |         |
            V               |   2| |  |         V
          +---+   ACCT    +---+--  |   ------>+---+
          |   |---------->| W | 4,5 --------->| F |
          +---+           +---+-------------->+---+

Figure 2: Login Sequence with HOST and ACCT Commands πŸ’œ

Figure 3 is the one for when HOST is used with the AUTH and ADAT commands discussed in [RFC2228] πŸ” and yes there's a NOTE here that's important πŸ™ˆ Section 4 has extra details about using the HOST command with TLS πŸ”’

          +---+   HOST    +---+ 1,3,5
          | B |---------->| W |------------------
          +---+           +---+                  |
                           | |                   |
                 2,500,502 | | 4,501,503,504     |
             --------------   -------------      |
            |                              |     |
            V                              |     |
          +---+   AUTH    +---+ 4,5        |     |
          |   |---------->| W |----------->|     |
          +---+           +---+            |     |
                       334 | |             |     |
             --------------  |             |     |
            |            234 |             |     |
            |    ------------              |     |
            V   |               4,5        |     |
          +---+ | ADAT    +---+----------->|     |
          |   |---------->| W | 335        |     |
          +---+ |         +---+-----       |     |
            ^   |           |       |      |     |
            |   |           |       |      |     |
             -----------------------       |     |
                |           |              |     |
            ----        235 |              |     |
           |  --------------               |     |
           | |                             |     V
           V V                  1          |   +---+
          +---+   USER    +---+--------------->| E |
          |   |---------->| W | 2          |   +---+
          +---+           +---+-------     |     ^
                           | |        |    |     |
                         3 | | 4,5    |    |     |
             --------------   ------  |    |     |
            |                       | |    |     |
            |                --------------------
            |              1|       | |    |
            V               |       |  ------->+---+
          +---+   PASS    +---+ 2   |      |   | S |
          |   |---------->| W |--------------->+---+
          +---+           +---+     |      |
                            |       |      |
                            |4,5    |      |
                            |       |       -->+---+
                            |        --------->| F |
                             ----------------->+---+

Figure 3: Login Sequence with HOST and AUTH/ADAT Commands πŸ“

last one, and it's a whole vibe πŸ‘‘ after logging in with the security commands discussed in [RFC2228], the server might want an extra account, and the client can specify it with ACCT πŸ’… so Figure 4 shows the typical flow when HOST is used with AUTH and ADAT to log in to an FTP virtual host and ACCT is used to specify an account 🌈

          +---+   HOST    +---+ 1,3,5
          | B |---------->| W |------------------
          +---+           +---+                  |
                           | |                   |
                 2,500,502 | | 4,501,503,504     |
            +--------------   --------------     |
            |                               |    |
            V                               |    |
          +---+   AUTH    +---+ 4,5         |    |
          |   |---------->| W |------------>|    |
          +---+           +---+             |    |
                       334 | |              |    |
             --------------  |              |    |
            |            234 |              |    |
            |    ------------               |    |
            V   |               4,5         |    |
          +---+ | ADAT    +---+------------>|    |
          |   |---------->| W | 335         |    |
          +---+ |         +---+-----        |    |
            ^   |           |       |       |    |
            |   |           |       |       |    |
             -----------------------        |    |
                |           |               |    |
            ----         235|               |    |
           |  --------------                |    |
           | |                              |    |
           V V                  1           |    V
          +---+   USER    +---+--------------->+---+
          |   |---------->| W | 2        ----->| E |
          +---+           +---+-------  |  --->+---+
                           | |        | | | |
                         3 | | 4,5    | | | |
             --------------   ------  | | | |
            |                       | | | | |
            |                -----------  | |
            |              1|       | |   | |
            V               |       | |   | |
          +---+   PASS    +---+ 2   |  ------->+---+
          |   |---------->| W |--------------->| S |
          +---+           +---+   ------------>+---+
                           | |   |  |     | |

                         3 | |4,5|  |     | |
             --------------   ---------   |  ----
            |                    |  |  |  |      |
            |                -------------       |
            |            1,3|    |  |  |         |
            V               |   2|  |  |         V
          +---+   ACCT    +---+--   |   ------>+---+
          |   |---------->| W | 4,5  --------->| F |
          +---+           +---+--------------->+---+

Figure 4: Login Sequence with HOST and AUTH/ADAT/ACCT Commands πŸŽ€


3.2.3. State Diagrams ✨

3.3. HOST Command Errors ✨

okay bestie, so the server-PI SHOULD return a 500 or 502 reply if it doesn't recognize or implement the HOST command, as specified in [RFC959] πŸ’…. Like, a server-PI that's older or just doesn't follow this spec would be expected to send back a 500 or 502 reply. Totally normal, no cap πŸ™ˆ

As we talked about in Section 3 of this document, if someone sends a HOST command AFTER a user has been authenticated, the server MUST treat it as an invalid sequence of commands and send back a 503 reply. Not me sending HOST late to the party πŸ’€

A 501 reply SHOULD be sent if the hostname is syntactically invalid 🫢, and a 504 reply SHOULD be sent if the hostname is syntactically valid but isn't a valid virtual hostname for that server 🌸. In all of these cases, the server-FTP process MUST do one of the following:

a. Ignore the HOST command and act as if it was never sent. A user-FTP process MAY then send a new HOST command with a different hostname πŸ¦‹. b. Close the connection πŸ₯€.

When a user-PI gets a 500 or 502 reply to a HOST command, it SHOULD assume the server-PI doesn't do virtual servers via the HOST command πŸŽ€. The user-PI MAY then keep going and log in as if the HOST command was never sent. Lowkey iconic fallback behavior ✨.

If a user-PI gets an error reply that's different from the ones described here, it SHOULD assume the virtual HOST is unavailable and end communications 😭.

A server-PI that gets a USER command to start authentication without having received a HOST command SHOULD NOT reject the USER command 🫢. Clients that follow earlier FTP specs don't send HOST commands at all, so it's giving "be nice to the old clients" energy 🌈. In this case, the server MAY act as if some default virtual host had been explicitly selected πŸ’œ, or the server MAY enter an environment that's different from any supported virtual hosts. Like, maybe one where all the accounts are combined, and the NVFS looks like it has subdirectories holding the NVFS for every supported virtual host 🧚. Main character server energy πŸ‘‘.

3.4. FEAT Response for HOST Command ✨

When replying to the FEAT command [RFC2389], a server-FTP process that supports the HOST command MUST include a line containing the single word "HOST" πŸŽ€. This word is case insensitive, but it SHOULD be sent in upper case so it's easiest for different implementations to understand each other πŸ’–. So the response SHOULD be:

C> FEAT
S> 211- <any descriptive text>
S>  ...
S>  HOST
S>  ...
S> 211 End

The ellipses are placeholders where other features can go, but they're not required πŸ¦‹. The one-space indentation of the feature lines is mandatory [RFC2389] πŸ’….

4. Security Considerations πŸ”₯

Okay this section is SERIOUS, so pay attention πŸ‘€. As we talked about in Section 3 of this document, a server implementation MUST treat an extra HOST command that was sent before a user has been authenticated as though no previous HOST command was sent 😭. The server implementation MUST reset the authentication environment, because that's what lets each virtual host on an FTP server stay segregated from the others πŸ”. How the security environments are built can vary a lot depending on each server implementation and operating system, and those details are outside the scope of the protocol itself πŸ™ˆ. For example, a virtual host "foo.example.com" might use one username and password list, while "bar.example.com" on the same FTP server uses a different one πŸ’œ. In that kind of setup, resetting the security environment is necessary so the virtual servers look like they behave independently from the client's side, even though the actual implementation details don't matter at the protocol level 🌸.

Section 15.1.1 of [RFC4217] talks about using X.509 certificates for server authentication πŸ“œ. Keeping that info in mind, when securing FTP sessions with the mechanisms defined in [RFC4217], client implementations SHOULD verify that the hostname they put in the HOST command parameter matches the identity in the server's X.509 certificate, so man-in-the-middle attacks get blocked πŸ›‘οΈβœ¨.

When the HOST command is used together with the FTP security extensions introduced in [RFC2228] and [RFC4217], the HOST command SHOULD come before the security handshake when the user-PI is NOT providing the "server_name" in the extended client hello defined in [RFC6066] πŸ’…. This lets both the user-FTP and server-FTP processes map an FTP HOST to the correct server name in the server's certificate πŸŽ€. If the HOST command is sent AFTER the security handshake, mapping an FTP HOST to the correct certificate won't happen before the secure session is already established 😬.

For example, if a server-FTP process has several virtual hosts defined and no hostname was sent from a user-FTP process, the server-FTP process can't route the connection to the right virtual host when the connection is established πŸ™ƒ. So it's forced to pick a virtual host that will respond. When the user-PI tries to negotiate a secure connection, the virtual host the connection got routed to will respond with its server certificate during the security handshake πŸ”’. If that isn't the virtual host the user-FTP process meant to connect to, the user-PI won't be able to verify the server's identity from the certificate message πŸ’€.

However, if the user-PI IS providing the "server_name" in the extended client hello defined in Section 3 of [RFC6066], the user-PI MAY provide the HOST command after the security handshake πŸ¦‹. That's because the server can route the connection to the right virtual host based on the "server_name" extension, and the client can verify the server's identity from the matching server certificate message ✨. Even so, the server-PI MUST verify that the name in the HOST command matches the "server_name" provided in the extended client hello 🫢.

In general, client implementations SHOULD protect user credentials by using the FTP security extensions introduced in [RFC2228] and [RFC4217] πŸ”. A detailed discussion of securing FTP sessions is in those documents, and a general discussion of FTP security issues is in [RFC2577] πŸ“š.

5. IANA Considerations 🌈

IANA has registered the following FTP extension according to the procedure established by [RFC5797] πŸ’œ:

+------+---------+-------------+------+------+----------------------+
| cmd  | FEAT    | description | type | conf | RFC#s/References and |
|      | Code    |             |      |      | Notes                |
+------+---------+-------------+------+------+----------------------+
| HOST | HOST    | Hostname    | a    | o    | RFC 7151             |
+------+---------+-------------+------+------+----------------------+

6. References πŸ“š

6.1. Normative References

[RFC959]   Postel, J. and J. Reynolds, "File Transfer Protocol
           (FTP)", STD 9, RFC 959, October 1985.

[RFC1034]  Mockapetris, P., "Domain Names - Concepts and Facilities",
           STD 13, RFC 1034, November 1987.

[RFC1035]  Mockapetris, P., "Domain Names - Implementation and
           Specification", STD 13, RFC 1035, November 1987.

[RFC1123]  Braden, R., "Requirements for Internet Hosts - Application
           and Support", STD 3, RFC 1123, October 1989.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC2228]  Horowitz, M. and S. Lunt, "FTP Security Extensions", RFC
           2228, October 1997.

[RFC2389]  Hethmon, P. and R. Elz, "Feature negotiation mechanism for
           the File Transfer Protocol", RFC 2389, August 1998.

[RFC2640]  Curtin, B., "Internationalization of the File Transfer
           Protocol", RFC 2640, July 1999.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66, RFC
           3986, January 2005.

[RFC4217]  Ford-Hutchinson, P., "Securing FTP with TLS", RFC 4217,
           October 2005.

[RFC5234]  Crocker, D. and P. Overell, "Augmented BNF for Syntax
           Specifications: ABNF", STD 68, RFC 5234, January 2008.

[RFC5890]  Klensin, J., "Internationalized Domain Names for
           Applications (IDNA): Definitions and Document Framework",
           RFC 5890, August 2010.

[RFC6066]  Eastlake, D., "Transport Layer Security (TLS) Extensions:
           Extension Definitions", RFC 6066, January 2011.

6.2. Informative References

[RFC1945]  Berners-Lee, T., Fielding, R., and H. Nielsen, "Hypertext
           Transfer Protocol -- HTTP/1.0", RFC 1945, May 1996.

[RFC2577]  Allman, M. and S. Ostermann, "FTP Security
           Considerations", RFC 2577, May 1999.

[RFC2616]  Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
           Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
           Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.

[RFC3875]  Robinson, D. and K. Coar, "The Common Gateway Interface
           (CGI) Version 1.1", RFC 3875, October 2004.

[RFC5797]  Klensin, J. and A. Hoenes, "FTP Command and Extension
           Registry", RFC 5797, March 2010.

Appendix A. Unworkable Alternatives 🧚

Because adding a new command to FTP is such a big deal, it's worth going over some suggested alternatives to a HOST command and why they don't work πŸ’…. These ideas have been floated before, but each one got rejected for the reasons listed in its section of this appendix 🫢.

A.1. Overloading the CWD Command πŸ¦‹

One suggested method to fake virtual hosts is for the client to just send a CWD command after connecting, using the virtual hostname as the argument 🌸. That would let the server-FTP process set up each virtual host's file store as a subdirectory in its NVFS. It's simple in concept, and most server-FTP implementations support it without any code changes ✨. But while it's simple to describe and build, it has a few drawbacks 😬:

a. The CWD command is only available after the user-PI has authenticated itself to the server-FTP process. So all virtual hosts would need to share one authentication scheme if they used this method πŸ”.

b. To make the virtual host truly transparent, one of these has to be true πŸ€”: the server-FTP process gets modified to show the special nature of this first CWD command (which kinda defeats the whole point πŸ™ƒ), or all users see the exact same NVFS view when they connect (they have to connect to the same initial directory), or the NVFS implements the full set of virtual host directories at every possible initial directory for any possible user πŸ’€.

c. Unless the server is specially modified, a user connecting this way to a virtual host could easily move to any other virtual host on the same server-FTP process, which exposes what the virtual host really is πŸ‘€.

A.2. Overloading the ACCT Command πŸ’…

okay so the next idea was to just overload the ACCT command for FTP virtual hosts 🧚 but ngl it's a no from me, and the problem is when ACCT gets sent in the request flow. USER -> PASS -> ACCT is the login order from Sections 5.4 and 6 of [RFC959], and honestly it kinda works if one user just has a bunch of accounts on one server πŸŽ€. It falls apart for virtual hosts for two reasons:

a. The first problem is certificate negotiation when you're using the FTP security extensions in [RFC2228] and [RFC4217] πŸ”₯. To protect user credentials, the security mechanism and certificate have to be negotiated before the client sends any login credentials. The issue with using ACCT here is that nothing makes sure the certificate matches the right virtual host before the credentials go out 😭.

b. The second problem is how user credentials work for FTP virtual hosts. FTP server implementations can let each virtual host have its own custom user credentials 🌸. In one implementation, for example, the virtual host negotiation happens first, and then the credentials are looked up through that virtual host's own account mechanism. So again, the virtual host negotiation has to happen before the user credentials are sent 🫢.

A.3. Overloading the USER Command πŸ¦‹

another suggestion was to overload syntax that's already well known, by piggybacking on the existing USER command. Here's the example:

C> USER foo@example.com
S> 331 Password required
C> PASS bar
S> 230 User logged in

in this one, the user "foo" might be trying to log in to the virtual host "example.com" on an FTP server ✨. It sounds plausible at first, but it causes a bunch of implementation problems πŸ™ˆ:

a. Some network environments already use the "username@hostname" syntax for network credentials, where the "hostname" part points to where the user's credentials live in the network hierarchy πŸ’œ. With "foo@example.com", it gets really hard to tell apart two things: user "foo" logging in to a virtual host named "example.com" on an FTP server, and user "foo@example.com" logging in to an FTP server with no virtual host specified 😡.

b. When you use the FTP security extensions in [RFC2228] and [RFC4217], the security mechanism and certificate have to be negotiated before the client sends login credentials πŸ”. More specifically, the AUTH/ADAT commands must be sent before the USER command so the user credentials stay safe πŸ›‘οΈ. If you overload the USER command, there's no way to make sure the certificate matches the right virtual host before the client sends the user credentials πŸ’€.

A.4. Conclusion πŸ‘‘

after looking at all those alternatives, the group concluded that to get a proper emulation of "real" FTP servers, supporting virtual hosts needs changes on both the client and the server 🌈. So a brand-new FTP command is the most likely solution to give us the level of support we need ⭐.

Appendix B. Acknowledgements 🫢

Robert Elz and Paul Hethmon gave a super detailed discussion of the HOST command in their Internet-Draft called "Extensions to FTP", written while they were working with the FTPEXT Working Group of the IETF πŸŽ€. Their work formed the basis for a lot of this document, and we are so grateful for their help πŸ’–. They also want to credit Bernhard Rosenkraenzer for first suggesting and describing the HOST command πŸ“.

A bunch of people gave a ton of constructive feedback on earlier versions of this document, and that feedback really shaped where it ended up 🌸. Lots of their suggestions got put in, and their contributions are gratefully acknowledged πŸ’œ. There are way too many people to name here, but the authors specifically want to thank Alexey Melnikov, Alfred Hoenes, John Klensin, Joe Touch, Paul Ford-Hutchinson, Daniel Stenberg, Mykyta Yevstifeyev, Alec Rowell, Jaroslav Dunajsky, Wade Hilmo, Anthony Bryan, and Barry Leiba for their help ✨🌈.

Authors' Addresses πŸ–‹οΈ

Paul Hethmon
Hethmon Brothers
2305 Chukar Road
Knoxville, TN  37923
USA

EMail: phethmon@hethmon.com


Robert McMurray
Microsoft Corporation
One Microsoft Way
Redmond, WA  98052
USA

EMail: robmcm@microsoft.com
πŸ“¦ where this page comes from