// Currently, it provides three sets of APIs: file processing, MIME processing,
// and configurations.
-#include <string>
+#include <bitset>
#include <cstring>
+#include <string>
#include "main/snort_types.h"
namespace snort
{
+#define FILE_ID_MAX 1024
+typedef std::bitset<FILE_ID_MAX> FileTypeBitSet;
+
class FileContext;
class FileInfo;
class Flow;
}
SO_PUBLIC uint64_t get_file_processed_size(Flow* flow);
-FilePosition get_file_position(Packet* pkt);
+SO_PUBLIC FilePosition get_file_position(Packet* pkt);
+SO_PUBLIC void get_magic_rule_ids_from_type(const std::string& type,
+ const std::string& version, FileTypeBitSet& ids_set);
}
#endif
return fileIdentifier.get_rule_from_id(id);
}
+void FileConfig::get_magic_rule_ids_from_type(const std::string& type,
+ const std::string& version, snort::FileTypeBitSet& ids_set)
+{
+ return fileIdentifier.get_magic_rule_ids_from_type(type, version, ids_set);
+}
+
std::string FileConfig::file_type_name(uint32_t id)
{
if (SNORT_FILE_TYPE_UNKNOWN == id)
else
return nullptr;
}
+
+namespace snort
+{
+ void get_magic_rule_ids_from_type(const std::string& type, const std::string& version, snort::FileTypeBitSet& ids_set)
+ {
+ FileConfig* conf = get_file_config();
+ if(conf)
+ conf->get_magic_rule_ids_from_type(type, version, ids_set);
+ else
+ ids_set.reset();
+ }
+}
+
{
public:
FileMagicRule* get_rule_from_id(uint32_t);
+ void get_magic_rule_ids_from_type(const std::string&, const std::string&,
+ snort::FileTypeBitSet&);
void process_file_rule(FileMagicRule&);
void process_file_policy_rule(FileRule&);
bool process_file_magic(FileMagicData&);
unsigned FileFlows::file_flow_data_id = 0;
static THREAD_LOCAL uint32_t max_file_id = 0;
+namespace snort
+{
+ FilePosition get_file_position(Packet* pkt)
+ {
+ FilePosition position = SNORT_FILE_POSITION_UNKNOWN;
+ Packet* p = (Packet*)pkt;
+
+ if (p->is_full_pdu())
+ position = SNORT_FILE_FULL;
+ else if (p->is_pdu_start())
+ position = SNORT_FILE_START;
+ else if (p->packet_flags & PKT_PDU_TAIL)
+ position = SNORT_FILE_END;
+ else if (get_file_processed_size(p->flow))
+ position = SNORT_FILE_MIDDLE;
+
+ return position;
+ }
+}
+
void FileFlows::handle_retransmit (Packet*)
{
if (file_policy == nullptr)
{
current_file_id = pending_file_id = file_id;
}
-namespace snort
-{
-FilePosition get_file_position(Packet* pkt)
-{
- FilePosition position = SNORT_FILE_POSITION_UNKNOWN;
- Packet* p = (Packet*)pkt;
-
- if (p->is_full_pdu())
- position = SNORT_FILE_FULL;
- else if (p->is_pdu_start())
- position = SNORT_FILE_START;
- else if (p->packet_flags & PKT_PDU_TAIL)
- position = SNORT_FILE_END;
- else if (get_file_processed_size(p->flow))
- position = SNORT_FILE_MIDDLE;
-
- return position;
-}
-}
+
FileInspect::FileInspect(FileIdModule* fm)
{
fm->load_config(config);
init_merge_hash();
}
- if (rule.id > FILE_ID_MAX)
+ if (rule.id >= FILE_ID_MAX)
{
- ParseError("file type: rule id %u larger than %d", rule.id, FILE_ID_MAX);
+ ParseError("file type: rule id %u exceeds max id of %d", rule.id, FILE_ID_MAX-1);
return;
}
return nullptr;
}
+void FileIdentifier::get_magic_rule_ids_from_type(const std::string& type,
+ const std::string& version, snort::FileTypeBitSet& ids_set)
+{
+ ids_set.reset();
+
+ for(uint32_t i; i < FILE_ID_MAX; i++)
+ {
+ if(type == file_magic_rules[i].type)
+ {
+ if(version.empty() or version == file_magic_rules[i].version)
+ {
+ ids_set.set(file_magic_rules[i].id);
+ }
+ }
+ }
+}
+
//--------------------------------------------------------------------------
// unit tests
//--------------------------------------------------------------------------
#include "file_lib.h"
-#define FILE_ID_MAX 1024
-
#define MAX_BRANCH (UINT8_MAX + 1)
enum IdNodeState
void insert_file_rule(FileMagicRule& rule);
uint32_t find_file_type_id(const uint8_t* buf, int len, uint64_t offset, void** context);
FileMagicRule* get_rule_from_id(uint32_t);
+ void get_magic_rule_ids_from_type(const std::string&, const std::string&, snort::FileTypeBitSet&);
private:
void init_merge_hash();
#include "config.h"
#endif
-#include <bitset>
-
#include "framework/ips_option.h"
#include "framework/module.h"
#include "file_api/file_flows.h"
#include "file_api/file_identifier.h"
+#include "log/messages.h"
#include "profiler/profiler.h"
#include "protocols/packet.h"
using namespace snort;
-typedef std::bitset<FILE_ID_MAX> TypeBitSet;
-
#define s_name "file_type"
static THREAD_LOCAL ProfileStats fileTypePerfStats;
class FileTypeOption : public IpsOption
{
public:
- FileTypeOption(TypeBitSet &);
+ FileTypeOption(FileTypeBitSet&);
CursorActionType get_cursor_type() const override
{ return CAT_NONE; }
EvalStatus eval(Cursor&, Packet*) override;
- TypeBitSet types;
+ FileTypeBitSet types;
};
//-------------------------------------------------------------------------
// class methods
//-------------------------------------------------------------------------
-FileTypeOption::FileTypeOption(TypeBitSet& t) : IpsOption(s_name)
+FileTypeOption::FileTypeOption(FileTypeBitSet& t) : IpsOption(s_name)
{
types = t;
}
bool begin(const char*, int, SnortConfig*) override;
bool set(const char*, Value&, SnortConfig*) override;
- bool set_types(long);
-
ProfileStats* get_profile() const override
{ return &fileTypePerfStats; }
{ return DETECT; }
public:
- TypeBitSet types;
+ FileTypeBitSet types;
+
+private:
+ bool parse_type_and_version(std::string& token);
};
bool FileTypeModule::begin(const char*, int, SnortConfig*)
return true;
}
-bool FileTypeModule::set_types(long t)
-{
- if ( t < 0 or t > FILE_ID_MAX )
- return false;
-
- types.set((uint32_t)t);
-
- return true;
-}
-
bool FileTypeModule::set(const char*, Value& v, SnortConfig*)
{
if ( !v.is("~") )
while ( v.get_next_token(tok) )
{
- long n;
-
if ( tok[0] == '"' )
tok.erase(0, 1);
if ( tok[tok.length()-1] == '"' )
tok.erase(tok.length()-1, 1);
- if ( v.strtol(n, tok) )
+ if (! parse_type_and_version(tok) )
+ return false;
+ }
+ return true;
+}
+
+// Parse a file_type token and add the rule ID associated with the type
+// into the set of file types to match.
+//
+// The file_type token can have the following format where TYPENAME and
+// VER? are strings:
+//
+// TYPENAME -- Type by itself will match all versions of that type.
+// TYPENAME,VER1 -- Match type and version
+// TYPENAME,VER1,VER2,... -- Match type and any of the specified versions.
+//
+// Multiple types are separated by spaces:
+// TYPE1,VER1 TYPE2 TYPE3,VER1,VER2 -- Match any of these types
+//
+bool FileTypeModule::parse_type_and_version(std::string& token)
+{
+ std::istringstream stream(token);
+ std::string type_name;
+ std::string version;
+ FileTypeBitSet ids_set;
+
+ if(!std::getline(stream, type_name, ','))
+ return false;
+
+ if(!std::getline(stream, version, ','))
+ {
+ // Match all versions of this type.
+ get_magic_rule_ids_from_type(type_name, "", ids_set);
+ if(ids_set.none())
{
- if ( !set_types(n) )
- return false;
+ ParseError("Invalid file_type type '%s'. Not found in file_rules.", type_name.c_str());
+ return false;
}
- else
+
+ types |= ids_set;
+ return true;
+ }
+
+ get_magic_rule_ids_from_type(type_name, version, ids_set);
+ if(ids_set.none())
+ {
+ ParseError("Invalid file_type type '%s' or version '%s'. Not found in file_rules.", type_name.c_str(), version.c_str());
+ return false;
+ }
+
+ types |= ids_set;
+
+ while(std::getline(stream, version, ','))
+ {
+ get_magic_rule_ids_from_type(type_name, version, ids_set);
+ if(ids_set.none())
+ {
+ ParseError("Invalid file_type type '%s' or version '%s'. Not found in file_rules.", type_name.c_str(), version.c_str());
return false;
+ }
+
+ types |= ids_set;
}
+
return true;
}