zeek/scripts/base/protocols/http/partial-content.bro
Seth Hall 597a4d6704 Hopefully the last major script reorganization.
- policy/ renamed to scripts/

- By default BROPATH now contains:
	- scripts/
	- scripts/policy
	- scripts/site

- *Nearly* all tests pass.

- All of scripts/base/ is loaded by main.cc
	- Can be disabled by setting $BRO_NO_BASE_SCRIPTS
	- Scripts in scripts/base/ don't use relative path loading to ease use of BRO_NO_BASE_SCRIPTS (to copy and paste that script).

- The scripts in scripts/base/protocols/ only (or soon will only) do logging and state building.

- The scripts in scripts/base/frameworks/ add functionality without causing any additional overhead.

- All "detection" activity happens through scripts in scripts/policy/.

- Communications framework modified temporarily to need an environment variable to actually enable (ENABLE_COMMUNICATION=1)
	- This is so the communications framework can be loaded as part
	  of the base without causing trouble when it's not needed.
	- This will be removed once a resolution to ticket #540 is reached.
2011-08-05 23:09:53 -04:00

94 lines
2.6 KiB
Text

##! This script makes it possible for the HTTP analysis scripts to analyze
##! the apparent normal case of "206 Partial Content" responses.
##!
##! This script doesn't work yet and isn't loaded by default.
module HTTP;
export {
redef enum Notice::Type += {
Partial_Content_Out_Of_Order,
};
type Range: record {
from: count;
to: count;
} &log;
redef record Info += {
current_range: count &default=0;
request_ranges: vector of Range &optional;
response_range: Range &optional;
};
## Index is client IP address, server IP address, and URL being requested. The
## URL is tracked as part of the index in case multiple partial content segmented
## files are being transferred simultaneously between the server and client.
global partial_content_files: table[addr, addr, string] of Info &read_expire=5mins &redef;
}
event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=2
{
local parts: table[count] of string;
if ( is_orig && name == "RANGE" )
{
# Example --> Range: bytes=1-1,2336-4951
parts = split(value, /[=]/);
if ( 2 in parts )
{
local ranges = split(parts[2], /,/);
for ( i in ranges )
{
if ( ! c$http?$request_ranges )
c$http$request_ranges = vector();
parts = split(ranges[i], /-/);
local r: Range = [$from=extract_count(parts[1]), $to=extract_count(parts[2])];
print r;
c$http$request_ranges[|c$http$request_ranges|] = r;
}
}
}
else if ( ! is_orig && name == "CONTENT-RANGE" )
{
# Example --> Content-Range: bytes 2336-4951/489528
parts = split(value, /[0-9]*/);
c$http$response_range = [$from=extract_count(parts[2]), $to=extract_count(parts[4])];
}
}
event http_reply(c: connection, version: string, code: count, reason: string) &priority=5
{
if ( code != 206 || ! c$http?$request_ranges )
return;
local url = build_url(c$http);
if ( [c$id$orig_h, c$id$resp_h, url] !in partial_content_files )
{
partial_content_files[c$id$orig_h, c$id$resp_h, url] = copy(c$http);
}
}
event http_entity_data(c: connection, is_orig: bool, length: count, data: string)
{
if ( is_orig || c$http$status_code != 206 || ! c$http?$request_ranges )
return;
local url = build_url(c$http);
local http = partial_content_files[c$id$orig_h, c$id$resp_h, url];
local range = http$request_ranges[http$current_range];
print http$current_range;
if ( http$current_range == 0 &&
c$http$response_range$from == 0 )
{
print "correct file beginning!";
}
}
event http_end_entity(c: connection, is_orig: bool)
{
print "end entity";
++c$http$current_range;
}