suricata
datasets.c
Go to the documentation of this file.
1 /* Copyright (C) 2017-2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #include "suricata-common.h"
25 #include "conf.h"
26 #include "datasets.h"
27 #include "datasets-string.h"
28 #include "datasets-md5.h"
29 #include "datasets-sha256.h"
30 #include "datasets-reputation.h"
31 #include "util-thash.h"
32 #include "util-print.h"
33 #include "util-crypt.h" // encode base64
34 #include "util-base64.h" // decode base64
35 #include "util-byte.h"
36 
38 static Dataset *sets = NULL;
39 static uint32_t set_ids = 0;
40 static bool experimental_warning = false;
41 
42 static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
43  DataRepType *rep);
44 
45 static inline void DatasetUnlockData(THashData *d)
46 {
47  (void) THashDecrUsecnt(d);
48  THashDataUnlock(d);
49 }
50 static bool DatasetIsStatic(const char *save, const char *load);
51 
52 enum DatasetTypes DatasetGetTypeFromString(const char *s)
53 {
54  if (strcasecmp("md5", s) == 0)
55  return DATASET_TYPE_MD5;
56  if (strcasecmp("sha256", s) == 0)
57  return DATASET_TYPE_SHA256;
58  if (strcasecmp("string", s) == 0)
59  return DATASET_TYPE_STRING;
60  return DATASET_TYPE_NOTSET;
61 }
62 
63 static Dataset *DatasetAlloc(const char *name)
64 {
65  Dataset *set = SCCalloc(1, sizeof(*set));
66  if (set) {
67  set->id = set_ids++;
68  }
69  return set;
70 }
71 
72 static Dataset *DatasetSearchByName(const char *name)
73 {
74  Dataset *set = sets;
75  while (set) {
76  if (strcasecmp(name, set->name) == 0 && set->hidden == false) {
77  return set;
78  }
79  set = set->next;
80  }
81  return NULL;
82 }
83 
84 static int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs)
85 {
86  if (ins % 2 != 0)
87  return -1;
88  if (outs != ins / 2)
89  return -1;
90 
91  uint8_t hash[outs];
92  size_t i, x;
93  for (x = 0, i = 0; i < ins; i+=2, x++) {
94  char buf[3] = { 0, 0, 0 };
95  buf[0] = in[i];
96  buf[1] = in[i+1];
97 
98  long value = strtol(buf, NULL, 16);
99  if (value >= 0 && value <= 255)
100  hash[x] = (uint8_t)value;
101  else {
102  SCLogError(SC_ERR_INVALID_HASH, "hash byte out of range %ld", value);
103  return -1;
104  }
105  }
106 
107  memcpy(out, hash, outs);
108  return 0;
109 }
110 
111 static int ParseRepLine(const char *in, size_t ins, DataRepType *rep_out)
112 {
113  SCLogDebug("in '%s'", in);
114  char raw[ins + 1];
115  memcpy(raw, in, ins);
116  raw[ins] = '\0';
117  char *line = raw;
118 
119  char *ptrs[1] = {NULL};
120  int idx = 0;
121 
122  size_t i = 0;
123  while (i < ins + 1) {
124  if (line[i] == ',' || line[i] == '\n' || line[i] == '\0') {
125  line[i] = '\0';
126  SCLogDebug("line '%s'", line);
127 
128  ptrs[idx] = line;
129  idx++;
130 
131  if (idx == 1)
132  break;
133  } else {
134  i++;
135  }
136  }
137 
138  if (idx != 1) {
139  SCLogDebug("idx %d", idx);
140  return -1;
141  }
142 
143  uint16_t v = 0;
144  int r = StringParseU16RangeCheck(&v, 10, strlen(ptrs[0]), ptrs[0], 0, USHRT_MAX);
145  if (r != (int)strlen(ptrs[0])) {
147  "'%s' is not a valid reputation value (0-65535)", ptrs[0]);
148  return -1;
149  }
150  SCLogDebug("v %"PRIu16" raw %s", v, ptrs[0]);
151 
152  rep_out->value = v;
153  return 0;
154 }
155 
156 static int DatasetLoadMd5(Dataset *set)
157 {
158  if (strlen(set->load) == 0)
159  return 0;
160 
161  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
162  const char *fopen_mode = "r";
163  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
164  fopen_mode = "a+";
165  }
166 
167  FILE *fp = fopen(set->load, fopen_mode);
168  if (fp == NULL) {
169  SCLogError(SC_ERR_DATASET, "fopen '%s' failed: %s",
170  set->load, strerror(errno));
171  return -1;
172  }
173 
174  uint32_t cnt = 0;
175  char line[1024];
176  while (fgets(line, (int)sizeof(line), fp) != NULL) {
177  /* straight black/white list */
178  if (strlen(line) == 33) {
179  line[strlen(line) - 1] = '\0';
180  SCLogDebug("line: '%s'", line);
181 
182  uint8_t hash[16];
183  if (HexToRaw((const uint8_t *)line, 32, hash, sizeof(hash)) < 0)
184  FatalError(SC_ERR_FATAL, "bad hash for dataset %s/%s",
185  set->name, set->load);
186 
187  if (DatasetAdd(set, (const uint8_t *)hash, 16) < 0)
188  FatalError(SC_ERR_FATAL, "dataset data add failed %s/%s",
189  set->name, set->load);
190  cnt++;
191 
192  /* list with rep data */
193  } else if (strlen(line) > 33 && line[32] == ',') {
194  line[strlen(line) - 1] = '\0';
195  SCLogDebug("MD5 with REP line: '%s'", line);
196 
197  uint8_t hash[16];
198  if (HexToRaw((const uint8_t *)line, 32, hash, sizeof(hash)) < 0)
199  FatalError(SC_ERR_FATAL, "bad hash for dataset %s/%s",
200  set->name, set->load);
201 
202  DataRepType rep = { .value = 0};
203  if (ParseRepLine(line+33, strlen(line)-33, &rep) < 0)
204  FatalError(SC_ERR_FATAL, "bad rep for dataset %s/%s",
205  set->name, set->load);
206 
207  SCLogDebug("rep v:%u", rep.value);
208  if (DatasetAddwRep(set, hash, 16, &rep) < 0)
209  FatalError(SC_ERR_FATAL, "dataset data add failed %s/%s",
210  set->name, set->load);
211 
212  cnt++;
213  }
214  else {
215  FatalError(SC_ERR_FATAL, "MD5 bad line len %u: '%s'",
216  (uint32_t)strlen(line), line);
217  }
218  }
219 
220  fclose(fp);
221  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
222  return 0;
223 }
224 
225 static int DatasetLoadSha256(Dataset *set)
226 {
227  if (strlen(set->load) == 0)
228  return 0;
229 
230  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
231  const char *fopen_mode = "r";
232  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
233  fopen_mode = "a+";
234  }
235 
236  FILE *fp = fopen(set->load, fopen_mode);
237  if (fp == NULL) {
238  SCLogError(SC_ERR_DATASET, "fopen '%s' failed: %s",
239  set->load, strerror(errno));
240  return -1;
241  }
242 
243  uint32_t cnt = 0;
244  char line[1024];
245  while (fgets(line, (int)sizeof(line), fp) != NULL) {
246  /* straight black/white list */
247  if (strlen(line) == 65) {
248  line[strlen(line) - 1] = '\0';
249  SCLogDebug("line: '%s'", line);
250 
251  uint8_t hash[32];
252  if (HexToRaw((const uint8_t *)line, 64, hash, sizeof(hash)) < 0)
253  FatalError(SC_ERR_FATAL, "bad hash for dataset %s/%s",
254  set->name, set->load);
255 
256  if (DatasetAdd(set, (const uint8_t *)hash, (uint32_t)32) < 0)
257  FatalError(SC_ERR_FATAL, "dataset data add failed %s/%s",
258  set->name, set->load);
259  cnt++;
260 
261  /* list with rep data */
262  } else if (strlen(line) > 65 && line[64] == ',') {
263  line[strlen(line) - 1] = '\0';
264  SCLogDebug("SHA-256 with REP line: '%s'", line);
265 
266  uint8_t hash[32];
267  if (HexToRaw((const uint8_t *)line, 64, hash, sizeof(hash)) < 0)
268  FatalError(SC_ERR_FATAL, "bad hash for dataset %s/%s",
269  set->name, set->load);
270 
271  DataRepType rep = { .value = 0 };
272  if (ParseRepLine(line+65, strlen(line)-65, &rep) < 0)
273  FatalError(SC_ERR_FATAL, "bad rep for dataset %s/%s",
274  set->name, set->load);
275 
276  SCLogDebug("rep %u", rep.value);
277 
278  if (DatasetAddwRep(set, hash, 32, &rep) < 0)
279  FatalError(SC_ERR_FATAL, "dataset data add failed %s/%s",
280  set->name, set->load);
281  cnt++;
282  }
283  }
284 
285  fclose(fp);
286  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
287  return 0;
288 }
289 
290 static int DatasetLoadString(Dataset *set)
291 {
292  if (strlen(set->load) == 0)
293  return 0;
294 
295  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
296  const char *fopen_mode = "r";
297  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
298  fopen_mode = "a+";
299  }
300 
301  FILE *fp = fopen(set->load, fopen_mode);
302  if (fp == NULL) {
303  SCLogError(SC_ERR_DATASET, "fopen '%s' failed: %s",
304  set->load, strerror(errno));
305  return -1;
306  }
307 
308  uint32_t cnt = 0;
309  char line[1024];
310  while (fgets(line, (int)sizeof(line), fp) != NULL) {
311  if (strlen(line) <= 1)
312  continue;
313 
314  char *r = strchr(line, ',');
315  if (r == NULL) {
316  line[strlen(line) - 1] = '\0';
317  SCLogDebug("line: '%s'", line);
318 
319  // coverity[alloc_strlen : FALSE]
320  uint8_t decoded[strlen(line)];
321  uint32_t len = DecodeBase64(decoded, (const uint8_t *)line, strlen(line), 1);
322  if (len == 0)
323  FatalError(SC_ERR_FATAL, "bad base64 encoding %s/%s",
324  set->name, set->load);
325 
326  if (DatasetAdd(set, (const uint8_t *)decoded, len) < 0)
327  FatalError(SC_ERR_FATAL, "dataset data add failed %s/%s",
328  set->name, set->load);
329  cnt++;
330  } else {
331  line[strlen(line) - 1] = '\0';
332  SCLogDebug("line: '%s'", line);
333 
334  *r = '\0';
335 
336  // coverity[alloc_strlen : FALSE]
337  uint8_t decoded[strlen(line)];
338  uint32_t len = DecodeBase64(decoded, (const uint8_t *)line, strlen(line), 1);
339  if (len == 0)
340  FatalError(SC_ERR_FATAL, "bad base64 encoding %s/%s",
341  set->name, set->load);
342 
343  r++;
344  SCLogDebug("r '%s'", r);
345 
346  DataRepType rep = { .value = 0 };
347  if (ParseRepLine(r, strlen(r), &rep) < 0)
348  FatalError(SC_ERR_FATAL, "die: bad rep");
349  SCLogDebug("rep %u", rep.value);
350 
351  if (DatasetAddwRep(set, (const uint8_t *)decoded, len, &rep) < 0)
352  FatalError(SC_ERR_FATAL, "dataset data add failed %s/%s",
353  set->name, set->load);
354  cnt++;
355 
356  SCLogDebug("line with rep %s, %s", line, r);
357  }
358  }
359 
360  fclose(fp);
361  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
362  return 0;
363 }
364 
365 extern bool g_system;
366 
370 };
371 
372 static void DatasetGetPath(const char *in_path,
373  char *out_path, size_t out_size, enum DatasetGetPathType type)
374 {
375  char path[PATH_MAX];
376  struct stat st;
377 
378  if (PathIsAbsolute(in_path)) {
379  strlcpy(path, in_path, sizeof(path));
380  strlcpy(out_path, path, out_size);
381  return;
382  }
383 
384  const char *data_dir = ConfigGetDataDirectory();
385  if (stat(data_dir, &st) != 0) {
386  SCLogDebug("data-dir '%s': %s", data_dir, strerror(errno));
387  return;
388  }
389 
390  snprintf(path, sizeof(path), "%s/%s", data_dir, in_path); // TODO WINDOWS
391 
392  if (type == TYPE_LOAD) {
393  if (stat(path, &st) != 0) {
394  SCLogDebug("path %s: %s", path, strerror(errno));
395  if (!g_system) {
396  snprintf(path, sizeof(path), "%s", in_path);
397  }
398  }
399  }
400  strlcpy(out_path, path, out_size);
401  SCLogDebug("in_path \'%s\' => \'%s\'", in_path, out_path);
402 }
403 
404 /** \brief look for set by name without creating it */
405 Dataset *DatasetFind(const char *name, enum DatasetTypes type)
406 {
408  Dataset *set = DatasetSearchByName(name);
409  if (set) {
410  if (set->type != type) {
412  return NULL;
413  }
414  }
416  return set;
417 }
418 
419 Dataset *DatasetGet(const char *name, enum DatasetTypes type,
420  const char *save, const char *load)
421 {
422  if (strlen(name) > DATASET_NAME_MAX_LEN) {
423  return NULL;
424  }
425 
427  if (!experimental_warning) {
428  SCLogNotice("dataset and datarep features are experimental and subject to change");
429  experimental_warning = true;
430  }
431  Dataset *set = DatasetSearchByName(name);
432  if (set) {
433  if (type != DATASET_TYPE_NOTSET && set->type != type) {
434  SCLogError(SC_ERR_DATASET, "dataset %s already "
435  "exists and is of type %u",
436  set->name, set->type);
438  return NULL;
439  }
440 
441  if ((save == NULL || strlen(save) == 0) &&
442  (load == NULL || strlen(load) == 0)) {
443  // OK, rule keyword doesn't have to set state/load,
444  // even when yaml set has set it.
445  } else {
446  if ((save == NULL && strlen(set->save) > 0) ||
447  (save != NULL && strcmp(set->save, save) != 0)) {
448  SCLogError(SC_ERR_DATASET, "dataset %s save mismatch: %s != %s",
449  set->name, set->save, save);
451  return NULL;
452  }
453  if ((load == NULL && strlen(set->load) > 0) ||
454  (load != NULL && strcmp(set->load, load) != 0)) {
455  SCLogError(SC_ERR_DATASET, "dataset %s load mismatch: %s != %s",
456  set->name, set->load, load);
458  return NULL;
459  }
460  }
461 
463  return set;
464  } else {
465  if (type == DATASET_TYPE_NOTSET) {
466  SCLogError(SC_ERR_DATASET, "dataset %s not defined", name);
467  goto out_err;
468  }
469  }
470 
471  set = DatasetAlloc(name);
472  if (set == NULL) {
473  goto out_err;
474  }
475 
476  strlcpy(set->name, name, sizeof(set->name));
477  set->type = type;
478  if (save && strlen(save)) {
479  strlcpy(set->save, save, sizeof(set->save));
480  SCLogDebug("name %s save '%s'", name, set->save);
481  }
482  if (load && strlen(load)) {
483  strlcpy(set->load, load, sizeof(set->load));
484  SCLogDebug("set \'%s\' loading \'%s\' from \'%s\'", set->name, load, set->load);
485  }
486 
487  char cnf_name[128];
488  snprintf(cnf_name, sizeof(cnf_name), "datasets.%s.hash", name);
489 
490  switch (type) {
491  case DATASET_TYPE_MD5:
492  set->hash = THashInit(cnf_name, sizeof(Md5Type), Md5StrSet,
494  if (set->hash == NULL)
495  goto out_err;
496  if (DatasetLoadMd5(set) < 0)
497  goto out_err;
498  break;
499  case DATASET_TYPE_STRING:
500  set->hash = THashInit(cnf_name, sizeof(StringType), StringSet,
502  if (set->hash == NULL)
503  goto out_err;
504  if (DatasetLoadString(set) < 0)
505  goto out_err;
506  break;
507  case DATASET_TYPE_SHA256:
508  set->hash = THashInit(cnf_name, sizeof(Sha256Type), Sha256StrSet,
510  if (set->hash == NULL)
511  goto out_err;
512  if (DatasetLoadSha256(set) < 0)
513  goto out_err;
514  break;
515  }
516 
517  SCLogDebug("set %p/%s type %u save %s load %s",
518  set, set->name, set->type, set->save, set->load);
519 
520  set->next = sets;
521  sets = set;
522 
524  return set;
525 out_err:
526  if (set) {
527  if (set->hash) {
528  THashShutdown(set->hash);
529  }
530  SCFree(set);
531  }
533  return NULL;
534 }
535 
536 static bool DatasetIsStatic(const char *save, const char *load)
537 {
538  /* A set is static if it does not have any dynamic properties like
539  * save and/or state defined but has load defined.
540  * */
541  if ((load != NULL && strlen(load) > 0) &&
542  (save == NULL || strlen(save) == 0)) {
543  return true;
544  }
545  return false;
546 }
547 
548 void DatasetReload(void)
549 {
550  /* In order to reload the datasets, just mark the current sets as hidden
551  * and clean them up later.
552  * New datasets shall be created with the rule reload and do not require
553  * any intervention.
554  * */
556  Dataset *set = sets;
557  while (set) {
558  if (!DatasetIsStatic(set->save, set->load) || set->from_yaml == true) {
559  SCLogDebug("Not a static set, skipping %s", set->name);
560  set = set->next;
561  continue;
562  }
563  set->hidden = true;
564  SCLogDebug("Set %s at %p hidden successfully", set->name, set);
565  set = set->next;
566  }
568 }
569 
571 {
572  SCLogDebug("Post Reload Cleanup starting.. Hidden sets will be removed");
574  Dataset *cur = sets;
575  Dataset *prev = NULL;
576  while (cur) {
577  Dataset *next = cur->next;
578  if (cur->hidden == false) {
579  prev = cur;
580  cur = next;
581  continue;
582  }
583  // Delete the set in case it was hidden
584  if (prev != NULL) {
585  prev->next = next;
586  } else {
587  sets = next;
588  }
589  THashShutdown(cur->hash);
590  SCFree(cur);
591  cur = next;
592  }
594 }
595 
596 int DatasetsInit(void)
597 {
598  SCLogDebug("datasets start");
599  int n = 0;
600  ConfNode *datasets = ConfGetNode("datasets");
601  if (datasets != NULL) {
602  int list_pos = 0;
603  ConfNode *iter = NULL;
604  TAILQ_FOREACH(iter, &datasets->head, next) {
605  if (iter->name == NULL) {
606  list_pos++;
607  continue;
608  }
609 
610  char save[PATH_MAX] = "";
611  char load[PATH_MAX] = "";
612 
613  const char *set_name = iter->name;
614  if (strlen(set_name) > DATASET_NAME_MAX_LEN) {
615  FatalError(SC_ERR_CONF_NAME_TOO_LONG, "set name '%s' too long, max %d chars",
616  set_name, DATASET_NAME_MAX_LEN);
617  }
618 
619  ConfNode *set_type =
620  ConfNodeLookupChild(iter, "type");
621  if (set_type == NULL) {
622  list_pos++;
623  continue;
624  }
625 
626  ConfNode *set_save =
627  ConfNodeLookupChild(iter, "state");
628  if (set_save) {
629  DatasetGetPath(set_save->val, save, sizeof(save), TYPE_STATE);
630  strlcpy(load, save, sizeof(load));
631  } else {
632  ConfNode *set_load =
633  ConfNodeLookupChild(iter, "load");
634  if (set_load) {
635  DatasetGetPath(set_load->val, load, sizeof(load), TYPE_LOAD);
636  }
637  }
638 
639  char conf_str[1024];
640  snprintf(conf_str, sizeof(conf_str), "datasets.%d.%s", list_pos, set_name);
641 
642  SCLogDebug("(%d) set %s type %s. Conf %s", n, set_name, set_type->val, conf_str);
643 
644  if (strcmp(set_type->val, "md5") == 0) {
645  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_MD5, save, load);
646  if (dset == NULL)
647  FatalError(SC_ERR_FATAL, "failed to setup dataset for %s", set_name);
648  SCLogDebug("dataset %s: id %d type %s", set_name, n, set_type->val);
649  dset->from_yaml = true;
650  n++;
651 
652  } else if (strcmp(set_type->val, "sha256") == 0) {
653  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_SHA256, save, load);
654  if (dset == NULL)
655  FatalError(SC_ERR_FATAL, "failed to setup dataset for %s", set_name);
656  SCLogDebug("dataset %s: id %d type %s", set_name, n, set_type->val);
657  dset->from_yaml = true;
658  n++;
659 
660  } else if (strcmp(set_type->val, "string") == 0) {
661  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_STRING, save, load);
662  if (dset == NULL)
663  FatalError(SC_ERR_FATAL, "failed to setup dataset for %s", set_name);
664  SCLogDebug("dataset %s: id %d type %s", set_name, n, set_type->val);
665  dset->from_yaml = true;
666  n++;
667  }
668 
669  list_pos++;
670  }
671  }
672  SCLogDebug("datasets done: %p", datasets);
673  return 0;
674 }
675 
676 void DatasetsDestroy(void)
677 {
678  SCLogDebug("destroying datasets: %p", sets);
680  Dataset *set = sets;
681  while (set) {
682  SCLogDebug("destroying set %s", set->name);
683  Dataset *next = set->next;
684  THashShutdown(set->hash);
685  SCFree(set);
686  set = next;
687  }
688  sets = NULL;
690  SCLogDebug("destroying datasets done: %p", sets);
691 }
692 
693 static int SaveCallback(void *ctx, const uint8_t *data, const uint32_t data_len)
694 {
695  FILE *fp = ctx;
696  //PrintRawDataFp(fp, data, data_len);
697  if (fp) {
698  return fwrite(data, data_len, 1, fp);
699  }
700  return 0;
701 }
702 
703 static int Md5AsAscii(const void *s, char *out, size_t out_size)
704 {
705  const Md5Type *md5 = s;
706  uint32_t x;
707  int i;
708  char str[256];
709  for (i = 0, x = 0; x < sizeof(md5->md5); x++) {
710  i += snprintf(&str[i], 255-i, "%02x", md5->md5[x]);
711  }
712  strlcat(out, str, out_size);
713  strlcat(out, "\n", out_size);
714  return strlen(out);
715 }
716 
717 static int Sha256AsAscii(const void *s, char *out, size_t out_size)
718 {
719  const Sha256Type *sha = s;
720  uint32_t x;
721  int i;
722  char str[256];
723  for (i = 0, x = 0; x < sizeof(sha->sha256); x++) {
724  i += snprintf(&str[i], 255-i, "%02x", sha->sha256[x]);
725  }
726  strlcat(out, str, out_size);
727  strlcat(out, "\n", out_size);
728  return strlen(out);
729 }
730 
731 void DatasetsSave(void)
732 {
733  SCLogDebug("saving datasets: %p", sets);
735  Dataset *set = sets;
736  while (set) {
737  if (strlen(set->save) == 0)
738  goto next;
739 
740  FILE *fp = fopen(set->save, "w");
741  if (fp == NULL)
742  goto next;
743 
744  SCLogDebug("dumping %s to %s", set->name, set->save);
745 
746  switch (set->type) {
747  case DATASET_TYPE_STRING:
748  THashWalk(set->hash, StringAsBase64, SaveCallback, fp);
749  break;
750  case DATASET_TYPE_MD5:
751  THashWalk(set->hash, Md5AsAscii, SaveCallback, fp);
752  break;
753  case DATASET_TYPE_SHA256:
754  THashWalk(set->hash, Sha256AsAscii, SaveCallback, fp);
755  break;
756  }
757 
758  fclose(fp);
759 
760  next:
761  set = set->next;
762  }
764 }
765 
766 static int DatasetLookupString(Dataset *set, const uint8_t *data, const uint32_t data_len)
767 {
768  if (set == NULL)
769  return -1;
770 
771  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep.value = 0 };
772  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
773  if (rdata) {
774  THashDataUnlock(rdata);
775  return 1;
776  }
777  return 0;
778 }
779 
780 static DataRepResultType DatasetLookupStringwRep(Dataset *set,
781  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
782 {
783  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
784 
785  if (set == NULL)
786  return rrep;
787 
788  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = *rep };
789  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
790  if (rdata) {
791  StringType *found = rdata->data;
792  rrep.found = true;
793  rrep.rep = found->rep;
794  DatasetUnlockData(rdata);
795  return rrep;
796  }
797  return rrep;
798 }
799 
800 static int DatasetLookupMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
801 {
802  if (set == NULL)
803  return -1;
804 
805  if (data_len != 16)
806  return -1;
807 
808  Md5Type lookup = { .rep.value = 0 };
809  memcpy(lookup.md5, data, data_len);
810  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
811  if (rdata) {
812  DatasetUnlockData(rdata);
813  return 1;
814  }
815  return 0;
816 }
817 
818 static DataRepResultType DatasetLookupMd5wRep(Dataset *set,
819  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
820 {
821  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
822 
823  if (set == NULL)
824  return rrep;
825 
826  if (data_len != 16)
827  return rrep;
828 
829  Md5Type lookup = { .rep.value = 0};
830  memcpy(lookup.md5, data, data_len);
831  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
832  if (rdata) {
833  Md5Type *found = rdata->data;
834  rrep.found = true;
835  rrep.rep = found->rep;
836  DatasetUnlockData(rdata);
837  return rrep;
838  }
839  return rrep;
840 }
841 
842 static int DatasetLookupSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
843 {
844  if (set == NULL)
845  return -1;
846 
847  if (data_len != 32)
848  return -1;
849 
850  Sha256Type lookup = { .rep.value = 0 };
851  memcpy(lookup.sha256, data, data_len);
852  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
853  if (rdata) {
854  DatasetUnlockData(rdata);
855  return 1;
856  }
857  return 0;
858 }
859 
860 static DataRepResultType DatasetLookupSha256wRep(Dataset *set,
861  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
862 {
863  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
864 
865  if (set == NULL)
866  return rrep;
867 
868  if (data_len != 32)
869  return rrep;
870 
871  Sha256Type lookup = { .rep.value = 0 };
872  memcpy(lookup.sha256, data, data_len);
873  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
874  if (rdata) {
875  Sha256Type *found = rdata->data;
876  rrep.found = true;
877  rrep.rep = found->rep;
878  DatasetUnlockData(rdata);
879  return rrep;
880  }
881  return rrep;
882 }
883 
884 /**
885  * \brief see if \a data is part of the set
886  * \param set dataset
887  * \param data data to look up
888  * \param data_len length in bytes of \a data
889  * \retval -1 error
890  * \retval 0 not found
891  * \retval 1 found
892  */
893 int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len)
894 {
895  if (set == NULL)
896  return -1;
897 
898  switch (set->type) {
899  case DATASET_TYPE_STRING:
900  return DatasetLookupString(set, data, data_len);
901  case DATASET_TYPE_MD5:
902  return DatasetLookupMd5(set, data, data_len);
903  case DATASET_TYPE_SHA256:
904  return DatasetLookupSha256(set, data, data_len);
905  }
906  return -1;
907 }
908 
909 DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
910  const DataRepType *rep)
911 {
912  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
913  if (set == NULL)
914  return rrep;
915 
916  switch (set->type) {
917  case DATASET_TYPE_STRING:
918  return DatasetLookupStringwRep(set, data, data_len, rep);
919  case DATASET_TYPE_MD5:
920  return DatasetLookupMd5wRep(set, data, data_len, rep);
921  case DATASET_TYPE_SHA256:
922  return DatasetLookupSha256wRep(set, data, data_len, rep);
923  }
924  return rrep;
925 }
926 
927 /**
928  * \retval 1 data was added to the hash
929  * \retval 0 data was not added to the hash as it is already there
930  * \retval -1 failed to add data to the hash
931  */
932 static int DatasetAddString(Dataset *set, const uint8_t *data, const uint32_t data_len)
933 {
934  if (set == NULL)
935  return -1;
936 
937  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
938  .rep.value = 0 };
939  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
940  if (res.data) {
941  DatasetUnlockData(res.data);
942  return res.is_new ? 1 : 0;
943  }
944  return -1;
945 }
946 
947 /**
948  * \retval 1 data was added to the hash
949  * \retval 0 data was not added to the hash as it is already there
950  * \retval -1 failed to add data to the hash
951  */
952 static int DatasetAddStringwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
953  DataRepType *rep)
954 {
955  if (set == NULL)
956  return -1;
957 
958  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
959  .rep = *rep };
960  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
961  if (res.data) {
962  DatasetUnlockData(res.data);
963  return res.is_new ? 1 : 0;
964  }
965  return -1;
966 }
967 
968 static int DatasetAddMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
969 {
970  if (set == NULL)
971  return -1;
972 
973  if (data_len != 16)
974  return -2;
975 
976  Md5Type lookup = { .rep.value = 0 };
977  memcpy(lookup.md5, data, 16);
978  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
979  if (res.data) {
980  DatasetUnlockData(res.data);
981  return res.is_new ? 1 : 0;
982  }
983  return -1;
984 }
985 
986 static int DatasetAddMd5wRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
987  DataRepType *rep)
988 {
989  if (set == NULL)
990  return -1;
991 
992  if (data_len != 16)
993  return -2;
994 
995  Md5Type lookup = { .rep = *rep };
996  memcpy(lookup.md5, data, 16);
997  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
998  if (res.data) {
999  DatasetUnlockData(res.data);
1000  return res.is_new ? 1 : 0;
1001  }
1002  return -1;
1003 }
1004 
1005 static int DatasetAddSha256wRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1006  DataRepType *rep)
1007 {
1008  if (set == NULL)
1009  return -1;
1010 
1011  if (data_len != 32)
1012  return -2;
1013 
1014  Sha256Type lookup = { .rep = *rep };
1015  memcpy(lookup.sha256, data, 32);
1016  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1017  if (res.data) {
1018  DatasetUnlockData(res.data);
1019  return res.is_new ? 1 : 0;
1020  }
1021  return -1;
1022 }
1023 
1024 static int DatasetAddSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1025 {
1026  if (set == NULL)
1027  return -1;
1028 
1029  if (data_len != 32)
1030  return -2;
1031 
1032  Sha256Type lookup = { .rep.value = 0 };
1033  memcpy(lookup.sha256, data, 32);
1034  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1035  if (res.data) {
1036  DatasetUnlockData(res.data);
1037  return res.is_new ? 1 : 0;
1038  }
1039  return -1;
1040 }
1041 
1042 int DatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
1043 {
1044  if (set == NULL)
1045  return -1;
1046 
1047  switch (set->type) {
1048  case DATASET_TYPE_STRING:
1049  return DatasetAddString(set, data, data_len);
1050  case DATASET_TYPE_MD5:
1051  return DatasetAddMd5(set, data, data_len);
1052  case DATASET_TYPE_SHA256:
1053  return DatasetAddSha256(set, data, data_len);
1054  }
1055  return -1;
1056 }
1057 
1058 static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1059  DataRepType *rep)
1060 {
1061  if (set == NULL)
1062  return -1;
1063 
1064  switch (set->type) {
1065  case DATASET_TYPE_STRING:
1066  return DatasetAddStringwRep(set, data, data_len, rep);
1067  case DATASET_TYPE_MD5:
1068  return DatasetAddMd5wRep(set, data, data_len, rep);
1069  case DATASET_TYPE_SHA256:
1070  return DatasetAddSha256wRep(set, data, data_len, rep);
1071  }
1072  return -1;
1073 }
1074 
1075 /** \brief add serialized data to set
1076  * \retval int 1 added
1077  * \retval int 0 already in hash
1078  * \retval int -1 API error (not added)
1079  * \retval int -2 DATA error
1080  */
1081 int DatasetAddSerialized(Dataset *set, const char *string)
1082 {
1083  if (set == NULL)
1084  return -1;
1085 
1086  switch (set->type) {
1087  case DATASET_TYPE_STRING: {
1088  // coverity[alloc_strlen : FALSE]
1089  uint8_t decoded[strlen(string)];
1090  uint32_t len = DecodeBase64(decoded, (const uint8_t *)string, strlen(string), 1);
1091  if (len == 0) {
1092  return -2;
1093  }
1094 
1095  return DatasetAddString(set, decoded, len);
1096  }
1097  case DATASET_TYPE_MD5: {
1098  if (strlen(string) != 32)
1099  return -2;
1100  uint8_t hash[16];
1101  if (HexToRaw((const uint8_t *)string, 32, hash, sizeof(hash)) < 0)
1102  return -2;
1103  return DatasetAddMd5(set, hash, 16);
1104  }
1105  case DATASET_TYPE_SHA256: {
1106  if (strlen(string) != 64)
1107  return -2;
1108  uint8_t hash[32];
1109  if (HexToRaw((const uint8_t *)string, 64, hash, sizeof(hash)) < 0)
1110  return -2;
1111  return DatasetAddSha256(set, hash, 32);
1112  }
1113  }
1114  return -1;
1115 }
1116 
1117 /**
1118  * \retval 1 data was removed from the hash
1119  * \retval 0 data not removed (busy)
1120  * \retval -1 data not found
1121  */
1122 static int DatasetRemoveString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1123 {
1124  if (set == NULL)
1125  return -1;
1126 
1127  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1128  .rep.value = 0 };
1129  return THashRemoveFromHash(set->hash, &lookup);
1130 }
1131 
1132 static int DatasetRemoveMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1133 {
1134  if (set == NULL)
1135  return -1;
1136 
1137  if (data_len != 16)
1138  return -2;
1139 
1140  Md5Type lookup = { .rep.value = 0 };
1141  memcpy(lookup.md5, data, 16);
1142  return THashRemoveFromHash(set->hash, &lookup);
1143 }
1144 
1145 static int DatasetRemoveSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1146 {
1147  if (set == NULL)
1148  return -1;
1149 
1150  if (data_len != 32)
1151  return -2;
1152 
1153  Sha256Type lookup = { .rep.value = 0 };
1154  memcpy(lookup.sha256, data, 32);
1155  return THashRemoveFromHash(set->hash, &lookup);
1156 }
1157 
1158 /** \brief remove serialized data from set
1159  * \retval int 1 removed
1160  * \retval int 0 found but busy (not removed)
1161  * \retval int -1 API error (not removed)
1162  * \retval int -2 DATA error */
1163 int DatasetRemoveSerialized(Dataset *set, const char *string)
1164 {
1165  if (set == NULL)
1166  return -1;
1167 
1168  switch (set->type) {
1169  case DATASET_TYPE_STRING: {
1170  // coverity[alloc_strlen : FALSE]
1171  uint8_t decoded[strlen(string)];
1172  uint32_t len = DecodeBase64(decoded, (const uint8_t *)string, strlen(string), 1);
1173  if (len == 0) {
1174  return -2;
1175  }
1176 
1177  return DatasetRemoveString(set, decoded, len);
1178  }
1179  case DATASET_TYPE_MD5: {
1180  if (strlen(string) != 32)
1181  return -2;
1182  uint8_t hash[16];
1183  if (HexToRaw((const uint8_t *)string, 32, hash, sizeof(hash)) < 0)
1184  return -2;
1185  return DatasetRemoveMd5(set, hash, 16);
1186  }
1187  case DATASET_TYPE_SHA256: {
1188  if (strlen(string) != 64)
1189  return -2;
1190  uint8_t hash[32];
1191  if (HexToRaw((const uint8_t *)string, 64, hash, sizeof(hash)) < 0)
1192  return -2;
1193  return DatasetRemoveSha256(set, hash, 32);
1194  }
1195  }
1196  return -1;
1197 }
util-byte.h
SC_ERR_DATASET
@ SC_ERR_DATASET
Definition: util-error.h:355
sets_lock
SCMutex sets_lock
Definition: datasets.c:37
StringType::rep
DataRepType rep
Definition: datasets-string.h:31
len
uint8_t len
Definition: app-layer-dnp3.h:2
datasets-string.h
DataRepResultType::rep
DataRepType rep
Definition: datasets-reputation.h:33
THashDataGetResult::data
THashData * data
Definition: util-thash.h:205
datasets-md5.h
Dataset::name
char name[DATASET_NAME_MAX_LEN+1]
Definition: datasets.h:39
ConfNode_::val
char * val
Definition: conf.h:34
Dataset::id
uint32_t id
Definition: datasets.h:41
Dataset::save
char save[PATH_MAX]
Definition: datasets.h:47
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
datasets-sha256.h
THashRemoveFromHash
int THashRemoveFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:747
TYPE_STATE
@ TYPE_STATE
Definition: datasets.c:368
Md5Type
Definition: datasets-md5.h:29
Dataset::hash
THashTableContext * hash
Definition: datasets.h:44
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:175
Sha256Type::sha256
uint8_t sha256[32]
Definition: datasets-sha256.h:30
Md5Type::rep
DataRepType rep
Definition: datasets-md5.h:31
DataRepResultType::found
bool found
Definition: datasets-reputation.h:32
Dataset::type
enum DatasetTypes type
Definition: datasets.h:40
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
THashInit
THashTableContext * THashInit(const char *cnf_prefix, size_t data_size, int(*DataSet)(void *, void *), void(*DataFree)(void *), uint32_t(*DataHash)(void *), bool(*DataCompare)(void *, void *))
Definition: util-thash.c:293
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
util-base64.h
DATASET_TYPE_SHA256
@ DATASET_TYPE_SHA256
Definition: datasets.h:34
Sha256Type::rep
DataRepType rep
Definition: datasets-sha256.h:31
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
datasets-reputation.h
DecodeBase64
uint32_t DecodeBase64(uint8_t *dest, const uint8_t *src, uint32_t len, int strict)
Decodes a base64-encoded string buffer into an ascii-encoded byte buffer.
Definition: util-base64.c:91
Md5Type::md5
uint8_t md5[16]
Definition: datasets-md5.h:30
SC_ERR_CONF_NAME_TOO_LONG
@ SC_ERR_CONF_NAME_TOO_LONG
Definition: util-error.h:275
Md5StrCompare
bool Md5StrCompare(void *a, void *b)
Definition: datasets-md5.c:42
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
DataRepResultType
Definition: datasets-reputation.h:31
Md5StrHash
uint32_t Md5StrHash(void *s)
Definition: datasets-md5.c:50
StringSet
int StringSet(void *dst, void *src)
Definition: datasets-string.c:61
datasets.h
TYPE_LOAD
@ TYPE_LOAD
Definition: datasets.c:369
type
uint8_t type
Definition: decode-icmpv4.h:0
DatasetAdd
int DatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
Definition: datasets.c:1042
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
StringAsBase64
int StringAsBase64(const void *s, char *out, size_t out_size)
Definition: datasets-string.c:46
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
res
PoolThreadReserved res
Definition: stream-tcp-private.h:0
DATASET_TYPE_NOTSET
#define DATASET_TYPE_NOTSET
Definition: datasets.h:31
util-print.h
DatasetGet
Dataset * DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load)
Definition: datasets.c:419
util-crypt.h
DatasetPostReloadCleanup
void DatasetPostReloadCleanup(void)
Definition: datasets.c:570
Sha256StrSet
int Sha256StrSet(void *dst, void *src)
Definition: datasets-sha256.c:33
DatasetsDestroy
void DatasetsDestroy(void)
Definition: datasets.c:676
THashDataGetResult
Definition: util-thash.h:204
StringType
Definition: datasets-string.h:29
DatasetsSave
void DatasetsSave(void)
Definition: datasets.c:731
conf.h
DatasetLookup
int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len)
see if data is part of the set
Definition: datasets.c:893
StringType::ptr
uint8_t * ptr
Definition: datasets-string.h:32
DatasetRemoveSerialized
int DatasetRemoveSerialized(Dataset *set, const char *string)
remove serialized data from set
Definition: datasets.c:1163
Sha256StrHash
uint32_t Sha256StrHash(void *s)
Definition: datasets-sha256.c:50
g_system
bool g_system
Definition: suricata.c:223
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:814
THashShutdown
void THashShutdown(THashTableContext *ctx)
shutdown the flow engine
Definition: util-thash.c:325
DatasetTypes
DatasetTypes
Definition: datasets.h:30
Dataset::next
struct Dataset * next
Definition: datasets.h:49
THashData_::data
void * data
Definition: util-thash.h:93
Sha256Type
Definition: datasets-sha256.h:29
Sha256StrFree
void Sha256StrFree(void *s)
Definition: datasets-sha256.c:62
THashData_
Definition: util-thash.h:86
suricata-common.h
StringHash
uint32_t StringHash(void *s)
Definition: datasets-string.c:88
DATASET_NAME_MAX_LEN
#define DATASET_NAME_MAX_LEN
Definition: datasets.h:37
ConfNode_::name
char * name
Definition: conf.h:33
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:39
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
Md5StrSet
int Md5StrSet(void *dst, void *src)
Definition: datasets-md5.c:33
StringCompare
bool StringCompare(void *a, void *b)
Definition: datasets-string.c:77
THashGetFromHash
struct THashDataGetResult THashGetFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:505
FatalError
#define FatalError(x,...)
Definition: util-debug.h:532
THashLookupFromHash
THashData * THashLookupFromHash(THashTableContext *ctx, void *data)
look up data in the hash
Definition: util-thash.c:615
DataRepType::value
uint16_t value
Definition: datasets-reputation.h:28
THashDecrUsecnt
#define THashDecrUsecnt(h)
Definition: util-thash.h:169
DatasetFind
Dataset * DatasetFind(const char *name, enum DatasetTypes type)
look for set by name without creating it
Definition: datasets.c:405
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
DatasetsInit
int DatasetsInit(void)
Definition: datasets.c:596
str
#define str(s)
Definition: suricata-common.h:273
DatasetGetTypeFromString
enum DatasetTypes DatasetGetTypeFromString(const char *s)
Definition: datasets.c:52
THashWalk
int THashWalk(THashTableContext *ctx, THashFormatFunc FormatterFunc, THashOutputFunc OutputterFunc, void *output_ctx)
Walk the hash.
Definition: util-thash.c:360
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
Dataset::hidden
bool hidden
Definition: datasets.h:43
DatasetReload
void DatasetReload(void)
Definition: datasets.c:548
DatasetGetPathType
DatasetGetPathType
Definition: datasets.c:367
Sha256StrCompare
bool Sha256StrCompare(void *a, void *b)
Definition: datasets-sha256.c:42
DATASET_TYPE_MD5
@ DATASET_TYPE_MD5
Definition: datasets.h:33
DATASET_TYPE_STRING
@ DATASET_TYPE_STRING
Definition: datasets.h:32
StringParseU16RangeCheck
int StringParseU16RangeCheck(uint16_t *res, int base, uint16_t len, const char *str, uint16_t min, uint16_t max)
Definition: util-byte.c:429
DatasetAddSerialized
int DatasetAddSerialized(Dataset *set, const char *string)
add serialized data to set
Definition: datasets.c:1081
Dataset
Definition: datasets.h:38
Dataset::from_yaml
bool from_yaml
Definition: datasets.h:42
util-thash.h
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:232
Dataset::load
char load[PATH_MAX]
Definition: datasets.h:46
SC_ERR_INVALID_NUMERIC_VALUE
@ SC_ERR_INVALID_NUMERIC_VALUE
Definition: util-error.h:90
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
DataRepType
Definition: datasets-reputation.h:27
Md5StrFree
void Md5StrFree(void *s)
Definition: datasets-md5.c:62
SC_ERR_INVALID_HASH
@ SC_ERR_INVALID_HASH
Definition: util-error.h:319
SCMutex
#define SCMutex
Definition: threads-debug.h:114
StringFree
void StringFree(void *s)
Definition: datasets-string.c:102
ConfigGetDataDirectory
const char * ConfigGetDataDirectory()
Definition: util-conf.c:82
DatasetLookupwRep
DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
Definition: datasets.c:909