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 "suricata.h"
26 #include "conf.h"
27 #include "datasets.h"
28 #include "datasets-string.h"
29 #include "datasets-ipv4.h"
30 #include "datasets-ipv6.h"
31 #include "datasets-md5.h"
32 #include "datasets-sha256.h"
33 #include "datasets-reputation.h"
34 #include "util-conf.h"
35 #include "util-thash.h"
36 #include "util-print.h"
37 #include "util-base64.h" // decode base64
38 #include "util-byte.h"
39 #include "util-misc.h"
40 #include "util-path.h"
41 #include "util-debug.h"
42 
44 static Dataset *sets = NULL;
45 static uint32_t set_ids = 0;
46 
47 static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
48  DataRepType *rep);
49 
50 static inline void DatasetUnlockData(THashData *d)
51 {
52  (void) THashDecrUsecnt(d);
53  THashDataUnlock(d);
54 }
55 static bool DatasetIsStatic(const char *save, const char *load);
56 static void GetDefaultMemcap(uint64_t *memcap, uint32_t *hashsize);
57 
58 enum DatasetTypes DatasetGetTypeFromString(const char *s)
59 {
60  if (strcasecmp("md5", s) == 0)
61  return DATASET_TYPE_MD5;
62  if (strcasecmp("sha256", s) == 0)
63  return DATASET_TYPE_SHA256;
64  if (strcasecmp("string", s) == 0)
65  return DATASET_TYPE_STRING;
66  if (strcasecmp("ipv4", s) == 0)
67  return DATASET_TYPE_IPV4;
68  if (strcasecmp("ip", s) == 0)
69  return DATASET_TYPE_IPV6;
70  return DATASET_TYPE_NOTSET;
71 }
72 
73 static Dataset *DatasetAlloc(const char *name)
74 {
75  Dataset *set = SCCalloc(1, sizeof(*set));
76  if (set) {
77  set->id = set_ids++;
78  }
79  return set;
80 }
81 
82 static Dataset *DatasetSearchByName(const char *name)
83 {
84  Dataset *set = sets;
85  while (set) {
86  if (strcasecmp(name, set->name) == 0 && set->hidden == false) {
87  return set;
88  }
89  set = set->next;
90  }
91  return NULL;
92 }
93 
94 static int HexToRaw(const uint8_t *in, size_t ins, uint8_t *out, size_t outs)
95 {
96  if (ins < 2)
97  return -1;
98  if (ins % 2 != 0)
99  return -1;
100  if (outs != ins / 2)
101  return -1;
102 
103  uint8_t hash[outs];
104  memset(hash, 0, outs);
105  size_t i, x;
106  for (x = 0, i = 0; i < ins; i+=2, x++) {
107  char buf[3] = { 0, 0, 0 };
108  buf[0] = in[i];
109  buf[1] = in[i+1];
110 
111  long value = strtol(buf, NULL, 16);
112  if (value >= 0 && value <= 255)
113  hash[x] = (uint8_t)value;
114  else {
115  SCLogError("hash byte out of range %ld", value);
116  return -1;
117  }
118  }
119 
120  memcpy(out, hash, outs);
121  return 0;
122 }
123 
124 static int ParseRepLine(const char *in, size_t ins, DataRepType *rep_out)
125 {
126  SCLogDebug("in '%s'", in);
127  char raw[ins + 1];
128  memcpy(raw, in, ins);
129  raw[ins] = '\0';
130  char *line = raw;
131 
132  char *ptrs[1] = {NULL};
133  int idx = 0;
134 
135  size_t i = 0;
136  while (i < ins + 1) {
137  if (line[i] == ',' || line[i] == '\n' || line[i] == '\0') {
138  line[i] = '\0';
139  SCLogDebug("line '%s'", line);
140 
141  ptrs[idx] = line;
142  idx++;
143 
144  if (idx == 1)
145  break;
146  } else {
147  i++;
148  }
149  }
150 
151  if (idx != 1) {
152  SCLogDebug("idx %d", idx);
153  return -1;
154  }
155 
156  uint16_t v = 0;
157  int r = StringParseU16RangeCheck(&v, 10, strlen(ptrs[0]), ptrs[0], 0, USHRT_MAX);
158  if (r != (int)strlen(ptrs[0])) {
159  SCLogError("'%s' is not a valid reputation value (0-65535)", ptrs[0]);
160  return -1;
161  }
162  SCLogDebug("v %"PRIu16" raw %s", v, ptrs[0]);
163 
164  rep_out->value = v;
165  return 0;
166 }
167 
168 static int DatasetLoadIPv4(Dataset *set)
169 {
170  if (strlen(set->load) == 0)
171  return 0;
172 
173  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
174  const char *fopen_mode = "r";
175  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
176  fopen_mode = "a+";
177  }
178 
179  FILE *fp = fopen(set->load, fopen_mode);
180  if (fp == NULL) {
181  SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
182  return -1;
183  }
184 
185  uint32_t cnt = 0;
186  char line[1024];
187  while (fgets(line, (int)sizeof(line), fp) != NULL) {
188  char *r = strchr(line, ',');
189  if (r == NULL) {
190  line[strlen(line) - 1] = '\0';
191  SCLogDebug("line: '%s'", line);
192 
193  struct in_addr in;
194  if (inet_pton(AF_INET, line, &in) != 1) {
195  FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
196  continue;
197  }
198 
199  if (DatasetAdd(set, (const uint8_t *)&in.s_addr, 4) < 0) {
200  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
201  continue;
202  }
203  cnt++;
204 
205  /* list with rep data */
206  } else {
207  line[strlen(line) - 1] = '\0';
208  SCLogDebug("IPv4 with REP line: '%s'", line);
209 
210  *r = '\0';
211 
212  struct in_addr in;
213  if (inet_pton(AF_INET, line, &in) != 1) {
214  FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
215  continue;
216  }
217 
218  r++;
219 
220  DataRepType rep = { .value = 0 };
221  if (ParseRepLine(r, strlen(r), &rep) < 0) {
222  FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
223  continue;
224  }
225 
226  SCLogDebug("rep v:%u", rep.value);
227  if (DatasetAddwRep(set, (const uint8_t *)&in.s_addr, 4, &rep) < 0) {
228  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
229  continue;
230  }
231 
232  cnt++;
233  }
234  }
236 
237  fclose(fp);
238  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
239  return 0;
240 }
241 
242 static int ParseIpv6String(Dataset *set, char *line, struct in6_addr *in6)
243 {
244  /* Checking IPv6 case */
245  char *got_colon = strchr(line, ':');
246  if (got_colon) {
247  uint32_t ip6addr[4];
248  if (inet_pton(AF_INET6, line, in6) != 1) {
249  FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
250  return -1;
251  }
252  memcpy(&ip6addr, in6->s6_addr, sizeof(ip6addr));
253  /* IPv4 in IPv6 notation needs transformation to internal Suricata storage */
254  if (ip6addr[0] == 0 && ip6addr[1] == 0 && ip6addr[2] == 0xFFFF0000) {
255  ip6addr[0] = ip6addr[3];
256  ip6addr[2] = 0;
257  ip6addr[3] = 0;
258  memcpy(in6, ip6addr, sizeof(struct in6_addr));
259  }
260  } else {
261  /* IPv4 case */
262  struct in_addr in;
263  if (inet_pton(AF_INET, line, &in) != 1) {
264  FatalErrorOnInit("dataset data parse failed %s/%s: %s", set->name, set->load, line);
265  return -1;
266  }
267  memset(in6, 0, sizeof(struct in6_addr));
268  memcpy(in6, &in, sizeof(struct in_addr));
269  }
270  return 0;
271 }
272 
273 static int DatasetLoadIPv6(Dataset *set)
274 {
275  if (strlen(set->load) == 0)
276  return 0;
277 
278  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
279  const char *fopen_mode = "r";
280  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
281  fopen_mode = "a+";
282  }
283 
284  FILE *fp = fopen(set->load, fopen_mode);
285  if (fp == NULL) {
286  SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
287  return -1;
288  }
289 
290  uint32_t cnt = 0;
291  char line[1024];
292  while (fgets(line, (int)sizeof(line), fp) != NULL) {
293  char *r = strchr(line, ',');
294  if (r == NULL) {
295  line[strlen(line) - 1] = '\0';
296  SCLogDebug("line: '%s'", line);
297 
298  struct in6_addr in6;
299  int ret = ParseIpv6String(set, line, &in6);
300  if (ret < 0) {
301  FatalErrorOnInit("unable to parse IP address");
302  continue;
303  }
304 
305  if (DatasetAdd(set, (const uint8_t *)&in6.s6_addr, 16) < 0) {
306  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
307  continue;
308  }
309  cnt++;
310 
311  /* list with rep data */
312  } else {
313  line[strlen(line) - 1] = '\0';
314  SCLogDebug("IPv6 with REP line: '%s'", line);
315 
316  *r = '\0';
317 
318  struct in6_addr in6;
319  int ret = ParseIpv6String(set, line, &in6);
320  if (ret < 0) {
321  FatalErrorOnInit("unable to parse IP address");
322  continue;
323  }
324 
325  r++;
326 
327  DataRepType rep = { .value = 0 };
328  if (ParseRepLine(r, strlen(r), &rep) < 0) {
329  FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
330  continue;
331  }
332 
333  SCLogDebug("rep v:%u", rep.value);
334  if (DatasetAddwRep(set, (const uint8_t *)&in6.s6_addr, 16, &rep) < 0) {
335  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
336  continue;
337  }
338 
339  cnt++;
340  }
341  }
343 
344  fclose(fp);
345  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
346  return 0;
347 }
348 
349 static int DatasetLoadMd5(Dataset *set)
350 {
351  if (strlen(set->load) == 0)
352  return 0;
353 
354  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
355  const char *fopen_mode = "r";
356  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
357  fopen_mode = "a+";
358  }
359 
360  FILE *fp = fopen(set->load, fopen_mode);
361  if (fp == NULL) {
362  SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
363  return -1;
364  }
365 
366  uint32_t cnt = 0;
367  char line[1024];
368  while (fgets(line, (int)sizeof(line), fp) != NULL) {
369  /* straight black/white list */
370  if (strlen(line) == 33) {
371  line[strlen(line) - 1] = '\0';
372  SCLogDebug("line: '%s'", line);
373 
374  uint8_t hash[16];
375  if (HexToRaw((const uint8_t *)line, 32, hash, sizeof(hash)) < 0) {
376  FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
377  continue;
378  }
379 
380  if (DatasetAdd(set, (const uint8_t *)hash, 16) < 0) {
381  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
382  continue;
383  }
384  cnt++;
385 
386  /* list with rep data */
387  } else if (strlen(line) > 33 && line[32] == ',') {
388  line[strlen(line) - 1] = '\0';
389  SCLogDebug("MD5 with REP line: '%s'", line);
390 
391  uint8_t hash[16];
392  if (HexToRaw((const uint8_t *)line, 32, hash, sizeof(hash)) < 0) {
393  FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
394  continue;
395  }
396 
397  DataRepType rep = { .value = 0};
398  if (ParseRepLine(line + 33, strlen(line) - 33, &rep) < 0) {
399  FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
400  continue;
401  }
402 
403  SCLogDebug("rep v:%u", rep.value);
404  if (DatasetAddwRep(set, hash, 16, &rep) < 0) {
405  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
406  continue;
407  }
408 
409  cnt++;
410  }
411  else {
412  FatalErrorOnInit("MD5 bad line len %u: '%s'", (uint32_t)strlen(line), line);
413  continue;
414  }
415  }
417 
418  fclose(fp);
419  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
420  return 0;
421 }
422 
423 static int DatasetLoadSha256(Dataset *set)
424 {
425  if (strlen(set->load) == 0)
426  return 0;
427 
428  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
429  const char *fopen_mode = "r";
430  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
431  fopen_mode = "a+";
432  }
433 
434  FILE *fp = fopen(set->load, fopen_mode);
435  if (fp == NULL) {
436  SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
437  return -1;
438  }
439 
440  uint32_t cnt = 0;
441  char line[1024];
442  while (fgets(line, (int)sizeof(line), fp) != NULL) {
443  /* straight black/white list */
444  if (strlen(line) == 65) {
445  line[strlen(line) - 1] = '\0';
446  SCLogDebug("line: '%s'", line);
447 
448  uint8_t hash[32];
449  if (HexToRaw((const uint8_t *)line, 64, hash, sizeof(hash)) < 0) {
450  FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
451  continue;
452  }
453 
454  if (DatasetAdd(set, (const uint8_t *)hash, (uint32_t)32) < 0) {
455  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
456  continue;
457  }
458  cnt++;
459 
460  /* list with rep data */
461  } else if (strlen(line) > 65 && line[64] == ',') {
462  line[strlen(line) - 1] = '\0';
463  SCLogDebug("SHA-256 with REP line: '%s'", line);
464 
465  uint8_t hash[32];
466  if (HexToRaw((const uint8_t *)line, 64, hash, sizeof(hash)) < 0) {
467  FatalErrorOnInit("bad hash for dataset %s/%s", set->name, set->load);
468  continue;
469  }
470 
471  DataRepType rep = { .value = 0 };
472  if (ParseRepLine(line + 65, strlen(line) - 65, &rep) < 0) {
473  FatalErrorOnInit("bad rep for dataset %s/%s", set->name, set->load);
474  continue;
475  }
476 
477  SCLogDebug("rep %u", rep.value);
478 
479  if (DatasetAddwRep(set, hash, 32, &rep) < 0) {
480  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
481  continue;
482  }
483  cnt++;
484  }
485  }
487 
488  fclose(fp);
489  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
490  return 0;
491 }
492 
493 static int DatasetLoadString(Dataset *set)
494 {
495  if (strlen(set->load) == 0)
496  return 0;
497 
498  SCLogConfig("dataset: %s loading from '%s'", set->name, set->load);
499  const char *fopen_mode = "r";
500  if (strlen(set->save) > 0 && strcmp(set->save, set->load) == 0) {
501  fopen_mode = "a+";
502  }
503 
504  FILE *fp = fopen(set->load, fopen_mode);
505  if (fp == NULL) {
506  SCLogError("fopen '%s' failed: %s", set->load, strerror(errno));
507  return -1;
508  }
509 
510  uint32_t cnt = 0;
511  char line[1024];
512  while (fgets(line, (int)sizeof(line), fp) != NULL) {
513  if (strlen(line) <= 1)
514  continue;
515 
516  char *r = strchr(line, ',');
517  if (r == NULL) {
518  line[strlen(line) - 1] = '\0';
519  SCLogDebug("line: '%s'", line);
520 
521  // coverity[alloc_strlen : FALSE]
522  uint8_t decoded[strlen(line)];
523  uint32_t consumed = 0, num_decoded = 0;
524  Base64Ecode code = DecodeBase64(decoded, strlen(line), (const uint8_t *)line,
525  strlen(line), &consumed, &num_decoded, BASE64_MODE_STRICT);
526  if (code == BASE64_ECODE_ERR) {
527  FatalErrorOnInit("bad base64 encoding %s/%s", set->name, set->load);
528  continue;
529  }
530 
531  if (DatasetAdd(set, (const uint8_t *)decoded, num_decoded) < 0) {
532  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
533  continue;
534  }
535  cnt++;
536  } else {
537  line[strlen(line) - 1] = '\0';
538  SCLogDebug("line: '%s'", line);
539 
540  *r = '\0';
541 
542  // coverity[alloc_strlen : FALSE]
543  uint8_t decoded[strlen(line)];
544  uint32_t consumed = 0, num_decoded = 0;
545  Base64Ecode code = DecodeBase64(decoded, strlen(line), (const uint8_t *)line,
546  strlen(line), &consumed, &num_decoded, BASE64_MODE_STRICT);
547  if (code == BASE64_ECODE_ERR) {
548  FatalErrorOnInit("bad base64 encoding %s/%s", set->name, set->load);
549  continue;
550  }
551 
552  r++;
553  SCLogDebug("r '%s'", r);
554 
555  DataRepType rep = { .value = 0 };
556  if (ParseRepLine(r, strlen(r), &rep) < 0) {
557  FatalErrorOnInit("die: bad rep");
558  continue;
559  }
560  SCLogDebug("rep %u", rep.value);
561 
562  if (DatasetAddwRep(set, (const uint8_t *)decoded, num_decoded, &rep) < 0) {
563  FatalErrorOnInit("dataset data add failed %s/%s", set->name, set->load);
564  continue;
565  }
566  cnt++;
567 
568  SCLogDebug("line with rep %s, %s", line, r);
569  }
570  }
572 
573  fclose(fp);
574  SCLogConfig("dataset: %s loaded %u records", set->name, cnt);
575  return 0;
576 }
577 
578 extern bool g_system;
579 
583 };
584 
585 static void DatasetGetPath(const char *in_path,
586  char *out_path, size_t out_size, enum DatasetGetPathType type)
587 {
588  char path[PATH_MAX];
589  struct stat st;
590 
591  if (PathIsAbsolute(in_path)) {
592  strlcpy(path, in_path, sizeof(path));
593  strlcpy(out_path, path, out_size);
594  return;
595  }
596 
597  const char *data_dir = ConfigGetDataDirectory();
598  if (stat(data_dir, &st) != 0) {
599  SCLogDebug("data-dir '%s': %s", data_dir, strerror(errno));
600  return;
601  }
602 
603  snprintf(path, sizeof(path), "%s/%s", data_dir, in_path); // TODO WINDOWS
604 
605  if (type == TYPE_LOAD) {
606  if (stat(path, &st) != 0) {
607  SCLogDebug("path %s: %s", path, strerror(errno));
608  if (!g_system) {
609  snprintf(path, sizeof(path), "%s", in_path);
610  }
611  }
612  }
613  strlcpy(out_path, path, out_size);
614  SCLogDebug("in_path \'%s\' => \'%s\'", in_path, out_path);
615 }
616 
617 /** \brief look for set by name without creating it */
618 Dataset *DatasetFind(const char *name, enum DatasetTypes type)
619 {
621  Dataset *set = DatasetSearchByName(name);
622  if (set) {
623  if (set->type != type) {
625  return NULL;
626  }
627  }
629  return set;
630 }
631 
632 Dataset *DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load,
633  uint64_t memcap, uint32_t hashsize)
634 {
635  uint64_t default_memcap = 0;
636  uint32_t default_hashsize = 0;
637  if (strlen(name) > DATASET_NAME_MAX_LEN) {
638  return NULL;
639  }
640 
642  Dataset *set = DatasetSearchByName(name);
643  if (set) {
644  if (type != DATASET_TYPE_NOTSET && set->type != type) {
645  SCLogError("dataset %s already "
646  "exists and is of type %u",
647  set->name, set->type);
649  return NULL;
650  }
651 
652  if ((save == NULL || strlen(save) == 0) &&
653  (load == NULL || strlen(load) == 0)) {
654  // OK, rule keyword doesn't have to set state/load,
655  // even when yaml set has set it.
656  } else {
657  if ((save == NULL && strlen(set->save) > 0) ||
658  (save != NULL && strcmp(set->save, save) != 0)) {
659  SCLogError("dataset %s save mismatch: %s != %s", set->name, set->save, save);
661  return NULL;
662  }
663  if ((load == NULL && strlen(set->load) > 0) ||
664  (load != NULL && strcmp(set->load, load) != 0)) {
665  SCLogError("dataset %s load mismatch: %s != %s", set->name, set->load, load);
667  return NULL;
668  }
669  }
670 
672  return set;
673  } else {
674  if (type == DATASET_TYPE_NOTSET) {
675  SCLogError("dataset %s not defined", name);
676  goto out_err;
677  }
678  }
679 
680  set = DatasetAlloc(name);
681  if (set == NULL) {
682  goto out_err;
683  }
684 
685  strlcpy(set->name, name, sizeof(set->name));
686  set->type = type;
687  if (save && strlen(save)) {
688  strlcpy(set->save, save, sizeof(set->save));
689  SCLogDebug("name %s save '%s'", name, set->save);
690  }
691  if (load && strlen(load)) {
692  strlcpy(set->load, load, sizeof(set->load));
693  SCLogDebug("set \'%s\' loading \'%s\' from \'%s\'", set->name, load, set->load);
694  }
695 
696  char cnf_name[128];
697  snprintf(cnf_name, sizeof(cnf_name), "datasets.%s.hash", name);
698 
699  GetDefaultMemcap(&default_memcap, &default_hashsize);
700  switch (type) {
701  case DATASET_TYPE_MD5:
702  set->hash = THashInit(cnf_name, sizeof(Md5Type), Md5StrSet, Md5StrFree, Md5StrHash,
703  Md5StrCompare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
704  hashsize > 0 ? hashsize : default_hashsize);
705  if (set->hash == NULL)
706  goto out_err;
707  if (DatasetLoadMd5(set) < 0)
708  goto out_err;
709  break;
710  case DATASET_TYPE_STRING:
711  set->hash = THashInit(cnf_name, sizeof(StringType), StringSet, StringFree, StringHash,
712  StringCompare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
713  hashsize > 0 ? hashsize : default_hashsize);
714  if (set->hash == NULL)
715  goto out_err;
716  if (DatasetLoadString(set) < 0)
717  goto out_err;
718  break;
719  case DATASET_TYPE_SHA256:
720  set->hash = THashInit(cnf_name, sizeof(Sha256Type), Sha256StrSet, Sha256StrFree,
721  Sha256StrHash, Sha256StrCompare, load != NULL ? 1 : 0,
722  memcap > 0 ? memcap : default_memcap,
723  hashsize > 0 ? hashsize : default_hashsize);
724  if (set->hash == NULL)
725  goto out_err;
726  if (DatasetLoadSha256(set) < 0)
727  goto out_err;
728  break;
729  case DATASET_TYPE_IPV4:
730  set->hash = THashInit(cnf_name, sizeof(IPv4Type), IPv4Set, IPv4Free, IPv4Hash,
731  IPv4Compare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
732  hashsize > 0 ? hashsize : default_hashsize);
733  if (set->hash == NULL)
734  goto out_err;
735  if (DatasetLoadIPv4(set) < 0)
736  goto out_err;
737  break;
738  case DATASET_TYPE_IPV6:
739  set->hash = THashInit(cnf_name, sizeof(IPv6Type), IPv6Set, IPv6Free, IPv6Hash,
740  IPv6Compare, load != NULL ? 1 : 0, memcap > 0 ? memcap : default_memcap,
741  hashsize > 0 ? hashsize : default_hashsize);
742  if (set->hash == NULL)
743  goto out_err;
744  if (DatasetLoadIPv6(set) < 0)
745  goto out_err;
746  break;
747  }
748 
749  if (set->hash && SC_ATOMIC_GET(set->hash->memcap_reached)) {
750  SCLogError("dataset too large for set memcap");
751  goto out_err;
752  }
753 
754  SCLogDebug("set %p/%s type %u save %s load %s",
755  set, set->name, set->type, set->save, set->load);
756 
757  set->next = sets;
758  sets = set;
759 
761  return set;
762 out_err:
763  if (set) {
764  if (set->hash) {
765  THashShutdown(set->hash);
766  }
767  SCFree(set);
768  }
770  return NULL;
771 }
772 
773 static bool DatasetIsStatic(const char *save, const char *load)
774 {
775  /* A set is static if it does not have any dynamic properties like
776  * save and/or state defined but has load defined.
777  * */
778  if ((load != NULL && strlen(load) > 0) &&
779  (save == NULL || strlen(save) == 0)) {
780  return true;
781  }
782  return false;
783 }
784 
785 void DatasetReload(void)
786 {
787  /* In order to reload the datasets, just mark the current sets as hidden
788  * and clean them up later.
789  * New datasets shall be created with the rule reload and do not require
790  * any intervention.
791  * */
793  Dataset *set = sets;
794  while (set) {
795  if (!DatasetIsStatic(set->save, set->load) || set->from_yaml == true) {
796  SCLogDebug("Not a static set, skipping %s", set->name);
797  set = set->next;
798  continue;
799  }
800  set->hidden = true;
801  SCLogDebug("Set %s at %p hidden successfully", set->name, set);
802  set = set->next;
803  }
805 }
806 
808 {
809  SCLogDebug("Post Reload Cleanup starting.. Hidden sets will be removed");
811  Dataset *cur = sets;
812  Dataset *prev = NULL;
813  while (cur) {
814  Dataset *next = cur->next;
815  if (cur->hidden == false) {
816  prev = cur;
817  cur = next;
818  continue;
819  }
820  // Delete the set in case it was hidden
821  if (prev != NULL) {
822  prev->next = next;
823  } else {
824  sets = next;
825  }
826  THashShutdown(cur->hash);
827  SCFree(cur);
828  cur = next;
829  }
831 }
832 
833 static void GetDefaultMemcap(uint64_t *memcap, uint32_t *hashsize)
834 {
835  const char *str = NULL;
836  if (ConfGet("datasets.defaults.memcap", &str) == 1) {
837  if (ParseSizeStringU64(str, memcap) < 0) {
838  SCLogWarning("memcap value cannot be deduced: %s,"
839  " resetting to default",
840  str);
841  *memcap = 0;
842  }
843  }
844  if (ConfGet("datasets.defaults.hashsize", &str) == 1) {
845  if (ParseSizeStringU32(str, hashsize) < 0) {
846  SCLogWarning("hashsize value cannot be deduced: %s,"
847  " resetting to default",
848  str);
849  *hashsize = 0;
850  }
851  }
852 }
853 
854 int DatasetsInit(void)
855 {
856  SCLogDebug("datasets start");
857  ConfNode *datasets = ConfGetNode("datasets");
858  uint64_t default_memcap = 0;
859  uint32_t default_hashsize = 0;
860  GetDefaultMemcap(&default_memcap, &default_hashsize);
861  if (datasets != NULL) {
862  int list_pos = 0;
863  ConfNode *iter = NULL;
864  TAILQ_FOREACH(iter, &datasets->head, next) {
865  if (iter->name == NULL) {
866  list_pos++;
867  continue;
868  }
869 
870  char save[PATH_MAX] = "";
871  char load[PATH_MAX] = "";
872  uint64_t memcap = 0;
873  uint32_t hashsize = 0;
874 
875  const char *set_name = iter->name;
876  if (strlen(set_name) > DATASET_NAME_MAX_LEN) {
878  "set name '%s' too long, max %d chars", set_name, DATASET_NAME_MAX_LEN);
879  continue;
880  }
881 
882  ConfNode *set_type =
883  ConfNodeLookupChild(iter, "type");
884  if (set_type == NULL) {
885  list_pos++;
886  continue;
887  }
888 
889  ConfNode *set_save =
890  ConfNodeLookupChild(iter, "state");
891  if (set_save) {
892  DatasetGetPath(set_save->val, save, sizeof(save), TYPE_STATE);
893  strlcpy(load, save, sizeof(load));
894  } else {
895  ConfNode *set_load =
896  ConfNodeLookupChild(iter, "load");
897  if (set_load) {
898  DatasetGetPath(set_load->val, load, sizeof(load), TYPE_LOAD);
899  }
900  }
901 
902  ConfNode *set_memcap = ConfNodeLookupChild(iter, "memcap");
903  if (set_memcap) {
904  if (ParseSizeStringU64(set_memcap->val, &memcap) < 0) {
905  SCLogWarning("memcap value cannot be"
906  " deduced: %s, resetting to default",
907  set_memcap->val);
908  memcap = 0;
909  }
910  }
911  ConfNode *set_hashsize = ConfNodeLookupChild(iter, "hashsize");
912  if (set_hashsize) {
913  if (ParseSizeStringU32(set_hashsize->val, &hashsize) < 0) {
914  SCLogWarning("hashsize value cannot be"
915  " deduced: %s, resetting to default",
916  set_hashsize->val);
917  hashsize = 0;
918  }
919  }
920  char conf_str[1024];
921  snprintf(conf_str, sizeof(conf_str), "datasets.%d.%s", list_pos, set_name);
922 
923  SCLogDebug("set %s type %s. Conf %s", set_name, set_type->val, conf_str);
924 
925  if (strcmp(set_type->val, "md5") == 0) {
926  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_MD5, save, load,
927  memcap > 0 ? memcap : default_memcap,
928  hashsize > 0 ? hashsize : default_hashsize);
929  if (dset == NULL) {
930  FatalErrorOnInit("failed to setup dataset for %s", set_name);
931  continue;
932  }
933  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
934  dset->from_yaml = true;
935 
936  } else if (strcmp(set_type->val, "sha256") == 0) {
937  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_SHA256, save, load,
938  memcap > 0 ? memcap : default_memcap,
939  hashsize > 0 ? hashsize : default_hashsize);
940  if (dset == NULL) {
941  FatalErrorOnInit("failed to setup dataset for %s", set_name);
942  continue;
943  }
944  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
945  dset->from_yaml = true;
946 
947  } else if (strcmp(set_type->val, "string") == 0) {
948  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_STRING, save, load,
949  memcap > 0 ? memcap : default_memcap,
950  hashsize > 0 ? hashsize : default_hashsize);
951  if (dset == NULL) {
952  FatalErrorOnInit("failed to setup dataset for %s", set_name);
953  continue;
954  }
955  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
956  dset->from_yaml = true;
957 
958  } else if (strcmp(set_type->val, "ipv4") == 0) {
959  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_IPV4, save, load,
960  memcap > 0 ? memcap : default_memcap,
961  hashsize > 0 ? hashsize : default_hashsize);
962  if (dset == NULL) {
963  FatalErrorOnInit("failed to setup dataset for %s", set_name);
964  continue;
965  }
966  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
967  dset->from_yaml = true;
968 
969  } else if (strcmp(set_type->val, "ip") == 0) {
970  Dataset *dset = DatasetGet(set_name, DATASET_TYPE_IPV6, save, load,
971  memcap > 0 ? memcap : default_memcap,
972  hashsize > 0 ? hashsize : default_hashsize);
973  if (dset == NULL) {
974  FatalErrorOnInit("failed to setup dataset for %s", set_name);
975  continue;
976  }
977  SCLogDebug("dataset %s: id %u type %s", set_name, dset->id, set_type->val);
978  dset->from_yaml = true;
979  }
980 
981  list_pos++;
982  }
983  }
984  SCLogDebug("datasets done: %p", datasets);
985  return 0;
986 }
987 
988 void DatasetsDestroy(void)
989 {
990  SCLogDebug("destroying datasets: %p", sets);
992  Dataset *set = sets;
993  while (set) {
994  SCLogDebug("destroying set %s", set->name);
995  Dataset *next = set->next;
996  THashShutdown(set->hash);
997  SCFree(set);
998  set = next;
999  }
1000  sets = NULL;
1002  SCLogDebug("destroying datasets done: %p", sets);
1003 }
1004 
1005 static int SaveCallback(void *ctx, const uint8_t *data, const uint32_t data_len)
1006 {
1007  FILE *fp = ctx;
1008  //PrintRawDataFp(fp, data, data_len);
1009  if (fp) {
1010  return fwrite(data, data_len, 1, fp);
1011  }
1012  return 0;
1013 }
1014 
1015 static int Md5AsAscii(const void *s, char *out, size_t out_size)
1016 {
1017  const Md5Type *md5 = s;
1018  char str[256];
1019  PrintHexString(str, sizeof(str), (uint8_t *)md5->md5, sizeof(md5->md5));
1020  strlcat(out, str, out_size);
1021  strlcat(out, "\n", out_size);
1022  return strlen(out);
1023 }
1024 
1025 static int Sha256AsAscii(const void *s, char *out, size_t out_size)
1026 {
1027  const Sha256Type *sha = s;
1028  char str[256];
1029  PrintHexString(str, sizeof(str), (uint8_t *)sha->sha256, sizeof(sha->sha256));
1030  strlcat(out, str, out_size);
1031  strlcat(out, "\n", out_size);
1032  return strlen(out);
1033 }
1034 
1035 static int IPv4AsAscii(const void *s, char *out, size_t out_size)
1036 {
1037  const IPv4Type *ip4 = s;
1038  char str[256];
1039  PrintInet(AF_INET, ip4->ipv4, str, sizeof(str));
1040  strlcat(out, str, out_size);
1041  strlcat(out, "\n", out_size);
1042  return strlen(out);
1043 }
1044 
1045 static int IPv6AsAscii(const void *s, char *out, size_t out_size)
1046 {
1047  const IPv6Type *ip6 = s;
1048  char str[256];
1049  bool is_ipv4 = true;
1050  for (int i = 4; i <= 15; i++) {
1051  if (ip6->ipv6[i] != 0) {
1052  is_ipv4 = false;
1053  break;
1054  }
1055  }
1056  if (is_ipv4) {
1057  PrintInet(AF_INET, ip6->ipv6, str, sizeof(str));
1058  } else {
1059  PrintInet(AF_INET6, ip6->ipv6, str, sizeof(str));
1060  }
1061  strlcat(out, str, out_size);
1062  strlcat(out, "\n", out_size);
1063  return strlen(out);
1064 }
1065 
1066 void DatasetsSave(void)
1067 {
1068  SCLogDebug("saving datasets: %p", sets);
1070  Dataset *set = sets;
1071  while (set) {
1072  if (strlen(set->save) == 0)
1073  goto next;
1074 
1075  FILE *fp = fopen(set->save, "w");
1076  if (fp == NULL)
1077  goto next;
1078 
1079  SCLogDebug("dumping %s to %s", set->name, set->save);
1080 
1081  switch (set->type) {
1082  case DATASET_TYPE_STRING:
1083  THashWalk(set->hash, StringAsBase64, SaveCallback, fp);
1084  break;
1085  case DATASET_TYPE_MD5:
1086  THashWalk(set->hash, Md5AsAscii, SaveCallback, fp);
1087  break;
1088  case DATASET_TYPE_SHA256:
1089  THashWalk(set->hash, Sha256AsAscii, SaveCallback, fp);
1090  break;
1091  case DATASET_TYPE_IPV4:
1092  THashWalk(set->hash, IPv4AsAscii, SaveCallback, fp);
1093  break;
1094  case DATASET_TYPE_IPV6:
1095  THashWalk(set->hash, IPv6AsAscii, SaveCallback, fp);
1096  break;
1097  }
1098 
1099  fclose(fp);
1100 
1101  next:
1102  set = set->next;
1103  }
1105 }
1106 
1107 static int DatasetLookupString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1108 {
1109  if (set == NULL)
1110  return -1;
1111 
1112  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep.value = 0 };
1113  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1114  if (rdata) {
1115  DatasetUnlockData(rdata);
1116  return 1;
1117  }
1118  return 0;
1119 }
1120 
1121 static DataRepResultType DatasetLookupStringwRep(Dataset *set,
1122  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1123 {
1124  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1125 
1126  if (set == NULL)
1127  return rrep;
1128 
1129  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len, .rep = *rep };
1130  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1131  if (rdata) {
1132  StringType *found = rdata->data;
1133  rrep.found = true;
1134  rrep.rep = found->rep;
1135  DatasetUnlockData(rdata);
1136  return rrep;
1137  }
1138  return rrep;
1139 }
1140 
1141 static int DatasetLookupIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1142 {
1143  if (set == NULL)
1144  return -1;
1145 
1146  if (data_len != 4)
1147  return -1;
1148 
1149  IPv4Type lookup = { .rep.value = 0 };
1150  memcpy(lookup.ipv4, data, 4);
1151  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1152  if (rdata) {
1153  DatasetUnlockData(rdata);
1154  return 1;
1155  }
1156  return 0;
1157 }
1158 
1159 static DataRepResultType DatasetLookupIPv4wRep(
1160  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1161 {
1162  DataRepResultType rrep = { .found = false, .rep = { .value = 0 } };
1163 
1164  if (set == NULL)
1165  return rrep;
1166 
1167  if (data_len != 4)
1168  return rrep;
1169 
1170  IPv4Type lookup = { .rep.value = 0 };
1171  memcpy(lookup.ipv4, data, data_len);
1172  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1173  if (rdata) {
1174  IPv4Type *found = rdata->data;
1175  rrep.found = true;
1176  rrep.rep = found->rep;
1177  DatasetUnlockData(rdata);
1178  return rrep;
1179  }
1180  return rrep;
1181 }
1182 
1183 static int DatasetLookupIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1184 {
1185  if (set == NULL)
1186  return -1;
1187 
1188  if (data_len != 16 && data_len != 4)
1189  return -1;
1190 
1191  IPv6Type lookup = { .rep.value = 0 };
1192  memcpy(lookup.ipv6, data, data_len);
1193  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1194  if (rdata) {
1195  DatasetUnlockData(rdata);
1196  return 1;
1197  }
1198  return 0;
1199 }
1200 
1201 static DataRepResultType DatasetLookupIPv6wRep(
1202  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1203 {
1204  DataRepResultType rrep = { .found = false, .rep = { .value = 0 } };
1205 
1206  if (set == NULL)
1207  return rrep;
1208 
1209  if (data_len != 16 && data_len != 4)
1210  return rrep;
1211 
1212  IPv6Type lookup = { .rep.value = 0 };
1213  memcpy(lookup.ipv6, data, data_len);
1214  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1215  if (rdata) {
1216  IPv6Type *found = rdata->data;
1217  rrep.found = true;
1218  rrep.rep = found->rep;
1219  DatasetUnlockData(rdata);
1220  return rrep;
1221  }
1222  return rrep;
1223 }
1224 
1225 static int DatasetLookupMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1226 {
1227  if (set == NULL)
1228  return -1;
1229 
1230  if (data_len != 16)
1231  return -1;
1232 
1233  Md5Type lookup = { .rep.value = 0 };
1234  memcpy(lookup.md5, data, data_len);
1235  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1236  if (rdata) {
1237  DatasetUnlockData(rdata);
1238  return 1;
1239  }
1240  return 0;
1241 }
1242 
1243 static DataRepResultType DatasetLookupMd5wRep(Dataset *set,
1244  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1245 {
1246  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1247 
1248  if (set == NULL)
1249  return rrep;
1250 
1251  if (data_len != 16)
1252  return rrep;
1253 
1254  Md5Type lookup = { .rep.value = 0};
1255  memcpy(lookup.md5, data, data_len);
1256  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1257  if (rdata) {
1258  Md5Type *found = rdata->data;
1259  rrep.found = true;
1260  rrep.rep = found->rep;
1261  DatasetUnlockData(rdata);
1262  return rrep;
1263  }
1264  return rrep;
1265 }
1266 
1267 static int DatasetLookupSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1268 {
1269  if (set == NULL)
1270  return -1;
1271 
1272  if (data_len != 32)
1273  return -1;
1274 
1275  Sha256Type lookup = { .rep.value = 0 };
1276  memcpy(lookup.sha256, data, data_len);
1277  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1278  if (rdata) {
1279  DatasetUnlockData(rdata);
1280  return 1;
1281  }
1282  return 0;
1283 }
1284 
1285 static DataRepResultType DatasetLookupSha256wRep(Dataset *set,
1286  const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1287 {
1288  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1289 
1290  if (set == NULL)
1291  return rrep;
1292 
1293  if (data_len != 32)
1294  return rrep;
1295 
1296  Sha256Type lookup = { .rep.value = 0 };
1297  memcpy(lookup.sha256, data, data_len);
1298  THashData *rdata = THashLookupFromHash(set->hash, &lookup);
1299  if (rdata) {
1300  Sha256Type *found = rdata->data;
1301  rrep.found = true;
1302  rrep.rep = found->rep;
1303  DatasetUnlockData(rdata);
1304  return rrep;
1305  }
1306  return rrep;
1307 }
1308 
1309 /**
1310  * \brief see if \a data is part of the set
1311  * \param set dataset
1312  * \param data data to look up
1313  * \param data_len length in bytes of \a data
1314  * \retval -1 error
1315  * \retval 0 not found
1316  * \retval 1 found
1317  */
1318 int DatasetLookup(Dataset *set, const uint8_t *data, const uint32_t data_len)
1319 {
1320  if (set == NULL)
1321  return -1;
1322 
1323  switch (set->type) {
1324  case DATASET_TYPE_STRING:
1325  return DatasetLookupString(set, data, data_len);
1326  case DATASET_TYPE_MD5:
1327  return DatasetLookupMd5(set, data, data_len);
1328  case DATASET_TYPE_SHA256:
1329  return DatasetLookupSha256(set, data, data_len);
1330  case DATASET_TYPE_IPV4:
1331  return DatasetLookupIPv4(set, data, data_len);
1332  case DATASET_TYPE_IPV6:
1333  return DatasetLookupIPv6(set, data, data_len);
1334  }
1335  return -1;
1336 }
1337 
1338 DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1339  const DataRepType *rep)
1340 {
1341  DataRepResultType rrep = { .found = false, .rep = { .value = 0 }};
1342  if (set == NULL)
1343  return rrep;
1344 
1345  switch (set->type) {
1346  case DATASET_TYPE_STRING:
1347  return DatasetLookupStringwRep(set, data, data_len, rep);
1348  case DATASET_TYPE_MD5:
1349  return DatasetLookupMd5wRep(set, data, data_len, rep);
1350  case DATASET_TYPE_SHA256:
1351  return DatasetLookupSha256wRep(set, data, data_len, rep);
1352  case DATASET_TYPE_IPV4:
1353  return DatasetLookupIPv4wRep(set, data, data_len, rep);
1354  case DATASET_TYPE_IPV6:
1355  return DatasetLookupIPv6wRep(set, data, data_len, rep);
1356  }
1357  return rrep;
1358 }
1359 
1360 /**
1361  * \retval 1 data was added to the hash
1362  * \retval 0 data was not added to the hash as it is already there
1363  * \retval -1 failed to add data to the hash
1364  */
1365 static int DatasetAddString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1366 {
1367  if (set == NULL)
1368  return -1;
1369 
1370  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1371  .rep.value = 0 };
1372  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1373  if (res.data) {
1374  DatasetUnlockData(res.data);
1375  return res.is_new ? 1 : 0;
1376  }
1377  return -1;
1378 }
1379 
1380 /**
1381  * \retval 1 data was added to the hash
1382  * \retval 0 data was not added to the hash as it is already there
1383  * \retval -1 failed to add data to the hash
1384  */
1385 static int DatasetAddStringwRep(
1386  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1387 {
1388  if (set == NULL)
1389  return -1;
1390 
1391  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1392  .rep = *rep };
1393  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1394  if (res.data) {
1395  DatasetUnlockData(res.data);
1396  return res.is_new ? 1 : 0;
1397  }
1398  return -1;
1399 }
1400 
1401 static int DatasetAddIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1402 {
1403  if (set == NULL) {
1404  return -1;
1405  }
1406 
1407  if (data_len < 4) {
1408  return -2;
1409  }
1410 
1411  IPv4Type lookup = { .rep.value = 0 };
1412  memcpy(lookup.ipv4, data, 4);
1413  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1414  if (res.data) {
1415  DatasetUnlockData(res.data);
1416  return res.is_new ? 1 : 0;
1417  }
1418  return -1;
1419 }
1420 
1421 static int DatasetAddIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1422 {
1423  if (set == NULL) {
1424  return -1;
1425  }
1426 
1427  if (data_len != 16) {
1428  return -2;
1429  }
1430 
1431  IPv6Type lookup = { .rep.value = 0 };
1432  memcpy(lookup.ipv6, data, 16);
1433  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1434  if (res.data) {
1435  DatasetUnlockData(res.data);
1436  return res.is_new ? 1 : 0;
1437  }
1438  return -1;
1439 }
1440 
1441 static int DatasetAddIPv4wRep(
1442  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1443 {
1444  if (set == NULL)
1445  return -1;
1446 
1447  if (data_len < 4)
1448  return -2;
1449 
1450  IPv4Type lookup = { .rep = *rep };
1451  memcpy(lookup.ipv4, data, 4);
1452  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1453  if (res.data) {
1454  DatasetUnlockData(res.data);
1455  return res.is_new ? 1 : 0;
1456  }
1457  return -1;
1458 }
1459 
1460 static int DatasetAddIPv6wRep(
1461  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1462 {
1463  if (set == NULL)
1464  return -1;
1465 
1466  if (data_len != 16)
1467  return -2;
1468 
1469  IPv6Type lookup = { .rep = *rep };
1470  memcpy(lookup.ipv6, data, 16);
1471  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1472  if (res.data) {
1473  DatasetUnlockData(res.data);
1474  return res.is_new ? 1 : 0;
1475  }
1476  return -1;
1477 }
1478 
1479 static int DatasetAddMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1480 {
1481  if (set == NULL)
1482  return -1;
1483 
1484  if (data_len != 16)
1485  return -2;
1486 
1487  Md5Type lookup = { .rep.value = 0 };
1488  memcpy(lookup.md5, data, 16);
1489  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1490  if (res.data) {
1491  DatasetUnlockData(res.data);
1492  return res.is_new ? 1 : 0;
1493  }
1494  return -1;
1495 }
1496 
1497 static int DatasetAddMd5wRep(
1498  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1499 {
1500  if (set == NULL)
1501  return -1;
1502 
1503  if (data_len != 16)
1504  return -2;
1505 
1506  Md5Type lookup = { .rep = *rep };
1507  memcpy(lookup.md5, data, 16);
1508  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1509  if (res.data) {
1510  DatasetUnlockData(res.data);
1511  return res.is_new ? 1 : 0;
1512  }
1513  return -1;
1514 }
1515 
1516 static int DatasetAddSha256wRep(
1517  Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
1518 {
1519  if (set == NULL)
1520  return -1;
1521 
1522  if (data_len != 32)
1523  return -2;
1524 
1525  Sha256Type lookup = { .rep = *rep };
1526  memcpy(lookup.sha256, data, 32);
1527  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1528  if (res.data) {
1529  DatasetUnlockData(res.data);
1530  return res.is_new ? 1 : 0;
1531  }
1532  return -1;
1533 }
1534 
1535 static int DatasetAddSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1536 {
1537  if (set == NULL)
1538  return -1;
1539 
1540  if (data_len != 32)
1541  return -2;
1542 
1543  Sha256Type lookup = { .rep.value = 0 };
1544  memcpy(lookup.sha256, data, 32);
1545  struct THashDataGetResult res = THashGetFromHash(set->hash, &lookup);
1546  if (res.data) {
1547  DatasetUnlockData(res.data);
1548  return res.is_new ? 1 : 0;
1549  }
1550  return -1;
1551 }
1552 
1553 int DatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
1554 {
1555  if (set == NULL)
1556  return -1;
1557 
1558  switch (set->type) {
1559  case DATASET_TYPE_STRING:
1560  return DatasetAddString(set, data, data_len);
1561  case DATASET_TYPE_MD5:
1562  return DatasetAddMd5(set, data, data_len);
1563  case DATASET_TYPE_SHA256:
1564  return DatasetAddSha256(set, data, data_len);
1565  case DATASET_TYPE_IPV4:
1566  return DatasetAddIPv4(set, data, data_len);
1567  case DATASET_TYPE_IPV6:
1568  return DatasetAddIPv6(set, data, data_len);
1569  }
1570  return -1;
1571 }
1572 
1573 static int DatasetAddwRep(Dataset *set, const uint8_t *data, const uint32_t data_len,
1574  DataRepType *rep)
1575 {
1576  if (set == NULL)
1577  return -1;
1578 
1579  switch (set->type) {
1580  case DATASET_TYPE_STRING:
1581  return DatasetAddStringwRep(set, data, data_len, rep);
1582  case DATASET_TYPE_MD5:
1583  return DatasetAddMd5wRep(set, data, data_len, rep);
1584  case DATASET_TYPE_SHA256:
1585  return DatasetAddSha256wRep(set, data, data_len, rep);
1586  case DATASET_TYPE_IPV4:
1587  return DatasetAddIPv4wRep(set, data, data_len, rep);
1588  case DATASET_TYPE_IPV6:
1589  return DatasetAddIPv6wRep(set, data, data_len, rep);
1590  }
1591  return -1;
1592 }
1593 
1594 typedef int (*DatasetOpFunc)(Dataset *set, const uint8_t *data, const uint32_t data_len);
1595 
1596 static int DatasetOpSerialized(Dataset *set, const char *string, DatasetOpFunc DatasetOpString,
1597  DatasetOpFunc DatasetOpMd5, DatasetOpFunc DatasetOpSha256, DatasetOpFunc DatasetOpIPv4,
1598  DatasetOpFunc DatasetOpIPv6)
1599 {
1600  if (set == NULL)
1601  return -1;
1602 
1603  switch (set->type) {
1604  case DATASET_TYPE_STRING: {
1605  // coverity[alloc_strlen : FALSE]
1606  uint8_t decoded[strlen(string)];
1607  uint32_t consumed = 0, num_decoded = 0;
1608  Base64Ecode code = DecodeBase64(decoded, strlen(string), (const uint8_t *)string,
1609  strlen(string), &consumed, &num_decoded, BASE64_MODE_STRICT);
1610  if (code == BASE64_ECODE_ERR) {
1611  return -2;
1612  }
1613 
1614  return DatasetOpString(set, decoded, num_decoded);
1615  }
1616  case DATASET_TYPE_MD5: {
1617  if (strlen(string) != 32)
1618  return -2;
1619  uint8_t hash[16];
1620  if (HexToRaw((const uint8_t *)string, 32, hash, sizeof(hash)) < 0)
1621  return -2;
1622  return DatasetOpMd5(set, hash, 16);
1623  }
1624  case DATASET_TYPE_SHA256: {
1625  if (strlen(string) != 64)
1626  return -2;
1627  uint8_t hash[32];
1628  if (HexToRaw((const uint8_t *)string, 64, hash, sizeof(hash)) < 0)
1629  return -2;
1630  return DatasetOpSha256(set, hash, 32);
1631  }
1632  case DATASET_TYPE_IPV4: {
1633  struct in_addr in;
1634  if (inet_pton(AF_INET, string, &in) != 1)
1635  return -2;
1636  return DatasetOpIPv4(set, (uint8_t *)&in.s_addr, 4);
1637  }
1638  case DATASET_TYPE_IPV6: {
1639  struct in6_addr in;
1640  if (inet_pton(AF_INET6, string, &in) != 1)
1641  return -2;
1642  return DatasetOpIPv6(set, (uint8_t *)&in.s6_addr, 16);
1643  }
1644  }
1645  return -1;
1646 }
1647 
1648 /** \brief add serialized data to set
1649  * \retval int 1 added
1650  * \retval int 0 already in hash
1651  * \retval int -1 API error (not added)
1652  * \retval int -2 DATA error
1653  */
1654 int DatasetAddSerialized(Dataset *set, const char *string)
1655 {
1656  return DatasetOpSerialized(set, string, DatasetAddString, DatasetAddMd5, DatasetAddSha256,
1657  DatasetAddIPv4, DatasetAddIPv6);
1658 }
1659 
1660 /** \brief add serialized data to set
1661  * \retval int 1 added
1662  * \retval int 0 already in hash
1663  * \retval int -1 API error (not added)
1664  * \retval int -2 DATA error
1665  */
1666 int DatasetLookupSerialized(Dataset *set, const char *string)
1667 {
1668  return DatasetOpSerialized(set, string, DatasetLookupString, DatasetLookupMd5,
1669  DatasetLookupSha256, DatasetLookupIPv4, DatasetLookupIPv6);
1670 }
1671 
1672 /**
1673  * \retval 1 data was removed from the hash
1674  * \retval 0 data not removed (busy)
1675  * \retval -1 data not found
1676  */
1677 static int DatasetRemoveString(Dataset *set, const uint8_t *data, const uint32_t data_len)
1678 {
1679  if (set == NULL)
1680  return -1;
1681 
1682  StringType lookup = { .ptr = (uint8_t *)data, .len = data_len,
1683  .rep.value = 0 };
1684  return THashRemoveFromHash(set->hash, &lookup);
1685 }
1686 
1687 static int DatasetRemoveIPv4(Dataset *set, const uint8_t *data, const uint32_t data_len)
1688 {
1689  if (set == NULL)
1690  return -1;
1691 
1692  if (data_len != 4)
1693  return -2;
1694 
1695  IPv4Type lookup = { .rep.value = 0 };
1696  memcpy(lookup.ipv4, data, 4);
1697  return THashRemoveFromHash(set->hash, &lookup);
1698 }
1699 
1700 static int DatasetRemoveIPv6(Dataset *set, const uint8_t *data, const uint32_t data_len)
1701 {
1702  if (set == NULL)
1703  return -1;
1704 
1705  if (data_len != 16)
1706  return -2;
1707 
1708  IPv6Type lookup = { .rep.value = 0 };
1709  memcpy(lookup.ipv6, data, 16);
1710  return THashRemoveFromHash(set->hash, &lookup);
1711 }
1712 
1713 static int DatasetRemoveMd5(Dataset *set, const uint8_t *data, const uint32_t data_len)
1714 {
1715  if (set == NULL)
1716  return -1;
1717 
1718  if (data_len != 16)
1719  return -2;
1720 
1721  Md5Type lookup = { .rep.value = 0 };
1722  memcpy(lookup.md5, data, 16);
1723  return THashRemoveFromHash(set->hash, &lookup);
1724 }
1725 
1726 static int DatasetRemoveSha256(Dataset *set, const uint8_t *data, const uint32_t data_len)
1727 {
1728  if (set == NULL)
1729  return -1;
1730 
1731  if (data_len != 32)
1732  return -2;
1733 
1734  Sha256Type lookup = { .rep.value = 0 };
1735  memcpy(lookup.sha256, data, 32);
1736  return THashRemoveFromHash(set->hash, &lookup);
1737 }
1738 
1739 /** \brief remove serialized data from set
1740  * \retval int 1 removed
1741  * \retval int 0 found but busy (not removed)
1742  * \retval int -1 API error (not removed)
1743  * \retval int -2 DATA error */
1744 int DatasetRemoveSerialized(Dataset *set, const char *string)
1745 {
1746  return DatasetOpSerialized(set, string, DatasetRemoveString, DatasetRemoveMd5,
1747  DatasetRemoveSha256, DatasetRemoveIPv4, DatasetRemoveIPv6);
1748 }
util-byte.h
sets_lock
SCMutex sets_lock
Definition: datasets.c:43
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:188
datasets-md5.h
Dataset::name
char name[DATASET_NAME_MAX_LEN+1]
Definition: datasets.h:41
ConfNode_::val
char * val
Definition: conf.h:34
BASE64_ECODE_ERR
@ BASE64_ECODE_ERR
Definition: util-base64.h:73
Dataset::id
uint32_t id
Definition: datasets.h:43
Dataset::save
char save[PATH_MAX]
Definition: datasets.h:49
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:198
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
datasets-sha256.h
IPv6Compare
bool IPv6Compare(void *a, void *b)
Definition: datasets-ipv6.c:40
THashRemoveFromHash
int THashRemoveFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:775
TYPE_STATE
@ TYPE_STATE
Definition: datasets.c:581
Md5Type
Definition: datasets-md5.h:29
Dataset::hash
THashTableContext * hash
Definition: datasets.h:46
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:181
IPv6Hash
uint32_t IPv6Hash(void *s)
Definition: datasets-ipv6.c:48
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
PrintHexString
void PrintHexString(char *str, size_t size, uint8_t *buf, size_t buf_len)
Definition: util-print.c:265
Dataset::type
enum DatasetTypes type
Definition: datasets.h:42
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
THashConsolidateMemcap
void THashConsolidateMemcap(THashTableContext *ctx)
Definition: util-thash.c:339
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
ConfigGetDataDirectory
const char * ConfigGetDataDirectory(void)
Definition: util-conf.c:80
Md5Type::md5
uint8_t md5[16]
Definition: datasets-md5.h:30
DATASET_TYPE_IPV6
@ DATASET_TYPE_IPV6
Definition: datasets.h:36
hashsize
#define hashsize(n)
Definition: util-hash-lookup3.c:67
Md5StrCompare
bool Md5StrCompare(void *a, void *b)
Definition: datasets-md5.c:41
DatasetLookupSerialized
int DatasetLookupSerialized(Dataset *set, const char *string)
add serialized data to set
Definition: datasets.c:1666
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:49
DatasetGet
Dataset * DatasetGet(const char *name, enum DatasetTypes type, const char *save, const char *load, uint64_t memcap, uint32_t hashsize)
Definition: datasets.c:632
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:335
StringSet
int StringSet(void *dst, void *src)
Definition: datasets-string.c:61
datasets.h
IPv6Set
int IPv6Set(void *dst, void *src)
Definition: datasets-ipv6.c:31
util-debug.h
TYPE_LOAD
@ TYPE_LOAD
Definition: datasets.c:582
DatasetAdd
int DatasetAdd(Dataset *set, const uint8_t *data, const uint32_t data_len)
Definition: datasets.c:1553
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
datasets-ipv6.h
IPv6Type::ipv6
uint8_t ipv6[16]
Definition: datasets-ipv6.h:30
DATASET_TYPE_NOTSET
#define DATASET_TYPE_NOTSET
Definition: datasets.h:31
IPv6Type::rep
DataRepType rep
Definition: datasets-ipv6.h:31
util-print.h
DatasetPostReloadCleanup
void DatasetPostReloadCleanup(void)
Definition: datasets.c:807
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:241
StringParseU16RangeCheck
int StringParseU16RangeCheck(uint16_t *res, int base, size_t len, const char *str, uint16_t min, uint16_t max)
Definition: util-byte.c:433
DatasetOpFunc
int(* DatasetOpFunc)(Dataset *set, const uint8_t *data, const uint32_t data_len)
Definition: datasets.c:1594
datasets-ipv4.h
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:249
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 *), bool reset_memcap, uint64_t memcap, uint32_t hashsize)
Definition: util-thash.c:295
Sha256StrSet
int Sha256StrSet(void *dst, void *src)
Definition: datasets-sha256.c:32
DatasetsDestroy
void DatasetsDestroy(void)
Definition: datasets.c:988
THashDataGetResult
Definition: util-thash.h:187
StringType
Definition: datasets-string.h:29
IPv4Set
int IPv4Set(void *dst, void *src)
Definition: datasets-ipv4.c:31
type
uint16_t type
Definition: decode-vlan.c:107
DatasetsSave
void DatasetsSave(void)
Definition: datasets.c:1066
conf.h
IPv6Type
Definition: datasets-ipv6.h:29
BASE64_MODE_STRICT
@ BASE64_MODE_STRICT
Definition: util-base64.h:52
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:1318
DATASET_TYPE_IPV4
@ DATASET_TYPE_IPV4
Definition: datasets.h:35
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:1744
Sha256StrHash
uint32_t Sha256StrHash(void *s)
Definition: datasets-sha256.c:49
g_system
bool g_system
Definition: suricata.c:191
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:786
THashShutdown
void THashShutdown(THashTableContext *ctx)
shutdown the flow engine
Definition: util-thash.c:347
DatasetTypes
DatasetTypes
Definition: datasets.h:30
Dataset::next
struct Dataset * next
Definition: datasets.h:51
THashData_::data
void * data
Definition: util-thash.h:92
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
util-conf.h
Sha256Type
Definition: datasets-sha256.h:29
Sha256StrFree
void Sha256StrFree(void *s)
Definition: datasets-sha256.c:61
THashData_
Definition: util-thash.h:85
IPv4Free
void IPv4Free(void *s)
Definition: datasets-ipv4.c:60
IPv4Hash
uint32_t IPv4Hash(void *s)
Definition: datasets-ipv4.c:48
suricata-common.h
util-path.h
StringHash
uint32_t StringHash(void *s)
Definition: datasets-string.c:88
FatalErrorOnInit
#define FatalErrorOnInit(...)
Fatal error IF we're starting up, and configured to consider errors to be fatal errors.
Definition: util-debug.h:511
DATASET_NAME_MAX_LEN
#define DATASET_NAME_MAX_LEN
Definition: datasets.h:39
ConfNode_::name
char * name
Definition: conf.h:33
PathIsAbsolute
int PathIsAbsolute(const char *path)
Check if a path is absolute.
Definition: util-path.c:44
Md5StrSet
int Md5StrSet(void *dst, void *src)
Definition: datasets-md5.c:32
StringCompare
bool StringCompare(void *a, void *b)
Definition: datasets-string.c:77
THashGetFromHash
struct THashDataGetResult THashGetFromHash(THashTableContext *ctx, void *data)
Definition: util-thash.c:530
THashLookupFromHash
THashData * THashLookupFromHash(THashTableContext *ctx, void *data)
look up data in the hash
Definition: util-thash.c:640
IPv4Type
Definition: datasets-ipv4.h:29
DataRepType::value
uint16_t value
Definition: datasets-reputation.h:28
ParseSizeStringU32
int ParseSizeStringU32(const char *size, uint32_t *res)
Definition: util-misc.c:181
THashDecrUsecnt
#define THashDecrUsecnt(h)
Definition: util-thash.h:167
IPv4Compare
bool IPv4Compare(void *a, void *b)
Definition: datasets-ipv4.c:40
DatasetFind
Dataset * DatasetFind(const char *name, enum DatasetTypes type)
look for set by name without creating it
Definition: datasets.c:618
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
DatasetsInit
int DatasetsInit(void)
Definition: datasets.c:854
str
#define str(s)
Definition: suricata-common.h:291
DatasetGetTypeFromString
enum DatasetTypes DatasetGetTypeFromString(const char *s)
Definition: datasets.c:58
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
THashWalk
int THashWalk(THashTableContext *ctx, THashFormatFunc FormatterFunc, THashOutputFunc OutputterFunc, void *output_ctx)
Walk the hash.
Definition: util-thash.c:381
SCFree
#define SCFree(p)
Definition: util-mem.h:61
ConfNode_
Definition: conf.h:32
Dataset::hidden
bool hidden
Definition: datasets.h:45
DatasetReload
void DatasetReload(void)
Definition: datasets.c:785
DatasetGetPathType
DatasetGetPathType
Definition: datasets.c:580
Sha256StrCompare
bool Sha256StrCompare(void *a, void *b)
Definition: datasets-sha256.c:41
DATASET_TYPE_MD5
@ DATASET_TYPE_MD5
Definition: datasets.h:33
DATASET_TYPE_STRING
@ DATASET_TYPE_STRING
Definition: datasets.h:32
THashDataGetResult::is_new
bool is_new
Definition: util-thash.h:189
IPv6Free
void IPv6Free(void *s)
Definition: datasets-ipv6.c:60
suricata.h
IPv4Type::ipv4
uint8_t ipv4[4]
Definition: datasets-ipv4.h:30
DatasetAddSerialized
int DatasetAddSerialized(Dataset *set, const char *string)
add serialized data to set
Definition: datasets.c:1654
Dataset
Definition: datasets.h:40
Dataset::from_yaml
bool from_yaml
Definition: datasets.h:44
IPv4Type::rep
DataRepType rep
Definition: datasets-ipv4.h:31
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:375
util-misc.h
util-thash.h
Dataset::load
char load[PATH_MAX]
Definition: datasets.h:48
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:61
SCMutex
#define SCMutex
Definition: threads-debug.h:114
StringFree
void StringFree(void *s)
Definition: datasets-string.c:102
Base64Ecode
Base64Ecode
Definition: util-base64.h:72
DecodeBase64
Base64Ecode DecodeBase64(uint8_t *dest, uint32_t dest_size, const uint8_t *src, uint32_t len, uint32_t *consumed_bytes, uint32_t *decoded_bytes, Base64Mode mode)
Decodes a base64-encoded string buffer into an ascii-encoded byte buffer.
Definition: util-base64.c:269
DatasetLookupwRep
DataRepResultType DatasetLookupwRep(Dataset *set, const uint8_t *data, const uint32_t data_len, const DataRepType *rep)
Definition: datasets.c:1338