diff --git a/src/datasets.c b/src/datasets.c index d6d625fee6..0b94dd1ec5 100644 --- a/src/datasets.c +++ b/src/datasets.c @@ -40,6 +40,17 @@ static uint32_t set_ids = 0; static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, DataRepType *rep); +enum DatasetTypes DatasetGetTypeFromString(const char *s) +{ + if (strcasecmp("md5", s) == 0) + return DATASET_TYPE_MD5; + if (strcasecmp("sha256", s) == 0) + return DATASET_TYPE_SHA256; + if (strcasecmp("string", s) == 0) + return DATASET_TYPE_STRING; + return DATASET_TYPE_NOTSET; +} + static Dataset *DatasetAlloc(const char *name) { Dataset *set = SCCalloc(1, sizeof(*set)); @@ -61,16 +72,6 @@ static Dataset *DatasetSearchByName(const char *name) return NULL; } -Dataset *DatasetGetByName(const char *name) -{ - Dataset *set = DatasetSearchByName(name); - if (set) - return set; - - return DatasetAlloc(name); -} - - static int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs) { if (ins % 2 != 0) @@ -360,6 +361,21 @@ static void DatasetGetPath(const char *in_path, SCLogNotice("in_path \'%s\' => \'%s\'", in_path, out_path); } +/** \brief look for set by name without creating it */ +Dataset *DatasetFind(const char *name, enum DatasetTypes type) +{ + SCMutexLock(&sets_lock); + Dataset *set = DatasetSearchByName(name); + if (set) { + if (set->type != type) { + SCMutexUnlock(&sets_lock); + return NULL; + } + } + SCMutexUnlock(&sets_lock); + return set; +} + Dataset *DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load) { @@ -936,3 +952,39 @@ static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data } return -1; } + +/** \brief add serialized data to set */ +int DatasetAddSerialized(Dataset *set, const char *string) +{ + if (set == NULL) + return -1; + + switch (set->type) { + case DATASET_TYPE_STRING: { + uint8_t decoded[strlen(string)]; + uint32_t len = DecodeBase64(decoded, (const uint8_t *)string, strlen(string), 1); + if (len == 0) { + return -1; + } + + return DatasetAddString(set, decoded, len); + } + case DATASET_TYPE_MD5: { + if (strlen(string) != 32) + return -1; + uint8_t hash[16]; + if (HexToRaw((const uint8_t *)string, 32, hash, sizeof(hash)) < 0) + return -1; + return DatasetAddMd5(set, hash, 16); + } + case DATASET_TYPE_SHA256: { + if (strlen(string) != 64) + return -1; + uint8_t hash[32]; + if (HexToRaw((const uint8_t *)string, 64, hash, sizeof(hash)) < 0) + return -1; + return DatasetAddSha256(set, hash, 32); + } + } + return -1; +} diff --git a/src/datasets.h b/src/datasets.h index 15d1445930..514340b46f 100644 --- a/src/datasets.h +++ b/src/datasets.h @@ -45,12 +45,14 @@ typedef struct Dataset { struct Dataset *next; } Dataset; -Dataset *DatasetGetByName(const char *name); +enum DatasetTypes DatasetGetTypeFromString(const char *s); +Dataset *DatasetFind(const char *name, enum DatasetTypes type); Dataset *DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load); int DatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len); int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len); DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep); +int DatasetAddSerialized(Dataset *set, const char *string); #endif /* __DATASETS_H__ */ diff --git a/src/runmode-unix-socket.c b/src/runmode-unix-socket.c index 04257b4408..72a9ed04d0 100644 --- a/src/runmode-unix-socket.c +++ b/src/runmode-unix-socket.c @@ -49,6 +49,8 @@ #include "conf-yaml-loader.h" +#include "datasets.h" + int unix_socket_mode_is_running = 0; typedef struct PcapFiles_ { @@ -629,6 +631,62 @@ TmEcode UnixSocketPcapFile(TmEcode tm, struct timespec *last_processed) } #ifdef BUILD_UNIX_SOCKET +/** + * \brief Command to add data to a dataset + * + * \param cmd the content of command Arguments as a json_t object + * \param answer the json_t object that has to be used to answer + * \param data pointer to data defining the context here a PcapCommand:: + */ +TmEcode UnixSocketDatasetAdd(json_t *cmd, json_t* answer, void *data) +{ + /* 1 get dataset name */ + json_t *narg = json_object_get(cmd, "setname"); + if (!json_is_string(narg)) { + json_object_set_new(answer, "message", json_string("setname is not a string")); + return TM_ECODE_FAILED; + } + const char *set_name = json_string_value(narg); + + /* 2 get the data type */ + json_t *targ = json_object_get(cmd, "settype"); + if (!json_is_string(targ)) { + json_object_set_new(answer, "message", json_string("settype is not a string")); + return TM_ECODE_FAILED; + } + const char *type = json_string_value(targ); + + /* 3 get value */ + json_t *varg = json_object_get(cmd, "datavalue"); + if (!json_is_string(varg)) { + json_object_set_new(answer, "message", json_string("datavalue is not string")); + return TM_ECODE_FAILED; + } + const char *value = json_string_value(varg); + + SCLogNotice("dataset-add: %s type %s value %s", set_name, type, value); + + enum DatasetTypes t = DatasetGetTypeFromString(type); + + Dataset *set = DatasetFind(set_name, t); + if (set == NULL) { + json_object_set_new(answer, "message", json_string("set not found or wrong type")); + return TM_ECODE_FAILED; + } + + int r = DatasetAddSerialized(set, value); + if (r == 1) { + json_object_set_new(answer, "message", json_string("data added")); + return TM_ECODE_OK; + } else if (r == 0) { + json_object_set_new(answer, "message", json_string("data already in set")); + return TM_ECODE_OK; + } else { + json_object_set_new(answer, "message", json_string("failed to add data")); + return TM_ECODE_FAILED; + } +} + /** * \brief Command to add a tenant handler * diff --git a/src/runmode-unix-socket.h b/src/runmode-unix-socket.h index c8a06e06bf..630246996c 100644 --- a/src/runmode-unix-socket.h +++ b/src/runmode-unix-socket.h @@ -31,6 +31,7 @@ int RunModeUnixSocketIsActive(void); TmEcode UnixSocketPcapFile(TmEcode tm, struct timespec *last_processed); #ifdef BUILD_UNIX_SOCKET +TmEcode UnixSocketDatasetAdd(json_t *cmd, json_t* answer, void *data); TmEcode UnixSocketRegisterTenantHandler(json_t *cmd, json_t* answer, void *data); TmEcode UnixSocketUnregisterTenantHandler(json_t *cmd, json_t* answer, void *data); TmEcode UnixSocketRegisterTenant(json_t *cmd, json_t* answer, void *data); diff --git a/src/unix-manager.c b/src/unix-manager.c index 105648087a..11f452cf15 100644 --- a/src/unix-manager.c +++ b/src/unix-manager.c @@ -1089,6 +1089,8 @@ int UnixManagerInit(void) UnixManagerRegisterCommand("memcap-show", UnixSocketShowMemcap, &command, UNIX_CMD_TAKE_ARGS); UnixManagerRegisterCommand("memcap-list", UnixSocketShowAllMemcap, NULL, 0); + UnixManagerRegisterCommand("dataset-add", UnixSocketDatasetAdd, &command, UNIX_CMD_TAKE_ARGS); + return 0; }