diff --git a/scripts/base/frameworks/files/main.bro b/scripts/base/frameworks/files/main.bro index ed73028236..71147a77aa 100644 --- a/scripts/base/frameworks/files/main.bro +++ b/scripts/base/frameworks/files/main.bro @@ -135,6 +135,20 @@ export { ## The default per-file reassembly buffer size. const reassembly_buffer_size = 524288 &redef; + ## Lookup to see if a particular file id exists and is still valid. + ## + ## fuid: the file id. + ## + ## Returns: T if the file uid is known. + global file_exists: function(fuid: string): bool; + + ## Lookup an :bro:see:`fa_file` record with the file id. + ## + ## fuid: the file id. + ## + ## Returns: the associated :bro:see:`fa_file` record. + global lookup_file: function(fuid: string): fa_file; + ## Allows the file reassembler to be used if it's necessary because the ## file is transferred out of order. ## @@ -338,6 +352,16 @@ function set_info(f: fa_file) f$info$is_orig = f$is_orig; } +function file_exists(fuid: string): bool + { + return __file_exists(fuid); + } + +function lookup_file(fuid: string): fa_file + { + return __lookup_file(fuid); + } + function set_timeout_interval(f: fa_file, t: interval): bool { return __set_timeout_interval(f$id, t); diff --git a/src/file_analysis/Manager.h b/src/file_analysis/Manager.h index dec308236a..1a5fb55f89 100644 --- a/src/file_analysis/Manager.h +++ b/src/file_analysis/Manager.h @@ -256,6 +256,14 @@ public: bool SetExtractionLimit(const string& file_id, RecordVal* args, uint64 n) const; + /** + * Try to retrieve a file that's being analyzed, using its identifier/hash. + * @param file_id the file identifier/hash. + * @return the File object mapped to \a file_id, or a null pointer if no + * mapping exists. + */ + File* LookupFile(const string& file_id) const; + /** * Queue attachment of an analzer to the file identifier. Multiple * analyzers of a given type can be attached per file identifier at a time @@ -332,37 +340,6 @@ protected: typedef PDict(bool) IDSet; typedef PDict(File) IDMap; - /** - * Create a new file to be analyzed or retrieve an existing one. - * @param file_id the file identifier/hash. - * @param conn network connection, if any, over which the file is - * transferred. - * @param tag network protocol, if any, over which the file is transferred. - * @param is_orig true if the file is being sent from connection originator - * or false if is being sent in the opposite direction (or if it - * this file isn't related to a connection). - * @param update_conn whether we need to update connection-related field - * in the \c fa_file record value associated with the file. - * @param an optional value of the source field to fill in. - * @return the File object mapped to \a file_id or a null pointer if - * analysis is being ignored for the associated file. An File - * object may be created if a mapping doesn't exist, and if it did - * exist, the activity time is refreshed along with any - * connection-related fields. - */ - File* GetFile(const string& file_id, Connection* conn = 0, - analyzer::Tag tag = analyzer::Tag::Error, - bool is_orig = false, bool update_conn = true, - const char* source_name = 0); - - /** - * Try to retrieve a file that's being analyzed, using its identifier/hash. - * @param file_id the file identifier/hash. - * @return the File object mapped to \a file_id, or a null pointer if no - * mapping exists. - */ - File* LookupFile(const string& file_id) const; - /** * Evaluate timeout policy for a file and remove the File object mapped to * \a file_id if needed. @@ -392,6 +369,29 @@ protected: */ std::string GetFileID(analyzer::Tag tag, Connection* c, bool is_orig); + /** + * Create a new file to be analyzed or retrieve an existing one. + * @param file_id the file identifier/hash. + * @param conn network connection, if any, over which the file is + * transferred. + * @param tag network protocol, if any, over which the file is transferred. + * @param is_orig true if the file is being sent from connection originator + * or false if is being sent in the opposite direction (or if it + * this file isn't related to a connection). + * @param update_conn whether we need to update connection-related field + * in the \c fa_file record value associated with the file. + * @param an optional value of the source field to fill in. + * @return the File object mapped to \a file_id or a null pointer if + * analysis is being ignored for the associated file. An File + * object may be created if a mapping doesn't exist, and if it did + * exist, the activity time is refreshed along with any + * connection-related fields. + */ + File* GetFile(const string& file_id, Connection* conn = 0, + analyzer::Tag tag = analyzer::Tag::Error, + bool is_orig = false, bool update_conn = true, + const char* source_name = 0); + /** * Check if analysis is available for files transferred over a given * network protocol. diff --git a/src/file_analysis/file_analysis.bif b/src/file_analysis/file_analysis.bif index 480d8c84d8..f445a9cf6a 100644 --- a/src/file_analysis/file_analysis.bif +++ b/src/file_analysis/file_analysis.bif @@ -71,6 +71,28 @@ function Files::__analyzer_name%(tag: Files::Tag%) : string return new StringVal(file_mgr->GetComponentName(tag)); %} +## :bro:see:`Files::file_exists`. +function Files::__file_exists%(fuid: string%): bool + %{ + if ( file_mgr->LookupFile(fuid->CheckString()) != nullptr ) + return new Val(true, TYPE_BOOL); + else + return new Val(false, TYPE_BOOL); + %} + +## :bro:see:`Files::lookup_file`. +function Files::__lookup_file%(fuid: string%): fa_file + %{ + auto f = file_mgr->LookupFile(fuid->CheckString()); + if ( f != nullptr ) + { + return f->GetVal()->Ref(); + } + + reporter->Error("file ID %s not a known file", fuid->CheckString()); + return 0; + %} + module GLOBAL; ## For use within a :bro:see:`get_file_handle` handler to set a unique diff --git a/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.file_exists_lookup_file/.stdout b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.file_exists_lookup_file/.stdout new file mode 100644 index 0000000000..d5dd2cab55 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.file-analysis.bifs.file_exists_lookup_file/.stdout @@ -0,0 +1,9 @@ +error: file ID asdf not a known file +warning: non-void function returns without a value: Files::lookup_file +This should fail but not crash +This should return F +F +lookup fid: FakNcS1Jfe01uljb3 +We should have found the file id: FakNcS1Jfe01uljb3 +This should return T +T diff --git a/testing/btest/scripts/base/frameworks/file-analysis/bifs/file_exists_lookup_file.bro b/testing/btest/scripts/base/frameworks/file-analysis/bifs/file_exists_lookup_file.bro new file mode 100644 index 0000000000..cba82bbfab --- /dev/null +++ b/testing/btest/scripts/base/frameworks/file-analysis/bifs/file_exists_lookup_file.bro @@ -0,0 +1,21 @@ +# @TEST-EXEC: bro -r $TRACES/http/get.trace %INPUT 2>&1 +# @TEST-EXEC: btest-diff .stdout + +event bro_init() + { + print "This should fail but not crash"; + print Files::lookup_file("asdf"); + + print "This should return F"; + print Files::file_exists("asdf"); + } + +event file_sniff(f: fa_file, meta: fa_metadata) + { + print "lookup fid: " + f$id; + local looked_up_file = Files::lookup_file(f$id); + print "We should have found the file id: " + looked_up_file$id ; + + print "This should return T"; + print Files::file_exists(f$id); + }