Merge branch 'topic/robin/record-table-default' into topic/robin/logging-internals

Includes additional fixes for the &default attribute's type checking.
This commit is contained in:
Robin Sommer 2011-04-17 12:03:58 -07:00
commit c132506203
146 changed files with 14037 additions and 7258 deletions

10
.gitmodules vendored
View file

@ -1,15 +1,15 @@
[submodule "aux/bro-aux"]
path = aux/bro-aux
url = git://git.icir.org/bro-aux
url = git://git.bro-ids.org/bro-aux
[submodule "aux/binpac"]
path = aux/binpac
url = git://git.icir.org/binpac
url = git://git.bro-ids.org/binpac
[submodule "aux/broccoli"]
path = aux/broccoli
url = git://git.icir.org/broccoli
url = git://git.bro-ids.org/broccoli
[submodule "aux/broctl"]
path = aux/broctl
url = git://git.icir.org/broctl
url = git://git.bro-ids.org/broctl
[submodule "aux/btest"]
path = aux/btest
url = git://git.icir.org/btest
url = git://git.bro-ids.org/btest

59
CHANGES
View file

@ -1,3 +1,62 @@
1.6-dev.71 Fri Apr 1 16:06:33 PDT 2011
- Removing code for the following no longer supported functionality.
* Trace rewriting.
* DFA state expiration in regexp engine.
* Active mapping.
* Unused hash functions.
(Robin Sommer)
- Fixing crashes when SSL is not configured correctly. (Robin Sommer)
1.6-dev.66 Tue Mar 29 21:52:01 PDT 2011
- Initial btest setup (Don Appleman and Robin Sommer)
- Porting the istate tests to btest (not finished) (Robin Sommer)
1.6-dev.63 Mon Mar 21 16:31:15 PDT 2011
- Changes to the way user-modifiable config files are installed (Jon Siwek)
* Duplicates of the distribution's configuration files are now
always installed with a .example suffix
* Added --binary-package configure option to toggle configure
logic specific to the creation of binary packages.
* When not in binary packaging mode, `make install` never
overwrites existing configure files in case they've been
modified. The previous behavior (CMake's default) would only
avoid overwriting modified files if one consistently uses the
same build directory and doesn't reconfigure.
- Fixed an issue with Mac package's pre-install script not preserving
ACLs. (Jon Siwek)
- Minor cleanup/refactor of the make-mac/rpm-packages scripts. (Jon
Siwek)
- Add explicit CMake check for compiler. (Jon Siwek)
- Add alternative way to set BROPATH for running bro from build/ dir.
(Jon Siwek)
- Fixing compiler warnings (Gregor Maier)
- Remvoing leftover local variables that caused compile error on Mac
OS X. (Gregor Maier)
1.6-dev.53 Fri Feb 25 17:03:05 PST 2011
- Fixing file detector leak in remote communication module. (Scott
Campbell)
- Updating independent-state tests to work with new setup. (Robin
Sommer)
1.6-dev.49 Fri Feb 25 15:37:28 PST 2011
- Enum IDs can have explicitly defined values. (Gregor Maier)

View file

@ -1,4 +1,12 @@
project(Bro)
project(Bro C CXX)
if (NOT CMAKE_C_COMPILER)
message(FATAL_ERROR "Could not find prerequisite C compiler")
endif ()
if (NOT CMAKE_CXX_COMPILER)
message(FATAL_ERROR "Could not find prerequisite C++ compiler")
endif ()
########################################################################
## CMake Configuration
@ -37,6 +45,10 @@ endif ()
get_filename_component(POLICYDIR ${POLICYDIR} ABSOLUTE)
configure_file(bro-path-dev.in ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.sh
"export BROPATH=`${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev.csh
"setenv BROPATH `${CMAKE_CURRENT_BINARY_DIR}/bro-path-dev`\n")
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" VERSION LIMIT_COUNT 1)

17
INSTALL
View file

@ -9,6 +9,8 @@ Prerequisites
Bro relies on the following libraries and tools, which need to be installed
before you begin:
* A C/C++ compiler
* Libpcap headers and libraries
Network traffic capture library
@ -35,7 +37,7 @@ before you begin:
though some platforms may require installation of a 'devel' package
for the headers.
* CMake 2.8 or greater
* CMake 2.6 or greater
CMake is a cross-platform, open-source build system, typically
not installed by default. See http://www.cmake.org for more
information regarding CMake and the installation steps below for
@ -92,6 +94,13 @@ with it. In the following we give a few simple examples. See the
quickstart guide at http://www.bro-ids.org for more information; you
can the source that in doc/quick-start.
For developers that wish to run Bro after performing "make", but
without performing "make install", see build/bro-path-dev for
an example.
For developers that wish to run Bro from the the build/ directory
after performing "make", but without performing "make install", they
will have to first set BROPATH to look for scripts inside the build
directory. Sourcing either build/bro-path-dev.sh or build/bro-path-dev.csh
as appropriate for the current shell accomplishes this. e.g.:
> ./configure
> make
> source build/bro-path-dev.sh
> ./build/src/bro

View file

@ -1 +1 @@
1.6-dev.49
1.6-dev.71

@ -1 +1 @@
Subproject commit 26d02716f9090651f319a4bfdf8ede49b3a7b53a
Subproject commit c3c7ef0dfddb0746d3762e41086ba42928e68483

@ -1 +1 @@
Subproject commit 7e50bac938af1831ecf9660159145a3c2e77e13d
Subproject commit 98f92eeb40281045159097764abddc428fb49bf2

@ -1 +1 @@
Subproject commit 9332ab3467191ac22be09d6941ebd469e7a334d0
Subproject commit 48d473398e577893b6c7f77d605ccdf266a2f93b

@ -1 +1 @@
Subproject commit 06b74a0f23767c8345ed146657120aba812f6764
Subproject commit 532dcd5aa51c8b29b2d71cd37e1d7c21e33cc715

View file

@ -1,3 +1,4 @@
#!/bin/sh
# After configured by CMake, this file prints the absolute path to policy
# files that come with the source distributions of Bro and Broctl as well
# as policy files that are generated by the BIF compiler at compile time
@ -6,7 +7,7 @@
# the build directory, avoiding the need to install it. This could be
# done like:
#
# BROPATH=`source bro-path-dev` ./src/bro
# BROPATH=`./bro-path-dev` ./src/bro
#
broPolicies=${PROJECT_SOURCE_DIR}/policy:${PROJECT_SOURCE_DIR}/policy/sigs:${PROJECT_SOURCE_DIR}/policy/time-machine

View file

@ -0,0 +1,20 @@
# Determines at `make install` time if a file, typically a configuration
# file placed in $PREFIX/etc, shouldn't be installed to prevent overwrite
# of an existing file.
#
# _srcfile: the file to install
# _dstfile: the absolute file name after installation
macro(InstallClobberImmune _srcfile _dstfile)
install(CODE "
if (EXISTS ${_dstfile})
message(STATUS \"Skipping: ${_dstfile} (already exists)\")
else ()
message(STATUS \"Installing: ${_dstfile}\")
# install() is not scriptable within install(), and
# configure_file() is the next best thing
configure_file(${_srcfile} ${_dstfile} COPY_ONLY)
# TODO: create additional install_manifest files?
endif ()
")
endmacro(InstallClobberImmune)

View file

@ -0,0 +1,39 @@
include(InstallClobberImmune)
# This macro can be used to install configuration files which
# users are expected to modify after installation. It will:
#
# - Always install one version of the file with a .example suffix
# - If binary packaging is enabled:
# Install the file in the typical CMake fashion, but append to the
# INSTALLED_CONFIG_FILES cache variable for use with the Mac package's
# pre/post install scripts
# - If binary packaging is not enabled:
# Install the script in a way such that it will check at `make install`
# time whether the file does not exist. See InstallClobberImmune.cmake
#
# _srcfile: the absolute path to the file to install
# _dstdir: absolute path to the directory in which to install the file
# _dstfilename: how to (re)name the file inside _dstdir
macro(InstallPackageConfigFile _srcfile _dstdir _dstfilename)
set(_dstfile ${_dstdir}/${_dstfilename})
# Always install the latest version of the file renamed as an example
install(FILES ${_srcfile} DESTINATION ${_dstdir}
RENAME ${_dstfilename}.example)
if (BINARY_PACKAGING_MODE)
# If packaging mode is enabled, always install the distribution's
# version of the file. The Mac package's pre/post install scripts
# or native functionality of RPMs will take care of not clobbering it.
install(FILES ${_srcfile} DESTINATION ${_dstdir} RENAME ${_dstfilename})
# This cache variable is what the Mac package pre/post install scripts
# use to avoid clobbering user-modified config files
set(INSTALLED_CONFIG_FILES
"${INSTALLED_CONFIG_FILES} ${_dstfile}" CACHE STRING "" FORCE)
else ()
# Have `make install` check at run time whether the file does not exist
InstallClobberImmune(${_srcfile} ${_dstfile})
endif ()
endmacro(InstallPackageConfigFile)

View file

@ -5,7 +5,7 @@
backupNamesFile=/tmp/bro_install_backups
version=@VERSION@
newFiles=""
sampleFiles=""
# check whether it's safe to remove backup configuration files that
# the most recent package install created
@ -28,10 +28,8 @@ if [ -e ${backupNamesFile} ]; then
# by the user, we should restore it to its original location
# and rename the new version appropriately.
newFileName=${origFileName}.${version}
newFiles="${newFiles}\n${newFileName}"
sampleFiles="${sampleFiles}\n${origFileName}.example"
mv ${origFileName} ${newFileName}
mv ${backupFile} ${origFileName}
fi
@ -40,12 +38,12 @@ if [ -e ${backupNamesFile} ]; then
rm ${backupNamesFile}
fi
if [ -n "${newFiles}" ]; then
if [ -n "${sampleFiles}" ]; then
# Use some apple script to display a message to user
/usr/bin/osascript << EOF
tell application "System Events"
activate
display alert "Existing configuration files differ from the ones that would be installed by this package. To avoid overwriting configuration which you may have modified, the following new config files have been installed:\n${newFiles}\n\nIf you have previously modified configuration files, please make sure that they are still compatible, else you should update your config files to the new versions."
display alert "Existing configuration files differ from the ones that would be installed by this package. To avoid overwriting configuration which you may have modified, the following new config files have been installed:\n${sampleFiles}\n\nIf you have previously modified configuration files, please make sure that they are still compatible, else you should update your config files to the new versions."
end tell
EOF
fi

View file

@ -20,7 +20,7 @@ backupFile () {
backupFile=${origFile}.${ver}
cp ${origFile} ${backupFile}
cp -p ${origFile} ${backupFile}
# the post upgrade script will check whether the installed
# config file actually differs from existing version

4
configure vendored
View file

@ -54,6 +54,7 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
--with-swig=PATH path to SWIG executable
Packaging Options (for developers):
--binary-package toggle special logic for binary packaging
--ignore-dirs=PATHS paths to ignore when creating source package
(semicolon delimited and quoted when multiple)
--pkg-name-prefix=NAME use the given name as the package prefix instead
@ -195,6 +196,9 @@ while [ $# -ne 0 ]; do
--with-swig=*)
append_cache_entry SWIG_EXECUTABLE PATH $optarg
;;
--binary-package)
append_cache_entry BINARY_PACKAGING_MODE BOOL true
;;
--ignore-dirs=*)
append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING $optarg
;;

View file

@ -3,6 +3,8 @@
# This script creates binary packages for Mac OS X.
# They can be found in build/ after running.
prefix=/opt/bro
# CMake/CPack versions before 2.8.2 have bugs that can create bad packages
CMAKE_PACK_REQ=2.8.3
CMAKE_VER=`cmake -version`
@ -37,31 +39,26 @@ else
fi
# Minimum Bro
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=/opt/bro \
--disable-broccoli --disable-broctl --pkg-name-prefix=Bro
cd build
make package
cd ..
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \
--disable-broccoli --disable-broctl --pkg-name-prefix=Bro \
--binary-package
( cd build && make package )
# Full Bro package
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=/opt/bro \
--pkg-name-prefix=Bro-all
cd build
make package
cd ..
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \
--pkg-name-prefix=Bro-all --binary-package
( cd build && make package )
# Broccoli
cd aux/broccoli
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=/opt/bro
cd build
make package
mv Broccoli*.dmg ../../../build/
cd ../../..
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \
--binary-package
( cd build && make package && mv Broccoli*.dmg ../../../build/ )
cd ../..
# Broctl
cd aux/broctl
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=/opt/bro
cd build
make package
mv Broctl*.dmg ../../../build/
cd ../../..
CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \
--binary-package
( cd build && make package && mv Broctl*.dmg ../../../build/ )
cd ../..

View file

@ -3,6 +3,8 @@
# This script generates binary RPM packages.
# They can be found in build/ after running.
prefix=/opt/bro
# CMake/CPack versions before 2.8.2 have bugs that can create bad packages
CMAKE_PACK_REQ=2.8.2
CMAKE_VER=`cmake -version`
@ -13,30 +15,22 @@ if [ "${CMAKE_VER}" \< "${CMAKE_PACK_REQ}" ]; then
fi
# Minimum Bro
./configure --prefix=/opt/bro --disable-broccoli --disable-broctl \
--pkg-name-prefix=Bro
cd build
make package
cd ..
./configure --prefix=${prefix} --disable-broccoli --disable-broctl \
--pkg-name-prefix=Bro --binary-package
( cd build && make package )
# Full Bro package
./configure --prefix=/opt/bro --pkg-name-prefix=Bro-all
cd build
make package
cd ..
./configure --prefix=${prefix} --pkg-name-prefix=Bro-all --binary-package
( cd build && make package )
# Broccoli
cd aux/broccoli
./configure --prefix=/opt/bro
cd build
make package
mv Broccoli*.rpm ../../../build/
cd ../../..
./configure --prefix=${prefix} --binary-package
( cd build && make package && mv Broccoli*.rpm ../../../build/ )
cd ../..
# Broctl
cd aux/broctl
./configure --prefix=/opt/bro
cd build
make package
mv Broctl*.rpm ../../../build/
cd ../../..
./configure --prefix=${prefix} --binary-package
( cd build && make package && mv Broctl*.rpm ../../../build/ )
cd ../..

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

@ -1120,14 +1120,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);
@ -1407,33 +1399,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

@ -1,218 +0,0 @@
// $Id: Active.cc 1282 2005-09-07 17:02:02Z vern $
#include "config.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <map>
#include "Active.h"
#include "util.h"
#include "Dict.h"
declare(PDict,string);
typedef PDict(string) MachineMap;
declare(PDict,MachineMap);
typedef PDict(MachineMap) ActiveMap;
declare(PDict,NumericData);
typedef PDict(NumericData) ActiveMapNumeric;
static ActiveMap active_map;
static ActiveMapNumeric active_map_numeric;
static MachineMap default_values;
static NumericData default_values_numeric;
static bool map_was_loaded = false;
bool get_map_result(uint32 ip_addr, const char* key, string& result)
{
const MachineMap* machine_map;
#ifndef ACTIVE_MAPPING
machine_map = &default_values;
#else
HashKey machinekey(ip_addr);
machine_map = active_map.Lookup(&machinekey);
if ( ! machine_map )
machine_map = &default_values;
#endif
HashKey mapkey(key);
string* entry = machine_map->Lookup(&mapkey);
if ( ! entry )
{
entry = default_values.Lookup(&mapkey);
}
if ( ! entry )
{
internal_error("Unknown active mapping entry requested: %s", key);
return false;
}
result = *entry;
return true;
}
bool get_map_result(uint32 ip_addr, const NumericData*& result)
{
#ifndef ACTIVE_MAPPING
result = &default_values_numeric;
return true;
#endif
HashKey machinekey(&ip_addr, 1);
NumericData* entry = active_map_numeric.Lookup(&machinekey);
if ( ! entry )
result = &default_values_numeric;
else
result = entry;
return true;
}
char* chop (char* s)
{
s[strlen(s) - 1] = 0;
return s;
}
map < const char *, ReassemblyPolicy, ltstr > reassem_names;
// Remember to index the table with IP address in network order!
bool load_mapping_table(const char* map_file)
{
reassem_names["BSD"] = RP_BSD;
reassem_names["linux"] = RP_LINUX;
reassem_names["last"] = RP_LAST;
reassem_names["first"] = RP_FIRST;
// Default values are read in from AM file under IP address 0.0.0.0
default_values.Insert(new HashKey("accepts_rst_outside_window"),
new string("no"));
default_values.Insert(new HashKey("accepts_rst_in_window"),
new string("yes"));
default_values.Insert(new HashKey("accepts_rst_in_sequence"),
new string("yes"));
default_values.Insert(new HashKey("mtu"),
new string("0"));
default_values_numeric.path_MTU = 0; // 0 = unknown
default_values_numeric.hops = 0; // 0 = unknown;
default_values_numeric.ip_reassem = RP_UNKNOWN;
default_values_numeric.tcp_reassem = RP_UNKNOWN;
default_values_numeric.accepts_rst_in_window = true;
default_values_numeric.accepts_rst_outside_window = false;
if ( map_file && strlen(map_file) )
{
FILE* f = fopen(map_file, "r");
if ( ! f )
return false;
char buf[512];
if ( ! fgets(buf, sizeof(buf), f) )
error("Error reading mapping file.\n");
int num_fields = atoi(buf);
string* field_names = new string[num_fields];
for ( int i = 0; i < num_fields; ++i )
{
if ( ! fgets(buf, sizeof(buf), f) )
error("Error reading mapping file.\n");
field_names[i] = chop(buf);
}
if ( ! fgets(buf, sizeof(buf), f) )
error("Error reading mapping file.\n");
int num_machines = atoi(buf);
for ( int j = 0; j < num_machines; ++j )
{ // read ip address, parse it
if ( ! fgets(buf, sizeof(buf), f) )
error("Error reading mapping file.\n");
uint32 ip;
in_addr in;
if ( ! inet_aton(chop(buf), &in) )
error("Error reading mapping file.\n");
ip = in.s_addr;
MachineMap* newmap;
NumericData* newnumeric;
if ( ip ) // ip = 0.0.0.0 = default values
{
newmap = new MachineMap;
newnumeric = new NumericData;
}
else
{
newmap = &default_values;
newnumeric = &default_values_numeric;
}
for ( int i = 0; i < num_fields; ++i )
{
if ( ! fgets(buf, sizeof(buf), f) )
error("Error reading mapping file.\n");
string fname = field_names[i];
chop(buf);
// Don't try to parse an unknown value ("").
if ( streq(buf, "") )
continue;
HashKey mapkey(fname.c_str());
newmap->Insert(&mapkey, new string(buf));
if ( fname == "mtu" )
newnumeric->path_MTU = atoi(buf);
else if ( fname == "hops" )
newnumeric->hops = atoi(buf);
else if ( fname == "tcp_segment_overlap" )
newnumeric->tcp_reassem = reassem_names[buf];
else if ( fname == "overlap_policy" )
newnumeric->ip_reassem = reassem_names[buf];
else if ( fname == "accepts_rst_in_window" )
newnumeric->accepts_rst_in_window = streq(buf, "yes");
else if ( fname == "accepts_rst_outside_window" )
newnumeric->accepts_rst_outside_window = streq(buf, "yes");
else if ( fname == "accepts_rst_in_sequence" )
newnumeric->accepts_rst_in_sequence = streq(buf, "yes");
else
warn("unrecognized mapping file tag:", fname.c_str());
}
HashKey machinekey(&ip, 1);
active_map.Insert(&machinekey, newmap);
active_map_numeric.Insert(&machinekey, newnumeric);
}
delete [] field_names;
}
map_was_loaded = true;
return true;
}

View file

@ -1,44 +0,0 @@
// $Id: Active.h 80 2004-07-14 20:15:50Z jason $
#ifndef active_h
#define active_h
#include <string>
using namespace std;
#include "util.h"
enum ReassemblyPolicy {
RP_UNKNOWN,
RP_BSD, // Left-trim to equal or lower offset frags
RP_LINUX, // Left-trim to strictly lower offset frags
RP_FIRST, // Accept only new (no previous value) octets
RP_LAST // Accept all
};
struct NumericData {
ReassemblyPolicy ip_reassem;
ReassemblyPolicy tcp_reassem;
unsigned short path_MTU; // 0 = unknown
unsigned char hops; // 0 = unknown
bool accepts_rst_in_window;
bool accepts_rst_outside_window;
bool accepts_rst_in_sequence;
};
// Return value is whether or not there was a known result for that
// machine (actually, IP address in network order); if not, a default
// is returned. Note that the map data is a string in all cases: the
// numeric form is more efficient and is to be preferred ordinarily.
bool get_map_result(uint32 ip_addr, const char* key, string& result);
// Basically a special case of get_map_result(), but returns numbers
// directly for efficiency reasons, since these are frequently
// looked up. ### Perhaps a better generic mechanism is in order.
bool get_map_result(uint32 ip_addr, const NumericData*& result);
// Reads in AM data from the specified file (basically [IP, policy] tuples)
// Should be called at initialization time.
bool load_mapping_table(const char* map_file);
#endif

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

@ -58,10 +58,11 @@ void Attr::AddTag(ODesc* d) const
d->Add(attr_name(Tag()));
}
Attributes::Attributes(attr_list* a, BroType* t)
Attributes::Attributes(attr_list* a, BroType* t, bool arg_in_record)
{
attrs = new attr_list(a->length());
type = t->Ref();
in_record = arg_in_record;
SetLocationInfo(&start_location, &end_location);
@ -200,39 +201,72 @@ void Attributes::CheckAttr(Attr* a)
{
BroType* atype = a->AttrExpr()->Type();
if ( type->Tag() != TYPE_TABLE || type->IsSet() )
if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
{
if ( ! same_type(atype, type) )
a->AttrExpr()->Error("&default value has inconsistent type", type);
if ( same_type(atype, type) )
// Ok.
break;
// Record defaults may be promotable.
if ( (type->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(), type->AsRecordType())) )
// Ok.
break;
a->AttrExpr()->Error("&default value has inconsistent type", type);
}
TableType* tt = type->AsTableType();
BroType* ytype = tt->YieldType();
if ( ! same_type(atype, tt->YieldType()) )
if ( ! in_record )
{
// &default applies to the type itself.
if ( ! same_type(atype, ytype) )
{
// It can still be a default function.
if ( atype->Tag() == TYPE_FUNC )
{
FuncType* f = atype->AsFuncType();
if ( ! f->CheckArgs(tt->IndexTypes()) ||
! same_type(f->YieldType(), tt->YieldType()) )
! same_type(f->YieldType(), ytype) )
Error("&default function type clash");
// Ok.
break;
}
else
{
BroType* ytype = tt->YieldType();
// Table defaults may be promotable.
if ( atype->Tag() == TYPE_RECORD && ytype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType()) )
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType())) )
// Ok.
break;
Error("&default value has inconsistent type 2");
}
// Ok.
break;
}
else
{
// &default applies to record field.
if ( same_type(atype, type) ||
(atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) )
// Ok.
break;
// Table defaults may be promotable.
if ( (ytype->Tag() == TYPE_RECORD && atype->Tag() == TYPE_RECORD &&
record_promotion_compatible(atype->AsRecordType(), ytype->AsRecordType())) )
// Ok.
break;
Error("&default value has inconsistent type");
}
}
}
break;
case ATTR_ROTATE_INTERVAL:

View file

@ -77,7 +77,7 @@ protected:
// Manages a collection of attributes.
class Attributes : public BroObj {
public:
Attributes(attr_list* a, BroType* t);
Attributes(attr_list* a, BroType* t, bool in_record);
~Attributes();
void AddAttr(Attr* a);
@ -104,6 +104,7 @@ protected:
BroType* type;
attr_list* attrs;
bool in_record;
};
#endif

View file

@ -131,15 +131,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})
@ -243,7 +235,6 @@ set(bro_SRCS
net_util.cc
util.cc
module_util.cc
Active.cc
Analyzer.cc
Anon.cc
ARP.cc
@ -358,12 +349,10 @@ set(bro_SRCS
TCP.cc
TCP_Endpoint.cc
TCP_Reassembler.cc
TCP_Rewriter.cc
Telnet.cc
Timer.cc
Traverse.cc
Trigger.cc
TwoWise.cc
Type.cc
UDP.cc
Val.cc
@ -375,10 +364,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

@ -21,11 +21,10 @@ DFA_State::DFA_State(int arg_state_num, const EquivClass* ec,
nfa_states = arg_nfa_states;
accept = arg_accept;
mark = 0;
lock = 0;
SymPartition(ec);
xtions = new DFA_State_Handle*[num_sym];
xtions = new DFA_State*[num_sym];
for ( int i = 0; i < num_sym; ++i )
xtions[i] = DFA_UNCOMPUTED_STATE_PTR;
@ -33,31 +32,14 @@ DFA_State::DFA_State(int arg_state_num, const EquivClass* ec,
DFA_State::~DFA_State()
{
for ( int i = 0; i < num_sym; ++i )
{
DFA_State_Handle* s = xtions[i];
if ( s && s != DFA_UNCOMPUTED_STATE_PTR )
StateUnref(s);
}
delete [] xtions;
delete nfa_states;
delete accept;
delete meta_ec;
}
void DFA_State::AddXtion(int sym, DFA_State_Handle* next_state)
void DFA_State::AddXtion(int sym, DFA_State* next_state)
{
// The order is important here: first StateRef() the new,
// then StateUnref() the old. Otherwise, we may get a problem
// if both are equal.
if ( next_state )
StateRef(next_state);
if ( xtions[sym] && xtions[sym] != DFA_UNCOMPUTED_STATE_PTR )
StateUnref(xtions[sym]);
xtions[sym] = next_state;
}
@ -94,14 +76,10 @@ void DFA_State::SymPartition(const EquivClass* ec)
meta_ec->BuildECs();
}
DFA_State_Handle* DFA_State::ComputeXtion(int sym, DFA_Machine* machine)
DFA_State* DFA_State::ComputeXtion(int sym, DFA_Machine* machine)
{
// Make sure we will not expire...
assert(IsLocked());
int equiv_sym = meta_ec->EquivRep(sym);
if ( xtions[equiv_sym] != DFA_UNCOMPUTED_STATE_PTR &&
StateIsValid(xtions[equiv_sym]) )
if ( xtions[equiv_sym] != DFA_UNCOMPUTED_STATE_PTR )
{
AddXtion(sym, xtions[equiv_sym]);
return xtions[sym];
@ -109,7 +87,7 @@ DFA_State_Handle* DFA_State::ComputeXtion(int sym, DFA_Machine* machine)
const EquivClass* ec = machine->EC();
DFA_State_Handle* next_d;
DFA_State* next_d;
NFA_state_list* ns = SymFollowSet(equiv_sym, ec);
if ( ns->length() > 0 )
@ -211,10 +189,10 @@ void DFA_State::ClearMarks()
for ( int i = 0; i < num_sym; ++i )
{
DFA_State_Handle* s = xtions[i];
DFA_State* s = xtions[i];
if ( s && s != DFA_UNCOMPUTED_STATE_PTR )
(*xtions[i])->ClearMarks();
xtions[i]->ClearMarks();
}
}
}
@ -243,7 +221,7 @@ void DFA_State::Dump(FILE* f, DFA_Machine* m)
int num_trans = 0;
for ( int sym = 0; sym < num_sym; ++sym )
{
DFA_State_Handle* s = xtions[sym];
DFA_State* s = xtions[sym];
if ( ! s )
continue;
@ -271,7 +249,7 @@ void DFA_State::Dump(FILE* f, DFA_Machine* m)
else
fprintf(f, "%stransition on %s to state %d",
++num_trans == 1 ? "\t" : "\n\t", xbuf,
(*s)->StateNum());
s->StateNum());
sym = i - 1;
}
@ -283,10 +261,10 @@ void DFA_State::Dump(FILE* f, DFA_Machine* m)
for ( int sym = 0; sym < num_sym; ++sym )
{
DFA_State_Handle* s = xtions[sym];
DFA_State* s = xtions[sym];
if ( s && s != DFA_UNCOMPUTED_STATE_PTR )
(*s)->Dump(f, m);
s->Dump(f, m);
}
}
@ -294,7 +272,7 @@ void DFA_State::Stats(unsigned int* computed, unsigned int* uncomputed)
{
for ( int sym = 0; sym < num_sym; ++sym )
{
DFA_State_Handle* s = xtions[sym];
DFA_State* s = xtions[sym];
if ( s == DFA_UNCOMPUTED_STATE_PTR )
(*uncomputed)++;
@ -313,11 +291,9 @@ unsigned int DFA_State::Size()
+ (centry ? padded_sizeof(CacheEntry) : 0);
}
DFA_State_Cache::DFA_State_Cache(int arg_maxsize)
{
maxsize = arg_maxsize;
head = tail = 0;
hits = misses = 0;
}
@ -328,13 +304,12 @@ DFA_State_Cache::~DFA_State_Cache()
while ( (e = (CacheEntry*) states.NextEntry(i)) )
{
assert(e->state);
StateInvalidate(e->state);
delete e->hash;
delete e;
}
}
DFA_State_Handle* DFA_State_Cache::Lookup(const NFA_state_list& nfas,
DFA_State* DFA_State_Cache::Lookup(const NFA_state_list& nfas,
HashKey** hash)
{
// We assume that state ID's don't exceed 10 digits, plus
@ -380,100 +355,24 @@ DFA_State_Handle* DFA_State_Cache::Lookup(const NFA_state_list& nfas,
delete *hash;
*hash = 0;
MoveToFront(e);
return e->state;
}
DFA_State_Handle* DFA_State_Cache::Insert(DFA_State* state, HashKey* hash)
DFA_State* DFA_State_Cache::Insert(DFA_State* state, HashKey* hash)
{
CacheEntry* e;
#ifdef EXPIRE_DFA_STATES
if ( states.Length() == maxsize )
{
// Remove oldest unlocked entry.
for ( e = tail; e; e = e->prev )
if ( ! (*e->state)->lock )
break;
if ( e )
Remove(e);
}
#endif
e = new CacheEntry;
#ifdef EXPIRE_DFA_STATES
// Insert as head.
e->state = new DFA_State_Handle(state);
e->state->state->centry = e;
#else
e->state = state;
e->state->centry = e;
#endif
e->hash = hash;
e->prev = 0;
e->next = head;
if ( head )
head->prev = e;
head = e;
if ( ! tail )
tail = e;
states.Insert(hash, e);
return e->state;
}
void DFA_State_Cache::Remove(CacheEntry* e)
{
if ( e == head )
{
head = e->next;
if ( head )
head->prev = 0;
}
else
e->prev->next = e->next;
if ( e == tail )
{
tail = e->prev;
if ( tail )
tail->next = 0;
}
else
e->next->prev = e->prev;
states.Remove(e->hash);
assert(e->state);
StateInvalidate(e->state);
delete e->hash;
delete e;
}
void DFA_State_Cache::MoveToFront(CacheEntry* e)
{
++hits;
if ( e->prev )
{
e->prev->next = e->next;
if ( e->next )
e->next->prev = e->prev;
else
tail = e->prev;
e->prev = 0;
e->next = head;
head->prev = e;
head = e;
}
}
void DFA_State_Cache::GetStats(Stats* s)
{
s->dfa_states = 0;
@ -490,9 +389,9 @@ void DFA_State_Cache::GetStats(Stats* s)
while ( (e = (CacheEntry*) states.NextEntry(i)) )
{
++s->dfa_states;
s->nfa_states += (*e->state)->NFAStateNum();
(*e->state)->Stats(&s->computed, &s->uncomputed);
s->mem += pad_size((*e->state)->Size()) + padded_sizeof(*e->state);
s->nfa_states += e->state->NFAStateNum();
e->state->Stats(&s->computed, &s->uncomputed);
s->mem += pad_size(e->state->Size()) + padded_sizeof(*e->state);
}
}
@ -514,9 +413,6 @@ DFA_Machine::DFA_Machine(NFA_Machine* n, EquivClass* arg_ec)
{
NFA_state_list* state_set = epsilon_closure(ns);
(void) StateSetToDFA_State(state_set, start_state, ec);
StateRef(start_state);
StateLock(start_state);
}
else
start_state = 0; // Jam
@ -524,12 +420,6 @@ DFA_Machine::DFA_Machine(NFA_Machine* n, EquivClass* arg_ec)
DFA_Machine::~DFA_Machine()
{
if ( start_state )
{
StateUnlock(start_state);
StateUnref(start_state);
}
delete dfa_state_cache;
Unref(nfa);
}
@ -541,8 +431,8 @@ void DFA_Machine::Describe(ODesc* d) const
void DFA_Machine::Dump(FILE* f)
{
(*start_state)->Dump(f, this);
(*start_state)->ClearMarks();
start_state->Dump(f, this);
start_state->ClearMarks();
}
void DFA_Machine::DumpStats(FILE* f)
@ -571,12 +461,11 @@ unsigned int DFA_Machine::MemoryAllocation() const
}
int DFA_Machine::StateSetToDFA_State(NFA_state_list* state_set,
DFA_State_Handle*& d, const EquivClass* ec)
DFA_State*& d, const EquivClass* ec)
{
HashKey* hash;
d = dfa_state_cache->Lookup(*state_set, &hash);
assert((! d) || StateIsValid(d));
if ( d )
return 0;

157
src/DFA.h
View file

@ -8,57 +8,12 @@
#include <assert.h>
// It's possible to use a fixed size cache of computed states for each DFA.
// If the number of DFA states reaches the given limit, old states are expired
// on a least-recently-used basis. This may impact the performance significantly
// if expired states have to be recalculated regularly, but it limits the
// amount of memory taken by a DFA.
//
// Enable by configuring with --with-expire-dfa-states.
class DFA_State;
// The cache marks expired states as invalid.
#define DFA_INVALID_STATE_PTR ((DFA_State*) -1)
// Transitions to the uncomputed state indicate that we haven't yet
// computed the state to go to.
#define DFA_UNCOMPUTED_STATE -2
#define DFA_UNCOMPUTED_STATE_PTR ((DFA_State_Handle*) DFA_UNCOMPUTED_STATE)
#ifdef EXPIRE_DFA_STATES
class DFA_State_Handle {
public:
// The reference counting keeps track of this *handle* (not the state).
void Ref() { assert(state); ++refcount; }
void Unref()
{
if ( --refcount == 0 )
delete this;
}
inline void Invalidate();
bool IsValid() const { return state != DFA_INVALID_STATE_PTR; }
DFA_State* State() const { return state; }
DFA_State* operator->() const { return state; }
protected:
friend class DFA_State_Cache;
DFA_State_Handle(DFA_State* arg_state)
{ state = arg_state; refcount = 1; }
inline ~DFA_State_Handle();
DFA_State* state;
int refcount;
};
#else
typedef DFA_State DFA_State_Handle;
#endif
#define DFA_UNCOMPUTED_STATE_PTR ((DFA_State*) DFA_UNCOMPUTED_STATE)
#include "NFA.h"
@ -76,9 +31,9 @@ public:
int StateNum() const { return state_num; }
int NFAStateNum() const { return nfa_states->length(); }
void AddXtion(int sym, DFA_State_Handle* next_state);
void AddXtion(int sym, DFA_State* next_state);
inline DFA_State_Handle* Xtion(int sym, DFA_Machine* machine);
inline DFA_State* Xtion(int sym, DFA_Machine* machine);
const AcceptingSet* Accept() const { return accept; }
void SymPartition(const EquivClass* ec);
@ -98,43 +53,29 @@ public:
void Stats(unsigned int* computed, unsigned int* uncomputed);
unsigned int Size();
// Locking a state will keep it from expiring from a cache.
void Lock() { ++lock; }
void Unlock() { --lock; }
#ifdef EXPIRE_DFA_STATES
bool IsLocked() { return lock != 0; }
#else
bool IsLocked() { return true; }
DFA_State* operator->(){ return this; }
#endif
protected:
friend class DFA_State_Cache;
DFA_State_Handle* ComputeXtion(int sym, DFA_Machine* machine);
DFA_State* ComputeXtion(int sym, DFA_Machine* machine);
void AppendIfNew(int sym, int_list* sym_list);
int state_num;
int num_sym;
DFA_State_Handle** xtions;
DFA_State** xtions;
AcceptingSet* accept;
NFA_state_list* nfa_states;
EquivClass* meta_ec; // which ec's make same transition
DFA_State* mark;
int lock;
CacheEntry* centry;
static unsigned int transition_counter; // see Xtion()
};
struct CacheEntry {
DFA_State_Handle* state;
DFA_State* state;
HashKey* hash;
CacheEntry* next;
CacheEntry* prev;
};
class DFA_State_Cache {
@ -143,13 +84,11 @@ public:
~DFA_State_Cache();
// If the caller stores the handle, it has to call Ref() on it.
DFA_State_Handle* Lookup(const NFA_state_list& nfa_states,
DFA_State* Lookup(const NFA_state_list& nfa_states,
HashKey** hash);
// Takes ownership of both; hash is the one returned by Lookup().
DFA_State_Handle* Insert(DFA_State* state, HashKey* hash);
void MoveToFront(DFA_State* state) { MoveToFront(state->centry); }
DFA_State* Insert(DFA_State* state, HashKey* hash);
int NumEntries() const { return states.Length(); }
@ -168,9 +107,6 @@ public:
void GetStats(Stats* s);
private:
void Remove(CacheEntry* e);
void MoveToFront(CacheEntry* e);
int maxsize;
int hits; // Statistics
@ -180,10 +116,6 @@ private:
// Hash indexed by NFA states (MD5s of them, actually).
PDict(CacheEntry) states;
// List in LRU order.
CacheEntry* head;
CacheEntry* tail;
};
declare(PList,DFA_State);
@ -196,7 +128,7 @@ public:
int* acc_array);
~DFA_Machine();
DFA_State_Handle* StartState() const { return start_state; }
DFA_State* StartState() const { return start_state; }
int NumStates() const { return dfa_state_cache->NumEntries(); }
@ -217,74 +149,18 @@ protected:
int state_count;
// The state list has to be sorted according to IDs.
int StateSetToDFA_State(NFA_state_list* state_set, DFA_State_Handle*& d,
int StateSetToDFA_State(NFA_state_list* state_set, DFA_State*& d,
const EquivClass* ec);
const EquivClass* EC() const { return ec; }
EquivClass* ec; // equivalence classes corresponding to NFAs
DFA_State_Handle* start_state;
DFA_State* start_state;
DFA_State_Cache* dfa_state_cache;
NFA_Machine* nfa;
};
#ifdef EXPIRE_DFA_STATES
inline DFA_State_Handle* DFA_State::Xtion(int sym, DFA_Machine* machine)
{
Lock();
// This is just a clumsy form of sampling... Instead of moving
// the state to the front of our LRU cache on each transition (which
// would be quite often) we just do it on every nth transition
// (counted across all DFA states). This is based on the observation
// that a very few of all states are used most of time.
// (currently n=10000; should it be configurable?)
if ( transition_counter++ % 10000 == 0 )
machine->Cache()->MoveToFront(this);
DFA_State_Handle* h;
if ( xtions[sym] == DFA_UNCOMPUTED_STATE_PTR ||
(xtions[sym] && ! xtions[sym]->IsValid()) )
h = ComputeXtion(sym, machine);
else
h = xtions[sym];
Unlock();
return h;
}
inline DFA_State_Handle::~DFA_State_Handle()
{
if ( state != DFA_INVALID_STATE_PTR )
delete state;
}
inline void DFA_State_Handle::Invalidate()
{
assert(state!=DFA_INVALID_STATE_PTR);
delete state;
state = DFA_INVALID_STATE_PTR;
Unref();
}
// Not nice but helps avoiding some overhead in the non-expiration case.
static inline void StateLock(DFA_State_Handle* s) { s->State()->Lock(); }
static inline void StateUnlock(DFA_State_Handle* s) { s->State()->Unlock(); }
static inline void StateRef(DFA_State_Handle* s) { s->Ref(); }
static inline void StateUnref(DFA_State_Handle* s) { s->Unref(); }
static inline void StateInvalidate(DFA_State_Handle* s) { s->Invalidate(); }
static inline bool StateIsValid(DFA_State_Handle* s)
{
return ! s || s->IsValid();
}
#else
inline DFA_State_Handle* DFA_State::Xtion(int sym, DFA_Machine* machine)
inline DFA_State* DFA_State::Xtion(int sym, DFA_Machine* machine)
{
if ( xtions[sym] == DFA_UNCOMPUTED_STATE_PTR )
return ComputeXtion(sym, machine);
@ -292,13 +168,4 @@ inline DFA_State_Handle* DFA_State::Xtion(int sym, DFA_Machine* machine)
return xtions[sym];
}
static inline void StateLock(DFA_State_Handle* s) { }
static inline void StateUnlock(DFA_State_Handle* s) { }
static inline void StateRef(DFA_State_Handle* s) { }
static inline void StateUnref(DFA_State_Handle* s) { }
static inline void StateInvalidate(DFA_State_Handle* s) { }
static inline bool StateIsValid(DFA_State_Handle* s) { return true; }
#endif
#endif

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

@ -3383,7 +3383,7 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list,
SetError("values in table(...) constructor do not specify a table");
}
attrs = arg_attrs ? new Attributes(arg_attrs, type) : 0;
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
}
Val* TableConstructorExpr::Eval(Frame* f) const
@ -3449,7 +3449,7 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list,
else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() )
SetError("values in set(...) constructor do not specify a set");
attrs = arg_attrs ? new Attributes(arg_attrs, type) : 0;
attrs = arg_attrs ? new Attributes(arg_attrs, type, false) : 0;
}
Val* SetConstructorExpr::Eval(Frame* f) const

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

@ -509,15 +509,7 @@ void builtin_run_time(const char* msg, BroObj* arg)
#include "bro.bif.func_h"
#include "logging.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 "logging.bif.func_def"
@ -533,15 +525,7 @@ void init_builtin_funcs()
#include "bro.bif.func_init"
#include "logging.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

@ -21,202 +21,14 @@
#include "Hash.h"
// Define *one* of the following as the universal hash function family to use.
// #define USE_DIETZFELBINGER // TwoWise
#define USE_H3
// #define USE_UHASH_CW
// #define USE_UMAC_NH
int hash_cnt_all = 0, hash_cnt_uhash = 0;
#if defined(USE_DIETZFELBINGER)
#include "TwoWise.h"
const TwoWise* two_wise = 0;
#elif defined(USE_H3)
#include "H3.h"
const H3<hash_t, UHASH_KEY_SIZE>* h3;
#elif defined(USE_UHASH_CW)
// The Carter-Wegman family of universal hash functions.
// f(x) = (sum(a_i * x_i) mod p) mod N
// where p is a prime number between N and 2N.
// Here N = 2^32.
class UHashCW {
typedef uint32 word_t;
public:
UHashCW(int arg_max_key_size)
{
max_num_words = (arg_max_key_size + sizeof(word_t) - 1) /
sizeof(word_t);
a = new word_t[max_num_words + 1];
x = new word_t[max_num_words + 1];
for ( int i = 0; i < max_num_words + 1; ++i )
a[i] = rand32bit();
b = rand64bit();
}
~UHashCW()
{
delete [] a;
delete [] x;
}
uint32 hash(int len, const u_char* data) const
{
int xlen = (len + sizeof(word_t) - 1) / sizeof(word_t);
ASSERT(xlen <= max_num_words);
x[xlen] = 0;
x[xlen-1] = 0; // pad with 0
memcpy(static_cast<void *>(x), data, len);
uint64 h = b;
for ( int i = 0; i < xlen; ++i )
h += (static_cast<uint64>(x[i]) * a[i]);
h += static_cast<uint64>(len) * a[xlen];
// h = h % kPrime
//
// Here we use a trick given that h is a Mersenne prime:
//
// Let K = 2^61. Let h = a * K + b.
// Thus, h = a * (K-1) + (a + b).
h = (h & kPrime) + (h >> 61);
if ( h >= kPrime )
h -= kPrime;
// h = h % 2^32
return static_cast<uint32>(0xffffffffUL & h);
}
protected:
static const uint64 kPrime = (static_cast<uint64>(1) << 61) - 1;
int max_num_words;
word_t* a;
uint64 b;
word_t* x;
};
const UHashCW* uhash_cw = 0;
#elif defined(USE_UMAC_NH)
// Use the NH hash function proposed in UMAC.
// (See http://www.cs.ucdavis.edu/~rogaway/umac/)
//
// Essentially, it is computed as:
//
// H = (x_0 +_16 k_0) * (x_1 +_16 k_1) +
// (x_2 +_16 k_2) * (x_3 +_16 k_3) + ...
//
// where {k_i} are keys for universal hashing,
// {x_i} are data words, and +_16 means plus mod 2^16.
//
// This is faster than UHASH_CW because no modulo operation
// is needed. But note that it is 2^-16 universal, while the
// other universal functions are (almost) 2^-32 universal.
//
// Note: UMAC now has a code release under a BSD-like license, and we may want
// to consider using it instead of our home-grown code.
#ifndef DEBUG
#error "UMAC/NH is experimental code."
#endif
class UMacNH {
// NH uses 16-bit words
typedef uint16 word_t;
public:
UMacNH(int arg_max_key_size)
{
max_num_words = (arg_max_key_size + sizeof(word_t) - 1) /
sizeof(word_t);
// Make max_num_words 2n+1
if ( max_num_words % 2 == 0 )
++max_num_words;
a = new word_t[max_num_words + 1];
x = new word_t[max_num_words + 1];
for ( int i = 0; i < max_num_words + 1; ++i )
a[i] = rand16bit();
}
~UMacNH()
{
delete [] a;
delete [] x;
}
uint32 hash(int len, const u_char* data) const
{
int xlen = (len + sizeof(word_t) - 1) / sizeof(word_t);
if ( xlen % 2 == 0 )
++xlen;
ASSERT(xlen <= max_num_words);
x[xlen] = len;
x[xlen-1] = 0; // pad with 0
if ( xlen >= 2 )
x[xlen-2] = 0;
memcpy(static_cast<void *>(x), data, len);
uint32 h = 0;
for ( int i = 0; i <= xlen; i += 2 )
h += (static_cast<uint32>(x[i] + a[i]) *
static_cast<uint32>(x[i+1] + a[i+1]));
return h;
}
protected:
int max_num_words;
word_t* a;
word_t* x;
};
const UMacNH* umac_nh = 0;
#else
#ifdef DEBUG
#error "No universal hash function is used."
#endif
#endif
void init_hash_function()
{
// Make sure we have already called init_random_seed().
ASSERT(hmac_key_set);
// Both Dietzfelbinger and H3 use random() to generate keys
// -- is it strong enough?
#if defined(USE_DIETZFELBINGER)
two_wise = new TwoWise((UHASH_KEY_SIZE + 3) >> 2);
#elif defined(USE_H3)
h3 = new H3<hash_t, UHASH_KEY_SIZE>();
#elif defined(USE_UHASH_CW)
uhash_cw = new UHashCW(UHASH_KEY_SIZE);
#elif defined(USE_UMAC_NH)
umac_nh = new UMacNH(UHASH_KEY_SIZE);
#endif
}
HashKey::HashKey(bro_int_t i)
@ -354,24 +166,11 @@ void* HashKey::CopyKey(const void* k, int s) const
hash_t HashKey::HashBytes(const void* bytes, int size)
{
++hash_cnt_all;
if ( size <= UHASH_KEY_SIZE )
{
const uint8* b = reinterpret_cast<const uint8*>(bytes);
++hash_cnt_uhash;
#if defined(USE_DIETZFELBINGER)
return two_wise->Hash(size, b);
#elif defined(USE_H3)
// H3 doesn't check if size is zero
return ( size == 0 ) ? 0 : (*h3)(bytes, size);
#elif defined(USE_UHASH_CW)
return uhash_cw->hash(size, b);
#elif defined(USE_UMAC_NH)
return umac_nh->hash(size, b);
#else
--hash_cnt_uhash;
#endif
}
// Fall back to HMAC/MD5 for longer data (which is usually rare).

View file

@ -86,7 +86,6 @@ protected:
int size, hash;
};
extern int hash_cnt_all, hash_cnt_uhash;
extern void init_hash_function();
#endif

View file

@ -248,7 +248,7 @@ void ID::UpdateValAttrs()
TypeDecl* fd = rt->FieldDecl(i);
if ( ! fd->attrs )
fd->attrs = new Attributes(new attr_list, rt->FieldType(i));
fd->attrs = new Attributes(new attr_list, rt->FieldType(i), true);
fd->attrs->AddAttr(new Attr(ATTR_LOG));
}

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

@ -211,8 +211,8 @@ int Specific_RE_Matcher::MatchAll(const u_char* bv, int n)
// matched is empty.
return n == 0;
DFA_State_Handle* d = dfa->StartState();
d = (*d)->Xtion(ecs[SYM_BOL], dfa);
DFA_State* d = dfa->StartState();
d = d->Xtion(ecs[SYM_BOL], dfa);
while ( d )
{
@ -220,13 +220,13 @@ int Specific_RE_Matcher::MatchAll(const u_char* bv, int n)
break;
int ec = ecs[*(bv++)];
d = (*d)->Xtion(ec, dfa);
d = d->Xtion(ec, dfa);
}
if ( d )
d = (*d)->Xtion(ecs[SYM_EOL], dfa);
d = d->Xtion(ecs[SYM_EOL], dfa);
return d && (*d)->Accept() != 0;
return d && d->Accept() != 0;
}
@ -236,26 +236,26 @@ int Specific_RE_Matcher::Match(const u_char* bv, int n)
// An empty pattern matches anything.
return 1;
DFA_State_Handle* d = dfa->StartState();
DFA_State* d = dfa->StartState();
d = (*d)->Xtion(ecs[SYM_BOL], dfa);
d = d->Xtion(ecs[SYM_BOL], dfa);
if ( ! d ) return 0;
for ( int i = 0; i < n; ++i )
{
int ec = ecs[bv[i]];
d = (*d)->Xtion(ec, dfa);
d = d->Xtion(ec, dfa);
if ( ! d )
break;
if ( (*d)->Accept() )
if ( d->Accept() )
return i + 1;
}
if ( d )
{
d = (*d)->Xtion(ecs[SYM_EOL], dfa);
if ( d && (*d)->Accept() )
d = d->Xtion(ecs[SYM_EOL], dfa);
if ( d && d->Accept() )
return n > 0 ? n : 1; // we can't return 0 here for match...
}
@ -268,12 +268,6 @@ void Specific_RE_Matcher::Dump(FILE* f)
dfa->Dump(f);
}
RE_Match_State::~RE_Match_State()
{
if ( current_state )
StateUnref(current_state);
}
bool RE_Match_State::Match(const u_char* bv, int n,
bool bol, bool eol, bool clear)
{
@ -289,9 +283,8 @@ bool RE_Match_State::Match(const u_char* bv, int n,
// Initialize state and copy the accepting states of the start
// state into the acceptance set.
current_state = dfa->StartState();
StateRef(current_state);
const AcceptingSet* ac = (*current_state)->Accept();
const AcceptingSet* ac = current_state->Accept();
if ( ac )
{
loop_over_list(*ac, i)
@ -303,20 +296,11 @@ bool RE_Match_State::Match(const u_char* bv, int n,
}
else if ( clear )
{
if ( current_state )
StateUnref(current_state);
current_state = dfa->StartState();
StateRef(current_state);
}
if ( ! current_state )
return false;
else
(*current_state)->Unlock();
current_pos = 0;
int old_matches = accepted.length();
@ -334,7 +318,7 @@ bool RE_Match_State::Match(const u_char* bv, int n,
else
ec = ecs[*(bv++)];
DFA_State_Handle* next_state = (*current_state)->Xtion(ec,dfa);
DFA_State* next_state = current_state->Xtion(ec,dfa);
if ( ! next_state )
{
@ -342,9 +326,9 @@ bool RE_Match_State::Match(const u_char* bv, int n,
break;
}
if ( (*next_state)->Accept() )
if ( next_state->Accept() )
{
const AcceptingSet* ac = (*next_state)->Accept();
const AcceptingSet* ac = next_state->Accept();
loop_over_list(*ac, i)
{
if ( ! accepted.is_member((*ac)[i]) )
@ -357,15 +341,9 @@ bool RE_Match_State::Match(const u_char* bv, int n,
++current_pos;
StateRef(next_state);
StateUnref(current_state);
current_state = next_state;
}
// Make sure our state doesn't expire until we return.
if ( current_state )
(*current_state)->Lock();
return accepted.length() != old_matches;
}
@ -377,31 +355,31 @@ int Specific_RE_Matcher::LongestMatch(const u_char* bv, int n)
// Use -1 to indicate no match.
int last_accept = -1;
DFA_State_Handle* d = dfa->StartState();
DFA_State* d = dfa->StartState();
d = (*d)->Xtion(ecs[SYM_BOL], dfa);
d = d->Xtion(ecs[SYM_BOL], dfa);
if ( ! d )
return -1;
if ( (*d)->Accept() )
if ( d->Accept() )
last_accept = 0;
for ( int i = 0; i < n; ++i )
{
int ec = ecs[bv[i]];
d = (*d)->Xtion(ec, dfa);
d = d->Xtion(ec, dfa);
if ( ! d )
break;
if ( (*d)->Accept() )
if ( d->Accept() )
last_accept = i + 1;
}
if ( d )
{
d = (*d)->Xtion(ecs[SYM_EOL], dfa);
if ( d && (*d)->Accept() )
d = d->Xtion(ecs[SYM_EOL], dfa);
if ( d && d->Accept() )
return n;
}

View file

@ -19,6 +19,7 @@ class NFA_Machine;
class DFA_Machine;
class Specific_RE_Matcher;
class RE_Matcher;
class DFA_State;
declare(PDict,char);
declare(PDict,CCL);
@ -126,13 +127,6 @@ protected:
AcceptingSet* accepted;
};
#ifdef EXPIRE_DFA_STATES
class DFA_State_Handle;
#else
class DFA_State;
typedef DFA_State DFA_State_Handle;
#endif
class RE_Match_State {
public:
RE_Match_State(Specific_RE_Matcher* matcher)
@ -143,8 +137,6 @@ public:
current_state = 0;
}
~RE_Match_State();
const AcceptingSet* Accepted() const { return &accepted; }
const int_list* MatchPositions() const { return &match_pos; }
@ -169,7 +161,7 @@ protected:
AcceptingSet accepted;
int_list match_pos;
DFA_State_Handle* current_state;
DFA_State* current_state;
int current_pos;
};

View file

@ -48,15 +48,8 @@ Reassembler::Reassembler(int init_seq, const uint32* ip_addr,
{
blocks = last_block = 0;
trim_seq = last_reassem_seq = init_seq;
const NumericData* host_profile;
get_map_result(ip_addr[0], host_profile); // breaks for IPv6
policy = (arg_type == REASSEM_TCP) ?
host_profile->tcp_reassem : host_profile->ip_reassem;
}
Reassembler::~Reassembler()
{
ClearBlocks();
@ -243,67 +236,7 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper,
return new_b;
}
// The blocks overlap.
#ifdef ACTIVE_MAPPING
if ( policy != RP_UNKNOWN )
{
if ( seq_delta(seq, b->seq) < 0 )
{ // The new block has a prefix that comes before b.
int prefix_len = seq_delta(b->seq, seq);
new_b = new DataBlock(data, prefix_len, seq, b->prev, b);
if ( b == blocks )
blocks = new_b;
data += prefix_len;
seq += prefix_len;
}
if ( policy == RP_LAST ||
// After handling the prefix block, BSD takes the rest
(policy == RP_BSD && new_b) ||
// Similar, but overwrite for same seq number
(policy == RP_LINUX && (new_b || seq == b->seq)) )
{
DataBlock* bprev = b->prev;
bool b_was_first = b == blocks;
while ( b && b->upper <= upper )
{
DataBlock* next = b->next;
delete b;
b = next;
}
new_b = new DataBlock(data, upper - seq, seq, bprev, b);
if ( b_was_first )
blocks = new_b;
// Trim the next block as needed.
if ( b && seq_delta(new_b->upper, b->seq) > 0 )
{
DataBlock* next_b =
new DataBlock(&b->block[upper - b->seq],
b->upper - upper, upper,
new_b, b->next);
if ( b == last_block )
last_block = next_b;
delete b;
}
}
else
{ // handle the piece that sticks out past b
new_b = b;
int len = upper - b->upper;
if ( len > 0 )
new_b = AddAndCheck(b, b->upper, upper, &data[b->upper - seq]);
}
}
else
{
#endif
// Default behavior - complain about overlaps.
// The blocks overlap, complain.
if ( seq_delta(seq, b->seq) < 0 )
{
// The new block has a prefix that comes before b.
@ -338,10 +271,6 @@ DataBlock* Reassembler::AddAndCheck(DataBlock* b, int seq, int upper,
(void) AddAndCheck(b, seq, upper, data);
}
#ifdef ACTIVE_MAPPING
} // else branch, for RP_UNKNOWN behavior
#endif
if ( new_b->prev == last_block )
last_block = new_b;
@ -365,7 +294,7 @@ bool Reassembler::DoSerialize(SerialInfo* info) const
// I'm not sure if it makes sense to actually save the buffered data.
// For now, we just remember the seq numbers so that we don't get
// complaints about missing content.
return SERIALIZE(trim_seq) && SERIALIZE(int(policy));
return SERIALIZE(trim_seq) && SERIALIZE(int(0));
}
bool Reassembler::DoUnserialize(UnserialInfo* info)
@ -374,11 +303,10 @@ bool Reassembler::DoUnserialize(UnserialInfo* info)
blocks = last_block = 0;
int p;
if ( ! UNSERIALIZE(&trim_seq) || ! UNSERIALIZE(&p) )
int dummy; // For backwards compatibility.
if ( ! UNSERIALIZE(&trim_seq) || ! UNSERIALIZE(&dummy) )
return false;
policy = ReassemblyPolicy(p);
last_reassem_seq = trim_seq;
return true;

View file

@ -5,7 +5,6 @@
#ifndef reassem_h
#define reassem_h
#include "Active.h"
#include "Obj.h"
class DataBlock {
@ -74,8 +73,6 @@ protected:
int last_reassem_seq;
int trim_seq; // how far we've trimmed
ReassemblyPolicy policy;
static unsigned int total_size;
};

View file

@ -3050,7 +3050,7 @@ void RemoteSerializer::InternalCommError(const char* msg)
#ifdef DEBUG_COMMUNICATION
DumpDebugData();
#else
internal_error(msg);
internal_error("%s", msg);
#endif
}
@ -3596,8 +3596,7 @@ bool SocketComm::ProcessConnectTo()
peer->retry = ntohl(args[3]);
peer->ssl = ntohl(args[4]);
Connect(peer);
return true;
return Connect(peer);
}
bool SocketComm::ProcessListen()
@ -3838,7 +3837,7 @@ bool SocketComm::Connect(Peer* peer)
if ( ! peer->io->Init() )
{
Error(fmt("can't init peer io: %s",
peer->io->Error()), peer);
peer->io->Error()), false);
return 0;
}
}
@ -3918,6 +3917,7 @@ bool SocketComm::Listen(uint32 ip, uint16 port, bool expect_ssl)
if ( bind(*listen_fd, (sockaddr*) &server, sizeof(server)) < 0 )
{
Error(fmt("can't bind to port %d, %s", port, strerror(errno)));
close(*listen_fd);
*listen_fd = -1;
if ( errno == EADDRINUSE )
@ -3972,7 +3972,7 @@ bool SocketComm::AcceptConnection(int fd)
if ( ! peer->io->Init() )
{
Error(fmt("can't init peer io: %s",
peer->io->Error()), peer);
peer->io->Error()), false);
return false;
}

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

@ -15,7 +15,6 @@
#include "Timer.h"
#include "NetVar.h"
#include "Sessions.h"
#include "Active.h"
#include "OSFinger.h"
#include "ICMP.h"
@ -465,37 +464,9 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
return;
}
// Check for TTL/MTU problems from Active Mapping
#ifdef ACTIVE_MAPPING
const NumericData* numeric = 0;
if ( ip4 )
{
get_map_result(ip4->ip_dst.s_addr, numeric);
if ( numeric->hops && ip4->ip_ttl < numeric->hops )
{
debug_msg("Packet destined for %s had ttl %d but there are %d hops to host.\n",
inet_ntoa(ip4->ip_dst), ip4->ip_ttl, numeric->hops);
return;
}
}
#endif
FragReassembler* f = 0;
uint32 frag_field = ip_hdr->FragField();
#ifdef ACTIVE_MAPPING
if ( ip4 && numeric && numeric->path_MTU && (frag_field & IP_DF) )
{
if ( htons(ip4->ip_len) > numeric->path_MTU )
{
debug_msg("Packet destined for %s has DF flag but its size %d is greater than pmtu of %d\n",
inet_ntoa(ip4->ip_dst), htons(ip4->ip_len), numeric->path_MTU);
return;
}
}
#endif
if ( (frag_field & 0x3fff) != 0 )
{
dump_this_packet = 1; // always record fragments
@ -661,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.
@ -675,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
@ -1354,7 +1318,7 @@ void NetSessions::Internal(const char* msg, const struct pcap_pkthdr* hdr,
const u_char* pkt)
{
DumpPacket(hdr, pkt);
internal_error(msg);
internal_error("%s", msg);
}
void NetSessions::Weird(const char* name,

View file

@ -935,7 +935,7 @@ void NotifierRegistry::Register(ID* id, NotifierRegistry::Notifier* notifier)
attr_list* a = new attr_list;
Attr* attr = new Attr(ATTR_TRACKED);
a->append(attr);
id->SetAttrs(new Attributes(a, id->Type()));
id->SetAttrs(new Attributes(a, id->Type(), false));
Unref(attr);
}

View file

@ -3,12 +3,10 @@
// See the file "COPYING" in the main distribution directory for copyright.
#include "Active.h"
#include "PIA.h"
#include "File.h"
#include "TCP.h"
#include "TCP_Reassembler.h"
#include "TCP_Rewriter.h"
#include "OSFinger.h"
#include "Event.h"
@ -48,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()
@ -74,7 +61,6 @@ TCP_Analyzer::~TCP_Analyzer()
delete orig;
delete resp;
delete src_pkt_writer;
}
void TCP_Analyzer::Init()
@ -82,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()
@ -412,49 +392,6 @@ bool TCP_Analyzer::ProcessRST(double t, TCP_Endpoint* endpoint,
else if ( endpoint->RST_cnt == 0 )
++endpoint->RST_cnt; // Remember we've seen a RST
#ifdef ACTIVE_MAPPING
// if ( peer->state == TCP_ENDPOINT_INACTIVE )
// debug_msg("rst while inactive\n"); // ### Cold-start: what to do?
// else
const NumericData* AM_policy;
get_map_result(ip->DstAddr4(), AM_policy);
if ( base_seq == endpoint->AckSeq() )
; // everyone should accept a RST in sequence
else if ( endpoint->window == 0 )
; // ### Cold Start: we don't know the window,
// so just go along for now
else
{
uint32 right_edge = endpoint->AckSeq() +
(endpoint->window << endpoint->window_scale);
if ( base_seq < right_edge )
{
if ( ! AM_policy->accepts_rst_in_window )
{
#if 0
debug_msg("Machine does not accept RST merely in window; ignoring. t=%.6f,base=%u, ackseq=%u, window=%hd \n",
network_time, base_seq, endpoint->AckSeq(), window);
#endif
return false;
}
}
else if ( ! AM_policy->accepts_rst_outside_window )
{
#if 0
debug_msg("Machine does not accept RST outside window; ignoring. t=%.6f,base=%u, ackseq=%u, window=%hd \n",
network_time, base_seq, endpoint->AckSeq(), window);
#endif
return false;
}
}
#endif
if ( len > 0 )
{
// This now happens often enough that it's
@ -1091,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",
@ -1801,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()) )
@ -1820,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());
@ -1955,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

@ -1,59 +0,0 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
// $Id: TwoWise.cc 1386 2005-09-14 21:42:13Z vern $
//
// Implementation of 2-wise independent hash functions. Contributed
// by Yin Zhang.
//
#include <stdlib.h>
#include "TwoWise.h"
TwoWise::TwoWise(int arg_dim)
{
dim = arg_dim;
int n = dim > 2 ? dim : 2;
a = new uint64[n];
b = new uint64[n];
c = new uint32[n];
for ( int i = 0; i < n; ++i )
{
a[i] = rand64bit() & ~(1ULL);
b[i] = rand64bit() & ~(1ULL);
c[i] = 0;
}
a0 = a[0];
b0 = b[0];
a1 = a[1];
b1 = b[1];
}
TwoWise::~TwoWise()
{
delete[] a;
delete[] b;
delete[] c;
}
void TwoWise::TestSpeed(uint32 N)
{
uint32 x = 0, i;
double start_time = current_time();
for ( i = 0; i < N; ++i )
x ^= Hash(i);
double end_time = current_time();
double time0 = end_time - start_time;
start_time = current_time();
for ( i = 0; i < N; ++i )
x ^= Hash(i, i);
end_time = current_time();
double time1 = end_time - start_time;
fprintf(stderr, "time0=%.6f time1=%.6f x=%u\n",
time0, time1, x);
}

View file

@ -1,92 +0,0 @@
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
// $Id: TwoWise.h 2809 2006-04-23 20:26:07Z vern $
//
// Implementation of 2-wise independent hash functions. Contributed
// by Yin Zhang.
//
#ifndef twowise_h
#define twowise_h
#include "util.h"
typedef union {
uint64 as_int64;
uint32 as_int32s[2];
uint32 as_int16s[4];
} int64views;
#ifdef WORDS_BIGENDIAN
#define TOP32BITS(h) h.as_int32s[0]
#else
#define TOP32BITS(h) h.as_int32s[1]
#endif
typedef union {
uint32 as_int32;
uint16 as_int16s[2];
uint16 as_int8s[4];
} int32views;
class TwoWise {
public:
TwoWise(int dim = 0);
~TwoWise();
uint32 Hash(uint32 k) const
{
int64views h;
h.as_int64 = a0*k + b0;
return TOP32BITS(h);
}
uint32 Hash(uint32 k0, uint32 k1) const
{
int64views h;
h.as_int64 = (a0*k0+b0) ^ (a1*k1+b1);
return TOP32BITS(h);
}
uint32 Hash(const uint32* k) const
{
int64views h;
h.as_int64 = (a0*k[0]+b0);
for ( int i = 1; i < dim; ++i )
h.as_int64 ^= (a[i]*k[i] + b[i]);
return TOP32BITS(h);
}
uint32 Hash(int size, const uint8* data) const
{
if ( size == 0 )
return 0;
// Copy data to c to resolve any potential alignment problem.
int num_words = (size + 3) >> 2;
c[num_words - 1] = 0; // pad with 0
memcpy(c, data, size);
int64views h;
h.as_int64 = (a0*c[0]+b0);
for ( int i = 1; i < num_words; ++i )
h.as_int64 ^= (a[i]*c[i] + b[i]);
return TOP32BITS(h);
}
void TestSpeed(uint32 N = 1000000);
private:
// Coefficients in Dietzfelbinger scheme.
uint64 a0, b0, a1, b1; // for 1-d and 2-d case
uint64 *a, *b; // for N-d case
uint32 *c;
int dim;
};
#endif // twowise_h

View file

@ -682,10 +682,10 @@ bool FuncType::DoUnserialize(UnserialInfo* info)
return UNSERIALIZE(&is_event);
}
TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs)
TypeDecl::TypeDecl(BroType* t, const char* i, attr_list* arg_attrs, bool in_record)
{
type = t;
attrs = arg_attrs ? new Attributes(arg_attrs, t) : 0;
attrs = arg_attrs ? new Attributes(arg_attrs, t, in_record) : 0;
id = i;
}
@ -925,7 +925,7 @@ const char* RecordType::AddFields(type_decl_list* others, attr_list* attr)
if ( log )
{
if ( ! td->attrs )
td->attrs = new Attributes(new attr_list, td->type);
td->attrs = new Attributes(new attr_list, td->type, true);
td->attrs->AddAttr(new Attr(ATTR_LOG));
}

View file

@ -389,7 +389,7 @@ protected:
class TypeDecl {
public:
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0);
TypeDecl(BroType* t, const char* i, attr_list* attrs = 0, bool in_record = false);
~TypeDecl();
const Attr* FindAttr(attr_tag a) const

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

@ -107,7 +107,7 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
id->SetType(t);
if ( attr )
id->AddAttrs(new Attributes(attr, t));
id->AddAttrs(new Attributes(attr, t, false));
if ( id->FindAttr(ATTR_PERSISTENT) || id->FindAttr(ATTR_SYNCHRONIZED) )
{
@ -231,7 +231,7 @@ void add_type(ID* id, BroType* t, attr_list* attr, int /* is_event */)
id->MakeType();
if ( attr )
id->SetAttrs(new Attributes(attr, t));
id->SetAttrs(new Attributes(attr, t, false));
}
void begin_func(ID* id, const char* module_name, function_flavor flavor,

View file

@ -1605,21 +1605,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

@ -23,7 +23,6 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void);
#include "bsd-getopt-long.h"
#include "input.h"
#include "Active.h"
#include "ScriptAnaly.h"
#include "DNS_Mgr.h"
#include "Frame.h"
@ -138,9 +137,6 @@ void usage()
fprintf(stderr, "bro version %s\n", bro_version());
fprintf(stderr, "usage: %s [options] [file ...]\n", prog);
fprintf(stderr, " <file> | policy file, or read stdin\n");
#ifdef ACTIVE_MAPPING
fprintf(stderr, " -a|--active-mapping <mapfile> | use active mapping results\n");
#endif
fprintf(stderr, " -d|--debug-policy | activate policy file debugging\n");
fprintf(stderr, " -e|--exec <bro code> | augment loaded policies by given code\n");
fprintf(stderr, " -f|--filter <filter> | tcpdump filter\n");
@ -158,7 +154,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
@ -347,7 +342,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;
@ -379,7 +373,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'},
@ -397,9 +390,6 @@ int main(int argc, char** argv)
{"print-id", required_argument, 0, 'I'},
{"status-file", required_argument, 0, 'U'},
#ifdef ACTIVE_MAPPING
{"active-mapping", no_argument, 0, 'a'},
#endif
#ifdef DEBUG
{"debug", required_argument, 0, 'B'},
#endif
@ -445,7 +435,7 @@ int main(int argc, char** argv)
opterr = 0;
char opts[256];
safe_strncpy(opts, "A: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
@ -455,16 +445,6 @@ int main(int argc, char** argv)
int op;
while ( (op = getopt_long(argc, argv, opts, long_opts, &long_optsind)) != EOF )
switch ( op ) {
case 'a':
#ifdef ACTIVE_MAPPING
fprintf(stderr, "Using active mapping file %s.\n", optarg);
active_file = optarg;
#else
fprintf(stderr, "Bro not compiled for active mapping.\n");
exit(1);
#endif
break;
case 'd':
fprintf(stderr, "Policy file debugging ON.\n");
g_policy_debug = true;
@ -525,10 +505,6 @@ int main(int argc, char** argv)
}
break;
case 'A':
transformed_writefile = optarg;
break;
case 'C':
override_ignore_checksums = 1;
break;
@ -713,13 +689,6 @@ int main(int argc, char** argv)
add_input_file(argv[optind++]);
}
if ( ! load_mapping_table(active_file.c_str()) )
{
fprintf(stderr, "Could not load active mapping file %s\n",
active_file.c_str());
exit(1);
}
dns_mgr = new DNS_Mgr(dns_type);
// It would nice if this were configurable. This is similar to the
@ -824,7 +793,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);

Some files were not shown because too many files have changed in this diff Show more