# $Id: http-reply.bro,v 1.14 2003/08/31 00:40:21 vern Exp $

@load http-request

redef capture_filters += {
	["http-reply"] = "tcp src port 80 or tcp src port 8080 or tcp src port 8000"
};

redef process_HTTP_replies = T;

event http_reply(c: connection, version: string, code: count, reason: string)
	{
	local s = lookup_http_request_stream(c);
	local msg = s$next_reply;

	init_http_message(msg);

	msg$initiated = T;
	msg$code = code;
	msg$reason = reason;
	}

function http_request_done(c: connection, stat: http_message_stat): any
	{
	local s = lookup_http_request_stream(c);
	local msg = s$next_request;
	msg$initiated = F;
	}

function http_reply_done(c: connection, stat: http_message_stat): any
	{
	local s = lookup_http_request_stream(c);
	local msg = s$next_reply;
	local req: string;
	local log_it: bool;

	if ( s$num_pending_requests == 0 )
		{
		# Weird - reply w/o request - perhaps due to cold start?
		req = "<unknown request>";
		log_it = F;
		}
	else
		{
		local r = s$requests[s$first_pending_request];

		# Remove pending request.
		delete s$requests[s$first_pending_request];
		--s$num_pending_requests;
		++s$first_pending_request;

		req = fmt("%s %s", r$method, r$URI);
		log_it = r$log_it;
		}

	local req_rep =
		fmt("%s (%d \"%s\" [\"%s\", %d%s%s])", 
			req, msg$code, msg$reason,
			msg$content_length, stat$body_length, 
			stat$interrupted ? " (interrupted)" : "",
			stat$content_gap_length > 0 ? 
				fmt(" (gap = %d bytes)", stat$content_gap_length) : "");

	if ( log_it )
		ALERT([$alert=HTTP_SensitiveURI, $conn=c,
			$msg=fmt("%s %s: %s",
				id_string(c$id), c$addl, req_rep)]);

	print http_log, fmt("%.6f %s %s", network_time(), s$id, req_rep);

	msg$initiated = F;
	}

event http_message_done(c: connection, is_orig: bool, stat: http_message_stat)
	{
	if ( is_orig )
		http_request_done(c, stat);
	else
		http_reply_done(c, stat);
	}

@load http-entity
event http_header(c: connection, is_orig: bool, name: string, value: string)
	{
	# Only rewrite top-level headers.
	local s = lookup_http_request_stream(c);
	local msg = get_http_message(s, is_orig);

	if ( msg$entity_level == 1 )
		{
		if ( name == "CONTENT-LENGTH" )
			msg$content_length = value;
		}
	}
