2.1. Policies for requests and responses

PNS offers great flexibility in proxy customization. Requests and commands, responses, headers, etc. can be managed individually in PNS. This means that it is not only possible to enable/disable them one-by-one, but custom actions can be assigned to them as well. The available options are listed in the description of each proxy, but the general guidelines are discussed here.

All important events of a protocol have an associated policy hash: usually there is one for the requests or commands and one for the responses. Where applicable for a protocol, there are other policy hashes defined as well (e.g., for controlling the capabilities available in the IMAP protocol, etc.). The entries of the hash are the possible events of the protocol (e.g., the request hash of the FTP protocol contains the possible commands - RMD, DELE, etc.) and an action associated with the event - what PNS should do when this event occurs. The available actions may slightly vary depending on the exact protocol and the hash, but usually they are the following:

ActionDescription
ACCEPT Enable the event; the command/response/etc. can be used and is allowed through the firewall.
REJECT Reject the event and send an error message. The event is blocked and the client notified. The communication can continue, the connection is not closed.
DROP Reject the event without sending an error message. The event is blocked but the client is not notified. The communication can continue, the connection is not closed. In some cases (depending on the protocol) this action is able to remove only a part of the message (e.g., a particular header in HTTP traffic) without rejecting the entire message.
ABORT Reject the event and terminate the connection.
POLICY Call a Python function to make a decision about the event. The final decision must be one of the above actions (i.e. POLICY is not allowed). The parameters received by the function are listed in the module descriptions. See the examples below and in the module descriptions for details.

Table 2.1.  Action codes for protocol events

The use of the policy hashes and the action codes is illustrated in the following examples.

Example 2.1. Customizing FTP commands

In this example the 'RMD' command is rejected, and the connection is terminated if the user attempts to delete a file.

class MyFtp(FtpProxy):
	def config(self):
		self.request["RMD"] = (FTP_REQ_REJECT)
		self.request["DELE"] = (FTP_REQ_ABORT)
Example 2.2. Using the POLICY action

This example calls a function called pUser (defined in the example) whenever a USER command is received within an FTP session. All other commands are accepted. The parameter of the USER command (i.e. the username) is examined: if it is 'user1' or 'user2', the connection is accepted, otherwise it is rejected.

class MyFtp(FtpProxy):
	def config(self):
		self.request["USER"] = (FTP_REQ_POLICY, self.pUser)
		self.request["*"] = (FTP_REQ_ACCEPT)

	def pUser(self,command):
		if self.request_parameter == "user1" or self.request_parameter == "user2":
			return FTP_REQ_ACCEPT
		return FTP_REQ_REJECT

It must be noted that there is a difference between how PNS processes the POLICY actions and all the other ones (e.g., ACCEPT, DROP, etc.). POLICY actions are evaluated on the policy (or Python) level of PNS, while the other ones on the proxy (or C) level. Since the proxies of PNS are written in C, and operate on the proxy level, the evaluation of POLICY actions is slightly slower, but this can be an issue only in very high-throughput environments with complex policy settings.