The File Transfer Protocol [PR85] is much more complex than the Finger protocol; it also, however, is highly structured and easy to parse, so interpreting an FTP dialog is straight-forward.
For FTP requests, Bro parses each line sent by the connection originator into a command (first word) and an argument (the remainder), splitting the two at the first instance of whitespace it finds, and converting the command to uppercase (to circumvent problems such as a policy script testing for ``store file'' commands as STOR or stor, and an attacker instead sending stOR, which the remote FTP server will happily accept). It then generates an ftp_request event with these and the corresponding connection as arguments.
FTP replies begin with a status code (a number), followed by any accompanying text. Replies also can indicate whether they continue to another line. Accordingly, for each line of reply the event engine generates an ftp_reply with the code, the text, a flag indicating continuation, and the corresponding connection as arguments.
As far as the event engine is concerned, that's it--100 lines of straight-forward C++. What is interesting about FTP is that all the remaining work can be done in Bro (about 300 lines for our site). The ftp_request handler keeps track of distinct FTP sessions, pulls out usernames to test against a list of sensitive ID's (and to annotate the connection's general summary), and, for any FTP request that manipulates a file, checks for access to sensitive files. Some of these checks depend on context; for example, a guest (or ``anonymous'') user should not attempt to manipulate user-configuration files, while for other users doing so is fine.
A final analysis step for ftp_request events is to parse any PORT request to extract the hostname and TCP port associated with an upcoming transfer. (The FTP protocol uses multiple TCP connections, one for the control information such as user requests, and others, dynamically created, for each data transfer.) This is an important step, because it enables the script to tell which subsequent connections belong to this FTP session and which do not. A site's policy might allow FTP access to particular servers, but any other access to those servers merits an alarm; but without parsing the PORT request, it can be impossible to distinguish a legitimate FTP data transfer connection from an illicit, non-FTP connection. Consequently, the script keeps track of pending data transfer connections, and when it encounters them, marks them as ftp-data applications, even if they do not use the well-known port associated with such transfers (the standard does not require them to do so).
We also note that, in addition to correctly identifying FTP-related traffic, parsing PORT requests makes it possible to detect ``FTP bounce'' attacks. In these attacks, a malicious FTP client instructs an FTP server to open a data transfer connection not back to it, but to a third, victim site. The client can thus manipulate the server into uploading data to an arbitrary service on the victim site, or to effectively port-scan the victim site (which the client does by using multiple bogus PORT requests and observing the completion status of subsequent data-transfer requests). Our script flags PORT requests that attempt any redirection of the data transfer connection. Interestingly, we added this check mostly because it was easy to do so; months later, we monitored the first of several subsequent FTP bounce attacks.
For ftp_reply events, most of the work is simply formatting a succinct one-line summary of the request and its result for recording in the FTP activity log. In addition, an FTP PASV request has a structure similar to a PORT request, except that the FTP server instead of the client determines the specifics of the subsequent data transfer connection. Consequently our script subjects PASV replies to the same analysis as PORT requests. Finally, there is nothing to prevent a different remote host from connecting to the data transfer port offered by a server via a PASV reply. It is hard to see why this might actually occur, but putting in a test for it is simple (unfortunately, there are some false alarms due to multi-homed clients; we use heuristics to reduce these); and, indeed, several months after adding it, it triggered, due to an attacker using 3-way FTP as (evidently) a way to disguise their trail.