I initially didn’t intend to cover any service Inspectors in detail but since the HTTP Inspector (HttpInspect) is so important, I decided to include it in my documentation.

Splitters

As I explained elsewhere, the Wizard - after seeing a “GET” early in a Flow - will determine that HttpInspect is the appropriate service Inspector for a given TCP Flow. HttpInspect is then queried by Binder for its Splitter - (HttpStreamSplitter). The chief responsibility of Splitters is to break a Flow into components. For example, HttpStreamSplitter breaks an HTTP Flow into HTTP requests, statuses, headers, and bodies.
Like all Splitters, HttpStreamSplitter has two key methods, HttpStreamSplitter::scan() and HttpStreamSplitter::reassemble(). Unlike other Splitters, HttpStreamSplitter::reassemble() actually does something. But let’s first talk about HttpStreamSplitter::scan().
name:

website:

comment:


scan()

The scan() method of every Splitter (other than the special case of Wizard's MagicSplitter) breaks up the payload into sections (Snort++’s term). These sections are logical chunks that can be analyzed by the associated service Inspector. In the case of HttpStreamSplitter, these sections are the HTTP request (from the client), HTTP status (from the server), HTTP header (from both clients and servers), and HTTP body (typically from the server but in the case of an HTTP POST, they can be from the client). Pseudo packets are created out of these sections. For example, one pseudo packet will be created from the HTTP request and one pseudo packet will be created from the HTTP header.
Here is an example of an HTTP request/header (request) and an HTTP status/header (response)
requestresponse
name:

website:

comment:


Cutters and HttpFlowData

HttpStreamSplitters rely on Cutter objects to do its “cutting”. The first packet from the client will be cut by a HttpRequestCutter and the first packet from the server will be cut by a HttpStatusCutter.
The logic of the Cutters is pretty straight-forward. For example, both the HttpRequestCutter and HttpStatusCutter objects
HttpRequestCutter and HttpStatusCutter both inherit from HttpStartCutter and neither override HttpStartCutter’s cut() method (i.e., they both inherit HttpStartCutter’s cut() method.)
simply make sure that there aren’t any illegal characters and look for a newline. The newline indicates the end of the request or status sections.
In order to keep track of service-specific (e.g. http-specific) information, each service Inspector has its own FlowData-derived class. In the case of HttpInspect, this FlowData-derived class is HttpFlowData. Among other tasks, HttpFlowData objects (there will be exactly one HttpFlowData object for each HTTP Flow) keep track of which section that HttpInspect is cutting and analyzing. In order to accomplish this, HttpInspect uses the type_expected[] array.
type_expected[] is initialized to SEC_REQUEST for the client and SEC_STATUS for the server since those are the two sections that would be expected first (and in that order) for an HTTP session. These two values influence which Cutter is chosen to split up a packet.
Unlike other Splitters, HttpStreamSplitter overrides the reassemble() method with something meaningful (i.e., it’s not a method that does nothing). This gives HttpStreamSplitter the opportunity to manipulate (e.g., decompress) the section before the pseudo packet (which is built from the section) is sent recursively
As discussed elsewhere, an ACK packet triggers the generation of one or more pseudo packets. These pseudo packets are sent through the pipe before the ACK packet is finished in the pipe. Hence, these pseudo packets are sent "recursively" through the pipe.
through the packet processing pipe. In the packet processing pipe, HttpInspect will inspect the pseudo packet and the pseudo packet will be run through the Rule Detection Engine.
As discussed elsewhere, the packet processing pipe for a pseudo packet is as follows:
name:

website:

comment:


HttpMsgSection

The service Inspector in the pipeline in the figure above is (of course) HttpInspect. HttpInspect inspects the pseudo packet with the help from a handful of objects of HttpMsgSection-derived classes: HttpMsgRequest, HttpMsgStatus, HttpMsgHeader, HttpMsgBody, HttpMsgTrailer, HttpMsgBodyChunk, and HttpMsgBodyOld.
Let’s look at HttpMsgRequest.
HttpInspect calls the analyze() method for whichever HttpMsgSection-derived class is appropriate. As discussed above, the first thing that HttpInspect expects from the client is an HTTP request so HttpMsgRequest::analyze() is called
Since HttpMsgRequest derives from HttpMsgStart (HttpMsgStatus does as well) and does not override analyze(), HttpMsgStart::analyze() is called instead. HttpMsgRequest does supply its own parse_start_line(), however, which is called by HttpMsgStart::analyze(). parse_start_line() is where most of the action occurs for HttpMsgStart::analyze().
. HttpMsgRequest::analyze() creates a HttpUri object (which its uri field will point to – see diagram above).
name:

website:

comment:


HttpTransaction

For each Flow that uses HTTP, there will be two HttpTransaction objects. One HttpTransaction will be created for the client to server direction and one HttpTransaction object will be created for the server to client direction. Each object will contain all of the sections (e.g., HttpMsgRequest) that have been seen by HttpInspect. For example, if HttpInspect asked HttpMsgHeader to analyze() an HTTP header (which of course comes after the request), the HttpTransaction object will be as follows:
The HttpTransaction object is important when HttpMsgHeader publishes an HttpEvent. We’ll talk about this in a moment.
Provided that nothing suspicious is found in a given HttpMsgSection, each HttpMsgSection-derived class must update type_expected[] when it's done. In the case of HttpMsgRequest (as long as nothing suspicious is found and the analysis is therefore not aborted), type_expected[] is set to SEC_HEADER. This ensures that HttpMsgHeader is the HttpMsgSection-derived class that handles the next section (which makes sense because an HTTP header should come after an HTTP request).
name:

website:

comment:


AppId's Relationship TO HttpInspect

HttpMsgSection-derived classes can publish events. The only HttpMsgSection-derived class that publishes any events is the HttpMsgHeader class and the only Inspector that subscribes() to the HttpMsgHeader’s published events is the AppId Inspector.
Let’s take a look at the event that HttpMsgHeader publishes.
AppId can follow a linked list (norm_heads) to the HTTP header field in which it is interested. For example, if AppId is interested in the HTTP header’s host field, it will look for this value in the HEAD_HOST (HEADer’s HOST field) NormalizedHeader’s norm field (in the diagram above, "www.myfavoriteamazingsite.com"). What AppId does with these fields is discussed in my AppId documentation
Just because HttpEvent only has a pointer to the HttpMsgHeader doesn’t mean that the subscriber (which is currently only the AppId Inspector) can’t access the fields of the HttpUri (e.g., path, method_id) of the associated HttpMsgRequest. The subscriber simply follows the transaction pointer to the HttpTransaction of the HttpMsgHeader for the HttpMsgRequest fields.
.
name:

website:

comment:


Rule Detection Engine

HttpInspect doesn't send everything from the pseudo packets through the MPSEs. I discuss what HttpInspect sends (and when it sends it) in the TCP example.
name:

website:

comment: