For my use-case, this is NOT a server-wide setting but a per-user
flag. Right now, the tls_control_required and tls_data_required
attributes control this in a server-wide fashion.
Requiring TLS per-user is a bit trickier. We would have to allow the
USER command, then return a 550 error if the user account provided
requires TLS (to prevent a bare PASS command from following).
I propose two new methods be added to the TLS_FTPHandler.
user_tls_control_required() and user_tls_data_required(). With these
new methods, the process_command() method would need to be changed
slightly.
Here is a theoretical implementation.
def user_tls_command_required(self, username):
if self.tls_control_required:
return True
return False
def user_tls_data_required(self, username):
if self.tls_data_required:
return True
return False
def process_command(self, cmd, *args, **kwargs):
if cmd == 'USER':
username = args[0]
else:
username = self.username
if cmd in ('USER', 'PASS'):
if self.user_tls_command_required(username) and not
self._ssl_established:
msg = "SSL/TLS required on the control channel."
self.respond("550 " + msg)
self.log_cmd(cmd, args[0], 550, msg)
return
elif cmd in ('PASV', 'EPSV', 'PORT', 'EPRT'):
if self.user_tls_command_required(username) and not
self._prot:
msg = "SSL/TLS required on the data channel."
self.respond("550 " + msg)
self.log_cmd(cmd, args[0], 550, msg)
return
FTPHandler.process_command(self, cmd, *args, **kwargs)
Then the user_tls_*_required() methods could be overridden to do per-
user lookups.
Disregard my code snippet. I have attached a patch that is simplified
and easier to read :-).