Module Ftp

This module defines the Ftp proxy interface as implemented by the Ftp proxy module.

Imported modules

Class FtpDataProxy

This class ensures one way data connections by setting the appropriate copy_to_* variable in Plug.

Class FtpProxy

By default deny everything, but data connection establishment. You should dervice your customized Ftp proxy classes in order to do something useful.

Usage

This section contains basic usage patterns, you as an administrator may need to do.

Default processing of commands

All requests are denied in the low level proxy implementation by default. To enable different commands and answers you'll need to extend the low-level proxy in Python. To see how this is done, see the next two sections.

Setting policy for commands

Changing the default behaviour of commands can be done using the hash named "command". This hash is indexed by the command name (e.g: USER or PWD), and each item in this hash is an action tuple, defining proxy behaviour for the given command.

The first item in this tuple is an integer value, determining the action to take, and also the interpretation of the remaining items in the tuple.

Possible values for the first item:

Example 4-3. Sample for anonymous only sessions in FTP

                class AnonFtp(FtpProxy):

                  def config(self):
                    self.fw_server_data.ip_s="192.168.0.1"
                    self.fw_client_data.ip_s="10.0.0.1"
                    self.commands["USER"] = (Ftp.FTP_CMD_POLICY, self.pUser)
                    self.commands["*"] = (Ftp.FTP_CMD_ACCEPT)

                  def pUser(self,command):
                    if self.request_parameter == "ftp" or self.request_parameter == "anonymous":
                      return Z_ACCEPT
                    return Z_DENY

Changing answer code or string

Like with commands, we have a hash for answers as well. This hash indexed by command concatenated with answer, and contains an action tuple in each item. A special wildcard character * matches every command. Another feature is that you don't need to write the full answer code, it's possible to write only the first, or the first two digits.

For example, all three index below is valid:

Table 4-35. Untitled

PWD200 Match exactly the answer 200 coming in reply to a PWD command.
PWD2 Match every answer starting with 2 in reply to a PWD command.
*20 Match every answer between 200 and 209 in reply to any command.

All answers are "denied" default. It's changed to "500 Error parsing answer", because dropping an answer is not permitted by RFC959. You may enable all answers with "*".

The precedence in processing hashtable entries is the following:

1. Exact match. (PWD200)

2. Exact command match, partial answer matches (PWD20, PWD2, PWD)

3. Wildcard command, with answer codes repeated as above. (*200, *20, *2, *)

Possible values for the first item in the action tuple:

Table 4-36. Untitled

FTP_ANS_ACCEPTallow answer without modification.
FTP_ANS_CHANGEchange answer code and message. (default) Second parameter contains a string, which will be sent back to client.
FTP_ANS_POLICYcall a Python function to decide what to do. this value uses an additional parameter, which must be a callable Python function. The function takes three parameters: self, command, answer
FTP_ANS_ABORT deny request, and drop conection.

Attributes

Table 4-37. Attributes for class FtpProxy

data_connect Object for the data connection
data_proxy proxy to use for data connections
data_port_min ports should be allocated above this variable
data_port_max ports should be allocated below this variable
data_mode FTP_DATA_KEEP, FTP_DATA_PASSIVE or FTP_DATA_ACTIVE can be used to force a connection type in server side. (default: FTP_DATA_KEEP)
transparent_mode (logical) TRUE for transparent proxy, FALSE otherwise (default: TRUE)
fw_server_data (ZorpSocket) Firewall address in server side. By default it contains the IP address of the interface towards the server.
fw_client_data (ZorpSocket) Firewall address in client side. By default it contains the IP address of the interface towards the client.
permit_unknown_command (boolean) Enable commands not understood (and not handled) by proxy. (Default: FALSE)
permit_empty_command (boolean) Enable lines without commands. (Default: FALSE)
max_line_length (integer) Maximum line lenght, what a proxy may transfer. (Default: 255)
max_username_length (integer) Maximum length of usernames. (Default: 32)
max_password_length (integer) Maximum length of passwords. (Default: 64)
commands (hash) normative policy hash, directing the proxy to do something with requests, without the need to call Python. indexed by the command (e.g. "USER", "PWD" etc) (default: empty)
answers (hash) normative policy hash directing the proxy to do something with answers. Indexed by the command, and the answer (e.g. "USER331", "PWD200" etc) (default: empty)
request_command (string) When a command goes up to policy level, you may change it with this. FIXME: Not yet used.
request_parameter (string) When a command goes up to policy level, this variable contains command parameters.
answer_code (string) When an answer goes up to policy level, this variable contains answer code.
answer_parameter (string) When an answer go up to policy level, this variable contain answer parameters.
restrict_client_connect(boolean) Restricting data connection in client side. Accept data connection only if it's coming from IP number equal with command channel endpoint. (Default: TRUE)
restrict_server_connect(boolean) Restricting data connection in server side. Accept data connection only if it's coming from IP number equal with command channel endpoint. (Default: FALSE)

Private attributes

Table 4-38. Untitled

stateconnection state 0 is initial, 1 one of the connections were established, 2 both connections established ready to start data proxy.
modesarray indexed by side, L for Listen or C for connect
listenslisten objects created by us, array indexed by side
connectsconnect objects created by us, array indexed by side
sidesdetermines the order in which sides must be processed (first listen/connect on sides[0] then on sides[1])
fdsarray indexed by side, containing the side specific fd
localsesalocal socket adress in server side. Used when data connections port is in a range.
localclsalocal socket adress in client side. Used when data connecion port is in range.

Method __destroy__

Deinitializes an FtpProxy class

Synopsis

__destroy__ ( self )

Description

Calls resetState() to destroy bound listeners and connectors. It destroys running data connection.

Arguments

Table 4-39. Arguments for FtpProxy.__destroy__()

selfthis instance

Constructor __init__

Initialize an FtpProxy instance

Synopsis

__init__ ( self,  session )

Description

This constructor initializes an FtpProxy instance by calling the inherited __init__ constructor with appropriate parameters, and setting up local attributes based on arguments.

Arguments

Table 4-40. Arguments for FtpProxy.__init__()

self this instance
sessionThe session object

Method acceptedCallback

Callback called when a connection was accepted on either side.

Synopsis

acceptedCallback (
        self,
        client,
        fd,
        )

Description

This callback is called if any of the sides was in L mode, and a connection was accepted on the listening socket.

Arguments

Table 4-41. Arguments for FtpProxy.acceptedCallback()

self this instance
clientthe client address which has connected
fd the file descriptor for the connection

Exceptions

  • InternalError

Notes

stores the parameters, increases the state and continues with the state machine

Method connectedCallback

Callback called when a connection was established.

Synopsis

connectedCallback ( self,  fd )

Description

This function is similar to [acceptedCallback], but used if we were in C (connect) mode.

.. [acceptedCallback] FtpDataConnect.acceptedCallback

Arguments

Table 4-42. Arguments for FtpProxy.connectedCallback()

self this instance
fdthe file descriptor for the connection

Exceptions

  • InternalError

Notes

stores the parameter, increases the state and continues with the state machine

Method loadAnswers

This function can be called by derived classes to initialize internal hashtables.

Synopsis

loadAnswers ( self )

Description

This function fills in the self.answers hash so that commonly used request/answer combinations are enabled.

Arguments

Table 4-43. Arguments for FtpProxy.loadAnswers()

selfthis instance

Method prepareData

Prepares the data channel on side side using mode mode.

Synopsis

prepareData (
        self,
        side,
        mode,
        )

Description

This function prepares the given side of the data connection. This means either to listen for connections (like passive mode on the client side) or to start establishing a connection (passive mode on the server side).

Arguments

Table 4-44. Arguments for FtpProxy.prepareData()

self this instance
side FTP_SIDE_CLIENT or FTP_SIDE_SERVER representing either the client or the server
mode L or C for Listen or Connect

Method resetData

Reset data connection state.

Synopsis

resetData ( self )

Description

Sets the initial state of everything, and destroy pending listeners.

Arguments

Table 4-45. Arguments for FtpProxy.resetData()

selfthis instance

Method startData

Start the data connection procedure as prepared by earlier prepare calls.

Synopsis

startData (
        self,
        side1,
        side2,
        way,
        )

Description

Previous calls to prepare determines how the data connection should be built. This function starts the state machine whose final state is to start a proxy on the established data connection.

Arguments

Table 4-46. Arguments for FtpProxy.startData()

side1 connect/listen on this side first
side2 connect/listen on this side after the first one succeeded
way direction

Exceptions

  • InternalError

Method stepData

Do the processing as required by the current state.

Synopsis

stepData ( self )

Description

This function is called each time after processing the current state finishes. This means that if the data connection on the server side is established we are ready to step one further and start accepting connections on the client side.

Arguments

Table 4-47. Arguments for FtpProxy.stepData()

selfthis instance

Exceptions

  • InternalError

Notes

If state == 2, stacks in the proxy and starts it with a session stacked out from self.session

In state 0 and 1 it either listens or connects, based on the type field of parms[state]

Method stopDataConnection

Callback called by the data proxy to indicate the end of the data connection.

Synopsis

stopDataConnection ( self )

Description

This callback is registered with the data proxy ([FtpDataProxy], see below), and is called when the data connection was terminated. It's task is to signal this condition to the Ftp proxy core.

.. [FtpDataProxy] FtpDataProxy

Arguments

Table 4-48. Arguments for FtpProxy.stopDataConnection()

selfthis instance

Class FtpProxyAllow

We defined two example classes derived from the default FtpProxy class, enabling some additional commands/answers from the FTP protocol. FtpProxyAllow as the name suggests allows any FTP command to pass through the proxy, and allows any answer in reply to them.

Method config

Default config for FtpProxyAllow.

Synopsis

config ( self )

Description

Enables all commands by setting permit_unknown_commands to TRUE and adding two wildcard entries to the commands and answers hash.

Arguments

Table 4-49. Arguments for FtpProxyAllow.config()

selfthis instance

Class FtpProxyMinimal

This proxy enables the minimal required protocol elements required by daily usage.

Method config

Configuration for FtpProxyMinimal

Synopsis

config ( self )

Description

It enables a minimal set of commands for a working FTP proxy, and sets permit_unknown_commands to FALSE.

Arguments

Table 4-50. Arguments for FtpProxyMinimal.config()

selfthis instance

Method test

Test function to log answers not enabled in config

Synopsis

test (
        self,
        command,
        answer,
        )

Description

This function is used to gather still useful answers not enabled in FtpProxyMinimal by default. It accepts any answers but sends a log message about it.

Arguments

Table 4-51. Arguments for FtpProxyMinimal.test()

selfthis instance
commandcommand
answeranswer