diff --git a/.gitmodules b/.gitmodules index 326e1fe506..12e758c23a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/CHANGES b/CHANGES index bfa5ab77f7..97facfe719 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,54 @@ +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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 65e1bc5983..11b8454d84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/INSTALL b/INSTALL index 1220d720ad..f0c59d79fb 100644 --- a/INSTALL +++ b/INSTALL @@ -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 diff --git a/VERSION b/VERSION index 6cbd1b507c..27bddc1266 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6-dev.53 +1.6-dev.71 diff --git a/aux/binpac b/aux/binpac index 26d02716f9..106cd9782f 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit 26d02716f9090651f319a4bfdf8ede49b3a7b53a +Subproject commit 106cd9782f1f9443743b49adccae26f0ee72621c diff --git a/aux/bro-aux b/aux/bro-aux index 7e50bac938..3ec53f69fd 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit 7e50bac938af1831ecf9660159145a3c2e77e13d +Subproject commit 3ec53f69fd45d8e2c0950dc0e7af117bb3e02c0d diff --git a/aux/broccoli b/aux/broccoli index 9332ab3467..d693ba5f14 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 9332ab3467191ac22be09d6941ebd469e7a334d0 +Subproject commit d693ba5f14c33a97e4f149e49196281cc075d289 diff --git a/aux/broctl b/aux/broctl index 06b74a0f23..b26dc6dc6a 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit 06b74a0f23767c8345ed146657120aba812f6764 +Subproject commit b26dc6dc6a9080abe7a062d0882e813acbb63248 diff --git a/aux/btest b/aux/btest index a2b04952ae..409bda3a00 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit a2b04952ae91dcd27d5e68a42d5d26c291ecb1f5 +Subproject commit 409bda3a003b18c4736ef168595f20118f4d0038 diff --git a/cmake/InstallClobberImmune.cmake b/cmake/InstallClobberImmune.cmake new file mode 100644 index 0000000000..77da312ef2 --- /dev/null +++ b/cmake/InstallClobberImmune.cmake @@ -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) diff --git a/cmake/InstallPackageConfigFile.cmake b/cmake/InstallPackageConfigFile.cmake new file mode 100644 index 0000000000..65a1724ea4 --- /dev/null +++ b/cmake/InstallPackageConfigFile.cmake @@ -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) diff --git a/cmake/package_postupgrade.sh.in b/cmake/package_postupgrade.sh.in index 7ae35185f6..0ef78413c3 100755 --- a/cmake/package_postupgrade.sh.in +++ b/cmake/package_postupgrade.sh.in @@ -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 diff --git a/cmake/package_preinstall.sh.in b/cmake/package_preinstall.sh.in index 790e750f0e..749b01fdfc 100755 --- a/cmake/package_preinstall.sh.in +++ b/cmake/package_preinstall.sh.in @@ -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 diff --git a/configure b/configure index f1d864640d..864e3e4803 100755 --- a/configure +++ b/configure @@ -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 ;; diff --git a/make-mac-packages b/make-mac-packages index 713d8d3311..c3b6736d20 100755 --- a/make-mac-packages +++ b/make-mac-packages @@ -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 ../.. diff --git a/make-rpm-packages b/make-rpm-packages index bbd797b8e2..503d80ef4e 100755 --- a/make-rpm-packages +++ b/make-rpm-packages @@ -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 ../.. diff --git a/policy/all.bro b/policy/all.bro index 4bbe3e8afe..637e0a3391 100644 --- a/policy/all.bro +++ b/policy/all.bro @@ -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 diff --git a/policy/bro.init b/policy/bro.init index e25038e1e7..ba180e5045 100644 --- a/policy/bro.init +++ b/policy/bro.init @@ -1117,14 +1117,6 @@ type bt_tracker_headers: table[string] of string; @load event.bif.bro -@load common-rw.bif.bro -@load finger-rw.bif.bro -@load ftp-rw.bif.bro -@load ident-rw.bif.bro -@load smtp-rw.bif.bro -@load http-rw.bif.bro -@load dns-rw.bif.bro - function subst(s: string, from: pattern, to: string): string { local p = split_all(s, from); @@ -1404,34 +1396,3 @@ const skip_http_data = F &redef; # Whether the analysis engine parses IP packets encapsulated in # UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro. const parse_udp_tunnels = F &redef; - -# Whether a commitment is required before writing the transformed -# trace for a connection into the dump file. -const requires_trace_commitment = F &redef; - -# Whether IP address anonymization is enabled. -const anonymize_ip_addr = F &redef; - -# Whether to omit place holder packets when rewriting. -const omit_rewrite_place_holder = T &redef; - -# Whether trace of various protocols is being rewritten. -const rewriting_http_trace = F &redef; -const rewriting_smtp_trace = F &redef; -const rewriting_ftp_trace = F &redef; -const rewriting_ident_trace = F &redef; -const rewriting_finger_trace = F &redef; -const rewriting_dns_trace = F &redef; -const rewriting_smb_trace = F &redef; - -# Whether we dump selected original packets to the output trace. -const dump_selected_source_packets = F &redef; - -# If true, we dump original packets to the output trace *if and only if* -# the connection is not rewritten; if false, the policy script can decide -# whether to dump a particular connection by calling dump_packets_of_connection. -# -# NOTE: DO NOT SET THIS TO TRUE WHEN ANONYMIZING A TRACE! -# (TODO: this variable should be disabled when using '-A' option) -const dump_original_packets_if_not_rewriting = F &redef; - diff --git a/policy/dns-anonymizer.bro b/policy/dns-anonymizer.bro deleted file mode 100644 index d85f31a395..0000000000 --- a/policy/dns-anonymizer.bro +++ /dev/null @@ -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); - } diff --git a/policy/finger.bro b/policy/finger.bro index 8cf1dbba65..7765ce45c6 100644 --- a/policy/finger.bro +++ b/policy/finger.bro @@ -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); - } diff --git a/policy/ftp-anonymizer.bro b/policy/ftp-anonymizer.bro deleted file mode 100644 index 560b85119b..0000000000 --- a/policy/ftp-anonymizer.bro +++ /dev/null @@ -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 = "-