From fe5f4b8e5333766fc76119d96e779960b84e954b Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Thu, 30 Jun 2011 11:37:15 -0500 Subject: [PATCH] Changes to make generated script docs understand new policy/ hierarchy. Added an arg to the search_for_files() util function that can return the subpath of BROPATH's policy/ dir in which the loaded file is found. This subpath is then used in both the the reST file's document title (so that script's named e.g. "base.bro" actually have some context) and in figuring out how to interlink with other generated docs of other scripts that are found in @load directives. I still need to overhaul things so the loading of "packages" is documented in a meaningful way and that the CMake targets are able to generate indexes for packages. --- doc/scripts/CMakeLists.txt | 196 +++++++++--------- doc/scripts/source/index.rst | 1 - doc/scripts/source/user.rst | 5 - src/BroDoc.cc | 98 +++++---- src/BroDoc.h | 8 +- src/Debug.cc | 2 +- src/OSFinger.cc | 2 +- src/RuleMatcher.cc | 2 +- src/scan.l | 10 +- src/util.cc | 81 +++++++- src/util.h | 3 +- .../doc.autogen-reST-example/example.rst | 2 +- 12 files changed, 262 insertions(+), 148 deletions(-) delete mode 100644 doc/scripts/source/user.rst diff --git a/doc/scripts/CMakeLists.txt b/doc/scripts/CMakeLists.txt index 3523806f4f..d01360f503 100644 --- a/doc/scripts/CMakeLists.txt +++ b/doc/scripts/CMakeLists.txt @@ -94,7 +94,7 @@ macro(REST_TARGET srcDir broInput) set(group "") endif () - if (${group} STREQUAL "default" OR ${group} STREQUAL "bifs") + if ("${group}" STREQUAL "default" OR "${group}" STREQUAL "bifs") set(BRO_ARGS --doc-scripts --exec '') else () set(BRO_ARGS --doc-scripts ${broInput}) @@ -127,117 +127,127 @@ macro(REST_TARGET srcDir broInput) endmacro(REST_TARGET) # Schedule Bro scripts for which to generate documentation. -# Note: the script may be located in a subdirectory off of one of the main -# directories in BROPATH. In that case, just list the script as 'foo/bar.bro' -rest_target(${CMAKE_CURRENT_SOURCE_DIR} example.bro internal) +# +# Note: any path prefix of the script (2nd argument of rest_target macro) +# will be used to derive what path under policy/ the generated documentation +# will be placed. -rest_target(${POLICY_SRC_DIR} conn.bro user) -rest_target(${POLICY_SRC_DIR} conn/base.bro user) -rest_target(${POLICY_SRC_DIR} conn/contents.bro user) +rest_target(${CMAKE_CURRENT_SOURCE_DIR} example.bro) -rest_target(${POLICY_SRC_DIR} dns.bro policy/dns-index) -rest_target(${POLICY_SRC_DIR} dns/auth-addl.bro policy/dns-index) -rest_target(${POLICY_SRC_DIR} dns/base.bro policy/dns-index) -rest_target(${POLICY_SRC_DIR} dns/consts.bro policy/dns-index) -rest_target(${POLICY_SRC_DIR} dns/detect.bro policy/dns-index) -rest_target(${POLICY_SRC_DIR} dns/passive-replication.bro policy/dns-index) +rest_target(${CMAKE_BINARY_DIR}/src bro.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src const.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src event.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src logging.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src strings.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src types.bif.bro) -# TODO: these don't currently work due to something that looks like a -# circular dependency. They'll also change to the 'default' group once -# loaded from bro.init. -#rest_target(${POLICY_SRC_DIR} dpd.bro policy/dpd-index) -#rest_target(${POLICY_SRC_DIR} dpd/base.bro policy/dpd-index) -#rest_target(${POLICY_SRC_DIR} dpd/dyn-disable.bro policy/dpd-index) -#rest_target(${POLICY_SRC_DIR} dpd/packet-segment-logging.bro policy/dpd-index) +set(psd ${POLICY_SRC_DIR}) -rest_target(${POLICY_SRC_DIR} ftp.bro policy/ftp-index) -rest_target(${POLICY_SRC_DIR} ftp/base.bro policy/ftp-index) -rest_target(${POLICY_SRC_DIR} ftp/detect.bro policy/ftp-index) -rest_target(${POLICY_SRC_DIR} ftp/file-extract.bro policy/ftp-index) -rest_target(${POLICY_SRC_DIR} ftp/software.bro policy/ftp-index) -rest_target(${POLICY_SRC_DIR} ftp/utils-commands.bro policy/ftp-index) +rest_target(${psd} bro.init) +rest_target(${psd} site.bro) -rest_target(${POLICY_SRC_DIR} functions.bro user) +rest_target(${psd} detectors/http-MHR.bro) -# TODO: hot.conn.bro currently won't load because hot.bro doesn't exist -#rest_target(${POLICY_SRC_DIR} hot.conn.bro user) +rest_target(${psd} frameworks/communication/base.bro) +rest_target(${psd} frameworks/communication/listen-clear.bro) +rest_target(${psd} frameworks/communication/listen-ssl.bro) -rest_target(${POLICY_SRC_DIR} http.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/base-extended.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/base.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/detect-intel.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/detect-sqli.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/detect-webapps.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/file-extract.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/file-hash.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/file-ident.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/headers.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/software.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/utils.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/var-extraction-cookies.bro policy/http-index) -rest_target(${POLICY_SRC_DIR} http/var-extraction-uri.bro policy/http-index) +rest_target(${psd} frameworks/dpd/base.bro) +rest_target(${psd} frameworks/dpd/dyn-disable.bro) +rest_target(${psd} frameworks/dpd/packet-segment-logging.bro) -rest_target(${POLICY_SRC_DIR} irc.bro policy/irc-index) -rest_target(${POLICY_SRC_DIR} irc/base.bro policy/irc-index) -rest_target(${POLICY_SRC_DIR} irc/dcc-send.bro policy/irc-index) +rest_target(${psd} frameworks/intel/base.bro) -rest_target(${POLICY_SRC_DIR} known-services.bro user) -rest_target(${POLICY_SRC_DIR} known-hosts.bro user) +rest_target(${psd} frameworks/logging/base.bro) +rest_target(${psd} frameworks/logging/plugins/ascii.bro) -rest_target(${POLICY_SRC_DIR} metrics.bro policy/metrics-index) -rest_target(${POLICY_SRC_DIR} metrics/base.bro policy/metrics-index) -rest_target(${POLICY_SRC_DIR} metrics/conn-example.bro policy/metrics-index) -rest_target(${POLICY_SRC_DIR} metrics/http-example.bro policy/metrics-index) +rest_target(${psd} frameworks/metrics/base.bro) +rest_target(${psd} frameworks/metrics/conn-example.bro) +rest_target(${psd} frameworks/metrics/http-example.bro) -rest_target(${POLICY_SRC_DIR} mime.bro policy/mime-index) -rest_target(${POLICY_SRC_DIR} mime/base.bro policy/mime-index) -rest_target(${POLICY_SRC_DIR} mime/file-extract.bro policy/mime-index) -rest_target(${POLICY_SRC_DIR} mime/file-hash.bro policy/mime-index) -rest_target(${POLICY_SRC_DIR} mime/file-ident.bro policy/mime-index) +rest_target(${psd} frameworks/notice/action-filters.bro) +rest_target(${psd} frameworks/notice/base.bro) +rest_target(${psd} frameworks/notice/weird.bro) -rest_target(${POLICY_SRC_DIR} notice-action-filters.bro user) -rest_target(${POLICY_SRC_DIR} notice.bro user) -rest_target(${POLICY_SRC_DIR} site.bro user) +rest_target(${psd} frameworks/packet-filter/base.bro) +rest_target(${psd} frameworks/packet-filter/netstats.bro) -rest_target(${POLICY_SRC_DIR} signatures.bro policy/sig-index) -rest_target(${POLICY_SRC_DIR} signatures/base.bro policy/sig-index) +rest_target(${psd} frameworks/signatures/base.bro) -rest_target(${POLICY_SRC_DIR} smtp.bro policy/smtp-index) -rest_target(${POLICY_SRC_DIR} smtp/base-extended.bro policy/smtp-index) -rest_target(${POLICY_SRC_DIR} smtp/base.bro policy/smtp-index) -rest_target(${POLICY_SRC_DIR} smtp/detect.bro policy/smtp-index) -rest_target(${POLICY_SRC_DIR} smtp/software.bro policy/smtp-index) -rest_target(${POLICY_SRC_DIR} smtp/utils.bro policy/smtp-index) -rest_target(${POLICY_SRC_DIR} smtp/webmail-ident.bro policy/smtp-index) +rest_target(${psd} frameworks/software/base.bro) +rest_target(${psd} frameworks/software/vulnerable.bro) -rest_target(${POLICY_SRC_DIR} software.bro policy/software-index) -rest_target(${POLICY_SRC_DIR} software/base.bro policy/software-index) -rest_target(${POLICY_SRC_DIR} software/vulnerable.bro policy/software-index) +rest_target(${psd} integration/barnyard2/base.bro) +rest_target(${psd} integration/barnyard2/event.bro) +rest_target(${psd} integration/barnyard2/types.bro) -rest_target(${POLICY_SRC_DIR} ssh.bro policy/ssh-index) -rest_target(${POLICY_SRC_DIR} ssh/base.bro policy/ssh-index) -rest_target(${POLICY_SRC_DIR} ssh/software.bro policy/ssh-index) +rest_target(${psd} protocols/conn/base.bro) +rest_target(${psd} protocols/conn/contents.bro) +rest_target(${psd} protocols/conn/inactivity.bro) +rest_target(${psd} protocols/conn/known-hosts.bro) +rest_target(${psd} protocols/conn/known-services.bro) -rest_target(${POLICY_SRC_DIR} ssl-ciphers.bro policy/ssl-index) -rest_target(${POLICY_SRC_DIR} ssl-errors.bro policy/ssl-index) -rest_target(${POLICY_SRC_DIR} ssl.bro policy/ssl-index) +rest_target(${psd} protocols/dns/auth-addl.bro) +rest_target(${psd} protocols/dns/base.bro) +rest_target(${psd} protocols/dns/consts.bro) +rest_target(${psd} protocols/dns/detect.bro) -rest_target(${POLICY_SRC_DIR} utils/pattern.bro user) -rest_target(${POLICY_SRC_DIR} weird.bro user) +rest_target(${psd} protocols/ftp/base.bro) +rest_target(${psd} protocols/ftp/detect.bro) +rest_target(${psd} protocols/ftp/file-extract.bro) +rest_target(${psd} protocols/ftp/software.bro) +rest_target(${psd} protocols/ftp/utils-commands.bro) -# Finding out what scripts bro will generate documentation for by default -# can be done like: `bro --doc-scripts --exec ""` -rest_target(${POLICY_SRC_DIR} bro.init default) -rest_target(${POLICY_SRC_DIR} logging-ascii.bro default) -rest_target(${POLICY_SRC_DIR} logging.bro default) -rest_target(${POLICY_SRC_DIR} pcap.bro default) -rest_target(${POLICY_SRC_DIR} server-ports.bro default) -rest_target(${CMAKE_BINARY_DIR}/src bro.bif.bro bifs) -rest_target(${CMAKE_BINARY_DIR}/src const.bif.bro bifs) -rest_target(${CMAKE_BINARY_DIR}/src event.bif.bro bifs) -rest_target(${CMAKE_BINARY_DIR}/src logging.bif.bro bifs) -rest_target(${CMAKE_BINARY_DIR}/src strings.bif.bro bifs) -rest_target(${CMAKE_BINARY_DIR}/src types.bif.bro bifs) +rest_target(${psd} protocols/http/base.bro) +rest_target(${psd} protocols/http/detect-intel.bro) +rest_target(${psd} protocols/http/detect-sqli.bro) +rest_target(${psd} protocols/http/detect-webapps.bro) +rest_target(${psd} protocols/http/file-extract.bro) +rest_target(${psd} protocols/http/file-hash.bro) +rest_target(${psd} protocols/http/file-ident.bro) +rest_target(${psd} protocols/http/headers.bro) +rest_target(${psd} protocols/http/software.bro) +rest_target(${psd} protocols/http/utils.bro) +rest_target(${psd} protocols/http/var-extraction-cookies.bro) +rest_target(${psd} protocols/http/var-extraction-uri.bro) + +rest_target(${psd} protocols/irc/base.bro) +rest_target(${psd} protocols/irc/dcc-send.bro) + +rest_target(${psd} protocols/mime/base.bro) +rest_target(${psd} protocols/mime/file-extract.bro) +rest_target(${psd} protocols/mime/file-hash.bro) +rest_target(${psd} protocols/mime/file-ident.bro) + +rest_target(${psd} protocols/smtp/base.bro) +rest_target(${psd} protocols/smtp/detect.bro) +rest_target(${psd} protocols/smtp/software.bro) + +rest_target(${psd} protocols/ssh/base.bro) +rest_target(${psd} protocols/ssh/software.bro) + +#rest_target(${psd} protocols/ssl/base.bro) +#rest_target(${psd} protocols/ssl/ssl-ciphers.bro) +#rest_target(${psd} protocols/ssl/ssl-errors.bro) +#rest_target(${psd} protocols/ssl/ssl.bro) +#rest_target(${psd} protocols/ssl/validate.bro) + +rest_target(${psd} protocols/syslog/base.bro) +rest_target(${psd} protocols/syslog/consts.bro) + +rest_target(${psd} tuning/defaults/packet-fragments.bro) +rest_target(${psd} tuning/defaults/remove-high-volume-notices.bro) +rest_target(${psd} tuning/track-all-assets.bro) + +rest_target(${psd} utils/addrs.bro) +rest_target(${psd} utils/conn_ids.bro) +rest_target(${psd} utils/directions-and-hosts.bro) +rest_target(${psd} utils/files.bro) +rest_target(${psd} utils/numbers.bro) +rest_target(${psd} utils/paths.bro) +rest_target(${psd} utils/pattern.bro) +rest_target(${psd} utils/strings.bro) +rest_target(${psd} utils/thresholds.bro) # create temporary list of all docs to include in the master policy/index file file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/tmp_policy_index diff --git a/doc/scripts/source/index.rst b/doc/scripts/source/index.rst index 91864f1881..049b548896 100644 --- a/doc/scripts/source/index.rst +++ b/doc/scripts/source/index.rst @@ -13,7 +13,6 @@ Contents: builtins default bifs - user policy/dns-index policy/ftp-index policy/http-index diff --git a/doc/scripts/source/user.rst b/doc/scripts/source/user.rst deleted file mode 100644 index 3d5804b7df..0000000000 --- a/doc/scripts/source/user.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. This is a stub doc to which the build process can append. - -Other User-Facing Policy Scripts -================================ - diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 621209391a..e71026a250 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -3,9 +3,11 @@ #include #include #include +#include #include "BroDoc.h" #include "BroDocObj.h" +#include "util.h" BroDoc::BroDoc(const std::string& rel, const std::string& abs) { @@ -15,25 +17,19 @@ BroDoc::BroDoc(const std::string& rel, const std::string& abs) else source_filename = abs.substr(f_pos + 1); - if ( rel == abs ) + if ( rel[0] == '/' || rel[0] == '.' ) { - // The Bro script must have been loaded from an explicit path, - // so just use the basename as the document title + // The Bro script must not be on a subpath of the policy/ dir of + // BROPATH, so just use the basename as the document title doc_title = source_filename; } else { - // Must have relied on BROPATH to load the script, keep the relative - // directory as part of the source file name - size_t ext_pos = rel.find_last_of('.'); - std::string rel_ext = rel.substr(ext_pos + 1); - ext_pos = abs.find_last_of('.'); - std::string abs_ext = abs.substr(ext_pos + 1); - - if ( rel_ext == abs_ext || std::string::npos == ext_pos ) - doc_title = rel; + // keep the relative directory as part of the document title + if ( rel.size() == 0 || rel[rel.size() - 1] == '/' ) + doc_title = rel + source_filename; else - doc_title = rel + "." + abs_ext; + doc_title = rel + "/" + source_filename; } reST_filename = doc_title; @@ -46,24 +42,6 @@ BroDoc::BroDoc(const std::string& rel, const std::string& abs) reST_filename = doc_title.substr(0, ext_pos); reST_filename += ".rst"; -/* - // if the bro source file is being loaded from a relative path, - // re-create that directory tree to store the output - size_t f_pos = reST_filename.find_last_of('/'); - if ( std::string::npos != f_pos ) - { - std::string outdir = reST_filename.substr(0, f_pos); - std::string subdir; - while ( ! outdir.empty() ) - { - size_t pos = outdir.find_first_of('/'); - if ( pos != std::string::npos ) pos++; - subdir += outdir.substr(0, pos); - outdir.erase(0, pos); - ensure_dir(subdir.c_str()); - } - } -*/ // Instead of re-creating the directory hierarchy based on related // loads, just replace the directory separatories such that the reST // output will all be placed in a flat directory (the working dir). @@ -76,7 +54,7 @@ BroDoc::BroDoc(const std::string& rel, const std::string& abs) #ifdef DEBUG fprintf(stdout, "Documenting absolute source: %s\n", abs.c_str()); - fprintf(stdout, "\trelative load: %s\n", rel.c_str()); + fprintf(stdout, "\trelative dir: %s\n", rel.c_str()); fprintf(stdout, "\tdoc title: %s\n", doc_title.c_str()); fprintf(stdout, "\tbro file: %s\n", source_filename.c_str()); fprintf(stdout, "\trst file: %s\n", reST_filename.c_str()); @@ -93,12 +71,60 @@ BroDoc::~BroDoc() void BroDoc::AddImport(const std::string& s) { - size_t ext_pos = s.find_last_of('.'); + std::string lname(s); + // first strip any .bro extension + size_t ext_pos = lname.find(".bro"); + if ( ext_pos != std::string::npos ) + lname = lname.substr(0, ext_pos); - if ( ext_pos == std::string::npos ) - imports.push_back(s); + const char* full_filename = ""; + const char* subpath = ""; + FILE* f = search_for_file(lname.c_str(), "bro", &full_filename, true, + &subpath); + + if ( f ) + { + fclose(f); + + char* tmp = copy_string(full_filename); + char* filename = basename(tmp); + extern char* PACKAGE_LOADER; + + if ( streq(filename, PACKAGE_LOADER) ) + { + // link to the package's index + // TODO: check that this works + string pkg(subpath); + pkg += "/index"; + imports.push_back(pkg); + } + else + { + if ( subpath[0] == '/' || subpath[0] == '.' ) + { + // it's not a subpath of policy/, so just add the name of it + // as it's given in the @load directive + imports.push_back(lname); + } + else + { + // combine the base file name of script in the @load directive + // with the subpath of BROPATH's policy/ directory + string fname(subpath); + char* othertmp = copy_string(lname.c_str()); + fname.append("/").append(basename(othertmp)); + imports.push_back(fname); + delete [] othertmp; + } + } + + delete [] tmp; + delete [] full_filename; + delete [] subpath; + } else - imports.push_back(s.substr(0, ext_pos)); + fprintf(stderr, "Failed to document '@load %s' in file: %s\n", + s.c_str(), reST_filename.c_str()); } void BroDoc::SetPacketFilter(const std::string& s) diff --git a/src/BroDoc.h b/src/BroDoc.h index 5c9b175958..e98b511478 100644 --- a/src/BroDoc.h +++ b/src/BroDoc.h @@ -24,9 +24,11 @@ public: * If the filename doesn't end in ".bro", then ".rst" is just appended. * Any '/' characters in the reST file name that result from choice of * the 'rel' parameter are replaced with '^'. - * @param rel A string representing the path relative to BROPATH off of - * which the source file is loaded or generally any filesystem - * path to a Bro script. May or may not have .bro file extension. + * @param subpath A string representing a subpath of BROPATH's policy/ + * directory in which the source file is located. It can + * also be full path to the file or a full path that's in BROPATH, + * but in either of those cases, the parameter is essentially + * ignored and the document title is just derived from file name * @param abs The absolute path to the Bro script for which to generate * documentation. */ diff --git a/src/Debug.cc b/src/Debug.cc index 272d6739ae..6a0bbfdbb7 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -343,7 +343,7 @@ vector parse_location_string(const string& s) plr.type = plrUnknown; FILE* throwaway = search_for_file(filename.c_str(), "bro", - &full_filename, true); + &full_filename, true, 0); if ( ! throwaway ) { debug_msg("No such policy file: %s.\n", filename.c_str()); diff --git a/src/OSFinger.cc b/src/OSFinger.cc index f7b4903700..56f55f1225 100644 --- a/src/OSFinger.cc +++ b/src/OSFinger.cc @@ -295,7 +295,7 @@ void OSFingerprint::load_config(const char* file) uint32 ln=0; char buf[MAXLINE]; char* p; - FILE* c = search_for_file( file, "osf", 0, false); + FILE* c = search_for_file( file, "osf", 0, false, 0); if (!c) { diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index 4bc28b4c32..5cf6059249 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -197,7 +197,7 @@ bool RuleMatcher::ReadFiles(const name_list& files) for ( int i = 0; i < files.length(); ++i ) { - rules_in = search_for_file( files[i], "sig", 0, false); + rules_in = search_for_file( files[i], "sig", 0, false, 0); if ( ! rules_in ) { error("Can't open signature file", files[i]); diff --git a/src/scan.l b/src/scan.l index 8b599939db..553260a479 100644 --- a/src/scan.l +++ b/src/scan.l @@ -348,7 +348,7 @@ when return TOK_WHEN; // All we have to do is pretend we've already scanned it. const char* full_filename; - FILE* f = search_for_file(new_file, "bro", &full_filename, true); + FILE* f = search_for_file(new_file, "bro", &full_filename, true, 0); if ( f ) { @@ -537,6 +537,7 @@ static int load_files_with_prefix(const char* orig_file) const char* prefix = prefixes[i]; const char* full_filename = ""; + const char* bropath_subpath = ""; FILE* f; if ( streq(orig_file, "-") ) @@ -561,7 +562,7 @@ static int load_files_with_prefix(const char* orig_file) else strcpy(new_filename, orig_file); - f = search_for_file(new_filename, "bro", &full_filename, true); + f = search_for_file(new_filename, "bro", &full_filename, true, &bropath_subpath); delete [] new_filename; } @@ -576,6 +577,7 @@ static int load_files_with_prefix(const char* orig_file) { fclose(f); delete [] full_filename; + delete [] bropath_subpath; return 0; } } @@ -621,10 +623,12 @@ static int load_files_with_prefix(const char* orig_file) if ( generate_documentation ) { - current_reST_doc = new BroDoc(orig_file, full_filename); + current_reST_doc = new BroDoc(bropath_subpath, full_filename); docs_generated.push_back(current_reST_doc); } + delete [] bropath_subpath; + // "orig_file", could be an alias for yytext, which is ephemeral // and will be zapped after the yy_switch_to_buffer() below. yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); diff --git a/src/util.cc b/src/util.cc index 6c3f39bf72..4b4e833ef2 100644 --- a/src/util.cc +++ b/src/util.cc @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef HAVE_MALLINFO # include @@ -881,7 +882,7 @@ const char* bro_prefixes() return p; } -static const char* PACKAGE_LOADER = "__load__.bro"; +const char* PACKAGE_LOADER = "__load__.bro"; // If filename is pointing to a directory that contains a file called // PACKAGE_LOADER, returns the files path. Otherwise returns filename itself. @@ -915,11 +916,73 @@ FILE* open_file(const char* filename, const char** full_filename, bool load_pkgs return f; } +// Returns the subpath of BROPATH's policy/ directory in which the loaded +// file in located. If it's not under a subpath of policy/ then the full +// path is returned, else the subpath of policy/ concatentated with any +// directory prefix of the file is returned. +void get_policy_subpath(const char* dir, const char* file, const char** subpath) + { + // first figure out if this is a subpath of policy/ + const char* ploc = strstr(dir, "policy"); + if ( ploc ) + if ( ploc[6] == '\0' ) + *subpath = copy_string(ploc + 6); + else if ( ploc[6] == '/' ) + *subpath = copy_string(ploc + 7); + else + *subpath = copy_string(dir); + else + *subpath = copy_string(dir); + + // and now add any directory parts of the filename + char full_filename_buf[1024]; + safe_snprintf(full_filename_buf, sizeof(full_filename_buf), + "%s/%s", dir, file); + char* tmp = copy_string(file); + const char* fdir = 0; + + if ( is_dir(full_filename_buf) ) + fdir = file; + + if ( ! fdir ) + fdir = dirname(tmp); + + if ( ! streq(fdir, ".") ) + { + size_t full_subpath_len = strlen(*subpath) + strlen(fdir) + 1; + bool needslash = false; + if ( strlen(*subpath) != 0 && (*subpath)[strlen(*subpath) - 1] != '/' ) + { + ++full_subpath_len; + needslash = true; + } + + char* full_subpath = new char[full_subpath_len]; + strcpy(full_subpath, *subpath); + if ( needslash ) + strcat(full_subpath, "/"); + strcat(full_subpath, fdir); + delete [] *subpath; + *subpath = full_subpath; + } + + delete [] tmp; + } + FILE* search_for_file(const char* filename, const char* ext, - const char** full_filename, bool load_pkgs) + const char** full_filename, bool load_pkgs, + const char** bropath_subpath) { if ( filename[0] == '/' || filename[0] == '.' ) + { + if ( bropath_subpath ) + { + char* tmp = copy_string(filename); + *bropath_subpath = copy_string(dirname(tmp)); + delete [] tmp; + } return open_file(filename, full_filename, load_pkgs); + } char path[1024], full_filename_buf[1024]; safe_strncpy(path, bro_path(), sizeof(path)); @@ -942,18 +1005,32 @@ FILE* search_for_file(const char* filename, const char* ext, "%s/%s.%s", dir_beginning, filename, ext); if ( access(full_filename_buf, R_OK) == 0 && ! is_dir(full_filename_buf) ) + { + if ( bropath_subpath ) + get_policy_subpath(dir_beginning, filename, bropath_subpath); return open_file(full_filename_buf, full_filename, load_pkgs); + } safe_snprintf(full_filename_buf, sizeof(full_filename_buf), "%s/%s", dir_beginning, filename); if ( access(full_filename_buf, R_OK) == 0 ) + { + if ( bropath_subpath ) + get_policy_subpath(dir_beginning, filename, bropath_subpath); return open_file(full_filename_buf, full_filename, load_pkgs); + } dir_beginning = ++dir_ending; } if ( full_filename ) *full_filename = copy_string(filename); + if ( bropath_subpath ) + { + char* tmp = copy_string(filename); + *bropath_subpath = copy_string(dirname(tmp)); + delete [] tmp; + } return 0; } diff --git a/src/util.h b/src/util.h index 6aad1271af..e3929fa850 100644 --- a/src/util.h +++ b/src/util.h @@ -189,8 +189,9 @@ extern int int_list_cmp(const void* v1, const void* v2); extern const char* bro_path(); extern const char* bro_prefixes(); +void get_policy_subpath(const char* dir, const char* file, const char** subpath); extern FILE* search_for_file(const char* filename, const char* ext, - const char** full_filename, bool load_pkgs); + const char** full_filename, bool load_pkgs, const char** bropath_subpath); // Renames the given file to a new temporary name, and opens a new file with // the original name. Returns new file or NULL on error. Inits rotate_info if diff --git a/testing/btest/Baseline/doc.autogen-reST-example/example.rst b/testing/btest/Baseline/doc.autogen-reST-example/example.rst index a7ef21d907..d9a6fd0adf 100644 --- a/testing/btest/Baseline/doc.autogen-reST-example/example.rst +++ b/testing/btest/Baseline/doc.autogen-reST-example/example.rst @@ -29,7 +29,7 @@ each of "columns", "event", "filter" depending on exactly what it's doing. :Author: Jon Siwek -:Imports: :doc:`notice ` +:Imports: :doc:`frameworks/notice/index ` Summary ~~~~~~~