zeek/scripts/base/protocols/http/partial-content.bro

98 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.
@load base/frameworks/notice
@load ./main
@load ./utils
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;
}