}
}
+/* code for registering buffers */
+
+#include "util-hash-lookup3.h"
+
+static HashListTable *g_buffer_type_hash = NULL;
+static int g_buffer_type_id = DETECT_SM_LIST_MAX; // past DETECT_SM_LIST_NOTSET
+static int g_buffer_type_reg_closed = 0;
+
+typedef struct DetectBufferType_ {
+ const char *string;
+ const char *description;
+ int id;
+ _Bool mpm;
+ _Bool packet; /**< compat to packet matches */
+ void (*SetupCallback)(Signature *);
+ _Bool (*ValidateCallback)(const Signature *);
+} DetectBufferType;
+
+static DetectBufferType **g_buffer_type_map = NULL;
+
+int DetectBufferTypeMaxId(void)
+{
+ return g_buffer_type_id;
+}
+
+static uint32_t DetectBufferTypeHashFunc(HashListTable *ht, void *data, uint16_t datalen)
+{
+ const DetectBufferType *map = (DetectBufferType *)data;
+ uint32_t hash = 0;
+
+ hash = hashlittle_safe(map->string, strlen(map->string), 0);
+ hash %= ht->array_size;
+
+ return hash;
+}
+
+static char DetectBufferTypeCompareFunc(void *data1, uint16_t len1, void *data2,
+ uint16_t len2)
+{
+ DetectBufferType *map1 = (DetectBufferType *)data1;
+ DetectBufferType *map2 = (DetectBufferType *)data2;
+
+ int r = (strcmp(map1->string, map2->string) == 0);
+ return r;
+}
+
+static void DetectBufferTypeFreeFunc(void *data)
+{
+ DetectBufferType *map = (DetectBufferType *)data;
+ if (map != NULL) {
+ SCFree(map);
+ }
+}
+
+int DetectBufferTypeInit(void)
+{
+ BUG_ON(g_buffer_type_hash);
+ g_buffer_type_hash = HashListTableInit(256,
+ DetectBufferTypeHashFunc,
+ DetectBufferTypeCompareFunc,
+ DetectBufferTypeFreeFunc);
+ if (g_buffer_type_hash == NULL)
+ return -1;
+
+ return 0;
+}
+
+void DetectBufferTypeFree(void)
+{
+ if (g_buffer_type_hash == NULL)
+ return;
+
+ HashListTableFree(g_buffer_type_hash);
+ g_buffer_type_hash = NULL;
+ return;
+}
+
+int DetectBufferTypeAdd(const char *string)
+{
+ DetectBufferType *map = SCCalloc(1, sizeof(*map));
+ if (map == NULL)
+ return -1;
+
+ map->string = string;
+ map->id = g_buffer_type_id++;
+
+ BUG_ON(HashListTableAdd(g_buffer_type_hash, (void *)map, 0) != 0);
+ SCLogDebug("buffer %s registered with id %d", map->string, map->id);
+ return map->id;
+}
+
+DetectBufferType *DetectBufferTypeLookupByName(const char *string)
+{
+ DetectBufferType map = { (char *)string, NULL, 0, 0, 0, NULL, NULL };
+
+ DetectBufferType *res = HashListTableLookup(g_buffer_type_hash, &map, 0);
+ return res;
+}
+
+int DetectBufferTypeRegister(const char *name)
+{
+ BUG_ON(g_buffer_type_reg_closed);
+ if (g_buffer_type_hash == NULL)
+ DetectBufferTypeInit();
+
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ if (!exists) {
+ return DetectBufferTypeAdd(name);
+ } else {
+ return exists->id;
+ }
+}
+
+void DetectBufferTypeSupportsPacket(const char *name)
+{
+ BUG_ON(g_buffer_type_reg_closed);
+ DetectBufferTypeRegister(name);
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ BUG_ON(!exists);
+ exists->packet = TRUE;
+ SCLogDebug("%p %s -- %d supports packet inspection", exists, name, exists->id);
+}
+
+void DetectBufferTypeSupportsMpm(const char *name)
+{
+ BUG_ON(g_buffer_type_reg_closed);
+ DetectBufferTypeRegister(name);
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ BUG_ON(!exists);
+ exists->mpm = TRUE;
+ SCLogDebug("%p %s -- %d supports mpm", exists, name, exists->id);
+}
+
+int DetectBufferTypeGetByName(const char *name)
+{
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ if (!exists) {
+ return -1;
+ }
+ return exists->id;
+}
+
+const char *DetectBufferTypeGetNameById(const int id)
+{
+ BUG_ON(id < 0 || id >= g_buffer_type_id);
+ BUG_ON(g_buffer_type_map == NULL);
+
+ if (g_buffer_type_map[id] == NULL)
+ return NULL;
+
+ return g_buffer_type_map[id]->string;
+}
+
+const DetectBufferType *DetectBufferTypeGetById(const int id)
+{
+ BUG_ON(id < 0 || id >= g_buffer_type_id);
+ BUG_ON(g_buffer_type_map == NULL);
+
+ return g_buffer_type_map[id];
+}
+
+void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
+{
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ if (!exists) {
+ return;
+ }
+ exists->description = desc;
+}
+
+const char *DetectBufferTypeGetDescriptionById(const int id)
+{
+ const DetectBufferType *exists = DetectBufferTypeGetById(id);
+ if (!exists) {
+ return NULL;
+ }
+ return exists->description;
+}
+
+const char *DetectBufferTypeGetDescriptionByName(const char *name)
+{
+ const DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ if (!exists) {
+ return NULL;
+ }
+ return exists->description;
+}
+
+_Bool DetectBufferTypeSupportsPacketGetById(const int id)
+{
+ const DetectBufferType *map = DetectBufferTypeGetById(id);
+ if (map == NULL)
+ return FALSE;
+ SCLogDebug("map %p id %d packet? %d", map, id, map->packet);
+ return map->packet;
+}
+
+_Bool DetectBufferTypeSupportsMpmGetById(const int id)
+{
+ const DetectBufferType *map = DetectBufferTypeGetById(id);
+ if (map == NULL)
+ return FALSE;
+ SCLogDebug("map %p id %d mpm? %d", map, id, map->mpm);
+ return map->mpm;
+}
+
+void DetectBufferTypeRegisterSetupCallback(const char *name,
+ void (*SetupCallback)(Signature *))
+{
+ BUG_ON(g_buffer_type_reg_closed);
+ DetectBufferTypeRegister(name);
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ BUG_ON(!exists);
+ exists->SetupCallback = SetupCallback;
+}
+
+void DetectBufferRunSetupCallback(const int id, Signature *s)
+{
+ const DetectBufferType *map = DetectBufferTypeGetById(id);
+ if (map && map->SetupCallback) {
+ map->SetupCallback(s);
+ }
+}
+
+void DetectBufferTypeRegisterValidateCallback(const char *name,
+ _Bool (*ValidateCallback)(const Signature *))
+{
+ BUG_ON(g_buffer_type_reg_closed);
+ DetectBufferTypeRegister(name);
+ DetectBufferType *exists = DetectBufferTypeLookupByName(name);
+ BUG_ON(!exists);
+ exists->ValidateCallback = ValidateCallback;
+}
+
+_Bool DetectBufferRunValidateCallback(const int id, const Signature *s)
+{
+ const DetectBufferType *map = DetectBufferTypeGetById(id);
+ if (map && map->ValidateCallback) {
+ return map->ValidateCallback(s);
+ }
+ return TRUE;
+}
+
+void DetectBufferTypeFinalizeRegistration(void)
+{
+ BUG_ON(g_buffer_type_hash == NULL);
+
+ const int size = g_buffer_type_id;
+ BUG_ON(!(size > 0));
+
+ g_buffer_type_map = SCCalloc(size, sizeof(DetectBufferType *));
+ BUG_ON(!g_buffer_type_map);
+
+ HashListTableBucket *b = HashListTableGetListHead(g_buffer_type_hash);
+ while (b) {
+ DetectBufferType *map = HashListTableGetListData(b);
+ g_buffer_type_map[map->id] = map;
+ SCLogDebug("name %s id %d mpm %s packet %s -- %s. "
+ "Callbacks: Setup %p Validate %p", map->string, map->id,
+ map->mpm ? "true" : "false", map->packet ? "true" : "false",
+ map->description, map->SetupCallback, map->ValidateCallback);
+ b = HashListTableGetListNext(b);
+ }
+ g_buffer_type_reg_closed = 1;
+}
+
/* code to control the main thread to do a reload */
enum DetectEngineSyncState {
uint32_t u = 0;
uint32_t sig_flags = 0;
SigMatch *sm, *pm;
+ const int nlists = DetectBufferTypeMaxId();
SCEnter();
+ /* run buffer type validation callbacks if any */
+ int x;
+ for (x = 0; x < nlists; x++) {
+ if (s->init_data->smlists[x]) {
+ if (DetectBufferRunValidateCallback(x, s) == FALSE) {
+ SCReturnInt(0);
+ }
+ }
+ }
+
if ((s->flags & SIG_FLAG_REQUIRE_PACKET) &&
(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
SCLogError(SC_ERR_INVALID_SIGNATURE, "can't mix packet keywords with "
}
}
}
-
+#if 0 // TODO figure out why this is even necessary
if ((s->init_data->smlists[DETECT_SM_LIST_FILEDATA] != NULL && s->alproto == ALPROTO_SMTP) ||
s->init_data->smlists[DETECT_SM_LIST_UMATCH] != NULL ||
s->init_data->smlists[DETECT_SM_LIST_HRUDMATCH] != NULL ||
s->flags |= SIG_FLAG_TOCLIENT;
s->flags &= ~SIG_FLAG_TOSERVER;
}
+#endif
if ((sig_flags & (SIG_FLAG_TOCLIENT | SIG_FLAG_TOSERVER)) == (SIG_FLAG_TOCLIENT | SIG_FLAG_TOSERVER)) {
SCLogError(SC_ERR_INVALID_SIGNATURE,"You seem to have mixed keywords "
"that require inspection in both directions. Atm we only "
SCReturnInt(0);
}
+ for (int i = 0; i < nlists; i++) {
+ if (s->init_data->smlists[i] == NULL)
+ continue;
+ if (!(DetectBufferTypeGetNameById(i)))
+ continue;
+
+ if (!(DetectBufferTypeSupportsPacketGetById(i))) {
+ SCLogError(SC_ERR_INVALID_SIGNATURE, "Signature combines packet "
+ "specific matches (like dsize, flags, ttl) with stream / "
+ "state matching by matching on app layer proto (like using "
+ "http_* keywords).");
+ SCReturnInt(0);
+ }
+ }
+
if (s->init_data->smlists_tail[DETECT_SM_LIST_UMATCH] ||
s->init_data->smlists_tail[DETECT_SM_LIST_HRUDMATCH] ||
s->init_data->smlists_tail[DETECT_SM_LIST_HCBDMATCH] ||
if (s->init_data->smlists[DETECT_SM_LIST_AMATCH] != NULL)
return 0;
+ /* for now assume that all registered buffer types are incompatible */
+ const int nlists = DetectBufferTypeMaxId();
+ for (int i = 0; i < nlists; i++) {
+ if (s->init_data->smlists[i] == NULL)
+ continue;
+ if (!(DetectBufferTypeGetNameById(i)))
+ continue;
+
+ SCReturnInt(0);
+ }
+
/* TMATCH list can be ignored, it contains TAGs and
* tags are compatible to IP-only. */
if (s->init_data->smlists[DETECT_SM_LIST_AMATCH] != NULL)
return 0;
+ /* for now assume that all registered buffer types are incompatible */
+ const int nlists = DetectBufferTypeMaxId();
+ for (int i = 0; i < nlists; i++) {
+ if (s->init_data->smlists[i] == NULL)
+ continue;
+ if (!(DetectBufferTypeGetNameById(i)))
+ continue;
+
+ SCReturnInt(0);
+ }
+
/* TMATCH list can be ignored, it contains TAGs and
* tags are compatible to DP-only. */
SCReturnInt(0);
}
+ /* for now assume that all registered buffer types are incompatible */
+ const int nlists = DetectBufferTypeMaxId();
+ for (int i = 0; i < nlists; i++) {
+ if (s->init_data->smlists[i] == NULL)
+ continue;
+ if (!(DetectBufferTypeGetNameById(i)))
+ continue;
+
+ SCReturnInt(0);
+ }
+
/* check for conflicting keywords */
SigMatch *sm = s->init_data->smlists[DETECT_SM_LIST_MATCH];
for ( ;sm != NULL; sm = sm->next) {
uint32_t cnt_payload = 0;
uint32_t cnt_applayer = 0;
uint32_t cnt_deonly = 0;
+ const int nlists = DetectBufferTypeMaxId();
if (!(de_ctx->flags & DE_QUIET)) {
SCLogDebug("building signature grouping structure, stage 1: "
}
}
+ /* run buffer type callbacks if any */
+ int x;
+ for (x = 0; x < nlists; x++) {
+ if (tmp_s->init_data->smlists[x])
+ DetectBufferRunSetupCallback(x, tmp_s);
+ }
+
de_ctx->sig_cnt++;
}
DetectBypassRegister();
DetectHttpRequestLineRegister();
DetectHttpResponseLineRegister();
+
+ /* close keyword registration */
+ DetectBufferTypeFinalizeRegistration();
}
void SigTableRegisterTests(void)