Merging in 'topic/robin/cleanup-rewriter'.

Removing everything related to trace rewriting.

(I wasn't too careful in ensuring that I catch everything in the
scripts; Seth is working on those anyway.)

(Merging by cherry-picking the corresponding commit, as the branch was
accidentally made off of the logging stuff).
This commit is contained in:
Robin Sommer 2011-04-01 15:23:50 -07:00
parent ec1b2b4d2a
commit a3a075174b
70 changed files with 20 additions and 5922 deletions

@ -1 +1 @@
Subproject commit 106cd9782f1f9443743b49adccae26f0ee72621c
Subproject commit c3c7ef0dfddb0746d3762e41086ba42928e68483

@ -1 +1 @@
Subproject commit 764b6167922662051b62d269ec0fbd14e2ce0c02
Subproject commit 98f92eeb40281045159097764abddc428fb49bf2

@ -1 +1 @@
Subproject commit d693ba5f14c33a97e4f149e49196281cc075d289
Subproject commit 48d473398e577893b6c7f77d605ccdf266a2f93b

@ -1 +1 @@
Subproject commit b26dc6dc6a9080abe7a062d0882e813acbb63248
Subproject commit 532dcd5aa51c8b29b2d71cd37e1d7c21e33cc715

@ -1 +1 @@
Subproject commit 409bda3a003b18c4736ef168595f20118f4d0038
Subproject commit a2b04952ae91dcd27d5e68a42d5d26c291ecb1f5

View file

@ -53,10 +53,8 @@
@load http-identified-files.bro
@load http-reply
@load http-request
@load http-rewriter
@load http
@load icmp
@load ident-rewriter
@load ident
@load inactivity
@load interconn
@ -111,7 +109,6 @@
@load site
@load smb
@load smtp-relay
@load smtp-rewriter
@load smtp
@load snort
@load software

View file

@ -1117,14 +1117,6 @@ type bt_tracker_headers: table[string] of string;
@load event.bif.bro
@load common-rw.bif.bro
@load finger-rw.bif.bro
@load ftp-rw.bif.bro
@load ident-rw.bif.bro
@load smtp-rw.bif.bro
@load http-rw.bif.bro
@load dns-rw.bif.bro
function subst(s: string, from: pattern, to: string): string
{
local p = split_all(s, from);
@ -1404,34 +1396,3 @@ const skip_http_data = F &redef;
# Whether the analysis engine parses IP packets encapsulated in
# UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro.
const parse_udp_tunnels = F &redef;
# Whether a commitment is required before writing the transformed
# trace for a connection into the dump file.
const requires_trace_commitment = F &redef;
# Whether IP address anonymization is enabled.
const anonymize_ip_addr = F &redef;
# Whether to omit place holder packets when rewriting.
const omit_rewrite_place_holder = T &redef;
# Whether trace of various protocols is being rewritten.
const rewriting_http_trace = F &redef;
const rewriting_smtp_trace = F &redef;
const rewriting_ftp_trace = F &redef;
const rewriting_ident_trace = F &redef;
const rewriting_finger_trace = F &redef;
const rewriting_dns_trace = F &redef;
const rewriting_smb_trace = F &redef;
# Whether we dump selected original packets to the output trace.
const dump_selected_source_packets = F &redef;
# If true, we dump original packets to the output trace *if and only if*
# the connection is not rewritten; if false, the policy script can decide
# whether to dump a particular connection by calling dump_packets_of_connection.
#
# NOTE: DO NOT SET THIS TO TRUE WHEN ANONYMIZING A TRACE!
# (TODO: this variable should be disabled when using '-A' option)
const dump_original_packets_if_not_rewriting = F &redef;

View file

@ -1,107 +0,0 @@
# $Id:$
@load dns
@load anon
module DNS;
redef rewriting_dns_trace = T;
event dns_message(c: connection, is_orig: bool, msg: dns_msg, len: count)
{
if ( get_conn_transport_proto(c$id) == udp )
rewrite_dns_message(c, is_orig, msg, len);
}
event dns_request(c: connection, msg: dns_msg, query: string,
qtype: count, qclass: count)
{
if ( get_conn_transport_proto(c$id) == udp )
rewrite_dns_request(c, anonymize_host(query),
msg, qtype, qclass);
}
event dns_end(c: connection, msg: dns_msg)
{
if ( get_conn_transport_proto(c$id) == udp )
rewrite_dns_end(c, T);
}
event dns_query_reply(c: connection, msg: dns_msg, query: string,
qtype: count, qclass: count)
{
rewrite_dns_reply_question(c, msg, anonymize_host(query),
qtype, qclass);
}
event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr)
{
ans$query = anonymize_host(ans$query);
rewrite_dns_A_reply(c, msg, ans, anonymize_address(a, c$id));
}
#### FIXME: ANONYMIZE!
event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer,
a: addr, astr: string)
{
ans$query = anonymize_host(ans$query);
astr = "::";
a = anonymize_address(a, c$id);
rewrite_dns_AAAA_reply(c, msg, ans, a, astr);
}
event dns_NS_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string)
{
ans$query = anonymize_host(ans$query);
rewrite_dns_NS_reply(c, msg, ans, anonymize_host(name));
}
event dns_CNAME_reply(c: connection, msg: dns_msg, ans: dns_answer,
name: string)
{
ans$query = anonymize_host(ans$query);
rewrite_dns_CNAME_reply(c, msg, ans, anonymize_host(name));
}
event dns_MX_reply(c: connection, msg: dns_msg, ans: dns_answer,
name: string, preference: count)
{
ans$query = anonymize_host(ans$query);
rewrite_dns_MX_reply(c, msg, ans, anonymize_host(name), preference);
}
event dns_PTR_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string)
{
ans$query = anonymize_host(ans$query);
rewrite_dns_PTR_reply(c, msg, ans, anonymize_host(name));
}
event dns_SOA_reply(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa)
{
soa$mname = anonymize_host(soa$mname);
soa$rname = anonymize_host(soa$rname);
ans$query = anonymize_host(ans$query);
rewrite_dns_SOA_reply(c, msg, ans, soa);
}
event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer,
str: string)
{
str = anonymize_string(str);
ans$query = anonymize_host(ans$query);
rewrite_dns_TXT_reply(c, msg, ans, str);
}
event dns_EDNS_addl (c: connection, msg: dns_msg, ans: dns_edns_additional)
{
rewrite_dns_EDNS_addl(c, msg, ans);
}
event dns_rejected(c: connection, msg: dns_msg, query: string,
qtype: count, qclass: count)
{
#### Hmmm, this is probably not right - we are going to have to look
# at the question type to determine how to anonymize this.
rewrite_dns_reply_question(c, msg, anonymize_host(query),
qtype, qclass);
}

View file

@ -60,19 +60,6 @@ event finger_request(c: connection, full: bool, username: string, hostname: stri
req = fmt("(%s)", req);
append_addl_marker(c, req, " *");
if ( rewriting_finger_trace )
rewrite_finger_request(c, full,
public_user(username) ? username : "private user",
hostname);
}
event finger_reply(c: connection, reply_line: string)
{
local id = c$id;
if ( rewriting_finger_trace )
rewrite_finger_reply(c,
authorized_client(id$orig_h) ? "finger reply ..." : reply_line);
}
function is_finger_conn(c: connection): bool
@ -80,10 +67,3 @@ function is_finger_conn(c: connection): bool
return c$id$resp_p == finger;
}
event connection_state_remove(c: connection)
{
if ( rewriting_finger_trace && requires_trace_commitment &&
is_finger_conn(c) )
# Commit queued packets and all packets in future.
rewrite_commit_trace(c, T, T);
}

View file

@ -1,846 +0,0 @@
# $Id: ftp-anonymizer.bro 47 2004-06-11 07:26:32Z vern $
@load ftp
@load anon
# Definitions of constants.
# Check if those commands carry any argument; anonymize non-empty
# argument.
const ftp_cmds_with_no_arg = {
"CDUP", "QUIT", "REIN", "PASV", "STOU",
"ABOR", "PWD", "SYST", "NOOP",
"FEAT", "XPWD",
};
const ftp_cmds_with_file_arg = {
"APPE", "CWD", "DELE", "LIST", "MKD",
"NLST", "RMD", "RNFR", "RNTO", "RETR",
"STAT", "STOR", "SMNT",
# FTP extensions
"SIZE", "MDTM",
"MLSD", "MLST",
"XCWD",
};
# For following commands, we check if the argument conforms to the
# specification -- if so, it is safe to be left in the clear.
const ftp_cmds_with_safe_arg = {
"TYPE", "STRU", "MODE", "ALLO", "REST",
"HELP",
"MACB", # MacBinary encoding
};
# ftp_other_cmds can be redefined in site/trace-specific ways.
const ftp_other_cmds = {
"LPRT", "OPTS", "CLNT", "RETP",
"EPSV", "XPWD",
"SOCK", # old FTP command (RFC 354)
} &redef;
# Below defines patterns of arguments of FTP commands
# The following patterns are case-insensitive
const ftp_safe_cmd_arg_pattern =
/TYPE (([AE]( [NTC])?)|I|(L [0-9]+))/
| /STRU [FRP]/
| /MODE [SBC]/
| /ALLO [0-9]+([ \t]+R[ \t]+[0-9]+)?/
| /REST [!-~]+/
| /MACB (E|DISABLE|ENABLE)/
| /SITE TRUTH ON/
&redef;
# The following list includes privacy-safe [cmd, arg] pairs and can be
# customized for particular traces
const ftp_safe_arg_list: set[string, string] = {
} &redef;
# ftp_special_cmd_args offers an even more flexible way of customizing
# argument anonymization: for each [cmd, arg] pair in the table, the
# corresponding value will be the anonymized argument.
const ftp_special_cmd_args: table[string, string] of string = {
} &redef;
# The following words are safe to be left in the clear as the argument
# of a HELP command.
const ftp_help_words = {
"USER", "PORT", "STOR", "MSAM", "RNTO", "NLST", "MKD", "CDUP",
"PASS", "PASV", "APPE", "MRSQ", "ABOR", "SITE", "XMKD", "XCUP",
"ACCT", "TYPE", "MLFL", "MRCP", "DELE", "SYST", "RMD", "STOU",
"SMNT", "STRU", "MAIL", "ALLO", "CWD", "STAT", "XRMD", "SIZE",
"REIN", "MODE", "MSND", "REST", "XCWD", "HELP", "PWD", "MDTM",
"QUIT", "RETR", "MSOM", "RNFR", "LIST", "NOOP", "XPWD",
} &redef;
const ftp_port_pat = /[0-9]+([[:blank:]]*,[[:blank:]]*[0-9]+){5}/;
# Pattern for the argument of EPRT command.
# TODO: the pattern works fot the common case but is not RFC2428-complete.
const ftp_eprt_pat = /\|1\|[0-9]{1,3}(\.[0-9]{1,3}){3}\|[0-9]{1,5}\|/;
# IP addresses.
const ftp_ip_pat = /[0-9]{1,3}(\.[0-9]{1,3}){3}/;
# Domain names (deficiency: domain suffices of countries).
const ftp_domain_name_pat =
/([\-0-9a-zA-Z]+\.)+(com|edu|net|org|gov|mil|uk|fr|nl|es|jp|it)/;
# File names (printable characters).
const ftp_file_name_pat = /[[:print:]]+/;
# File names that can be left in the clear.
const ftp_public_files =
/\// | /\.\./ # "/" and ".."
| /(\/etc\/|master\.)?(passwd|shadow|s?pwd\.db)/ # ftp_hot_files
| /\/(etc|usr\/bin|bin|sbin|kernel)(\/)?/
| /\.rhosts/ | /\.forward/ # ftp_hot_guest_files
&redef;
const ftp_sensitive_files =
/.*(etc\/|master\.)?(passwd|shadow|s?pwd\.db)/ # ftp_hot_files
| /\/(etc|usr\/bin|bin|sbin|kernel)\/.*/
| /.*\.rhosts/ | /.*\.forward/ # ftp_hot_guest_files
&redef;
# Public servers.
const ftp_public_servers: set[addr] = {} &redef;
# Whether we keep all file names (valid or invalid) for public servers.
const ftp_keep_all_files_for_public_servers = F &redef;
# Public files.
const ftp_known_public_files: set[addr, string] = {} &redef;
# Hidden file/directory.
const ftp_hidden_file = /.*\/\.[^.\/].*/;
const ftp_public_hidden_file = /0/ &redef;
# Options for file commands (LIST, NLST) that can be left in the clear.
const ftp_known_option = /-[[:alpha:]]{1,5}[ ]*/;
const ftp_known_site_cmd = {
"UMASK", "GROUP", "INDEX", "GROUPS",
"IDLE", "GPASS", "EXEC", "CHECKMETHOD",
"CHMOD", "NEWER", "ALIAS", "CHECKSUM",
"HELP", "MINFO", "CDPATH",
"TRUTH", "UTIME",
} &redef;
const ftp_sensitive_ids: set[string] = {
"backdoor", "bomb", "diag", "gdm", "issadmin", "msql", "netfrack",
"netphrack", "own", "r00t", "root", "ruut", "smtp", "sundiag", "sync",
"sys", "sysadm", "sysdiag", "sysop", "sysoper", "system", "toor", "tour",
"y0uar3ownd",
};
redef anonymize_ip_addr = T;
redef rewriting_ftp_trace = T;
global ftp_anon_log = open_log_file("ftp-anon") &redef;
# Anonymized arguments, indexed by the anonymization seed.
global anonymized_args: table[string] of string;
# Arguments left in the clear, indexed by the argument and the context.
global ftp_arg_left_in_the_clear: set[string, string];
# Valid files on public servers.
global ftp_valid_public_files: set[addr, string];
type ftp_cmd_arg_anon_result: record {
anonymized: bool;
cmd: string;
arg: string;
};
# Whether anonymize_trace_specific_cmd_arg is defined:
const trace_specific_cmd_arg_anonymization = F &redef;
# This function is to be defined in a trace-specific script. By
# default, use ftp-anonymizer-trace.bro.
global anonymize_trace_specific_cmd_arg:
function(session: ftp_session_info, cmd: string, arg: string):
ftp_cmd_arg_anon_result;
# Anonymize FTP replies by message patterns.
const process_ftp_reply_by_message_pattern = F &redef;
global anonymize_ftp_reply_by_msg_pattern:
function(code: count, act_msg: string,
cmd_arg: ftp_cmd_arg, session: ftp_session_info): string;
# Anonymize an argument *completely* with a hash value of the string,
# and log the anonymization.
function anonymize_arg(typ: string, session: ftp_session_info, cmd: string, arg: string, seed: string): string
{
if ( arg == "" )
return ""; # an empty argument is safe
local arg_seed = string_cat(typ, seed, arg);
if ( arg_seed in anonymized_args )
return anonymized_args[arg_seed];
local a = anonymize_string(arg_seed);
anonymized_args[arg_seed] = a;
print ftp_anon_log,
fmt("anonymize_arg: (%s) {%s} %s \"%s\" to \"%s\" in [%s]",
typ, seed, cmd,
to_string_literal(arg), to_string_literal(a),
id_string(session$connection_id));
return a;
}
# This function is called whenever an argument is to be left in the
# clear. It logs the action if it hasn't occurred before.
function leave_in_the_clear(msg: string, session: ftp_session_info,
arg: string, context: string): string
{
if ( [arg, context] !in ftp_arg_left_in_the_clear )
{
add ftp_arg_left_in_the_clear[arg, context];
print ftp_anon_log, fmt("leave_in_the_clear: (%s) \"%s\" [%s] in [%s]",
msg, to_string_literal(arg), context,
id_string(session$connection_id));
}
return arg;
}
# Sometimes the argument of a file command contains an option string
# before the file name, such as in 'LIST -l /xyz/', the following
# function identifies such option strings and separate the argument
# accordingly.
type separate_option_str_result: record {
opt_str: string;
file_name: string;
};
function separate_option_str(file_name: string): separate_option_str_result
{
local ret: separate_option_str_result;
if ( file_name == /-[[:alpha:]]+( .*)?/ )
{
local parts = split_all(file_name, /-[[:alpha:]]+[ ]*/);
ret$opt_str = string_cat(parts[1], parts[2]);
parts[1] = ""; parts[2] = "";
ret$file_name = cat_string_array(parts);
return ret;
}
else
return [$opt_str = "", $file_name = file_name];
}
# Anonymize a user id
type login_status_type: enum {
LOGIN_PENDING,
LOGIN_SUCCESSFUL,
LOGIN_FAILED,
LOGIN_UNKNOWN,
};
function anonymize_user_id(session: ftp_session_info, id: string, login_status: login_status_type, msg: string): string
{
if ( id in ftp_guest_ids )
{
leave_in_the_clear("guest_id", session, id, msg);
return id;
}
else if ( id in ftp_sensitive_ids && login_status == LOGIN_FAILED )
{
leave_in_the_clear("sensitive_id", session, id, msg);
return id;
}
else
return anonymize_arg("user_name", session, "USER", id, cat(session$connection_id$resp_h, login_status));
}
# Anonymize a file name argument.
function anonymize_file_name_arg(session: ftp_session_info, cmd: string, arg: string, valid_file_name: bool): string
{
local file_name = arg;
local opt_str = "";
if ( cmd == /LIST|NLST/ )
{
# Separate the option from file name if there is one
local ret = separate_option_str(file_name);
if ( ret$opt_str != "" )
{
opt_str = ret$opt_str;
# Shall we anonymize the option string?
if ( opt_str != ftp_known_option )
{
# Anonymize the option conservatively
print ftp_anon_log, fmt("option_anonymized: \"%s\" from (%s %s)",
to_string_literal(opt_str), cmd, file_name);
opt_str = "-<option>";
}
else
# Leave in the clear
print ftp_anon_log, fmt("option_left_in_the_clear: \"%s\" from (%s %s)",
to_string_literal(opt_str), cmd, file_name);
file_name = ret$file_name;
}
}
if ( file_name == "" )
return opt_str;
if ( file_name != ftp_file_name_pat )
{
# Log special file names (e.g. those containing
# control characters) for manual inspection -- such
# file names are rare and may present problems in
# reply anonymization.
print ftp_anon_log, fmt("unrecognized_file_name: \"%s\" (%s) [%s]",
to_string_literal(file_name), cmd, id_string(session$connection_id));
}
if ( strstr(file_name, " ") > 0 )
{
# Log file names that contain spaces (for debugging only)
print ftp_anon_log, fmt("space_in_file_name: \"%s\" (%s) [%s]",
to_string_literal(file_name), cmd, id_string(session$connection_id));
}
# Compute the absolute and clean (without '..' and duplicate
# '/') path
local abs_path = absolute_path(session, file_name);
local resp_h = session$connection_id$resp_h;
local known_public_file =
[resp_h, abs_path] in ftp_known_public_files ||
[resp_h, abs_path] in ftp_valid_public_files;
if ( file_name == ftp_public_files || abs_path == ftp_public_files )
{
leave_in_the_clear("public_path_name", session,
arg, fmt("(%s %s) %s", cmd, file_name, abs_path));
}
else if ( resp_h in ftp_public_servers &&
(abs_path != ftp_hidden_file ||
abs_path == ftp_public_hidden_file) &&
(ftp_keep_all_files_for_public_servers || valid_file_name ||
known_public_file) )
{
if ( valid_file_name && ! known_public_file )
{
add ftp_valid_public_files[resp_h, abs_path];
print ftp_anon_log,
fmt("valid_public_file: [%s, \"%s\"]",
resp_h, to_string_literal(abs_path));
}
leave_in_the_clear("file_on_public_server", session, arg,
fmt("%s %s:%s", cmd, session$connection_id$resp_h, abs_path));
}
else
{
local anon_type: string;
if ( file_name == ftp_sensitive_files ||
abs_path == ftp_sensitive_files )
anon_type = "sensitive_path_name";
else if ( abs_path == ftp_hidden_file )
anon_type = "hidden_path_name";
else if ( resp_h in ftp_public_servers )
anon_type = "invalid_public_file";
else
anon_type = "path_name";
file_name = anonymize_arg(anon_type, session, cmd, abs_path, cat("file:", session$connection_id$resp_h));
}
# concatenate the option string with the file_name
return string_cat(opt_str, file_name);
}
# The argument is presumably privacy-safe, but we should not assume
# that it is the case. Instead, we check if the argument is legal and
# thus privacy-free.
function check_safe_arg(session: ftp_session_info, cmd: string,
arg: string): string
{
if ( cmd == "HELP" )
return ( arg in ftp_help_words ) ?
leave_in_the_clear("known_help_word", session,
arg,
fmt("%s %s", cmd, arg))
: anonymize_arg("unknown_help_string", session, cmd, arg, cmd);
else
# Note that we have already checked the (cmd, arg)
# against ftp_safe_cmd_arg_pattern. So the argument
# here must have an unrecognized pattern and should be
# anonymized.
return anonymize_arg("illegal_argument", session, cmd, arg, cmd);
}
function check_site_arg(session: ftp_session_info, cmd: string,
arg: string): string
{
local site_cmd_arg = split1(arg, /[ \t]*/);
local site_cmd = site_cmd_arg[1];
local site_cmd_upper = to_upper(site_cmd);
if ( site_cmd_upper in ftp_known_site_cmd )
{
if ( length(site_cmd_arg) > 1 )
{
# If the there is an argument after "SITE <cmd>"
local site_arg = site_cmd_arg[2];
site_arg =
anonymize_arg(fmt("arg_of_site_%s", site_cmd),
session, cmd, site_arg, cmd);
return string_cat(site_cmd, " ", site_arg);
}
else
{
return leave_in_the_clear("known_site_command", session,
site_cmd,
fmt("%s %s", cmd, arg));
}
}
else
return anonymize_arg("site_arg", session, cmd, arg, cmd);
}
function anonymize_port_arg(session: ftp_session_info, cmd: string,
arg: string): string
{
local data = parse_ftp_port(arg);
if ( data$valid )
{
local a: addr;
# Anonymize the address part
a = anonymize_address(data$h, session$connection_id);
return fmt_ftp_port(a, data$p);
}
else
return anonymize_arg("unrecognized_ftp_port", session, cmd, arg, "");
}
# EPRT is an extension to the PORT command
function anonymize_eprt_arg(session: ftp_session_info, cmd: string,
arg: string): string
{
if ( arg != ftp_eprt_pat )
return anonymize_arg("unrecognized_EPRT_arg", session, cmd, arg, "");
local parts = split(arg, /\|/);
# Anonymize the address part
local a = parse_dotted_addr(parts[3]);
a = anonymize_address(a, session$connection_id);
return fmt("|%s|%s|%s|", parts[2], a, parts[4]);
}
# Anonymize arguments of commands that we do not understand
function anonymize_other_arg(session: ftp_session_info, cmd: string, arg: string): string
{
local anon: string;
# Try to guess what the arg is
local data = parse_ftp_port(arg);
if ( arg == ftp_port_pat && data$valid )
# Here we do not check whether data$h == session$connection_id$orig_h
# because sometimes it's not the case, but we will try to anonymize it anyway.
{
anon = anonymize_port_arg(session, cmd, arg);
print ftp_anon_log, fmt("anonymize_arg: (%s) {} %s \"%s\" to \"%s\" in [%s]",
"port arg of non-port command",
cmd, arg, anon, id_string(session$connection_id));
}
else if ( arg == ftp_ip_pat )
{
local a = parse_dotted_addr(arg);
a = anonymize_address(a, session$connection_id);
anon = cat(a);
}
else if ( arg == ftp_domain_name_pat )
{
anon = "<domain name>";
}
else if ( arg == "." )
{
anon = arg;
leave_in_the_clear(".", session, arg, fmt("%s %s", cmd, arg));
}
else
# Anonymize by default.
anon = anonymize_arg("cannot_understand_arg",
session, cmd, arg, cmd);
return anon;
}
# Anonymize the command and argument, and put the results in
# cmd_arg$anonymized_{cmd, arg}
function anonymize_ftp_cmd_arg(session: ftp_session_info,
cmd_arg: ftp_cmd_arg)
{
local cmd = cmd_arg$cmd;
local arg = cmd_arg$arg;
local anon : string;
cmd_arg$anonymized_cmd = cmd;
local ret: ftp_cmd_arg_anon_result;
if ( trace_specific_cmd_arg_anonymization )
ret = anonymize_trace_specific_cmd_arg(session, cmd, arg);
else
ret$anonymized = F;
if ( ret$anonymized )
{
# If the trace-specific anonymization applies to the cmd_arg
print ftp_anon_log, fmt("anonymize_arg: (%s) \"%s %s\" to \"%s %s\" in [%s]",
"trace-specific",
cmd, to_string_literal(arg),
ret$cmd, to_string_literal(ret$arg),
id_string(session$connection_id));
cmd_arg$anonymized_cmd = ret$cmd;
anon = ret$arg;
}
else if ( [cmd, arg] in ftp_special_cmd_args )
{
anon = ftp_special_cmd_args[cmd, arg];
print ftp_anon_log, fmt("anonymize_arg: (%s) [%s] \"%s\" to \"%s\" in [%s]",
"special_arg_transformation",
cmd,
to_string_literal(arg),
to_string_literal(anon),
id_string(session$connection_id));
}
else if ( to_upper(string_cat(cmd, " ", arg)) == ftp_safe_cmd_arg_pattern ||
[cmd, arg] in ftp_safe_arg_list )
{
leave_in_the_clear("safe_arg", session, arg, fmt("%s %s", cmd, arg));
anon = arg;
}
else if ( cmd == "USER" || cmd == "ACCT" )
anon = (arg in ftp_guest_ids) ?
arg : anonymize_user_id(session, arg, LOGIN_PENDING, "");
else if ( cmd == "PASS" )
anon = "<password>";
else if ( cmd in ftp_cmds_with_no_arg )
anon = (arg == "") ?
"" :
anonymize_arg("should_have_been_empty",
session, cmd, arg, cmd);
else if ( cmd in ftp_cmds_with_file_arg )
{
if ( session$user in ftp_guest_ids )
anon = ( arg == "" ) ? "" : anonymize_file_name_arg(session, cmd, arg, F);
else
anon = "<path>";
}
else if ( cmd in ftp_cmds_with_safe_arg )
anon = check_safe_arg(session, cmd, arg);
else if ( cmd == "SITE" )
anon = check_site_arg(session, cmd, arg);
else if ( cmd == "PORT" )
anon = anonymize_port_arg(session, cmd, arg);
else if ( cmd == "EPRT" )
anon = anonymize_eprt_arg(session, cmd, arg);
else if ( cmd == "AUTH" )
anon = anonymize_arg("rejected_auth_arg", session, cmd, arg, cmd);
else
{
if ( cmd == /<.*>/ )
cmd_arg$anonymized_cmd = "";
else if ( cmd !in ftp_other_cmds )
{
local a = anonymize_string(string_cat("cmd:", cmd));
print ftp_anon_log, fmt("anonymize_cmd: (%s) \"%s\" [%s] to \"%s\" in [%s]",
"unrecognized command", to_string_literal(cmd),
to_string_literal(arg), a,
id_string(session$connection_id));
cmd_arg$anonymized_cmd = a;
}
anon = anonymize_other_arg(session, cmd, arg);
}
if ( cmd == "USER" )
session$anonymized_user = anon;
cmd_arg$anonymized_arg = anon;
}
# We delay anonymization of certain requests till we see the reply:
# when the argument of a USER command is a sensitive user ID, we
# anonymize the ID if the login is successful and leave the ID in the
# clear otherwise.
#
# The function returns T if the decision should be delayed.
function delay_rewriting_request(session: ftp_session_info, cmd: string,
arg: string): bool
{
return (cmd == "USER" && arg !in ftp_guest_ids) ||
(cmd == "AUTH") ||
(cmd in ftp_cmds_with_file_arg &&
session$connection_id$resp_h in ftp_public_servers);
}
function ftp_request_rewrite(c: connection, session: ftp_session_info,
cmd_arg: ftp_cmd_arg): bool
{
local cmd = cmd_arg$cmd;
local arg = cmd_arg$arg;
if ( delay_rewriting_request(session, cmd, arg) )
{
cmd_arg$rewrite_slot = reserve_rewrite_slot(c);
session$delayed_request_rewrite[cmd_arg$seq] = cmd_arg;
return F;
}
else
{
anonymize_ftp_cmd_arg(session, cmd_arg);
rewrite_ftp_request(c, cmd_arg$anonymized_cmd,
cmd_arg$anonymized_arg);
return T;
}
}
function do_rewrite_delayed_ftp_request(c: connection, delayed: ftp_cmd_arg)
{
seek_rewrite_slot(c, delayed$rewrite_slot);
rewrite_ftp_request(c, delayed$cmd == /<.*>/ ? "" : delayed$cmd,
delayed$anonymized_arg);
release_rewrite_slot(c, delayed$rewrite_slot);
delayed$rewrite_slot = 0;
}
function delayed_ftp_request_rewrite(c: connection, session: ftp_session_info,
delayed: ftp_cmd_arg,
current: ftp_cmd_arg,
reply_code: count)
{
local cmd = delayed$cmd;
local arg = delayed$arg;
if ( cmd == "USER" )
{
delayed$anonymized_cmd = cmd;
local login_status: login_status_type;
if ( reply_code == 0 )
login_status = LOGIN_UNKNOWN;
else if ( delayed$seq == current$seq ||
current$cmd == "PASS" ||
current$cmd == "ACCT" )
{
if ( reply_code >= 330 && reply_code < 340 ) # need PASS/ACCT
login_status = LOGIN_PENDING; # wait to see outcome of PASS
else if ( reply_code >= 400 && reply_code < 600 )
login_status = LOGIN_FAILED;
else if ( reply_code >= 230 && reply_code < 240 )
login_status = LOGIN_SUCCESSFUL;
else
login_status = LOGIN_UNKNOWN;
}
else if ( current$cmd == "USER" ) # another login attempt
login_status = LOGIN_FAILED;
else if ( reply_code == 230 )
login_status = LOGIN_SUCCESSFUL;
else if ( reply_code == 530 )
login_status = LOGIN_FAILED;
else
login_status = LOGIN_UNKNOWN;
if ( login_status != LOGIN_PENDING )
{
delayed$anonymized_arg =
anonymize_user_id(session, arg, login_status,
fmt("(%s %s) %s %s -> %d", cmd, arg, current$cmd, current$arg, reply_code));
do_rewrite_delayed_ftp_request(c, delayed);
}
}
else if ( cmd == "AUTH" )
{
delayed$anonymized_cmd = cmd;
if ( reply_code >= 500 && reply_code < 600 )
# if AUTH fails
{
anonymize_ftp_cmd_arg(session, delayed);
do_rewrite_delayed_ftp_request(c, delayed);
}
else if ( reply_code >= 300 && reply_code < 400 )
;
else # otherwise always anonymize the argument
{
delayed$anonymized_arg = "<auth_mechanism>";
do_rewrite_delayed_ftp_request(c, delayed);
}
}
else if ( cmd in ftp_cmds_with_file_arg && session$connection_id$resp_h in ftp_public_servers )
{
delayed$anonymized_cmd = cmd;
# The argument represents a valid file name on a
# public server only if the operation is successful.
delayed$anonymized_arg =
anonymize_file_name_arg(session, cmd, arg,
(cmd != "LIST" && cmd != "NLST" &&
reply_code >= 100 && reply_code < 300));
do_rewrite_delayed_ftp_request(c, delayed);
}
else
{
print ftp_anon_log, "ERROR! unrecognizable delayed ftp request rewrite";
anonymize_ftp_cmd_arg(session, delayed);
do_rewrite_delayed_ftp_request(c, delayed);
}
}
function process_delayed_rewrites(c: connection, session: ftp_session_info, reply_code: count, cmd_arg: ftp_cmd_arg)
{
local written: table[count] of ftp_cmd_arg;
for ( s in session$delayed_request_rewrite )
{
local ca = session$delayed_request_rewrite[s];
delayed_ftp_request_rewrite(c, session, ca, cmd_arg,
reply_code);
if ( ca$rewrite_slot == 0 )
written[ca$seq] = ca;
}
for ( s in written )
delete session$delayed_request_rewrite[s];
}
function ftp_reply_rewrite(c: connection, session: ftp_session_info,
code: count, msg: string, cont_resp: bool,
cmd_arg: ftp_cmd_arg)
{
local actual_code = session$reply_code;
local xyz = parse_ftp_reply_code(actual_code);
process_delayed_rewrites(c, session, actual_code, cmd_arg);
if ( process_ftp_reply_by_message_pattern )
{
# See *ftp-reply-pattern.bro* for reply anonymization
local anon_msg = anonymize_ftp_reply_by_msg_pattern(actual_code, msg,
cmd_arg, session);
rewrite_ftp_reply(c, code, anon_msg, cont_resp);
}
else
rewrite_ftp_reply(c, code, "<ftp reply message stripped out>", cont_resp);
}
const eliminate_scans = F &redef;
const port_scanners: set[addr] &redef;
global eliminate_scan_for_host: table[addr] of bool;
function eliminate_scan(id: conn_id): bool
{
local h = id$resp_h;
if ( h !in eliminate_scan_for_host )
{
# if the hash string starts with [0-7], i.e. with probability of 50%
eliminate_scan_for_host[h] = (/^[0-7]/ in md5_hmac(h));
if ( eliminate_scan_for_host[h] )
print ftp_anon_log, fmt("eliminate_scans_for_host %s", h);
}
return eliminate_scan_for_host[h];
}
redef call_ftp_connection_remove = T;
function ftp_connection_remove(c: connection)
{
if ( c$id in ftp_sessions )
{
local session = ftp_sessions[c$id];
process_delayed_rewrites(c, session, 0, find_ftp_pending_cmd(session$pending_requests, 0, ""));
}
if ( eliminate_scans && ! requires_trace_commitment )
print ftp_anon_log,
fmt("ERROR: requires_trace_commitment must be set to true in order to allow scan elimination");
if ( requires_trace_commitment )
{
local id = c$id;
local eliminate = F;
if ( eliminate_scans &&
# To check if the connection is part of a port scan
(id !in ftp_sessions ||
ftp_sessions[id]$num_requests == 0 ||
id$orig_h in port_scanners) &&
eliminate_scan(id) )
rewrite_commit_trace(c, F, T);
else
rewrite_commit_trace(c, T, T);
}
}

View file

@ -348,12 +348,6 @@ event ftp_excessive_filename(session: ftp_session_info,
session$log_it = T;
}
global ftp_request_rewrite: function(c: connection, session: ftp_session_info,
cmd_arg: ftp_cmd_arg);
global ftp_reply_rewrite: function(c: connection, session: ftp_session_info,
code: count, msg: string,
cont_resp: bool, cmd_arg: ftp_cmd_arg);
# Returns true if the given string is at least 25% composed of 8-bit
# characters.
function is_string_binary(s: string): bool
@ -518,9 +512,6 @@ event ftp_request(c: connection, command: string, arg: string)
}
}
if ( rewriting_ftp_trace )
ftp_request_rewrite(c, session, cmd_arg);
if ( command in ftp_all_cmds )
{
if ( command in ftp_untested_cmds )
@ -761,11 +752,6 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool)
do_ftp_reply(c, session, code, msg, cmd_arg$cmd, cmd_arg$arg);
}
if ( rewriting_ftp_trace )
{
ftp_reply_rewrite(c, session, code, msg, cont_resp, cmd_arg);
}
if ( ! cont_resp )
{
if ( ftp_cmd_pending(session$pending_requests) )

View file

@ -1,433 +0,0 @@
# $Id:$
# We can't do HTTP rewriting unless we process everything in the connection.
@load http-reply
@load http-entity
@load http-anon-server
@load http-anon-useragent
@load http-anon-utils
@load http-abstract
@load anon
module HTTP;
redef rewriting_http_trace = T;
redef http_entity_data_delivery_size = 18874368;
redef abstract_max_length = 18874368;
const rewrite_header_in_position = F;
const http_response_reasons = {
"no content", "ok", "moved permanently", "not modified",
"use local copy", "object not found", "forbidden", "okay",
"object moved", "found", "http", "redirecting to main server",
"internal server error", "not found", "unauthorized", "moved",
"redirected", "continue", "access forbidden", "partial content",
"redirect", "<empty>", "authorization required",
"request time-out", "moved temporarily", "",
};
const keep_alive_pat = /(([0-9]+|timeout=[0-9]+|max=[0-9]+),?)*/ ;
const content_type =
/video\/(x-flv)(;)?/ # video
| /audio\/(x-scpls)/
| /image\/(gif|bmp|jpeg|pjpeg|tiff|png|x-icon)(;)?(qs\=[0-9](\.[0-9])?)?,?/
| /application\/(octet-stream|x-www-form-urlencoded|x-javascript|rss\+xml|x-gzip|x-ns-proxy-autoconfig|pdf|pkix-crl|x-shockwave-flash|postscript|xml|rdf\+xml|excel|msword|x-wais-source)(;)?(charset=(iso-8859-1|iso8859-1|gb2312|windows-1251|windows-1252|utf-8))?/
| /text\/(plain|js|html|\*|css|xml|javascript);?(charset=(iso-8859-1|iso8859-1|gb2312|windows-1251|windows-1252|utf-8))?/
| /^unknown$/
;
const accept_enc_pat =
/(((x-)?deflate|(x-)?compress|\*|identity|(x-)?gzip|bzip|bzip2)(\; *q\=[0-9](\.[0-9])?)?,?)*/ ;
const accept_charset_pat =
/((windows-(1252|1251)|big5|iso-8859-(1|15)|\*|utf-(8|16))(\; *q\=[0-9](\.[0-9])?)?,?)*/ ;
const connection_pat = /((close|keep\-alive|transfer\-encoding|te),?)*/ ;
const http_methods =
/get|put|post|head|propfind|connect|options|proppatch|lock|unlock|move|delete|mkcol/ ;
const http_version = /(1\.0|1\.1)/ ;
const last_modified_pat =
/(Sun|Mon|Tue|Wed|Thu|Fri|Sat), [0-9]+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9][0-9][0-9][0-9] .*/
| /(-)?[0-9]+/
;
const vary_pat =
/((\*| *|accept|accept\-charset|negotiate|host|user\-agent|accept\-language|accept\-encoding|cookie),?)*/ ;
const accept_lang_pat =
/(( *|tw|cs|mx|tr|ru|sk|au|hn|sv|no|bg|en|ko|kr|ca|pl|nz|fr|ch|jo|gb|zh|hk|cn|lv|de|nl|dk|fi|nl|es|pe|it|pt|br|ve|cl|ja|jp|he|ha|ar|us|en-us|da)(\; *q\=[0-9](\.[0-9]+)?)?(,|-|\_)?)*/ ;
const accept_pat =
/(( *|audio|application|\*|gif|xml|xhtml\+xml|x-rgb|x-xbm|video|x-gsarcade-launch|mpeg|sgml|tiff|x-rgb|x-xbm|postscript|text|html|x-xbitmap|pjpeg|vnd.ms-powerpoint|vnd.ms-excel|msword|salt\+html|xhtml|plain|jpeg|jpg|x-shockwave-flash|x-|css|image|png|\*)(\; *q\=[0-9]*(\.[0-9]+)?)?(,|\/|\+)?)*/ ;
const tcn_pat = /list|choice|adhoc|re-choose|keep/;
const date_pat =
/(sun|mon|tue|wed|thu|fri|sat)\,*[0-9]+ *(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) *[0-9]+ ([0-9]+:)*[0-9]+ gmt/
| /(sun|mon|tue|wed|thu|fri|sat)*(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec) *[0-9]+ *([0-9]+:)*[0-9]+(am|pm)?( *[0-9]+)?( *gmt)?/ ;
const content_encoding_pat = /gzip|deflate|x-compress|x-gzip/;
const hashed_headers =
/COOKIE/
| /AUTHOR/
| /CACHE-CONTROL/
| /ETAG/
| /VIA/
| /X-VIA/
| /IISEXPORT/
| /SET-COOKIE/
| /X-JUNK/
| /PRAGMA/
| /AUTHORIZATION/
| /X-POWERED-BY/
| /X-CACHE/
| /X-FORWARDED-FOR/
| /X-PAD/
| /X-C/
| /XSERVER/
| /FROM/
| /CONTENT-DISPOSITION/
| /X-ASPNET-VERSION/
| /GUID/
| /REGIONDATA/
| /CLIENTID/
| /X-CACHE-HEADERS-SET-BY/
| /X-CACHE-LOOKUP/
| /WARNING/
| /MICROSOFTOFFICEWEBSERVER/
| /IF-NONE-MATCH/
| /X-AMZ-ID-[0-9]/
| /X-N/
| /X-TR/
| /X-RSN/
#| /X-POOKIE/ # these are weird ... next two are from slashdot
#| /X-FRY/
#| /X-BENDER/
| /RANGE/
| /IF-RANGE/
| /CONTENT-RANGE/
| /AD-REACH/
| /HMSERVER/
| /STATUS/
| /X-SERVED/
| /WWW-AUTHENTICATE/
| /X-RESPONDING-SERVER/
| /MAX-AGE/
| /POST-CHECK/
| /PRE-CHECK/
| /X-CONTENT-ENCODED-BY/
| /X-USER-IP/
| /X-ICAP-VERSION/
| /X-DELPHI/
| /AUTHENTICATION-INFO/
| /PPSERVER/
| /EDGE-CONTROL/
| /COMPRESSION-CONTROL/
| /CONTENT-MD5/
| /X-HOST/
| /P3P/
;
event http_request(c: connection, method: string,
original_URI: string, unescaped_URI: string, version: string)
{
if (! rewriting_trace() )
return;
print http_anon_log,
fmt(" > %s %s %s ", method, original_URI, version);
if ( to_lower(method) != http_methods )
{
print http_anon_log, fmt("*** Unknown method %s", method);
method = string_cat(" (anon-unknown) ", anonymize_string(method));
}
original_URI = anonymize_http_URI(original_URI);
if ( version != http_version )
{
print http_anon_log, fmt("*** Unknown version %s ", version);
version = string_cat(" (anon-unknown) ", anonymize_string(version));
}
print http_anon_log, fmt(" < %s %s %s ", method, original_URI, version);
rewrite_http_request(c, method, original_URI, version);
}
event http_reply(c: connection, version: string, code: count, reason: string)
{
if ( rewriting_trace() )
{
reason = to_lower(strip(reason));
if ( reason !in http_response_reasons )
{
print http_anon_log,
fmt("*** Unknown reply reason %s ", reason);
rewrite_http_reply(c, version, code,
anonymize_string(reason));
}
else
rewrite_http_reply(c, version, code, reason);
}
}
function check_pat(value: string, pat: pattern, name: string): string
{
if ( value == pat )
return value;
print http_anon_log, fmt("*** invalid %s: %s", name, value);
return "(anon-unknown): ";
}
function check_pat2(value: string, pat: pattern, name: string): string
{
if ( value == pat )
return value;
print http_anon_log, fmt("*** invalid %s: %s", name, value);
return fmt("(anon-unknown): %s", anonymize_string(value));
}
function check_pat3(value: string, pat: pattern): string
{
if ( value == pat )
return value;
return fmt("(anon-unknown): %s", anonymize_string(value));
}
event http_header(c: connection, is_orig: bool, name: string, value: string)
{
if ( ! rewriting_trace() )
return;
# 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 )
return;
value = strip(value);
if ( name == "CONTENT-LENGTH" )
{
# if ( rewrite_header_in_position )
# {
# local p = current_packet(c);
# if ( p$is_orig == is_orig )
# {
# # local s = lookup_http_request_stream(c);
# # local msg = get_http_message(s, is_orig);
# if ( msg$header_slot == 0 )
# msg$header_slot = reserve_rewrite_slot(c);
# }
# else
# print fmt("cannot reserve a slot at %.6f", network_time());
# }
print http_anon_log,
fmt("X-Original-Content-Length: %s --", value);
name = "X-Original-Content-Length";
}
else if ( name == "TRANSFER-ENCODING" || name == "TE" )
{
print http_anon_log, fmt("TRANSFER-ENCOODING: %s --", value);
name = "X-Original-Transfer-Encoding";
}
else if ( name == "HOST" )
{
local anon_host = "";
if ( value == simple_filename )
anon_host = anonymize_path(value);
else
anon_host = anonymize_host(value);
print http_anon_log, fmt("HOST: %s > %s", value, anon_host);
value = anon_host;
}
else if ( name == "REFERER" )
{
local anon_ref = anonymize_http_URI(value);
print http_anon_log, fmt("REFERER: %s > %s", value, anon_ref);
value = anon_ref;
}
else if ( name == "LOCATION" || name == "CONTENT-LOCATION" )
value = anonymize_http_URI(value);
else if ( name == "SERVER" )
value = filter_in_http_server(to_lower(value));
else if ( name == "USER-AGENT" )
value = filter_in_http_useragent(to_lower(value));
else if ( name == "KEEP-ALIVE" )
value = check_pat(value, keep_alive_pat, "keep-alive");
else if ( name == "DATE" || name == "IF-MODIFIED-SINCE" ||
name == "UNLESS-MODIFIED-SINCE" )
value = check_pat2(to_lower(value), date_pat, "date");
else if ( name == "ACCEPT-CHARSET" )
value = check_pat(to_lower(value), accept_charset_pat,
"accept-charset");
else if ( name == "CONTENT-TYPE" )
{
value = check_pat2(to_lower(value), content_type, "content-type");
# local stream = lookup_http_request_stream(c);
# local the_http_msg = get_http_message(stream, is_orig);
# the_http_msg$content_type = value;
}
else if ( name == "ACCEPT-ENCODING" )
value = check_pat2(to_lower(value), accept_enc_pat,
"accept-encoding");
else if ( name == "PAGE-COMPLETION-STATUS" )
value = check_pat2(to_lower(value), /(ab)?normal/,
"page-completion-status");
else if ( name == "CONNECTION" || name == "PROXY-CONNECTION" )
value = check_pat2(to_lower(value), connection_pat,
"connection type");
else if ( name == "LAST-MODIFIED" || name == "EXPIRES" )
value = check_pat(value, last_modified_pat, name);
else if (name == "ACCEPT-LANGUAGE" || name == "LANGUAGE")
value = check_pat2(to_lower(value), accept_lang_pat,
"accept-language");
else if ( name == "ACCEPT" )
value = check_pat(to_lower(value), accept_pat, "accept");
else if ( name == "ACCEPT-RANGES" )
value = check_pat2(to_lower(value), /(bytes|none) */,
"accept-ranges");
else if ( name == "MIME-VERSION" )
value = check_pat3(value, /[0-9]\.[0-9]/);
else if ( name == "TCN" )
value = check_pat3(value, tcn_pat);
else if ( name == "CONTENT-ENCODING" )
value = check_pat2(value, content_encoding_pat,
"content-encoding");
else if ( name == "CONTENT-LANGUAGE" )
value = check_pat2(value, accept_lang_pat, "content-language");
else if ( name == "ALLOW" )
value = check_pat3(value, http_methods);
else if ( name == "AGE" || name == "BANDWIDTH" )
value = check_pat3(value, /[0-9]+/);
else if ( name == "VARY" )
value = check_pat2(value, vary_pat, "vary");
else if ( name == hashed_headers )
value = anonymize_string(value);
else
{
print http_anon_log, fmt("unknown header: %s : %s", name, value);
value = string_cat("(anon-unknown): ", anonymize_string(value));
}
rewrite_http_header(c, is_orig, name, value);
}
event http_all_headers(c: connection, is_orig: bool, hlist: mime_header_list)
{
if ( ! rewriting_trace() )
return;
if ( rewrite_header_in_position )
{
local p = current_packet(c);
if ( p$is_orig == is_orig )
{
local s = lookup_http_request_stream(c);
local msg = get_http_message(s, is_orig);
if ( msg$header_slot == 0 )
msg$header_slot = reserve_rewrite_slot(c);
}
else
print fmt("cannot reserve a slot at %.6f", network_time());
# An empty line to mark the end of headers.
rewrite_http_data(c, is_orig, "\r\n");
}
}
event http_message_done(c: connection, is_orig: bool, stat: http_message_stat)
{
if ( ! rewriting_trace() )
return;
if ( stat$interrupted )
{
print http_log,
fmt("%.6f %s message interrupted at length=%d \"%s\"",
network_time(), id_string(c$id),
stat$body_length, stat$finish_msg);
}
local s = lookup_http_request_stream(c);
local msg = get_http_message(s, is_orig);
if ( msg$header_slot > 0 )
seek_rewrite_slot(c, msg$header_slot);
local data_length = 0;
local data_hash = "";
local sanitized_abstract = "";
if ( ! is_orig || stat$body_length > 0 )
{
data_length = byte_len(msg$abstract);
data_hash = anonymize_string(msg$abstract);
sanitized_abstract = string_fill(data_length, data_hash);
data_length += stat$content_gap_length;
rewrite_http_header(c, is_orig, "Content-Length",
fmt(" %d", data_length));
rewrite_http_header(c, is_orig, "X-anon-content-hash",
fmt(" %s", data_hash));
rewrite_http_header(c, is_orig, "X-Actual-Data-Length",
fmt(" %d; gap=%d, content-length=%s",
stat$body_length,
stat$content_gap_length,
msg$content_length));
}
if ( msg$header_slot > 0 )
{
release_rewrite_slot(c, msg$header_slot);
msg$header_slot = 0;
}
if ( ! rewrite_header_in_position )
# An empty line to mark the end of headers.
rewrite_http_data(c, is_orig, "\r\n");
if ( data_length > 0 )
rewrite_http_data(c, is_orig, sanitized_abstract);
}

View file

@ -1,137 +0,0 @@
# $Id: http-rewriter.bro 416 2004-09-17 03:52:28Z vern $
# We can't do HTTP rewriting unless we process everything in the connection.
@load http-reply
@load http-entity
module HTTP;
redef rewriting_http_trace = T;
redef http_entity_data_delivery_size = 4096;
const rewrite_header_in_position = F;
event http_request(c: connection, method: string,
original_URI: string, unescaped_URI: string, version: string)
{
if ( rewriting_trace() )
rewrite_http_request(c, method, original_URI, version);
}
event http_reply(c: connection, version: string, code: count, reason: string)
{
if ( rewriting_trace() )
rewrite_http_reply(c, version, code, reason);
}
event http_header(c: connection, is_orig: bool, name: string, value: string)
{
if ( ! rewriting_trace() )
return;
# 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" )
{
if ( rewrite_header_in_position )
{
local p = current_packet(c);
if ( p$is_orig == is_orig )
{
# local s = lookup_http_request_stream(c);
# local msg = get_http_message(s, is_orig);
if ( msg$header_slot == 0 )
msg$header_slot = reserve_rewrite_slot(c);
}
else
print fmt("cannot reserve a slot at %.6f", network_time());
}
# rewrite_http_header(c, is_orig,
# "X-Original-Content-Length", value);
}
else if ( name == "TRANSFER-ENCODING" )
rewrite_http_header(c, is_orig,
"X-Original-Transfer-Encoding", value);
else
rewrite_http_header(c, is_orig, name, value);
}
}
event http_all_headers(c: connection, is_orig: bool, hlist: mime_header_list)
{
if ( ! rewriting_trace() )
return;
if ( rewrite_header_in_position )
{
local p = current_packet(c);
if ( p$is_orig == is_orig )
{
local s = lookup_http_request_stream(c);
local msg = get_http_message(s, is_orig);
if ( msg$header_slot == 0 )
msg$header_slot = reserve_rewrite_slot(c);
}
else
print fmt("cannot reserve a slot at %.6f", network_time());
# An empty line to mark the end of headers.
rewrite_http_data(c, is_orig, "\r\n");
}
}
event http_message_done(c: connection, is_orig: bool, stat: http_message_stat)
{
if ( ! rewriting_trace() )
return;
local s = lookup_http_request_stream(c);
local msg = get_http_message(s, is_orig);
local data_length = 0;
if ( stat$interrupted )
{
print http_log,
fmt("%.6f %s message interrupted at length=%d \"%s\"",
network_time(), id_string(c$id),
stat$body_length, stat$finish_msg);
}
if ( msg$header_slot > 0 )
seek_rewrite_slot(c, msg$header_slot);
if ( ! is_orig || stat$body_length > 0 )
{
if ( include_HTTP_abstract )
data_length = byte_len(msg$abstract);
data_length = data_length + stat$content_gap_length;
rewrite_http_header(c, is_orig, "Content-Length",
fmt(" %d", data_length));
}
rewrite_http_header(c, is_orig, "X-Actual-Data-Length",
fmt(" %d; gap=%d, content-length=%s",
stat$body_length,
stat$content_gap_length,
msg$content_length));
if ( msg$header_slot > 0 )
{
release_rewrite_slot(c, msg$header_slot);
msg$header_slot = 0;
}
if ( ! rewrite_header_in_position )
# An empty line to mark the end of headers.
rewrite_http_data(c, is_orig, "\r\n");
if ( data_length > 0 )
rewrite_http_data(c, is_orig, msg$abstract);
}

View file

@ -1,115 +0,0 @@
# $Id: ident-rewriter.bro 47 2004-06-11 07:26:32Z vern $
@load ident
redef rewriting_ident_trace = T;
global public_ident_user_ids = { "root", } &redef;
global public_ident_systems = { "UNIX", } &redef;
const delay_rewriting_request = T;
function public_ident_user(id: string): bool
{
return id in public_ident_user_ids;
}
function public_system(system: string): bool
{
return system in public_ident_systems;
}
type ident_req: record {
lport: port;
rport: port;
rewrite_slot: count;
};
# Does not support pipelining ....
global ident_req_slots: table[addr, port, addr, port] of ident_req;
event ident_request(c: connection, lport: port, rport: port)
{
if ( ! rewriting_trace() )
return;
local id = c$id;
if ( delay_rewriting_request )
{
local slot = reserve_rewrite_slot(c);
ident_req_slots[id$orig_h, id$orig_p, id$resp_h, id$resp_p] =
[$lport = lport, $rport = rport, $rewrite_slot = slot];
}
else
rewrite_ident_request(c, lport, rport);
}
event ident_reply(c: connection, lport: port, rport: port,
user_id: string, system: string)
{
if ( ! rewriting_trace() )
return;
local id = c$id;
if ( [id$orig_h, id$orig_p, id$resp_h, id$resp_p] in ident_req_slots )
{
local req = ident_req_slots[id$orig_h, id$orig_p,
id$resp_h, id$resp_p];
seek_rewrite_slot(c, req$rewrite_slot);
rewrite_ident_request(c, req$lport, req$rport);
release_rewrite_slot(c, req$rewrite_slot);
delete ident_req_slots[id$orig_h, id$orig_p,
id$resp_h, id$resp_p];
}
rewrite_ident_reply(c, lport, rport,
public_system(system) ? system : "OTHER",
public_ident_user(user_id) ? user_id : "private user");
}
event ident_error(c: connection, lport: port, rport: port, line: string)
{
if ( ! rewriting_trace() )
return;
local id = c$id;
if ( [id$orig_h, id$orig_p, id$resp_h, id$resp_p] in ident_req_slots )
{
local req = ident_req_slots[id$orig_h, id$orig_p,
id$resp_h, id$resp_p];
seek_rewrite_slot(c, req$rewrite_slot);
rewrite_ident_request(c, req$lport, req$rport);
release_rewrite_slot(c, req$rewrite_slot);
delete ident_req_slots[id$orig_h, id$orig_p,
id$resp_h, id$resp_p];
}
rewrite_ident_error(c, lport, rport, line);
}
event connection_state_remove(c: connection)
{
if ( ! rewriting_trace() )
return;
local id = c$id;
if ( [id$orig_h, id$orig_p, id$resp_h, id$resp_p] in ident_req_slots )
{
local req = ident_req_slots[id$orig_h, id$orig_p,
id$resp_h, id$resp_p];
seek_rewrite_slot(c, req$rewrite_slot);
rewrite_ident_request(c, req$lport, req$rport);
release_rewrite_slot(c, req$rewrite_slot);
delete ident_req_slots[id$orig_h, id$orig_p,
id$resp_h, id$resp_p];
}
}

View file

@ -1,80 +0,0 @@
# $Id:$
redef rewriting_smb_trace = T;
event smb_message(c: connection, hdr: smb_hdr, is_orig: bool, cmd: string, body_length: count, body: string)
{
}
event smb_com_tree_connect_andx(c: connection, hdr: smb_hdr, path: string, service: string)
{
}
event smb_com_tree_disconnect(c: connection, hdr: smb_hdr)
{
}
event smb_com_nt_create_andx(c: connection, hdr: smb_hdr, name: string)
{
}
event smb_com_transaction(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
}
event smb_com_transaction2(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
}
event smb_com_trans_mailslot(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
}
event smb_com_trans_rap(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
}
event smb_com_trans_pipe(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
}
event smb_com_read_andx(c: connection, hdr: smb_hdr, data: string)
{
}
event smb_com_write_andx(c: connection, hdr: smb_hdr, data: string)
{
}
event smb_get_dfs_referral(c: connection, hdr: smb_hdr, max_referral_level: count, file_name: string)
{
}
event smb_com_negotiate(c: connection, hdr: smb_hdr)
{
}
event smb_com_negotiate_response(c: connection, hdr: smb_hdr, dialect_index: count)
{
}
event smb_com_setup_andx(c: connection, hdr: smb_hdr)
{
}
event smb_com_generic_andx(c: connection, hdr: smb_hdr)
{
}
event smb_com_close(c: connection, hdr: smb_hdr)
{
}
event smb_com_logoff_andx(c: connection, hdr: smb_hdr)
{
}
event smb_error(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string)
{
}

View file

@ -1,94 +0,0 @@
# $Id: smtp-rewriter.bro 4758 2007-08-10 06:49:23Z vern $
@load smtp
@load mime # need mime for content hash
module SMTP;
redef rewriting_smtp_trace = T;
# We want this event handler to execute *after* the one in smtp.bro.
event smtp_request(c: connection, is_orig: bool, command: string, arg: string)
{
if ( ! rewriting_trace() )
return;
local session = smtp_sessions[c$id];
if ( command != ">" )
{
if ( command == "." )
{
# A hack before we have MIME rewriter.
# rewrite_smtp_data(c, is_orig, fmt("X-number-of-lines: %d",
# session$num_lines_in_body));
rewrite_smtp_data(c, is_orig, fmt("X-number-of-bytes: %d",
session$num_bytes_in_body));
# Write empty line to avoid MIME analyzer complaints.
rewrite_smtp_data(c, is_orig, "");
rewrite_smtp_data(c, is_orig, fmt("%s", session$content_hash));
}
if ( command in smtp_legal_cmds )
{
# Avoid the situation in which we mistake
# mail contents for SMTP commands.
rewrite_smtp_request(c, is_orig, command, arg);
rewrite_push_packet(c, is_orig);
}
}
}
event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string,
msg: string, cont_resp: bool)
{
if ( ! rewriting_trace() )
return;
rewrite_smtp_reply(c, is_orig, code, msg, cont_resp);
}
function starts_with_leading_whitespace(s: string): bool
{
return /^[ \t]/ in s;
}
function rewrite_smtp_header_line(c: connection, is_orig: bool,
session: smtp_session_info, line: string)
{
if ( starts_with_leading_whitespace(line) )
{ # a continuing header
if ( session$keep_current_header )
rewrite_smtp_data(c, is_orig, line);
}
else
{
session$keep_current_header = F;
local pair = split1(line, /:/);
if ( length(pair) < 2 )
{
session$keep_current_header = T;
rewrite_smtp_data(c, is_orig, line);
}
else
{
local field_name = to_upper(pair[1]);
# Currently, the MIME analyzer is sensitive to
# CONTENT-TYPE and CONTENT_TRANSFER_ENCODING,
# so we want to remove these when anonymizing,
# because we can't ensure their integrity when
# rewriting message bodies.
#
# To be conservative, however, we strip out *all*
# CONTENT-* headers.
if ( /^CONTENT-/ !in field_name )
{
session$keep_current_header = T;
rewrite_smtp_data(c, is_orig, line);
}
}
}
}

View file

@ -505,15 +505,9 @@ event connection_state_remove(c: connection)
}
}
global rewrite_smtp_header_line:
function(c: connection, is_orig: bool,
session: smtp_session_info, line: string);
function smtp_header_line(c: connection, is_orig: bool,
session: smtp_session_info, line: string)
{
if ( rewriting_smtp_trace )
rewrite_smtp_header_line(c, is_orig, session, line);
}
function smtp_body_line(c: connection, is_orig: bool,

View file

@ -751,15 +751,6 @@ void Analyzer::FlipRoles()
resp_supporters = tmp;
}
int Analyzer::RewritingTrace()
{
LOOP_OVER_CHILDREN(i)
if ( (*i)->RewritingTrace() )
return 1;
return 0;
}
void Analyzer::ProtocolConfirmation()
{
if ( protocol_confirmed )
@ -904,17 +895,10 @@ void SupportAnalyzer::ForwardUndelivered(int seq, int len, bool is_orig)
Parent()->Undelivered(seq, len, is_orig);
}
TransportLayerAnalyzer::~TransportLayerAnalyzer()
{
delete rewriter;
}
void TransportLayerAnalyzer::Done()
{
Analyzer::Done();
if ( rewriter )
rewriter->Done();
}
void TransportLayerAnalyzer::SetContentsFile(unsigned int /* direction */,
@ -929,14 +913,6 @@ BroFile* TransportLayerAnalyzer::GetContentsFile(unsigned int /* direction */) c
return 0;
}
void TransportLayerAnalyzer::SetTraceRewriter(Rewriter* r)
{
if ( rewriter )
rewriter->Done();
delete rewriter;
rewriter = r;
}
void TransportLayerAnalyzer::PacketContents(const u_char* data, int len)
{
if ( packet_contents && len > 0 )

View file

@ -225,10 +225,6 @@ public:
virtual void ProtocolViolation(const char* reason,
const char* data = 0, int len = 0);
// Returns true if the analyzer or one of its children is rewriting
// the trace.
virtual int RewritingTrace();
virtual unsigned int MemoryAllocation() const;
// The following methods are proxies: calls are directly forwarded
@ -367,9 +363,7 @@ private:
class TransportLayerAnalyzer : public Analyzer {
public:
TransportLayerAnalyzer(AnalyzerTag::Tag tag, Connection* conn)
: Analyzer(tag, conn) { pia = 0; rewriter = 0; }
virtual ~TransportLayerAnalyzer();
: Analyzer(tag, conn) { pia = 0; }
virtual void Done();
virtual void UpdateEndpointVal(RecordVal* endp, int is_orig) = 0;
@ -381,11 +375,6 @@ public:
void SetPIA(PIA* arg_PIA) { pia = arg_PIA; }
PIA* GetPIA() const { return pia; }
Rewriter* TraceRewriter() { return rewriter; }
// Takes ownership.
void SetTraceRewriter(Rewriter* r);
// Raises packet_contents event.
void PacketContents(const u_char* data, int len);
@ -394,7 +383,6 @@ protected:
private:
PIA* pia;
Rewriter* rewriter;
};
#endif

View file

@ -130,15 +130,7 @@ set(BIF_SRCS
event.bif
const.bif
types.bif
common-rw.bif
finger-rw.bif
ident-rw.bif
dns-rw.bif
ftp-rw.bif
smtp-rw.bif
http-rw.bif
strings.bif
smb-rw.bif
)
foreach (bift ${BIF_SRCS})
@ -353,7 +345,6 @@ set(bro_SRCS
TCP.cc
TCP_Endpoint.cc
TCP_Reassembler.cc
TCP_Rewriter.cc
Telnet.cc
Timer.cc
Traverse.cc
@ -370,10 +361,7 @@ set(bro_SRCS
md5.c
patricia.c
setsignal.c
UDP_Rewriter.cc
DNS_Rewriter.cc
PacketDumper.cc
Rewriter.cc
strsep.c
${dns_SRCS}
${malloc_SRCS}

View file

@ -755,16 +755,6 @@ void Connection::FlipRoles()
root_analyzer->FlipRoles();
}
int Connection::RewritingTrace()
{
return root_analyzer ? root_analyzer->RewritingTrace() : 0;
}
Rewriter* Connection::TraceRewriter() const
{
return root_analyzer ? root_analyzer->TraceRewriter() : 0;
}
unsigned int Connection::MemoryAllocation() const
{
return padded_sizeof(*this)

View file

@ -23,7 +23,6 @@ class RuleHdrTest;
class Specific_RE_Matcher;
class TransportLayerAnalyzer;
class RuleEndpointState;
class Rewriter;
typedef enum {
NUL_IN_LINE,
@ -135,17 +134,6 @@ public:
TransportProto ConnTransport() const { return proto; }
// If we are rewriting the trace of the connection, then we do
// not record original packets. We are rewriting if at least one,
// then the analyzer is rewriting.
int RewritingTrace();
// If we are rewriting trace, we need a handle to the rewriter.
// Returns 0 if not rewriting. (Note that if multiple analyzers
// want to rewrite, only one of them is returned. It's undefined
// which one.)
Rewriter* TraceRewriter() const;
// True if we should record subsequent packets (either headers or
// in their entirety, depending on record_contents). We still
// record subsequent SYN/FIN/RST, regardless of how this is set.

View file

@ -45,9 +45,6 @@
// - We don't match signatures on connections which are completely handled
// by the compressor. Matching would require significant additional state
// w/o being very helpful.
//
// - Trace rewriting doesn't work if the compressor is turned on (this is
// not a conceptual problem, but simply not implemented).
#ifdef DEBUG

View file

@ -13,8 +13,6 @@
#include "DNS.h"
#include "Sessions.h"
#include "Event.h"
#include "DNS_Rewriter.h"
#include "TCP_Rewriter.h"
DNS_Interpreter::DNS_Interpreter(Analyzer* arg_analyzer)
{
@ -1134,11 +1132,6 @@ DNS_Analyzer::~DNS_Analyzer()
void DNS_Analyzer::Init()
{
if ( transformed_pkt_dump && RewritingTrace() &&
Conn()->ConnTransport() == TRANSPORT_UDP )
Conn()->GetRootAnalyzer()->SetTraceRewriter(
new DNS_Rewriter(this, transformed_pkt_dump_MTU,
transformed_pkt_dump));
}
void DNS_Analyzer::Done()
@ -1196,5 +1189,3 @@ void DNS_Analyzer::ExpireTimer(double t)
ADD_ANALYZER_TIMER(&DNS_Analyzer::ExpireTimer,
t + dns_session_timeout, 1, TIMER_DNS_EXPIRE);
}
#include "dns-rw.bif.func_def"

View file

@ -265,11 +265,6 @@ public:
virtual void Done();
virtual void ConnectionClosed(TCP_Endpoint* endpoint,
TCP_Endpoint* peer, int gen_event);
virtual int RewritingTrace()
{
return BifConst::rewriting_dns_trace ||
TCP_ApplicationAnalyzer::RewritingTrace();
}
void ExpireTimer(double t);

View file

@ -1,587 +0,0 @@
// $Id:$
//
// See the file "COPYING" in the main distribution directory for copyright.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>
#include "NetVar.h"
#include "DNS.h"
#include "Val.h"
#include "TCP.h"
#include "Anon.h"
#include "DNS_Rewriter.h"
DNS_Rewriter::DNS_Rewriter(Analyzer* analyzer, int arg_MTU,
PacketDumper* dumper)
: UDP_Rewriter(analyzer, arg_MTU, dumper)
{
pkt_size = 0;
current_pkt_id = 0;
pkt = new u_char[DNS_PKT_SIZE + DNS_HDR_SIZE];
}
void DNS_Rewriter::DnsCopyHeader(Val* msg)
{
// New header - reset packet size.
pkt_size = 0;
// Move msg->AsRecordVal() to a RecordVal* to optimize.
const RecordVal* msg_rec = msg->AsRecordVal();
int id = msg_rec->Lookup(0)->AsCount();
int opcode = msg_rec->Lookup(1)->AsCount();
int rcode = msg_rec->Lookup(2)->AsCount();
int QR = msg_rec->Lookup(3)->AsBool();
int AA = msg_rec->Lookup(4)->AsBool();
int TC = msg_rec->Lookup(5)->AsBool();
int RD = msg_rec->Lookup(6)->AsBool();
int RA = msg_rec->Lookup(7)->AsBool();
int Z = msg_rec->Lookup(8)->AsCount();
int qdcount = msg_rec->Lookup(9)->AsCount();
int ancount = msg_rec->Lookup(10)->AsCount();
int nscount = msg_rec->Lookup(11)->AsCount();
int arcount = msg_rec->Lookup(12)->AsCount();
current_pkt_id = id;
// Set the DNS flags.
uint16 flags = (QR << 15) | (AA << 10) | (TC << 9) |
(RD << 8) | (RA << 7) | (Z << 4);
flags |= rcode | (opcode << 11);
(void) WriteShortVal(id);
(void) WriteShortVal(flags);
(void) WriteShortVal(qdcount);
(void) WriteShortVal(ancount);
(void) WriteShortVal(nscount);
(void) WriteShortVal(arcount);
// We've finished the header.
pkt_size = DNS_HDR_SIZE;
// Assign all the pointers for dn_comp().
dpp = dn_ptrs;
*dpp++ = pkt;
*dpp++ = 0;
last_dn_ptr = dn_ptrs + sizeof dn_ptrs / sizeof dn_ptrs[0];
}
int DNS_Rewriter::DnsCopyQuery(Val* val)
{
const RecordVal* val_rec = val->AsRecordVal();
// int type = val_rec->Lookup(0)->AsCount();
const BroString* query = val_rec->Lookup(1)->AsString();
int atype = val_rec->Lookup(2)->AsCount();
int aclass = val_rec->Lookup(3)->AsCount();
return DnsCopyQuery(query, atype, aclass);
}
// Copy the question part of the query into memory.
// Return the number of bytes that the query string compressed to.
int DNS_Rewriter::DnsCopyQuery(const BroString* query, uint32 qtype,
uint32 qclass)
{
int len = query->Len();
int psize = pkt_size;
// Encode the query string.
const char* dname = (char*) query->Bytes();
len = dn_comp(dname, pkt + pkt_size, DNS_PKT_SIZE - pkt_size,
dn_ptrs, last_dn_ptr);
// Can't encode in less than 2 bytes, or about to overwrite.
if ( len < 1 || pkt_size + len + 4 > DNS_PKT_SIZE )
{
warn("dn_comp couldn't encode name into packet");
return 0;
}
pkt_size += len;
// Set type.
if ( ! WriteShortVal(qtype) )
{
pkt_size = psize;
return 0;
}
// Set class.
if ( ! WriteShortVal(qclass) )
{
pkt_size = psize;
return 0;
}
return len;
}
// PTR, NS and CNAME are all the same.
void DNS_Rewriter::DnsCopyPTR(Val* ans, const BroString* name)
{
DnsCopyCNAME(ans, name);
}
// Copy an NS RR into the packet.
void DNS_Rewriter::DnsCopyNS( Val* ans, const BroString* name)
{
DnsCopyCNAME(ans, name);
}
// Copy an A RR into the packet.
void DNS_Rewriter::DnsCopyA(Val* ans, uint32 addr)
{
int psize = pkt_size;
// Put query part into packet.
int len = DnsCopyQuery(ans);
if ( ! len )
return;
double TTL = ans->AsRecordVal()->Lookup(4)->AsInterval();
if ( ! WriteDoubleAsInt(TTL) )
{
pkt_size = psize;
return;
}
// Now we put in how long the resource data is (A rec is always 4).
if ( ! WriteShortVal(4) )
{
pkt_size = psize;
return;
}
// Stick in the address (already in network byte order).
if ( ! WriteVal(uint32(ntohl(addr))) )
{
pkt_size = psize;
return;
}
}
// Copy an AAAA RR into the packet.
void DNS_Rewriter::DnsCopyAAAA(Val* ans, addr_type addr, const BroString* addrstr)
{
int psize = pkt_size;
// Put query part into packet.
int len = DnsCopyQuery(ans);
if ( ! len || pkt_size + 6 > DNS_PKT_SIZE )
return;
double TTL = ans->AsRecordVal()->Lookup(4)->AsInterval();
if ( ! WriteDoubleAsInt(TTL))
{
pkt_size = psize;
return;
}
// Now we put in how long the resource data is (AAAA rec is always 16).
if ( ! WriteShortVal(16) )
{
pkt_size = psize;
return;
}
#ifdef BROv6
if ( ! WriteVal(addr) )
{
pkt_size = psize;
return;
}
#else
uint32 addr_copy[4];
char* addr_tmp = addrstr->Render(BroString::ESC_NONE);
inet_pton(AF_INET6, addr_tmp, addr_copy);
if ( ! WriteVal(addr_copy) )
{
pkt_size = psize;
return;
}
delete addr_tmp;
#endif
}
// Copy a CNAME RR into the packet.
void DNS_Rewriter::DnsCopyCNAME(Val* ans, const BroString* name)
{
int psize = pkt_size;
// Put query part into packet.
int len = DnsCopyQuery(ans);
if ( ! len || pkt_size + 6 > DNS_PKT_SIZE )
return;
double TTL = ans->AsRecordVal()->Lookup(4)->AsInterval();
if ( ! WriteDoubleAsInt(TTL))
{
pkt_size = psize;
return;
}
// Resource length (domain name length in packet).
// Have to skip till it's encoded, remember this spot.
u_char* resource_len = pkt + pkt_size;
pkt_size += 2;
// Encode the domain name.
const char* dname = (char*) name->CheckString();
len = dn_comp(dname, pkt + pkt_size, DNS_PKT_SIZE - pkt_size,
dn_ptrs, last_dn_ptr);
if ( len < 1 )
{
pkt_size = psize;
return;
}
pkt_size += len;
// Now we put in how long the name was to encode.
uint16 net_rdlen = htons(short(len));
memcpy(resource_len, &net_rdlen, sizeof(uint16));
}
// Copy a CNAME RR into the packet.
void DNS_Rewriter::DnsCopyTXT(Val* ans, const BroString* name)
{
int psize = pkt_size;
// Put query part into packet.
int len = DnsCopyQuery(ans);
if ( ! len || pkt_size + 6 > DNS_PKT_SIZE )
return;
double TTL = ans->AsRecordVal()->Lookup(4)->AsInterval();
if ( ! WriteDoubleAsInt(TTL))
{
pkt_size = psize;
return;
}
if ( ! WriteShortVal(name->Len()+1))
{
pkt_size = psize;
return;
}
if ( ! WriteVal(uint8(name->Len())))
{
pkt_size = psize;
return;
}
if ( ! WriteVal(name))
{
pkt_size = psize;
return;
}
}
// Copy an MX RR into the packet.
void DNS_Rewriter::DnsCopyMX(Val* ans, const BroString* name, uint32 preference)
{
int psize = pkt_size;
// Put query part into packet.
int len = DnsCopyQuery(ans);
if ( ! len || pkt_size + len + 6 > DNS_PKT_SIZE )
{
warn("DnsCopyMX: packet too large");
return;
}
double TTL = ans->AsRecordVal()->Lookup(4)->AsInterval();
if ( ! WriteDoubleAsInt(TTL) )
{
pkt_size = psize;
warn("DnsCopyMX: packet too large");
return;
}
// Resource length (domain name length in packet).
// Have to skip till it's, remember this spot.
u_char* resource_len = pkt + pkt_size;
pkt_size += 2;
if ( ! WriteShortVal(preference))
{
pkt_size = psize;
warn("DnsCopyMX: packet too large");
return;
}
// Encode the domain name.
const char* dname = (char*) name->CheckString();
len += dn_comp(dname, pkt + pkt_size, DNS_PKT_SIZE - pkt_size,
dn_ptrs, last_dn_ptr);
if ( len < 1 )
{
pkt_size = psize;
warn("DnsCopyMX: packet too large");
return;
}
pkt_size += len;
// 2 bytes for the preference size above.
len += 2;
// Now we put in how long the name was to encode.
uint16 net_rdlen = htons(short(len));
memcpy(resource_len, &net_rdlen, sizeof(uint16));
}
// Copy an SOA RR into the packet.
void DNS_Rewriter::DnsCopySOA(Val* ans, Val* soa)
{
u_char* resource_len;
int resource_offset = 0;
int psize = pkt_size;
const RecordVal* soa_rec = soa->AsRecordVal();
const BroString* mname = soa_rec->Lookup(0)->AsString();
const BroString* rname = soa_rec->Lookup(1)->AsString();
uint32 serial = soa_rec->Lookup(2)->AsCount();
double refresh = soa_rec->Lookup(3)->AsInterval();
double retry = soa_rec->Lookup(4)->AsInterval();
double expire = soa_rec->Lookup(5)->AsInterval();
double minimum = soa_rec->Lookup(6)->AsInterval();
// Put query part into packet.
int len = DnsCopyQuery(ans);
if ( ! len || len + 6 > DNS_PKT_SIZE )
return;
double TTL = ans->AsRecordVal()->Lookup(4)->AsInterval();
if ( ! WriteDoubleAsInt(TTL) )
{
pkt_size = psize;
return;
}
// Resource length: have to skip till it's encoded.
// Remember this spot and offset.
resource_len = pkt + pkt_size;
pkt_size += 2;
// Start counting from here (after rdlength).
resource_offset = pkt_size;
// Encode the domain name.
const char* dname = (char*) mname->CheckString();
len = dn_comp(dname, pkt + pkt_size, DNS_PKT_SIZE - pkt_size,
dn_ptrs, last_dn_ptr);
if ( len < 1 )
{
pkt_size = psize;
return;
}
pkt_size += len;
// Encode the domain name.
dname = (char*) rname->CheckString();
len = dn_comp(dname, pkt + pkt_size, DNS_PKT_SIZE - pkt_size,
dn_ptrs, last_dn_ptr);
if ( len < 1 )
{
pkt_size = psize;
return;
}
pkt_size += len;
if ( ! WriteVal(serial) || ! WriteDoubleAsInt(refresh) ||
! WriteDoubleAsInt(retry) || ! WriteDoubleAsInt(expire) ||
! WriteDoubleAsInt(minimum) )
{
pkt_size = psize;
return;
}
// Now we put in how long this packet was.
uint16 net_rdlen = htons(short(pkt_size - resource_offset));
memcpy(resource_len, &net_rdlen, sizeof(uint16));
}
void DNS_Rewriter::DnsCopyEDNSaddl(Val* ans)
{
const RecordVal* ans_rec = ans->AsRecordVal();
int ans_type = ans_rec->Lookup(0)->AsCount();
// BroString* query_name = ans_rec->Lookup(1)->AsString();
int atype = ans_rec->Lookup(2)->AsCount();
int aclass = ans_rec->Lookup(3)->AsCount();
int return_error = ans_rec->Lookup(4)->AsCount();
int version = ans_rec->Lookup(5)->AsCount();
int z = ans_rec->Lookup(6)->AsCount();
double ttl = ans_rec->Lookup(7)->AsInterval();
int is_query = ans_rec->Lookup(8)->AsCount();
int rcode = return_error;
int ecode = 0;
int psize = pkt_size;
if ( return_error > 0xff )
{
rcode &= 0xff;
ecode = return_error >> 8;
}
// Stick the version onto the ecode.
ecode = (ecode << 8) | version;
// Write fixed part of OPT RR
// Name '0'.
memset(pkt + pkt_size, 0, 1);
++pkt_size;
// Type (either 29 or 41).
if ( ! WriteShortVal(atype) )
{
pkt_size = psize;
return;
}
// UDP playload size
if ( ! WriteShortVal(aclass) )
{
pkt_size = psize;
return;
}
// Extended rcode + version.
if ( ! WriteShortVal(ecode) )
{
pkt_size = psize;
return;
}
// Z field.
if ( ! WriteShortVal(z) )
{
pkt_size = psize;
return;
}
// Data length (XXX:for now its zero!).
if ( ! WriteShortVal(0) )
{
pkt_size = psize;
return;
}
// Don't write data (XXX:we don't have it!).
}
// Does this packet match the current packet being worked on?
int DNS_Rewriter::DnsPktMatch(Val* msg)
{
return msg->AsRecordVal()->Lookup(0)->AsInt() == current_pkt_id;
}
// Supports copying of TXT values.
int DNS_Rewriter::WriteVal(const BroString* val)
{
int n = val->Len();
if ( pkt_size + n > DNS_PKT_SIZE )
{
warn("WriteVal: couldn't write data into packet");
return 0;
}
char* new_val = val->Render(BroString::ESC_NONE);
memcpy(pkt + pkt_size, new_val, n);
pkt_size += n;
delete[] new_val;
return n;
}
int DNS_Rewriter::WriteVal(const uint32* val)
{
if ( pkt_size + 16 > DNS_PKT_SIZE )
{
warn("WriteVal: couldn't write data into packet");
return 0;
}
memcpy(pkt + pkt_size, &val[0], sizeof(uint32)); pkt_size += 4;
memcpy(pkt + pkt_size, &val[1], sizeof(uint32)); pkt_size += 4;
memcpy(pkt + pkt_size, &val[2], sizeof(uint32)); pkt_size += 4;
memcpy(pkt + pkt_size, &val[3], sizeof(uint32)); pkt_size += 4;
return sizeof(uint32) * 4;
}
// Write a 32 bit value given in host order to the packet.
int DNS_Rewriter::WriteVal(uint32 val)
{
if ( pkt_size + 4 > DNS_PKT_SIZE )
{
warn("WriteVal: couldn't write data into packet");
return 0;
}
uint32 net_val = htonl(val);
memcpy(pkt + pkt_size, &net_val, sizeof(uint32));
pkt_size += 4;
return sizeof(uint32);
}
// Write a 16 bit value given in host order to the packet.
int DNS_Rewriter::WriteVal(uint16 val)
{
if ( pkt_size + 2 > DNS_PKT_SIZE )
{
warn("WriteShortVal: couldn't write data into packet");
return 0;
}
uint16 net_val = htons(val);
memcpy(pkt + pkt_size, &net_val, sizeof(uint16));
pkt_size += 2;
return sizeof(uint16);
}
// Write a 8 bit value given in host order to the packet.
int DNS_Rewriter::WriteVal(uint8 val)
{
if ( pkt_size + 1 > DNS_PKT_SIZE )
{
warn("WriteVal: couldn't write data into packet");
return 0;
}
memcpy(pkt + pkt_size, &val, sizeof(uint8));
pkt_size += sizeof(uint8);
return sizeof(uint8);
}

View file

@ -1,70 +0,0 @@
// $Id:$
//
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef dns_rewriter_h
#define dns_rewriter_h
#include "UDP.h"
#include "UDP_Rewriter.h"
#include "Rewriter.h"
#define DNS_HDR_SIZE 12
// DNS packets size. 512 is the *normal* size, but some packets are bigger
// than this, and the anonymization process can expand packets, so we
// pad this way out.
#define DNS_PKT_SIZE (512*4)
class DNS_Rewriter: public UDP_Rewriter {
public:
DNS_Rewriter(Analyzer* analyzer, int arg_MTU, PacketDumper* dumper);
virtual ~DNS_Rewriter() { delete pkt;}
void DnsCopyHeader(Val* val);
int DnsCopyQuery(const BroString* query, uint32 qtype, uint32 qclass);
int DnsCopyQuery(Val* val);
void DnsCopyNS(Val* ans, const BroString* name);
void DnsCopyPTR(Val* ans, const BroString* name);
void DnsCopyCNAME(Val* ans, const BroString* name);
void DnsCopyTXT(Val* ans, const BroString* name);
void DnsCopyA(Val* ans, uint32 addr);
// AAAA is weird, because the address is an IPv4 type.
// If we don't have IPv6, and if it's IPv6, it's a pointer
// to valid data.
void DnsCopyAAAA(Val* ans, addr_type addr, const BroString* addrstr);
void DnsCopyMX(Val* ans, const BroString* name, uint32 preference);
void DnsCopySOA(Val* ans, Val* soa);
void DnsCopyEDNSaddl(Val* ans);
int DnsPktMatch(Val* val);
const u_char* Packet() const { return pkt; }
int PacketSize() const { return pkt_size; }
void SetOrig( int orig ) { is_orig = orig; }
int IsOrig() { return is_orig; }
int WriteDoubleAsInt(double d) { return WriteVal(uint32(d)); }
int WriteShortVal(uint16 val) { return WriteVal(uint16(val)); }
int WriteVal(uint32 val);
int WriteVal(uint16 val);
int WriteVal(uint8 val);
int WriteVal(const uint32* val);
int WriteVal(const BroString* val);
private:
u_char* pkt; // the DNS packet
int pkt_size; // size of the packet
int current_pkt_id; // current ID (sanity checking)
int is_orig;
u_char* dn_ptrs[30]; // pointer to names in DNS packet
u_char** dpp; // points to current position in DNS packet
u_char** last_dn_ptr; // points to last entry in dn_ptrs
};
#endif

View file

@ -120,9 +120,6 @@ void EventMgr::Drain()
// Note: we might eventually need a general way to specify things to
// do after draining events.
extern void flush_rewriter_packet();
flush_rewriter_packet();
draining = false;
// We evaluate Triggers here. While this is somewhat unrelated to event

View file

@ -10,7 +10,6 @@
#include "FTP.h"
#include "NVT.h"
#include "Event.h"
#include "TCP_Rewriter.h"
FTP_Analyzer::FTP_Analyzer(Connection* conn)
: TCP_ApplicationAnalyzer(AnalyzerTag::FTP, conn)
@ -169,5 +168,3 @@ void FTP_Analyzer::DeliverStream(int length, const u_char* data, bool orig)
ConnectionEvent(f, vl);
}
#include "ftp-rw.bif.func_def"

View file

@ -14,11 +14,6 @@ public:
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual int RewritingTrace()
{
return BifConst::rewriting_ftp_trace ||
TCP_ApplicationAnalyzer::RewritingTrace();
}
static Analyzer* InstantiateAnalyzer(Connection* conn)
{

View file

@ -9,7 +9,6 @@
#include "NetVar.h"
#include "Finger.h"
#include "Event.h"
#include "TCP_Rewriter.h"
#include "ContentLine.h"
Finger_Analyzer::Finger_Analyzer(Connection* conn)
@ -87,5 +86,3 @@ void Finger_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig
ConnectionEvent(finger_reply, vl);
}
}
#include "finger-rw.bif.func_def"

View file

@ -17,8 +17,6 @@ public:
virtual void Done();
// Line-based input.
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual int RewritingTrace()
{ return BifConst::rewriting_finger_trace || TCP_ApplicationAnalyzer::RewritingTrace(); }
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new Finger_Analyzer(conn); }

View file

@ -497,15 +497,7 @@ void builtin_run_time(const char* msg, BroObj* arg)
}
#include "bro.bif.func_h"
#include "common-rw.bif.func_h"
#include "finger-rw.bif.func_h"
#include "ftp-rw.bif.func_h"
#include "http-rw.bif.func_h"
#include "ident-rw.bif.func_h"
#include "smtp-rw.bif.func_h"
#include "strings.bif.func_h"
#include "dns-rw.bif.func_h"
#include "bro.bif.func_def"
#include "strings.bif.func_def"
@ -519,15 +511,7 @@ void init_builtin_funcs()
gap_info = internal_type("gap_info")->AsRecordType();
#include "bro.bif.func_init"
#include "common-rw.bif.func_init"
#include "finger-rw.bif.func_init"
#include "ftp-rw.bif.func_init"
#include "http-rw.bif.func_init"
#include "ident-rw.bif.func_init"
#include "smtp-rw.bif.func_init"
#include "strings.bif.func_init"
#include "dns-rw.bif.func_init"
did_builtin_init = true;
}

View file

@ -12,7 +12,6 @@
#include "HTTP.h"
#include "Event.h"
#include "MIME.h"
#include "TCP_Rewriter.h"
const bool DEBUG_http = false;
@ -1756,5 +1755,3 @@ BroString* unescape_URI(const u_char* line, const u_char* line_end,
return new BroString(1, decoded_URI, URI_p - decoded_URI);
}
#include "http-rw.bif.func_def"

View file

@ -169,8 +169,6 @@ public:
virtual void Done();
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(int seq, int len, bool orig);
virtual int RewritingTrace()
{ return BifConst::rewriting_http_trace || TCP_ApplicationAnalyzer::RewritingTrace(); }
// Overriden from TCP_ApplicationAnalyzer
virtual void EndpointEOF(bool is_orig);

View file

@ -9,7 +9,6 @@
#include "NetVar.h"
#include "Ident.h"
#include "Event.h"
#include "TCP_Rewriter.h"
Ident_Analyzer::Ident_Analyzer(Connection* conn)
: TCP_ApplicationAnalyzer(AnalyzerTag::Ident, conn)
@ -245,6 +244,3 @@ void Ident_Analyzer::BadReply(int length, const char* line)
did_bad_reply = 1;
}
}
#include "ident-rw.bif.func_def"

View file

@ -14,11 +14,6 @@ public:
virtual void Done();
virtual void DeliverStream(int length, const u_char* data, bool is_orig);
virtual int RewritingTrace()
{
return BifConst::rewriting_ident_trace ||
TCP_ApplicationAnalyzer::RewritingTrace();
}
static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new Ident_Analyzer(conn); }

View file

@ -28,7 +28,6 @@
#include "Var.h"
#include "Logger.h"
#include "Net.h"
#include "TCP_Rewriter.h"
#include "Anon.h"
#include "PacketSort.h"
#include "Serializer.h"
@ -47,13 +46,6 @@ PList(PktSrc) pkt_srcs;
// FIXME: We should really merge PktDumper and PacketDumper.
// It's on my to-do [Robin].
PktDumper* pkt_dumper = 0;
PktDumper* pkt_transformed_dumper = 0;
// For trace of rewritten packets
PacketDumper* transformed_pkt_dump = 0;
// For trace of original packets from selected connections
PacketDumper* source_pkt_dump = 0;
int transformed_pkt_dump_MTU = 1514;
int reading_live = 0;
int reading_traces = 0;
@ -162,9 +154,8 @@ RETSIGTYPE watchdog(int /* signo */)
void net_init(name_list& interfaces, name_list& readfiles,
name_list& netflows, name_list& flowfiles,
const char* writefile, const char* transformed_writefile,
const char* filter, const char* secondary_filter,
int do_watchdog)
const char* writefile, const char* filter,
const char* secondary_filter, int do_watchdog)
{
init_net_var();
@ -320,37 +311,7 @@ void net_init(name_list& interfaces, name_list& readfiles,
id->SetVal(new StringVal(writefile));
}
if ( transformed_writefile )
{
pkt_transformed_dumper = new PktDumper(transformed_writefile);
if ( pkt_transformed_dumper->IsError() )
{
fprintf(stderr, "%s: can't open trace transformation write file \"%s\" - %s\n",
prog, writefile,
pkt_transformed_dumper->ErrorMsg());
exit(1);
}
transformed_pkt_dump =
new PacketDumper(pkt_transformed_dumper->PcapDumper());
// If both -A and -w are specified, -A will be the transformed
// trace file and -w will be the source packet trace file.
// Otherwise the packets will go to the same file.
if ( pkt_dumper )
source_pkt_dump =
new PacketDumper(pkt_dumper->PcapDumper());
}
else if ( pkt_dumper )
transformed_pkt_dump =
new PacketDumper(pkt_dumper->PcapDumper());
if ( BifConst::anonymize_ip_addr )
init_ip_addr_anonymizers();
else
for ( int i = 0; i < NUM_ADDR_ANONYMIZATION_METHODS; ++i )
ip_anonymizer[i] = 0;
if ( packet_sort_window > 0 )
packet_sorter = new PacketSortGlobalPQ();
@ -627,7 +588,6 @@ void net_finish(int drain_events)
}
delete pkt_dumper;
delete pkt_transformed_dumper;
// fprintf(stderr, "uhash: %d/%d\n", hash_cnt_uhash, hash_cnt_all);
@ -648,11 +608,6 @@ void net_delete()
delete sessions;
delete packet_sorter;
// Can't put this in net_finish() because packets might be
// dumped when connections are deleted.
if ( transformed_pkt_dump )
delete transformed_pkt_dump;
for ( int i = 0; i < NUM_ADDR_ANONYMIZATION_METHODS; ++i )
delete ip_anonymizer[i];
}

View file

@ -15,9 +15,8 @@
extern void net_init(name_list& interfaces, name_list& readfiles,
name_list& netflows, name_list& flowfiles,
const char* writefile, const char* transformed_writefile,
const char* filter, const char* secondary_filter,
int do_watchdog);
const char* writefile, const char* filter,
const char* secondary_filter, int do_watchdog);
extern void net_run();
extern void net_get_final_stats();
extern void net_finish(int drain_events);
@ -91,7 +90,6 @@ declare(PList,PktSrc);
extern PList(PktSrc) pkt_srcs;
extern PktDumper* pkt_dumper; // where to save packets
extern PktDumper* pkt_transformed_dumper;
extern char* writefile;

View file

@ -41,8 +41,4 @@ struct ltipid {
typedef set<IP_ID, ltipid> IP_IDSet;
uint16 NextIP_ID(const uint32 src_addr, const uint16 id);
extern PacketDumper* transformed_pkt_dump;
extern PacketDumper* source_pkt_dump;
extern int transformed_pkt_dump_MTU;
#endif

View file

@ -1,35 +0,0 @@
// $Id:$
//
// See the file "COPYING" in the main distribution directory for copyright.
#include "TCP_Rewriter.h"
#include "UDP_Rewriter.h"
// The following two are called from .bif's to obtain handle of Rewriter.
Rewriter* get_trace_rewriter(Val* conn_val)
{
Connection* conn = (Connection*) conn_val->AsRecordVal()->GetOrigin();
return get_trace_rewriter(conn);
}
Rewriter* get_trace_rewriter(Connection* conn)
{
if ( ! conn ||
(conn->ConnTransport() != TRANSPORT_TCP &&
conn->ConnTransport() != TRANSPORT_UDP) )
internal_error("connection for the trace rewriter does not exist");
Rewriter* rewriter = conn->TraceRewriter();
if ( rewriter )
return rewriter;
if ( ! transformed_pkt_dump )
return 0; // okay if we don't have an output file
else if ( ! conn->RewritingTrace() )
builtin_run_time("flag rewriting_..._trace is not set properly");
else
internal_error("trace rewriter not initialized");
return 0;
}

View file

@ -1,51 +0,0 @@
// $Id:$
//
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef rewriter_h
#define rewriter_h
class TracePacket;
class Rewriter {
public:
virtual ~Rewriter() {};
virtual void Done() {};
virtual void WriteData(int is_orig, int len, const u_char* data) = 0;
virtual void WriteData(int is_orig, const char* data) = 0;
virtual void WriteData(int is_orig, int len, const char* data) = 0;
virtual void WriteData(int is_orig, const BroString* str) = 0;
virtual void Push(int is_orig) = 0;
virtual void AbortPackets(int apply_to_future) = 0;
virtual void CommitPackets(int apply_to_future) = 0;
virtual unsigned int ReserveSlot() = 0;
virtual int SeekSlot(unsigned int slot) = 0;
virtual int ReturnFromSlot() = 0;
virtual int ReleaseSlot(unsigned int slot) = 0;
// Needed by all rewriters.
virtual TracePacket* CurrentPacket() const = 0;
virtual TracePacket* RewritePacket() const = 0;
// Whether to not anonymize client/server IP addresses.
virtual int LeaveAddrInTheClear(int is_orig) = 0;
};
extern Rewriter* get_trace_rewriter(Val* conn_val);
extern Rewriter* get_trace_rewriter(Connection* conn);
// This is the actual packet.
class TracePacket {
public:
virtual ~TracePacket() { }
virtual RecordVal* PacketVal() = 0;
virtual double TimeStamp() const = 0;
};
#endif

View file

@ -206,8 +206,6 @@ public:
DCE_RPC_Session::any_dce_rpc_event();
}
int RewritingTrace() { return BifConst::rewriting_smb_trace; }
protected:
SMB_Session* smb_session;
Contents_SMB* o_smb;

View file

@ -10,7 +10,6 @@
#include "SMTP.h"
#include "Event.h"
#include "ContentLine.h"
#include "TCP_Rewriter.h"
#undef SMTP_CMD_DEF
#define SMTP_CMD_DEF(cmd) #cmd,
@ -885,5 +884,3 @@ void SMTP_Analyzer::EndData()
mail = 0;
}
}
#include "smtp-rw.bif.func_def"

View file

@ -46,8 +46,6 @@ public:
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void ConnectionFinished(int half_finished);
virtual void Undelivered(int seq, int len, bool orig);
virtual int RewritingTrace()
{ return BifConst::rewriting_smtp_trace || TCP_ApplicationAnalyzer::RewritingTrace(); }
void SkipData() { skip_data = 1; } // skip delivery of data lines

View file

@ -632,13 +632,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
record_packet, record_content,
hdr, pkt, hdr_size);
// Override content record setting according to
// flags set by the policy script.
if ( BifConst::dump_original_packets_if_not_rewriting )
record_packet = record_content = 1;
if ( BifConst::dump_selected_source_packets )
record_packet = record_content = 0;
if ( f )
{
// Above we already recorded the fragment in its entirety.
@ -646,7 +639,7 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
Remove(f); // ###
}
else if ( record_packet && ! conn->RewritingTrace() )
else if ( record_packet )
{
if ( record_content )
dump_this_packet = 1; // save the whole thing

View file

@ -7,7 +7,6 @@
#include "File.h"
#include "TCP.h"
#include "TCP_Reassembler.h"
#include "TCP_Rewriter.h"
#include "OSFinger.h"
#include "Event.h"
@ -47,23 +46,12 @@ TCP_Analyzer::TCP_Analyzer(Connection* conn)
finished = 0;
reassembling = 0;
first_packet_seen = 0;
src_pkt_writer = 0;
orig = new TCP_Endpoint(this, 1);
resp = new TCP_Endpoint(this, 0);
orig->SetPeer(resp);
resp->SetPeer(orig);
if ( BifConst::dump_selected_source_packets )
{
if ( source_pkt_dump )
src_pkt_writer =
new TCP_SourcePacketWriter(this, source_pkt_dump);
else if ( transformed_pkt_dump )
src_pkt_writer =
new TCP_SourcePacketWriter(this, transformed_pkt_dump);
}
}
TCP_Analyzer::~TCP_Analyzer()
@ -73,7 +61,6 @@ TCP_Analyzer::~TCP_Analyzer()
delete orig;
delete resp;
delete src_pkt_writer;
}
void TCP_Analyzer::Init()
@ -81,12 +68,6 @@ void TCP_Analyzer::Init()
Analyzer::Init();
LOOP_OVER_GIVEN_CHILDREN(i, packet_children)
(*i)->Init();
// Can't put this in construction because RewritingTrace() is virtual.
if ( transformed_pkt_dump && Conn()->RewritingTrace() )
SetTraceRewriter(new TCP_Rewriter(this, transformed_pkt_dump,
transformed_pkt_dump_MTU,
BifConst::requires_trace_commitment));
}
void TCP_Analyzer::Done()
@ -1047,16 +1028,6 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
tcp_hdr_len <= uint32(caplen) )
ParseTCPOptions(tp, TCPOptionEvent, this, is_orig, 0);
if ( TraceRewriter() && current_hdr )
{
TCP_Rewriter* r = (TCP_Rewriter*) TraceRewriter();
r->NextPacket(is_orig, t, current_hdr, current_pkt,
current_hdr_size, ip->IP4_Hdr(), tp);
}
if ( src_pkt_writer && current_hdr )
src_pkt_writer->NextPacket(current_hdr, current_pkt);
if ( DEBUG_tcp_data_sent )
{
DEBUG_MSG("%.6f before DataSent: len=%d caplen=%d skip=%d\n",
@ -1757,8 +1728,6 @@ void TCP_Analyzer::EndpointEOF(TCP_Reassembler* endp)
LOOP_OVER_CONST_CHILDREN(i)
static_cast<TCP_ApplicationAnalyzer*>(*i)->EndpointEOF(endp->IsOrig());
TraceRewriterEOF(endp);
if ( close_deferred )
{
if ( DataPending(endp->Endpoint()) )
@ -1776,25 +1745,6 @@ void TCP_Analyzer::EndpointEOF(TCP_Reassembler* endp)
}
}
void TCP_Analyzer::TraceRewriterEOF(TCP_Reassembler* endp)
{
const analyzer_list& children(GetChildren());
LOOP_OVER_CONST_CHILDREN(i)
static_cast<TCP_ApplicationAnalyzer*>(*i)->TraceRewriterEOF(endp->IsOrig());
TCP_Rewriter* r = (TCP_Rewriter*) TraceRewriter();
if ( r )
{
// Add a FIN packet if there is one in the original trace.
int FIN_cnt = endp->IsOrig() ?
endp->GetTCPAnalyzer()->Orig()->FIN_cnt :
endp->GetTCPAnalyzer()->Resp()->FIN_cnt;
if ( FIN_cnt > 0 )
r->ScheduleFIN(endp->IsOrig());
}
}
void TCP_Analyzer::PacketWithRST()
{
const analyzer_list& children(GetChildren());
@ -1911,13 +1861,6 @@ void TCP_ApplicationAnalyzer::EndpointEOF(bool is_orig)
static_cast<TCP_SupportAnalyzer*>(sa)->EndpointEOF(is_orig);
}
void TCP_ApplicationAnalyzer::TraceRewriterEOF(bool is_orig)
{
SupportAnalyzer* sa = is_orig ? orig_supporters : resp_supporters;
for ( ; sa; sa = sa->Sibling() )
static_cast<TCP_SupportAnalyzer*>(sa)->TraceRewriterEOF(is_orig);
}
void TCP_ApplicationAnalyzer::ConnectionClosed(TCP_Endpoint* endpoint,
TCP_Endpoint* peer, int gen_event)
{

View file

@ -7,7 +7,6 @@
#include "Analyzer.h"
#include "TCP.h"
#include "Rewriter.h"
#include "PacketDumper.h"
// We define two classes here:
@ -18,8 +17,6 @@
class PIA_TCP;
class TCP_ApplicationAnalyzer;
class TCP_Reassembler;
class TCP_Rewriter;
class TCP_SourcePacketWriter;
class TCP_Flags {
public:
@ -75,9 +72,6 @@ public:
virtual void SetContentsFile(unsigned int direction, BroFile* f);
virtual BroFile* GetContentsFile(unsigned int direction) const;
TCP_SourcePacketWriter* SourcePacketWriter() const
{ return src_pkt_writer; }
// Callback to process a TCP option.
typedef int (*proc_tcp_option_t)(unsigned int opt, unsigned int optlen,
const u_char* option, TCP_Analyzer* analyzer,
@ -220,7 +214,6 @@ protected:
void ConnDeleteTimer(double t) { Conn()->DeleteTimer(t); }
void EndpointEOF(TCP_Reassembler* endp);
void TraceRewriterEOF(TCP_Reassembler* endp);
void ConnectionClosed(TCP_Endpoint* endpoint,
TCP_Endpoint* peer, int gen_event);
void ConnectionFinished(int half_finished);
@ -247,8 +240,6 @@ private:
analyzer_list packet_children;
TCP_SourcePacketWriter* src_pkt_writer;
unsigned int first_packet_seen: 2;
unsigned int reassembling: 1;
unsigned int is_partial: 1;
@ -288,7 +279,6 @@ public:
// The given endpoint's data delivery is complete.
virtual void EndpointEOF(bool is_orig);
virtual void TraceRewriterEOF(bool is_orig);
// Called whenever an end enters TCP_ENDPOINT_CLOSED or
// TCP_ENDPOINT_RESET. If gen_event is true and the connection
@ -332,7 +322,6 @@ public:
// These are passed on from TCP_Analyzer.
virtual void EndpointEOF(bool is_orig) { }
virtual void TraceRewriterEOF(bool is_orig) { }
virtual void ConnectionClosed(TCP_Endpoint* endpoint,
TCP_Endpoint* peer, int gen_event) { }
virtual void ConnectionFinished(int half_finished) { }

View file

@ -5,7 +5,6 @@
#include "Net.h"
#include "NetVar.h"
#include "TCP.h"
#include "TCP_Rewriter.h"
#include "TCP_Reassembler.h"
#include "Sessions.h"
#include "Event.h"

View file

@ -4,7 +4,6 @@
#include "TCP_Reassembler.h"
#include "TCP.h"
#include "TCP_Endpoint.h"
#include "TCP_Rewriter.h"
// Only needed for gap_report events.
#include "Event.h"
@ -185,10 +184,6 @@ void TCP_Reassembler::Undelivered(int up_to_seq)
// one for filtered traces, and may fail, for example, when
// the SYN packet carries data.
//
// Note, this check will confuse the EOF checker (and cause a
// missing FIN in the rewritten trace) when the content gap
// in the middle is discovered only after the FIN packet.
// Skip the undelivered part without reporting to the endpoint.
skip_deliveries = 1;
}
@ -235,11 +230,6 @@ void TCP_Reassembler::Undelivered(int up_to_seq)
dst_analyzer->ConnectionEvent(content_gap, vl);
}
TCP_Rewriter* r = (TCP_Rewriter*)
dst_analyzer->Conn()->TraceRewriter();
if ( r )
r->ContentGap(is_orig, len);
if ( type == Direct )
dst_analyzer->NextUndelivered(last_reassem_seq,
len, is_orig);

File diff suppressed because it is too large Load diff

View file

@ -1,401 +0,0 @@
// $Id: TCP_Rewriter.h 6916 2009-09-24 20:48:36Z vern $
#ifndef tcp_rewriter_h
#define tcp_rewriter_h
#include <queue>
#include <set>
using namespace std;
#include <pcap.h>
#include "Val.h"
#include "TCP.h"
#include "Anon.h"
#include "Analyzer.h"
#include "PacketDumper.h"
#include "Rewriter.h"
class TCP_Rewriter;
class TCP_TracePacket : public BroObj, virtual public TracePacket {
public:
TCP_TracePacket(TCP_Rewriter* trace_rewriter,
int packet_seq, double t, int is_orig,
const struct pcap_pkthdr* hdr,
int MTU, int initial_size);
~TCP_TracePacket();
int AppendLinkHeader(const u_char* chunk, int len);
int AppendIPHeader(const u_char* chunk, int len);
int AppendTCPHeader(const u_char* chunk, int len);
int AppendData(const u_char* chunk, int len);
// Finish() is called before dumping the packet. It sets length
// fields and computes checksums in TCP/IP headers.
int Finish(struct pcap_pkthdr*& hdr, const u_char*& pkt, int& length,
ipaddr32_t anon_src, ipaddr32_t anon_dst);
void Reuse();
int IsReuse() const { return reuse; }
double TimeStamp() const { return timestamp; }
int IsOrig() const { return is_orig; }
const struct pcap_pkthdr* Header() const { return &pcap_hdr; }
const u_char* Buffer() const { return pkt; }
int Length() const { return buffer_offset; }
// Note that Space() does not depend on buffer_size, but depends on MTU.
int Space() const { return mtu - buffer_offset; }
int IsEmpty() const
{ return SeqLength() == 0 && ! GetTCP_Flag(TH_RST); }
uint32 GetSeq() const;
void SetSeq(uint32 seq);
uint32 GetAck() const;
void SetAck(uint32 ack);
int GetTCP_Flag(int which) const;
void SetTCP_Flag(int which, int value);
int SeqLength() const;
int PayloadLength() const;
int FINScheduled() const { return FIN_scheduled; }
void ScheduleFIN(int fin = 1) { FIN_scheduled = fin; }
int OnHold() const { return on_hold; }
void SetOnHold(int x) { on_hold = x; }
int HasReservedSlot() const { return has_reserved_slot; }
void AddReservedSlot() { ++has_reserved_slot; }
int PredictedAsEmptyPlaceHolder() const
{ return predicted_as_empty_place_holder; }
void PredictAsEmptyPlaceHolder()
{ predicted_as_empty_place_holder = 1; }
// Whether the ACK on this packet confirms a content gap on
// the opposite direction.
int SeqGap() const { return seq_gap; }
void SetSeqGap(int len) { seq_gap = len; }
int PacketSeq() const { return packet_seq; }
TCP_Rewriter* TraceRewriter() const { return trace_rewriter; }
RecordVal* PacketVal();
void Describe(ODesc* d) const { packet_val->Describe(d); }
protected:
int Append(const u_char* chunk, int len);
RecordVal* packet_val;
TCP_Rewriter* trace_rewriter;
double timestamp;
int packet_seq;
int is_orig;
struct pcap_pkthdr pcap_hdr;
int mtu;
u_char* pkt; // of maximal length MTU
int ip_offset, tcp_offset, data_offset;
int buffer_size;
int buffer_offset;
int reuse; // whether it is an artificially replicated packet
int FIN_scheduled;
int on_hold; // do not dump it in Flush()
int seq_gap;
int has_reserved_slot;
int predicted_as_empty_place_holder;
};
// How a unidirectional flow ends.
#define END_BY_FIN 1
#define END_BY_RST 2
#define END_BY_PEER_RST 4
class TCP_RewriterEndpoint {
public:
TCP_RewriterEndpoint(TCP_Rewriter* rewriter);
~TCP_RewriterEndpoint();
void Init();
// A packet that contains a TCP segment.
void NextPacket(TCP_TracePacket* p);
void WriteData(int len, const u_char* data);
void SkipGap(int len);
void Push();
void ReqAck();
void Flush();
void Reset(int self);
uint32 NextSeq() const { return next_seq; }
int HasPacket() const { return next_packet != 0; }
inline TCP_Analyzer* Analyzer() const;
protected:
TCP_Rewriter* rewriter; // TCP rewriter for the connection
TCP_RewriterEndpoint* peer; // the peer TCP rewriter endpoint
TCP_Endpoint* endp; // the corresponding TCP endpoint
TCP_TracePacket* next_packet;
std::queue<BroString*> prolog;
double last_packet_time;
uint32 start_seq; // start seq -- sent in SYN
uint32 next_seq; // seq of next packet
uint32 last_ack; // last acknowledgement seq
int please_flush;
int flush_scheduled;
int flushed;
int established;
int end_of_data; // is it really useful?
int there_is_a_gap;
// Move onto the next packet header.
void SetNextPacket(TCP_TracePacket* p);
void PurgeProlog();
// Pour data into the current packet (next_packet).
void DoWriteData(int len, const u_char* data);
// Push the current packet (next_packet) to dumper.
void PushPacket();
// Please flush this endpoint after draining events.
void ScheduleFlush();
void GenerateFIN();
// Whether the packet is a "place holder" packet, i.e. it's
// harmless to omit the packet (except missing the timestamp
// it contains).
int IsPlaceHolderPacket(TCP_TracePacket* p);
void Weird(const char* name) const;
};
class TCP_RewriteSlot {
public:
TCP_RewriteSlot(TCP_TracePacket* p, unsigned int slot_number);
void WriteData(int is_orig, int len, const u_char* data);
void Dump();
unsigned int Number() const { return slot_number; }
TCP_TracePacket* Packet() const { return packet; }
bool isEmpty() const { return buf.empty(); }
protected:
TCP_Rewriter* rewriter;
TCP_TracePacket* packet;
unsigned int slot_number;
std::queue<BroString*> buf;
};
class TCP_Rewriter : public Rewriter {
public:
TCP_Rewriter(TCP_Analyzer* analyzer, PacketDumper* dumper, int MTU,
int wait_for_commitment = 0);
virtual ~TCP_Rewriter();
virtual void Done();
void Funeral();
// Phase 1 methods: called in packet processing.
// A TCP/IP packet.
void NextPacket(int is_orig, double t,
const struct pcap_pkthdr* pcap_hdr,
const u_char* pcap_pkt, // link level header
int hdr_size, // link level header size
const struct ip* ip,
const struct tcphdr* tp);
void ContentGap(int is_orig, int len);
void ScheduleFIN(int is_orig);
// Phase 2 methods: called in event processing.
void WriteData(int is_orig, int len, const u_char* data);
void WriteData(int is_orig, const char* data)
{ WriteData(is_orig, strlen(data), data); }
void WriteData(int is_orig, int len, const char* data)
{ WriteData(is_orig, len, (const u_char*) data); }
void WriteData(int is_orig, const BroString* str)
{ WriteData(is_orig, str->Len(), str->Bytes()); }
void WriteData(int is_orig, StringVal* str)
{ WriteData(is_orig, str->AsString()); }
void Push(int is_orig);
// When wait_for_commitment = 1, packets are not dumped until
// CommitPackets().
// When apply_to_future = 1, the same decision holds for future
// packets as well.
//
// Regarding why AbortPackets() takes an apply_to_future flag:
//
// The model is that there can be multiple commit/abort stages
// during the course of a connection. At the end of each
// stage, a commit or abort decision is made for packets
// generated during the stage. A possible scenario is that
// user may want to delete a middle part of a conversation
// while keeping the parts before and after intact, and cannot
// make the decision until the end of the middle part.
void AbortPackets(int apply_to_future);
void CommitPackets(int apply_to_future);
unsigned int ReserveSlot();
int SeekSlot(unsigned int slot);
int ReturnFromSlot();
int ReleaseSlot(unsigned int slot);
// Do not anonymize client/server IP address
int LeaveAddrInTheClear(int is_orig);
// Phase 3 methods: called in flushing after events.
// (None, because flushing is done through accessing endpoints directly.)
// Other methods.
void DumpPacket(TCP_RewriterEndpoint* endp, TCP_TracePacket* p);
void Weird(const char* name) const { analyzer->Weird(name); }
TCP_Analyzer* Analyzer() const { return analyzer; }
TCP_Endpoint* GetEndpoint(TCP_RewriterEndpoint* endp);
TCP_RewriterEndpoint* GetPeer(TCP_RewriterEndpoint* endp);
TracePacket* CurrentPacket() const { return current_packet; }
TracePacket* RewritePacket() const { return next_packet; }
// Needs to be static because it's passed as a pointer-to-function
// rather than pointer-to-member-function.
static int RewriteTCPOption(unsigned int opt, unsigned int optlen,
const u_char* option, TCP_Analyzer* analyzer,
bool is_orig, void* cookie);
protected:
// Under normal circumstances, we always rewrite into the
// "current packet" of the connection. However, sometimes we'd
// want to look a few packets ahead before deciding what to
// rewrite, in which case we may use {hold,release}_packet to
// specify the packet we are writing to.
// rewrite_packet (next_packet) always equals to
// current_packet under *normal mode*. hold_packet(p) dumps
// all packets *before* p, fixes rewrite_packet at p and turns
// the connection into *look-ahead* mode. Under look-ahead
// mode, release_packet(c) dumps all packets of on hold
// connection and makes the connection returns to normal mode
// so that rewrite_packet changes along with current_packet.
// When a packet is held, it is illegal to write to packets on
// the other half of the connection.
// Release next_packet
void ReleaseNextPacket();
// Hold packet p and release all packets before p.
void HoldPacket(TCP_TracePacket* p);
// Release all packets on hold and dump all the packets except
// the last one, which will be flushed at the end of the event.
void ReleasePacketsOnHold();
void CleanUpEmptyPlaceHolders();
void DoWriteData(int is_orig, int len, const u_char* data);
TCP_RewriterEndpoint* Endp(int is_orig) const
{ return is_orig ? orig : resp; }
TCP_Analyzer* analyzer;
PacketDumper* dumper;
TCP_RewriterEndpoint* orig;
TCP_RewriterEndpoint* resp;
int MTU;
int wait_for_commitment;
int discard_packets;
std::queue<char*> uncommited_packet_queue;
int next_packet_seq;
int packets_rewritten;
ipaddr32_t anon_addr[2];
int pending_content_gap;
TCP_TracePacket* current_packet;
TCP_TracePacket* next_packet;
std::deque<TCP_TracePacket*> packets_on_hold;
int holding_packets;
TCP_RewriteSlot* current_slot;
TCP_RewriteSlot* first_slot;
TCP_RewriteSlot* last_slot;
std::deque<TCP_RewriteSlot*> slot_queue;
typedef map<unsigned int, TCP_RewriteSlot*> slot_map_t;
slot_map_t reserved_slots;
int highest_slot_number;
TCP_RewriteSlot* add_slot();
TCP_RewriteSlot* find_slot(unsigned int slot);
friend class TCP_RewriteSlot;
int answered[2];
};
inline TCP_Analyzer* TCP_RewriterEndpoint::Analyzer() const
{
return rewriter->Analyzer();
}
// "Please flush the rewriter endpoint after event processing."
extern void schedule_flush(TCP_RewriterEndpoint* endp);
// "Please call rewriter->Funeral() after event processing."
extern void schedule_funeral(TCP_Rewriter* rewriter);
extern void flush_rewriter_packet();
class TCP_SourcePacket {
public:
TCP_SourcePacket(const struct pcap_pkthdr* pcap_hdr, const u_char* pcap_pkt);
~TCP_SourcePacket();
int Len() const { return hdr.caplen; }
const u_char* Pkt() const { return pkt; }
const struct pcap_pkthdr* Hdr() const { return &hdr; }
protected:
struct pcap_pkthdr hdr;
u_char* pkt;
};
// Write selected original packets to the trace
class TCP_SourcePacketWriter {
public:
TCP_SourcePacketWriter(TCP_Analyzer* /* analyzer */,
PacketDumper* arg_dumper);
~TCP_SourcePacketWriter();
void NextPacket(const struct pcap_pkthdr* pcap_hdr,
const u_char* pcap_pkt);
void Dump();
void Abort();
protected:
PacketDumper* dumper;
std::queue<TCP_SourcePacket*> source_packets;
void Purge(bool dump);
};
extern TCP_SourcePacketWriter* get_src_pkt_writer(TCP_Analyzer* analyzer);
#endif

View file

@ -7,7 +7,6 @@
#include "Net.h"
#include "NetVar.h"
#include "UDP.h"
#include "UDP_Rewriter.h"
UDP_Analyzer::UDP_Analyzer(Connection* conn)
: TransportLayerAnalyzer(AnalyzerTag::UDP, conn)
@ -25,9 +24,6 @@ UDP_Analyzer::~UDP_Analyzer()
void UDP_Analyzer::Init()
{
if ( transformed_pkt_dump && RewritingTrace() )
SetTraceRewriter(new UDP_Rewriter(this, transformed_pkt_dump_MTU,
transformed_pkt_dump));
}
void UDP_Analyzer::Done()
@ -164,17 +160,6 @@ void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig,
if ( caplen >= len )
ForwardPacket(len, data, is_orig, seq, ip, caplen);
if ( TraceRewriter() && current_hdr )
((UDP_Rewriter*) TraceRewriter())->NextPacket(is_orig,
current_timestamp, current_hdr, current_pkt,
current_hdr_size, ip->IP4_Hdr(), up);
#if 0
// XXX: needs to be implemented fully!
if ( src_pkt_writer && current_hdr )
src_pkt_writer->NextPacket(current_hdr, current_pkt);
#endif
}
void UDP_Analyzer::UpdateEndpointVal(RecordVal* endp, int is_orig)

View file

@ -6,9 +6,6 @@
#define udp_h
#include "Analyzer.h"
#include "Rewriter.h"
class UDP_Rewriter;
typedef enum {
UDP_INACTIVE, // no packet seen
@ -27,10 +24,6 @@ public:
static bool Available() { return true; }
// -- XXX -- only want to return yes if the protocol flag is
// on similar to TCP. (e.g. FTP_Connection etc.) /mc
int RewritingTrace() const { return 0; }
protected:
virtual void Done();
virtual void DeliverPacket(int len, const u_char* data, bool orig,

View file

@ -1,362 +0,0 @@
// $Id:$
//
// See the file "COPYING" in the main distribution directory for copyright.
#include "config.h"
#include <assert.h>
#include <stdlib.h>
#include "Event.h"
#include "Net.h"
#include "UDP_Rewriter.h"
#define MSG_PREFIX "UDP trace rewriter: "
#define DEBUG_MSG_A(x...)
// #define DEBUG_MSG_A DEBUG_MSG
UDP_Rewriter::UDP_Rewriter(Analyzer* arg_analyzer, int arg_MTU,
PacketDumper* arg_dumper)
{
analyzer = arg_analyzer;
MTU = arg_MTU;
dumper = arg_dumper;
packets_rewritten = 0;
current_packet = next_packet = 0;
if ( BifConst::anonymize_ip_addr )
{
anon_addr[0] = anonymize_ip(to_v4_addr(analyzer->Conn()->OrigAddr()),
ORIG_ADDR);
anon_addr[1] = anonymize_ip(to_v4_addr(analyzer->Conn()->RespAddr()),
RESP_ADDR);
}
else
anon_addr[0] = anon_addr[1] = 0;
}
void UDP_Rewriter::Done()
{
}
UDP_Rewriter::~UDP_Rewriter()
{
delete current_packet;
}
void UDP_Rewriter::WriteData(int is_orig, int len, const u_char* data)
{
DoWriteData(is_orig, len, data);
}
void UDP_Rewriter::DoWriteData(int is_orig, int len, const u_char* data)
{
struct pcap_pkthdr* hdr;
int length = len;
ipaddr32_t src = 0, dst = 0;
current_packet->AppendData(data,len);
// Mark data to be written.
current_packet->SetModified();
}
// Compose the packet so it can be written.
// Compute UDP/IP checksums, lengths, addresses.
int UDP_TracePacket::BuildPacket(struct pcap_pkthdr*& hdr,
const u_char*& arg_pkt, int& length,
ipaddr32_t anon_src, ipaddr32_t anon_dst)
{
struct ip* ip = (struct ip*) (pkt + ip_offset);
struct udphdr* up = (struct udphdr*) (pkt + udp_offset);
uint32 sum = 0;
// Fix IP addresses before computing the UDP checksum
if ( BifConst::anonymize_ip_addr )
{
ip->ip_src.s_addr = anon_src;
ip->ip_dst.s_addr = anon_dst;
}
// Create the IP header.
ip->ip_off = 0;
ip->ip_sum = 0;
ip->ip_hl = (udp_offset - ip_offset) >> 2;
ip->ip_len = htons(buffer_offset - ip_offset);
ip->ip_off = 0; // DF = 0, MF = 0, offset = 0
ip->ip_sum = 0;
ip->ip_sum = 0xffff - ones_complement_checksum((const void*) ip,
(udp_offset-ip_offset), sum);
pcap_hdr.caplen = pcap_hdr.len = buffer_offset;
hdr = &pcap_hdr;
arg_pkt = pkt;
length = buffer_offset;
// Create the UDP header.
up->uh_ulen = htons(buffer_offset - udp_offset);
up->uh_sum = 0;
up->uh_sum = 0xffff - udp_checksum(ip, up, buffer_offset - udp_offset);
// Create the pcap header.
//
// The below works around a potential type incompatibility
// on systems where pcap's timeval is different from the
// system-wide one. --cpk
//
timeval tv_tmp = double_to_timeval(timestamp);
pcap_hdr.ts.tv_sec = tv_tmp.tv_sec;
pcap_hdr.ts.tv_usec = tv_tmp.tv_usec;
pcap_hdr.caplen = pcap_hdr.len = buffer_offset;
hdr = &pcap_hdr;
arg_pkt = pkt;
length = buffer_offset;
return 1;
}
void UDP_Rewriter::NextPacket(int is_orig, double t,
const struct pcap_pkthdr* pcap_hdr,
const u_char* pcap_pkt, int hdr_size,
const struct ip* ip, const struct udphdr* up)
{
unsigned int ip_hdr_len = ip->ip_hl * 4;
// Cache the packet ....
UDP_TracePacket* p = new UDP_TracePacket(this, t, is_orig,
pcap_hdr, /*MTU */ 1024,
hdr_size + ip_hdr_len + sizeof(struct udphdr));
if ( ! p->AppendLinkHeader(pcap_pkt, hdr_size) )
internal_error(MSG_PREFIX "cannot append headers -- check MTU");
if ( ! p->AppendIPHeader((const u_char*) ip, sizeof(*ip)) )
internal_error(MSG_PREFIX "cannot append headers -- check MTU");
if ( ! p->AppendUDPHeader((const u_char*) up, sizeof(*up)) )
internal_error(MSG_PREFIX "cannot append headers -- check MTU");
// We only ever use one packet in UDP.
// ### This is potentially a leak.
next_packet = current_packet = p;
}
void UDP_Rewriter::Push(int)
{
internal_error("UDP_Rewriter::Push not implemented");
}
void UDP_Rewriter::AbortPackets(int)
{
internal_error("UDP_Rewriter::AbortPackets not implemented");
}
unsigned int UDP_Rewriter::ReserveSlot()
{
internal_error("UDP_Rewriter::ReserveSlot not implemented");
return 0;
}
int UDP_Rewriter::SeekSlot(unsigned int)
{
internal_error("UDP_Rewriter::SeekSlot not implemented");
return 0;
}
int UDP_Rewriter::ReturnFromSlot()
{
internal_error("UDP_Rewriter::ReturnFromSlot not implemented");
return 0;
}
int UDP_Rewriter::ReleaseSlot(unsigned int)
{
internal_error("UDP_Rewriter::ReleaseSlot not implemented");
return 0;
}
int UDP_Rewriter::LeaveAddrInTheClear(int is_orig)
{
internal_error("UDP_Rewriter::LeaveAddrInTheClear not implemented");
return 0;
}
void UDP_Rewriter::CommitPackets(int commit)
{
if ( current_packet && current_packet->IsModified() )
{
ipaddr32_t anon_src = 0, anon_dst = 0;
if ( current_packet->IsOrig() )
{
anon_src = anon_addr[0];
anon_dst = anon_addr[1];
}
else
{
anon_src = anon_addr[1];
anon_dst = anon_addr[0];
}
struct pcap_pkthdr* hdr;
const u_char* pkt;
int len;
current_packet->BuildPacket(hdr, pkt, len, anon_src, anon_dst);
dumper->DumpPacket(hdr, pkt, hdr->caplen);
}
delete current_packet;
next_packet = current_packet = 0;
++packets_rewritten;
}
UDP_TracePacket::UDP_TracePacket(UDP_Rewriter* arg_trace_rewriter,
double t, int arg_is_orig,
const struct pcap_pkthdr* arg_hdr,
int MTU, int initial_size)
{
trace_rewriter = arg_trace_rewriter;
pcap_hdr = *arg_hdr;
// packet_seq = arg_packet_seq;
timestamp = t;
is_orig = arg_is_orig;
mtu = MTU;
buffer_size = initial_size;
buffer_offset = 0;
pkt = new u_char[buffer_size];
ip_offset = udp_offset = data_offset = -1;
reuse = 0;
on_hold = 0;
modified = 0;
seq_gap = 0;
packet_val = 0;
packet_val = PacketVal();
}
UDP_TracePacket::~UDP_TracePacket()
{
packet_val->SetOrigin(0);
Unref(packet_val);
delete [] pkt;
}
RecordVal* UDP_TracePacket::PacketVal()
{
if ( packet_val )
Ref(packet_val);
else
{
packet_val = new RecordVal(packet_type);
packet_val->Assign(0, TraceRewriter()->GetAnalyzer()->BuildConnVal());
packet_val->Assign(1, new Val(IsOrig(), TYPE_BOOL));
packet_val->Assign(2, new Val(TimeStamp(), TYPE_TIME));
packet_val->SetOrigin(this);
}
return packet_val;
}
int UDP_TracePacket::AppendLinkHeader(const u_char* chunk, int len)
{
if ( ip_offset >= 0 && ip_offset != buffer_offset )
internal_error(MSG_PREFIX "link header must be appended before IP header");
if ( ! Append(chunk, len) )
return 0;
ip_offset = buffer_offset;
return 1;
}
int UDP_TracePacket::AppendIPHeader(const u_char* chunk, int len)
{
if ( udp_offset >= 0 && udp_offset != buffer_offset )
internal_error(MSG_PREFIX "IP header must be appended before udp header");
if ( ! Append(chunk, len) )
return 0;
udp_offset = buffer_offset;
return 1;
}
int UDP_TracePacket::AppendUDPHeader(const u_char* chunk, int len)
{
if ( data_offset >= 0 && data_offset != buffer_offset )
internal_error(MSG_PREFIX "tcp header must be appended before payload");
if ( udp_offset == buffer_offset )
{ // first UDP header chunk
int extra = (udp_offset - ip_offset) % 4;
if ( extra )
{
DEBUG_MSG(MSG_PREFIX "padding IP header");
if ( ! AppendIPHeader(0, 4 - extra) )
return 0;
}
}
if ( ! Append(chunk, len) )
return 0;
data_offset = buffer_offset;
return 1;
}
int UDP_TracePacket::AppendData(const u_char* chunk, int len)
{
// All headers must be appended before any data.
ASSERT(ip_offset >= 0 && udp_offset >= 0 && data_offset >= 0);
if ( data_offset == buffer_offset )
{ // first data chunk
int extra = (data_offset - udp_offset) % 4;
if ( extra )
{
if ( ! AppendUDPHeader(0, 4 - extra) )
return 0;
}
}
if ( ! Append(chunk, len) )
return 0;
return 1;
}
int UDP_TracePacket::Append(const u_char* chunk, int len)
{
if ( buffer_offset + len > buffer_size )
{
if ( buffer_offset + len > mtu )
return 0;
u_char* tmp = new u_char[mtu];
for ( int i = 0 ; i < buffer_size; ++i )
tmp[i] = pkt[i];
delete [] pkt;
pkt = tmp;
buffer_size = mtu;
}
ASSERT(buffer_offset + len <= buffer_size);
if ( chunk )
memcpy(pkt + buffer_offset, chunk, len);
else
// Fill with 0.
memset(pkt + buffer_offset, 0, len);
buffer_offset += len;
return 1;
}

View file

@ -1,138 +0,0 @@
// $Id:$
//
// See the file "COPYING" in the main distribution directory for copyright.
#ifndef udp_rewriter_h
#define udp_rewriter_h
using namespace std;
#include <queue>
#include <set>
#include <pcap.h>
#include "Val.h"
#include "UDP.h"
#include "Anon.h"
#include "Rewriter.h"
#include "PacketDumper.h"
class UDP_TracePacket : public BroObj, virtual public TracePacket {
public:
UDP_TracePacket(UDP_Rewriter* trace_rewriter, double t, int is_orig,
const struct pcap_pkthdr* hdr, int MTU, int initial_size);
~UDP_TracePacket();
int AppendLinkHeader(const u_char* chunk, int len);
int AppendIPHeader(const u_char* chunk, int len);
int AppendUDPHeader(const u_char* chunk, int len);
int AppendData(const u_char* chunk, int len);
void Reuse();
int IsReuse() const { return reuse; }
double TimeStamp() const { return timestamp; }
int IsOrig() const { return is_orig; }
const struct pcap_pkthdr* Header() const { return &pcap_hdr; }
const u_char* Buffer() const { return pkt; }
int Length() const { return buffer_offset; }
// Note that Space() does not depend on buffer_size, but depends on MTU.
int Space() const { return mtu - buffer_offset; }
void Describe(ODesc* d) const { packet_val->Describe(d); }
RecordVal* PacketVal();
UDP_Rewriter* TraceRewriter() const { return trace_rewriter;}
// has the packet been written to?
int IsModified() const { return modified; }
void SetModified() { modified = 1; }
// BuildPacket() is called before dumping the packet. It sets length
// fields and computes checksums in UDP/IP headers.
int BuildPacket(struct pcap_pkthdr*& hdr, const u_char*& arg_pkt,
int& length, ipaddr32_t anon_src, ipaddr32_t anon_dst);
private:
int Append(const u_char* chunk, int len);
RecordVal* packet_val;
UDP_Rewriter* trace_rewriter;
double timestamp;
int packet_seq;
int is_orig;
struct pcap_pkthdr pcap_hdr;
int mtu;
u_char* pkt; // of maximal length MTU
int ip_offset, udp_offset, data_offset;
int buffer_size;
int buffer_offset;
int reuse; // whether it is an artificially replicated packet
int on_hold; // do not dump it in Flush()
int seq_gap;
int modified;
};
class UDP_Rewriter: public Rewriter {
public:
UDP_Rewriter(Analyzer* analyzer, int arg_MTU, PacketDumper* dumper);
virtual ~UDP_Rewriter();
void Done();
// these are the virt funcs in Rewriter....
void WriteData(int is_orig, int len, const u_char* data);
void WriteData(int is_orig, const char* data)
{ WriteData(is_orig, strlen(data), data); }
void WriteData(int is_orig, int len, const char* data)
{ WriteData(is_orig, len, (const u_char*) data); }
void WriteData(int is_orig, const BroString* str)
{ WriteData(is_orig, str->Len(), str->Bytes()); }
Analyzer* GetAnalyzer() const { return analyzer; }
// Not need for udp, but declared in the virtual
// and might be useful
void Push(int);
void AbortPackets(int);
void CommitPackets(int);
unsigned int ReserveSlot();
int SeekSlot(unsigned int);
int ReturnFromSlot();
int ReleaseSlot(unsigned int);
TracePacket* CurrentPacket() const { return current_packet; };
TracePacket* RewritePacket() const { return next_packet; };
// A UDP/IP packet.
void NextPacket(int is_orig, double t,
const struct pcap_pkthdr* pcap_hdr,
const u_char* pcap_pkt, // link level header
int hdr_size, // link level header size
const struct ip* ip, const struct udphdr* tp);
// Do not anonymize client/server IP address.
int LeaveAddrInTheClear(int is_orig);
protected:
void DoWriteData(int is_orig, int len, const u_char* data);
Analyzer* analyzer;
PacketDumper* dumper;
int packets_rewritten;
int MTU;
ipaddr32_t anon_addr[2];
UDP_TracePacket* current_packet;
UDP_TracePacket* next_packet;
};
#endif

View file

@ -1587,21 +1587,6 @@ function global_ids%(%): id_table
return ids;
%}
%%{
#include "TCP_Rewriter.h"
// Trace rewriting functions.
class PacketDumper;
extern PacketDumper* transformed_pkt_dump;
extern void commit_trace(Val* conn_val, int commit, int future);
%%}
# True if we're rewriting (anonymizing), false otherwise.
function rewriting_trace%(%): bool
%{
return new Val(transformed_pkt_dump != 0, TYPE_BOOL);
%}
%%{
#include "Anon.h"
%%}

View file

@ -68,7 +68,6 @@ HEX [0-9a-fA-F]+
"%)" return check_c_mode(TOK_RPP);
"..." return check_c_mode(TOK_VAR_ARG);
"function" return check_c_mode(TOK_FUNCTION);
"rewriter" return check_c_mode(TOK_REWRITER);
"event" return check_c_mode(TOK_EVENT);
"const" return check_c_mode(TOK_CONST);
"enum" return check_c_mode(TOK_ENUM);
@ -83,11 +82,6 @@ HEX [0-9a-fA-F]+
"@ARGS@" return TOK_ARGS;
"@ARGC@" return TOK_ARGC;
"@WRITE@" return TOK_WRITE;
"@PUSH@" return TOK_PUSH;
"@EOF@" return TOK_EOF;
"@TRACE@" return TOK_TRACE;
"T" yylval.val = 1; return TOK_BOOL;
"F" yylval.val = 0; return TOK_BOOL;

View file

@ -35,7 +35,6 @@ string type_name;
enum {
C_SEGMENT_DEF,
FUNC_DEF,
REWRITER_DEF,
EVENT_DEF,
TYPE_DEF,
CONST_DEF,
@ -102,17 +101,6 @@ void set_decl_name(const char *name)
decl.c_fullname = "BifConst::";
break;
case REWRITER_DEF:
// XXX: Legacy. No module names / namespaces supported
// If support for namespaces is desired: add a namespace
// to c_namespace_* and bro_fullname and get rid of
// the hack to bro_name.
decl.c_namespace_start = "";
decl.c_namespace_end = "";
decl.bare_name = "rewrite_" + decl.bare_name;
decl.bro_name = "rewrite_";
break;
case FUNC_DEF:
decl.c_namespace_start = "namespace BifFunc { ";
decl.c_namespace_end = " } ";
@ -155,7 +143,6 @@ void set_decl_name(const char *name)
}
const char* arg_list_name = "BiF_ARGS";
const char* trace_rewriter_name = "trace_rewriter";
#include "bif_arg.h"
@ -282,9 +269,8 @@ void print_event_c_body(FILE *fp)
%token TOK_LPP TOK_RPP TOK_LPB TOK_RPB TOK_LPPB TOK_RPPB TOK_VAR_ARG
%token TOK_BOOL
%token TOK_FUNCTION TOK_REWRITER TOK_EVENT TOK_CONST TOK_ENUM
%token TOK_FUNCTION TOK_EVENT TOK_CONST TOK_ENUM
%token TOK_TYPE TOK_RECORD TOK_SET TOK_VECTOR TOK_TABLE TOK_MODULE
%token TOK_WRITE TOK_PUSH TOK_EOF TOK_TRACE
%token TOK_ARGS TOK_ARG TOK_ARGC
%token TOK_ID TOK_ATTR TOK_CSTR TOK_LF TOK_WS TOK_COMMENT
%token TOK_ATOM TOK_INT TOK_C_TOKEN
@ -335,7 +321,6 @@ definitions: definitions definition opt_ws
definition: event_def
| func_def
| rewriter_def
| c_code_segment
| enum_def
| const_def
@ -395,9 +380,6 @@ event_def: event_prefix opt_ws plain_head opt_attr end_of_head ';'
func_def: func_prefix opt_ws typed_head end_of_head body
;
rewriter_def: rewriter_prefix opt_ws plain_head end_of_head body
;
enum_def: enum_def_1 enum_list TOK_RPB
{
// First, put an end to the enum type decl.
@ -490,10 +472,6 @@ func_prefix: TOK_FUNCTION
{ set_definition_type(FUNC_DEF, 0); }
;
rewriter_prefix: TOK_REWRITER
{ set_definition_type(REWRITER_DEF, 0); }
;
event_prefix: TOK_EVENT
{ set_definition_type(EVENT_DEF, 0); }
;
@ -515,12 +493,9 @@ plain_head: head_1 args arg_end opt_ws
fprintf(fp_bro_init, "va_args: any");
else
{
if ( definition_type == REWRITER_DEF )
fprintf(fp_bro_init, "c: connection");
for ( int i = 0; i < (int) args.size(); ++i )
{
if ( i > 0 || definition_type == REWRITER_DEF )
if ( i > 0 )
fprintf(fp_bro_init, ", ");
args[i]->PrintBro(fp_bro_init);
}
@ -538,7 +513,7 @@ head_1: TOK_ID opt_ws arg_begin
const char* method_type = 0;
set_decl_name($1);
if ( definition_type == FUNC_DEF || definition_type == REWRITER_DEF )
if ( definition_type == FUNC_DEF )
{
method_type = "function";
print_line_directive(fp_func_def);
@ -551,7 +526,7 @@ head_1: TOK_ID opt_ws arg_begin
"global %s: %s%s(",
decl.bro_name.c_str(), method_type, $2);
if ( definition_type == FUNC_DEF || definition_type == REWRITER_DEF )
if ( definition_type == FUNC_DEF )
{
fprintf(fp_func_init,
"\t(void) new BuiltinFunc(%s, \"%s\", 0);\n",
@ -646,11 +621,6 @@ body_start: TOK_LPB c_code_begin
int argc = args.size();
fprintf(fp_func_def, "{");
if ( definition_type == REWRITER_DEF )
{
implicit_arg = 1;
++argc;
}
if ( argc > 0 || ! var_arg )
fprintf(fp_func_def, "\n");
@ -676,15 +646,6 @@ body_start: TOK_LPB c_code_begin
fprintf(fp_func_def, "\t\t}\n");
}
if ( definition_type == REWRITER_DEF )
{
fprintf(fp_func_def,
"\tRewriter* %s = get_trace_rewriter((*%s)[0]);\n",
trace_rewriter_name,
arg_list_name);
fprintf(fp_func_def, "\tif ( ! trace_rewriter )\n");
fprintf(fp_func_def, "\t\treturn 0;\n");
}
for ( int i = 0; i < (int) args.size(); ++i )
args[i]->PrintCDef(fp_func_def, i + implicit_arg);
print_line_directive(fp_func_def);
@ -693,8 +654,6 @@ body_start: TOK_LPB c_code_begin
body_end: TOK_RPB c_code_end
{
if ( definition_type == REWRITER_DEF )
fprintf(fp_func_def, "\n\treturn 0;\n");
fprintf(fp_func_def, "}");
}
;
@ -718,14 +677,6 @@ c_atom: TOK_ID
{ fprintf(fp_func_def, "%s", arg_list_name); }
| TOK_ARGC
{ fprintf(fp_func_def, "%s->length()", arg_list_name); }
| TOK_TRACE
{ fprintf(fp_func_def, "%s", trace_rewriter_name); }
| TOK_WRITE
{ fprintf(fp_func_def, "%s->WriteData", trace_rewriter_name); }
| TOK_PUSH
{ fprintf(fp_func_def, "%s->Push", trace_rewriter_name); }
| TOK_EOF
{ fprintf(fp_func_def, "%s->EndOfData", trace_rewriter_name); }
| TOK_CSTR
{ fprintf(fp_func_def, "%s", $1); }
| TOK_ATOM

View file

@ -1,107 +0,0 @@
%%{
#include "TCP_Rewriter.h"
%%}
rewriter commit_trace%(commit: bool, future: bool%)
%{
if ( commit )
@TRACE@->CommitPackets(future);
else
@TRACE@->AbortPackets(future);
%}
rewriter push_packet%(is_orig: bool%)
%{
@PUSH@(is_orig);
%}
rewriter leave_addr_in_the_clear%(is_orig: bool%)
%{
if ( ! @TRACE@->LeaveAddrInTheClear(is_orig) )
builtin_run_time("cannot leave IP address in the clear"
" (probably because some packets have already been rewritten before this call)");
%}
function current_packet%(c: connection%): packet
%{
Rewriter* rewriter = get_trace_rewriter(c);
if ( ! rewriter )
{
builtin_run_time("current_packet is not supported without specifying an output file");
return 0;
}
return rewriter->CurrentPacket()->PacketVal();
%}
function current_rewrite_packet%(c: connection%): packet
%{
Rewriter* rewriter = get_trace_rewriter(c);
if ( ! rewriter )
{
builtin_run_time("current_rewrite_packet is not supported without specifying an output file");
return 0;
}
return rewriter->RewritePacket()->PacketVal();
%}
# Reserve a slot in the current packet of the trace so that the
# slot can be filled later by seeking to it.
function reserve_rewrite_slot%(c: connection%): count
%{
Rewriter* rewriter = get_trace_rewriter(c);
if ( ! rewriter )
return new Val(0, TYPE_COUNT);
unsigned int slot = rewriter->ReserveSlot();
if ( slot == 0 )
builtin_run_time("reserve_rewrite_slot returning 0");
return new Val(slot, TYPE_COUNT);
%}
# Seek to a previously reserved slot so that rewrites afterwards
# will go into the slot instead of the current packet.
function seek_rewrite_slot%(c: connection, slot: count%): any
%{
Rewriter* rewriter = get_trace_rewriter(c);
if ( ! rewriter->SeekSlot(slot) )
builtin_run_time("cannot seek the rewrite slot");
return 0;
%}
# Return from any reserved slot to bring the rewrite pointer back to
# the current packet.
function return_from_rewrite_slot%(c: connection%): any
%{
Rewriter* rewriter = get_trace_rewriter(c);
rewriter->ReturnFromSlot();
return 0;
%}
# Release a rewrite slot and dump the slot to the trace (it cannot be
# seek'd again). If the rewrite pointer is currently at the slot, it
# will return to the current packet.
function release_rewrite_slot%(c: connection, slot: count%): any
%{
Rewriter* rewriter = get_trace_rewriter(c);
rewriter->ReleaseSlot(slot);
return 0;
%}
# Dump original packets on the connection up to this point to the
# output trace, if any.
function dump_packets_of_connection%(c: connection%): any
%{
Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP);
if ( ! tc )
run_time("connection does not have TCP analyzer");
TCP_SourcePacketWriter* pkt_writer = get_src_pkt_writer((TCP_Analyzer*) tc);
if ( pkt_writer )
pkt_writer->Dump();
return 0;
%}

View file

@ -5,15 +5,3 @@
const ignore_keep_alive_rexmit: bool;
const skip_http_data: bool;
const parse_udp_tunnels: bool;
const requires_trace_commitment: bool;
const anonymize_ip_addr: bool;
const omit_rewrite_place_holder: bool;
const rewriting_http_trace :bool;
const rewriting_smtp_trace: bool;
const rewriting_ftp_trace: bool;
const rewriting_ident_trace: bool;
const rewriting_finger_trace: bool;
const rewriting_dns_trace: bool;
const rewriting_smb_trace: bool;
const dump_selected_source_packets: bool;
const dump_original_packets_if_not_rewriting: bool;

View file

@ -1,99 +0,0 @@
# $Id: dns-rw.bif,v 1.1.2.6 2006/01/11 21:20:09 jason Exp $
# This is called for every message - snake out the header.
rewriter dns_message%(is_orig: bool, msg: dns_msg, len: count%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->SetOrig(is_orig);
dnsrewriter->DnsCopyHeader(msg);
%}
# Rewrite an DNS request.
rewriter dns_request%(query: string, msg: dns_msg, qtype: count, qclass: count%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyQuery(query->AsString(), qtype, qclass);
%}
# Called for every reply, contains the query part.
rewriter dns_reply_question%(msg: dns_msg,
qname: string, qtype: count, qclass: count%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyQuery(qname->AsString(), qtype, qclass);
%}
# Rewrite an DNS NS reply.
rewriter dns_NS_reply%(msg: dns_msg, dns_ans: dns_answer, name: string%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyNS(dns_ans, name->AsString());
%}
rewriter dns_A_reply%(msg: dns_msg, ans: dns_answer, a: addr%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
#ifdef BROv6
dnsrewriter->DnsCopyA(ans, to_v4_addr(a));
#else
dnsrewriter->DnsCopyA(ans, a);
#endif
%}
rewriter dns_AAAA_reply%(msg: dns_msg, ans: dns_answer, a: addr, astr: string%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyAAAA(ans, a, astr->AsString());
%}
rewriter dns_CNAME_reply%(msg: dns_msg, ans: dns_answer, name: string%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyCNAME(ans, name->AsString());
%}
rewriter dns_TXT_reply%(msg: dns_msg, ans: dns_answer, content: string%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyTXT(ans, content->AsString());
%}
rewriter dns_PTR_reply%(msg: dns_msg, ans: dns_answer, name: string%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyPTR(ans, name->AsString());
%}
rewriter dns_MX_reply%(msg: dns_msg, ans: dns_answer,
name: string, preference: count%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyMX(ans, name->AsString(), preference);
%}
rewriter dns_SOA_reply%(msg: dns_msg, ans: dns_answer, soa: dns_soa%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopySOA(ans, soa);
%}
rewriter dns_EDNS_addl%(msg: dns_msg, ans: dns_edns_additional%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
dnsrewriter->DnsCopyEDNSaddl(ans);
%}
# Call this at end of processing a DNS packet.
rewriter dns_end%(commit: bool%)
%{
DNS_Rewriter* dnsrewriter = ((DNS_Rewriter*) @TRACE@);
// We have been building the packet in the DNS rewriter, now
// write the whole packet here at once, then commit it.
@WRITE@(dnsrewriter->IsOrig(), dnsrewriter->PacketSize(),
(const u_char*) dnsrewriter->Packet());
@TRACE@->CommitPackets(commit);
%}

View file

@ -1,22 +0,0 @@
# Write a finger request to trace.
rewriter finger_request %(full: bool, username: string, hostpart: string%)
%{
const int is_orig = 1;
if ( full )
@WRITE@(is_orig, "/W ");
@WRITE@(is_orig, username->AsString());
if ( hostpart->Len() > 0 )
{
@WRITE@(is_orig, "@");
@WRITE@(is_orig, hostpart->AsString());
}
@WRITE@(is_orig, "\r\n");
%}
# Write a finger reply to trace.
rewriter finger_reply %(reply: string%)
%{
const int is_orig = 0;
@WRITE@(is_orig, reply->AsString());
@WRITE@(is_orig, "\r\n");
%}

View file

@ -1,27 +0,0 @@
# Rewrite an FTP request.
rewriter ftp_request%(command: string, arg: string%)
%{
const int is_orig = 1;
@WRITE@(is_orig, command->AsString());
if ( command->Len() > 0 && arg->Len() > 0 )
@WRITE@(is_orig, " ");
@WRITE@(is_orig, arg->AsString());
@WRITE@(is_orig, "\r\n");
%}
# Rewrite an FTP reply.
rewriter ftp_reply%(code: count, msg: string, cont_resp: bool%)
%{
const int is_orig = 0;
if ( code > 0 )
{
@WRITE@(is_orig, fmt("%03lu", (unsigned long) code));
if ( cont_resp )
@WRITE@(is_orig, "-");
else
@WRITE@(is_orig, " ");
}
@WRITE@(is_orig, msg->AsString());
@WRITE@(is_orig, "\r\n");
%}

View file

@ -1,61 +0,0 @@
%%{
#include "HTTP.h"
BroString* encode_URI(BroString* URI)
{
byte_vec encoded_URI = new unsigned char[URI->Len() * 3 + 1];
byte_vec end_of_URI = URI->Bytes() + URI->Len();
byte_vec q = encoded_URI;
for ( byte_vec p = URI->Bytes(); p < end_of_URI; ++p )
{
if ( is_reserved_URI_char(*p) ||
is_unreserved_URI_char(*p) || *p == '%' )
*q++ = *p;
else
escape_URI_char(*p, q);
}
*q = '\0';
return new BroString(1, encoded_URI, q - encoded_URI);
}
%%}
rewriter http_request%(method: string, URI: string, version: string%)
%{
const int is_orig = 1;
@WRITE@(is_orig, method->AsString());
@WRITE@(is_orig, " ");
@WRITE@(is_orig, URI->AsString());
@WRITE@(is_orig, " HTTP/");
@WRITE@(is_orig, version->AsString());
@WRITE@(is_orig, "\r\n");
%}
rewriter http_reply%(version: string, code: count, reason: string%)
%{
const int is_orig = 0;
@WRITE@(is_orig, "HTTP/");
@WRITE@(is_orig, version->AsString());
@WRITE@(is_orig, " ");
@WRITE@(is_orig, fmt("%lu", (unsigned long) code));
@WRITE@(is_orig, " ");
@WRITE@(is_orig, reason->AsString());
@WRITE@(is_orig, "\r\n");
%}
rewriter http_header%(is_orig: bool, name: string, value: string%)
%{
@WRITE@(is_orig, name->AsString());
@WRITE@(is_orig, ":");
@WRITE@(is_orig, value->AsString());
@WRITE@(is_orig, "\r\n");
%}
rewriter http_data%(is_orig: bool, data: string%)
%{
@WRITE@(is_orig, data->AsString());
%}

View file

@ -1,23 +0,0 @@
rewriter ident_request %(lport: port, rport: port%)
%{
const int is_orig = 1;
@WRITE@(is_orig, fmt("%u, %u\r\n", rport->Port(), lport->Port()));
%}
rewriter ident_reply %(lport: port, rport: port, sys_str: string, id_str: string%)
%{
const int is_orig = 0;
@WRITE@(is_orig, fmt("%u, %u : USERID : ", rport->Port(), lport->Port()));
@WRITE@(is_orig, sys_str->AsString());
@WRITE@(is_orig, " : ");
@WRITE@(is_orig, id_str->AsString());
@WRITE@(is_orig, "\r\n");
%}
rewriter ident_error %(lport: port, rport: port, msg_str: string%)
%{
const int is_orig = 0;
@WRITE@(is_orig, fmt("%u, %u : ERROR : ", rport->Port(), lport->Port()));
@WRITE@(is_orig, msg_str->AsString());
@WRITE@(is_orig, "\r\n");
%}

View file

@ -152,7 +152,6 @@ void usage()
fprintf(stderr, " -v|--version | print version and exit\n");
fprintf(stderr, " -x|--print-state <file.bst> | print contents of state file\n");
fprintf(stderr, " -z|--analyze <analysis> | run the specified policy file analysis\n");
fprintf(stderr, " -A|--transfile <writefile> | write transformed trace to given tcpdump file\n");
#ifdef DEBUG
fprintf(stderr, " -B|--debug <dbgstreams> | Enable debugging output for selected streams\n");
#endif
@ -339,7 +338,6 @@ int main(int argc, char** argv)
name_list netflows;
name_list flow_files;
name_list rule_files;
char* transformed_writefile = 0;
char* bst_file = 0;
char* id_name = 0;
char* events_file = 0;
@ -371,7 +369,6 @@ int main(int argc, char** argv)
{"version", no_argument, 0, 'v'},
{"print-state", required_argument, 0, 'x'},
{"analyze", required_argument, 0, 'z'},
{"transfile", required_argument, 0, 'A'},
{"no-checksums", no_argument, 0, 'C'},
{"dfa-cache", required_argument, 0, 'D'},
{"force-dns", no_argument, 0, 'F'},
@ -434,7 +431,7 @@ int main(int argc, char** argv)
opterr = 0;
char opts[256];
safe_strncpy(opts, "A:B:D:e:f:I:i:K:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGHLOPSWdghlv",
safe_strncpy(opts, "B:D:e:f:I:i:K:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGHLOPSWdghlv",
sizeof(opts));
#ifdef USE_PERFTOOLS
@ -504,10 +501,6 @@ int main(int argc, char** argv)
}
break;
case 'A':
transformed_writefile = optarg;
break;
case 'C':
override_ignore_checksums = 1;
break;
@ -795,7 +788,7 @@ int main(int argc, char** argv)
if ( dns_type != DNS_PRIME )
net_init(interfaces, read_files, netflows, flow_files,
writefile, transformed_writefile,
writefile,
user_pcap_filter ? user_pcap_filter : "tcp or udp",
secondary_path->Filter(), do_watchdog);

View file

@ -37,8 +37,7 @@ int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len)
{
// ### Note, this is only correct for IPv4. This routine is only
// used by the connection compressor (which we turn off for IPv6
// traffic) and trace rewriting (which currently doesn't support
// IPv6 either).
// traffic).
int tcp_len = tp->th_off * 4 + len;
uint32 sum;

View file

@ -1,16 +0,0 @@
rewriter smb_header%(is_orig: bool, hdr: smb_hdr%)
%{
const int is_orig = 0;
@WRITE@(is_orig, 1, "\xff");
@WRITE@(is_orig, 3, "SMB");
@WRITE@(is_orig, 1, hdr->command);
@WRITE@(is_orig, 4, hdr->error);
@WRITE@(is_orig, 1, hdr->flags);
@WRITE@(is_orig, 2, hdr->flags2);
@WRITE@(is_orig, 6, "\x0\x0\x0\x0\x0\x0");
@WRITE@(is_orig, 6, "\x0\x0\x0\x0\x0\x0");
@WRITE@(is_orig, 2, hdr->tid);
@WRITE@(is_orig, 2, hdr->pid);
@WRITE@(is_orig, 2, hdr->mid);
%}

View file

@ -1,45 +0,0 @@
rewriter smtp_request%(is_orig: bool, command: string, arg: string%)
%{
if ( command->Len() > 0 )
{
u_char ch = command->Bytes()[0];
if ( isalpha(ch) )
{ // Do not dump artificial commands: ">", ".", "***"
@WRITE@(is_orig, command->AsString());
@WRITE@(is_orig, 1, " ");
}
}
@WRITE@(is_orig, arg->AsString());
@WRITE@(is_orig, 2, "\r\n");
%}
rewriter smtp_reply%(is_orig: bool, code: count, msg: string, cont_resp: bool%)
%{
const char* str = fmt("%lu", (unsigned long) code);
int len = strlen(str);
@WRITE@(is_orig, len, str);
if ( cont_resp )
@WRITE@(is_orig, "-");
else
@WRITE@(is_orig, " ");
@WRITE@(is_orig, msg->AsString());
@WRITE@(is_orig, "\r\n");
%}
# Since SMTP data is delivered by lines ending with CRLF, this
# function takes a line without the trailing CRLF and dumps the string
# followed by CRLF. If you want to dump multiple lines, please dump
# them one at a time (without trailing CRLF's).
rewriter smtp_data%(is_orig: bool, data: string%)
%{
if ( data->Len() > 0 && data->Bytes()[0] == '.')
@WRITE@(is_orig, ".");
@WRITE@(is_orig, data->AsString());
@WRITE@(is_orig, "\r\n");
%}