A server MAY have a policy statement somewhere that might:
- Deny any command before TLS is negotiated (this might cause
problems if a SITE or some such command is required prior to
login).
- Deny certain commands before TLS is negotiated (e.g., USER,
PASS, or ACCT).
- Deny insecure USER commands for certain users (e.g., not
ftp/anonymous).
- Deny secure USER commands for certain users (e.g.,
ftp/anonymous).
- Define the level(s) of TLS to be allowed.
- Define the CipherSuites allowed to be used (perhaps on a per
host/domain/... basis).
- Allow TLS authentication as a substitute for local
authentication.
- Define data connection policies (see next section).
It is possible that the TLS negotiation may not be completed
satisfactorily for the server, in which case it can be one of
these states.
The TLS negotiation failed completely
In this case, the control connection should still be in an
unprotected mode and the server SHOULD issue an unprotected
’421’ reply to end the session.
The TLS negotiation completed successfully, but the server
decides that the session parameters are not acceptable (e.g.,
Distinguished Name in the client certificate is not permitted
to use the server).
In this case, the control connection should still be in a
protected state, so the server MAY either continue to refuse
to service commands or issue a protected ’421’ reply and
close the connection.
The TLS negotiation failed during the TLS handshake
In this case, the control connection is in an unknown state
and the server SHOULD simply drop the control connection.
The server code will be responsible for implementing the required
policies and ensuring that the client is prevented from circumventing
the chosen security by refusing to service those commands that are
against policy.
10.2. The Server’s View of the Data Connection
The server can take one of four basic views of the data connection.
1 - Don’t allow encryption at all (in which case the PROT command
should not allow any value other than ’C’ - if it is allowed
at all).
2 - Allow the client to choose protection or not.
3 - Insist on data protection (in which case the PROT command must
be issued prior to the first attempted data transfer).
4 - Decide on one of the above three for each and every data
connection.
The server SHOULD only check the status of the data protection level
(for options 3 and 4 above) on the actual command that will initiate
the data transfer (and not on the PORT or PASV). The following
commands, defined in [RFC-959], cause data connections to be opened
and thus may be rejected before any 1xx message due to an incorrect
PROT setting.
STOR
RETR
NLST
LIST
STOU
APPE
The reply to indicate that the PROT setting is incorrect is ’521 data
connection cannot be opened with this PROT setting’
If the protection level indicates that TLS is required, then it
should be negotiated once the data connection is made. Thus, the
’150’ reply only states that the command can be used given the
current PROT level. Should the server not like the TLS negotiation,
then it will close the data port immediately and follow the ’150’
command with a ’522’ reply, which indicates that the TLS negotiation
failed or was unacceptable. (Note: This means that the application
can pass a standard list of CipherSuites to the TLS layer for
negotiation, and review the one negotiated for applicability in each
instance).
The Security Considerations section discusses the issue of cross-
checking any certificates used to authenticate the data connection
with the one(s) used to authenticate the control connection. This is
an important security step.
It is reasonable for the server to insist that the data connection
uses a TLS cached session. This might be a cache of a previous data
connection or of a cleared control connection. If this is the reason
for the refusal to allow the data transfer, then the ’522’ reply
should indicate this.
Note: This has an important impact on client design, but allows
servers to minimise the cycles used during TLS negotiation by
refusing to perform a full negotiation with a previously
authenticated client.
It should be noted that the TLS authentication of the server will be
authentication of the server host itself and not a user on the server
host.
10.3. The Client’s View of the Control Connection
In most cases, it is likely that the client will be using TLS because
the server would refuse to interact insecurely. To allow for this,
clients SHOULD be flexible enough to manage the securing of a session
at the appropriate time and still allow the user/server policies to
dictate exactly when during the session the security is negotiated.
In the case where it is the client that is insisting on the securing
of the session, the client will need to ensure that the negotiations
are all completed satisfactorily and will need to be able to sensibly
inform the user should the server not support, or not be prepared to
use, the required security levels.
Clients SHOULD be coded in such a manner as to allow the timing of
the AUTH, PBSZ, and PROT commands to be flexible and dictated by the
server. It is quite reasonable for a server to refuse certain
commands prior to these commands. Similarly, it is quite possible
that a SITE or quoted command might be needed by a server prior to
the AUTH. A client MUST allow a user to override the timing of these
commands to suit a specific server.
For example, a client SHOULD NOT insist on sending the AUTH as the
first command in a session, nor should it insist on issuing a
PBSZ/PROT pair directly after the AUTH. This may well be the default
behaviour, but must be overridable by a user.
The TLS negotiation may not be completed satisfactorily for the
client, in which case it will be in one of these states:
The TLS negotiation failed completely
In this case, the control connection should still be in an
unprotected mode and the client should issue an unprotected
QUIT command to end the session.
The TLS negotiation completed successfully, but the client decides
that the session parameters are not acceptable (e.g.,
Distinguished Name in certificate is not the actual server
expected).
In this case, the control connection should still be up in a
protected state, so the client should issue a protected QUIT
command to end the session.
The TLS negotiation failed during the TLS handshake.
In this case, the control connection is in an unknown state and
the client should simply drop the control connection.
10.4. The Client’s View of the Data Connection
Client security policies
Clients do not typically have ’policies’ as such, instead they
rely on the user to define their actions and, to a certain extent,
are reactive to the server policy. Thus, a client will need to
have commands that will allow the user to switch the protection
level of the data connection dynamically; however, there may be a
general ’policy’ that attempts all LIST and NLST commands on a
Clear connection first (and automatically switches to Private if
it fails). In this case, there would need to be a user command
available to ensure that a given data transfer was not attempted
on an insecure data connection.
Clients also need to understand that the level of the PROT setting
is only checked for a particular data transfer after that transfer
has been requested. Thus, a refusal by the server to accept a
particular data transfer should not be read by the client as a
refusal to accept that data protection level completely, as not
only may other data transfers be acceptable at that protection
level, but it is entirely possible that the same transfer may be
accepted at the same protection level at a later point in the
session.
It should be noted that the TLS authentication of the client
should be an authentication of a user on the client host and not
the client host itself.
11. Who Negotiates What, Where, and How
11.1. Do we protect at all?
Client issues ’AUTH TLS’, server accepts or rejects. If the server
needs AUTH, then it refuses to accept certain commands until it gets
a successfully protected session.
11.2. What level of protection do we use on the Control connection?
Decided entirely by the TLS CipherSuite negotiation.
11.3. Do we protect data connections in general?
Client issues PROT command, server accepts or rejects.
11.4. Is protection required for a particular data transfer?
A client would have already issued a PROT command if it required the
connection to be protected.
If a server needs to have the connection protected, then it will
reply to the STOR/RETR/NLST/... command with a ’522’, indicating that
the current state of the data connection protection level is not
sufficient for that data transfer at that time.
11.5. What level of protection is required for a particular data
transfer?
Decided entirely by the TLS CipherSuite negotiation.
Thus, for flexibility, it can be seen that it is desirable for the
FTP application to be able to interact with the TLS layer upon which
it sits to define and discover the exact TLS CipherSuites that are to
be/have been negotiated and to make decisions accordingly.
12. Timing Diagrams
These timing diagrams aim to help explain exactly how the TLS
handshake and session protection fits into the existing logic of the
FTP protocol. Of course, the FTP protocol itself is not well
described with respect to the timing of commands and responses in
[RFC-959], so this is partly based on empirical observation of
existing widespread client and server implementations.
12.1. Establishing a Protected Session
Client Server
control data data control
====================================================================
socket()
bind()
socket()
connect() ----------------------------------------------> accept()
<---------------------------------------------- 220
AUTH TLS ---------------------------------------------->
<---------------------------------------------- 234
TLSneg() <----------------------------------------------> TLSneg()
PBSZ 0 ---------------------------------------------->
<---------------------------------------------- 200
PROT P ---------------------------------------------->
<---------------------------------------------- 200
USER fred ---------------------------------------------->
<---------------------------------------------- 331
PASS pass ---------------------------------------------->
<---------------------------------------------- 230
Note 1: The order of the PBSZ/PROT pair and the USER/PASS pair (with
respect to each other) is not important (i.e., the USER/PASS can
happen prior to the PBSZ/PROT, or the server can refuse to allow a
PBSZ/PROT pair until the USER/PASS pair has happened).
Note 2: The PASS command might not be required at all (if the USER
parameter and any client identity presented provide sufficient
authentication). The server would indicate this by issuing a ’232’
reply to the USER command instead of the ’331’, which requests a PASS
from the client (see below).
Note 3: The AUTH command might not be the first command after the
receipt of the 220 welcome message.
12.2. Establishing a Protected Session Without a Password Request
(The TLS Authentication is Sufficient)
Client Server
control data data control
====================================================================
socket()
bind()
socket()
connect() ----------------------------------------------> accept()
<---------------------------------------------- 220
AUTH TLS ---------------------------------------------->
<---------------------------------------------- 234
TLSneg() <----------------------------------------------> TLSneg()
PBSZ 0 ---------------------------------------------->
<---------------------------------------------- 200
PROT P ---------------------------------------------->
<---------------------------------------------- 200
USER fred ---------------------------------------------->
<---------------------------------------------- 232
12.3. Establishing a Protected Session and then Clearing with the CCC
Command
Client Server
control data data control
====================================================================
socket()
bind()
socket()
connect() ----------------------------------------------> accept()
<---------------------------------------------- 220
AUTH TLS ---------------------------------------------->
<---------------------------------------------- 234
TLSneg() <----------------------------------------------> TLSneg()
PBSZ 0 ---------------------------------------------->
<---------------------------------------------- 200
PROT P ---------------------------------------------->
<---------------------------------------------- 200
USER fred ---------------------------------------------->
<---------------------------------------------- 232
CCC ---------------------------------------------->
<---------------------------------------------- 200
TLSshutdown() <-------------------------------------> TLSshutdown()
- The rest of the control session continues in plaintext with
protected data transfers (due to PROT P).
Note: This has serious security issues (see Security Considerations
section) but may be useful in a firewall/NAT scenario.
12.4. A Standard Data Transfer Without Protection
Client Server
control data data control
====================================================================
socket()
bind()
PORT w,x,y,z,a,b ----------------------------------------->
<----------------------------------------------------- 200
STOR file ------------------------------------------------>
socket()
bind()
<----------------------------------------------------- 150
accept() <----------- connect()
write() -----------> read()
close() -----------> close()
<----------------------------------------------------- 226
12.5. A Firewall-Friendly Data Transfer Without Protection
Client Server
control data data control
====================================================================
PASV -------------------------------------------------------->
socket()
bind()
<------------------------------------------ 227 (w,x,y,z,a,b)
socket()
STOR file --------------------------------------------------->
connect() ----------> accept()
<-------------------------------------------------------- 150
write() ----------> read()
close() ----------> close()
<-------------------------------------------------------- 226
Note: Implementers should be aware that the connect()/accept()
function is performed prior to the receipt of the reply from the STOR
command. This contrasts the with situation when a non-firewall-
friendly PORT is used prior to the STOR, and the accept()/connect()
is performed after the reply from the aforementioned STOR has been
dealt with.
12.6. A Standard Data Transfer with Protection
Client Server
control data data control
====================================================================
socket()
bind()
PORT w,x,y,z,a,b -------------------------------------------->
<-------------------------------------------------------- 200
STOR file --------------------------------------------------->
socket()
bind()
<-------------------------------------------------------- 150
accept() <---------- connect()
TLSneg() <----------> TLSneg()
TLSwrite() ----------> TLSread()
TLSshutdown() -------> TLSshutdown()
close() ----------> close()
<-------------------------------------------------------- 226
12.7. A Firewall-Friendly Data Transfer with Protection
Client Server
control data data control
====================================================================
PASV -------------------------------------------------------->
socket()
bind()
<------------------------------------------ 227 (w,x,y,z,a,b)
socket()
STOR file --------------------------------------------------->
connect() ----------> accept()
<-------------------------------------------------------- 150
TLSneg() <---------> TLSneg()
TLSwrite() ---------> TLSread()
TLSshutdown() -------> TLSshutdown()
close() ---------> close()
<-------------------------------------------------------- 226
13. Discussion of the REIN Command
The REIN command, defined in [RFC-959], allows the user to reset the
state of the FTP session. From [RFC-959]:
REINITIALIZE (REIN)
This command terminates a USER, flushing all I/O and account
information, except to allow any transfer in progress to be
completed. All parameters are reset to the default settings
and the control connection is left open. This is identical to
the state in which a user finds himself immediately after the
control connection is opened. A USER command may be expected
to follow.
When this command is processed by the server, the TLS session(s) MUST
be cleared and the control and data connections revert to
unprotected, clear communications. It MAY be acceptable to use
cached TLS sessions for subsequent connections, however, a server
MUST NOT mandate this.
If the REIN command is being used to clear a TLS session, then the
reply to the REIN command MUST be sent in a protected session prior
to the session(s) being cleared.
14. Discussion of the STAT and ABOR Commands
The ABOR and STAT commands and the use of TCP Urgent Pointers
[RFC-959] describes the use of Telnet commands (IP and DM) and the
TCP Urgent pointer to indicate the transmission of commands on the
control channel during the execution of a data transfer. FTP uses
the Telnet Interrupt Process and Data Mark commands in conjunction