suricata
util-classification-config.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 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 Anoop Saldanha <anoopsaldanha@gmail.com>
22  *
23  * Used for parsing a classification.config file
24  */
25 
26 #include "suricata-common.h"
27 #include "detect.h"
28 #include "detect-engine.h"
29 #include "util-hash.h"
30 
31 #include "conf.h"
33 #include "util-unittest.h"
34 #include "util-error.h"
35 #include "util-debug.h"
36 #include "util-fmemopen.h"
37 
38 /* Regex to parse the classtype argument from a Signature. The first substring
39  * holds the classtype name, the second substring holds the classtype the
40  * classtype description, and the third argument holds the priority */
41 #define DETECT_CLASSCONFIG_REGEX "^\\s*config\\s*classification\\s*:\\s*([a-zA-Z][a-zA-Z0-9-_]*)\\s*,\\s*(.+)\\s*,\\s*(\\d+)\\s*$"
42 
43 /* Default path for the classification.config file */
44 #if defined OS_WIN32 || defined __CYGWIN__
45 #define SC_CLASS_CONF_DEF_CONF_FILEPATH CONFIG_DIR "\\\\classification.config"
46 #else
47 #define SC_CLASS_CONF_DEF_CONF_FILEPATH CONFIG_DIR "/classification.config"
48 #endif
49 
50 static pcre *regex = NULL;
51 static pcre_extra *regex_study = NULL;
52 
53 uint32_t SCClassConfClasstypeHashFunc(HashTable *ht, void *data, uint16_t datalen);
54 char SCClassConfClasstypeHashCompareFunc(void *data1, uint16_t datalen1,
55  void *data2, uint16_t datalen2);
56 void SCClassConfClasstypeHashFree(void *ch);
57 static const char *SCClassConfGetConfFilename(const DetectEngineCtx *de_ctx);
58 
59 void SCClassConfInit(void)
60 {
61  const char *eb = NULL;
62  int eo;
63  int opts = 0;
64 
65  regex = pcre_compile(DETECT_CLASSCONFIG_REGEX, opts, &eb, &eo, NULL);
66  if (regex == NULL) {
67  SCLogDebug("Compile of \"%s\" failed at offset %" PRId32 ": %s",
68  DETECT_CLASSCONFIG_REGEX, eo, eb);
69  return;
70  }
71 
72  regex_study = pcre_study(regex, 0, &eb);
73  if (eb != NULL) {
74  pcre_free(regex);
75  regex = NULL;
76  SCLogDebug("pcre study failed: %s", eb);
77  return;
78  }
79  return;
80 }
81 
83 {
84  if (regex != NULL) {
85  pcre_free(regex);
86  regex = NULL;
87  }
88  if (regex_study != NULL) {
89  pcre_free(regex_study);
90  regex_study = NULL;
91  }
92 }
93 
94 
95 /**
96  * \brief Inits the context to be used by the Classification Config parsing API.
97  *
98  * This function initializes the hash table to be used by the Detection
99  * Engine Context to hold the data from the classification.config file,
100  * obtains the file desc to parse the classification.config file, and
101  * inits the regex used to parse the lines from classification.config
102  * file.
103  *
104  * \param de_ctx Pointer to the Detection Engine Context.
105  *
106  * \retval fp NULL on error
107  */
108 static FILE *SCClassConfInitContextAndLocalResources(DetectEngineCtx *de_ctx, FILE *fd)
109 {
110  const char *filename = NULL;
111 
112  /* init the hash table to be used by the classification config Classtypes */
116  if (de_ctx->class_conf_ht == NULL) {
117  SCLogError(SC_ERR_HASH_TABLE_INIT, "Error initializing the hash "
118  "table");
119  goto error;
120  }
121 
122  /* if it is not NULL, use the file descriptor. The hack so that we can
123  * avoid using a dummy classification file for testing purposes and
124  * instead use an input stream against a buffer containing the
125  * classification strings */
126  if (fd == NULL) {
127  filename = SCClassConfGetConfFilename(de_ctx);
128  if ( (fd = fopen(filename, "r")) == NULL) {
129 #ifdef UNITTESTS
130  if (RunmodeIsUnittests())
131  goto error; // silently fail
132 #endif
133  SCLogError(SC_ERR_FOPEN, "Error opening file: \"%s\": %s", filename, strerror(errno));
134  goto error;
135  }
136  }
137 
138  return fd;
139 
140  error:
141  if (de_ctx->class_conf_ht != NULL) {
142  HashTableFree(de_ctx->class_conf_ht);
143  de_ctx->class_conf_ht = NULL;
144  }
145  if (fd != NULL) {
146  fclose(fd);
147  fd = NULL;
148  }
149 
150  return NULL;
151 }
152 
153 
154 /**
155  * \brief Returns the path for the Classification Config file. We check if we
156  * can retrieve the path from the yaml conf file. If it is not present,
157  * return the default path for the classification file which is
158  * "./classification.config".
159  *
160  * \retval log_filename Pointer to a string containing the path for the
161  * Classification Config file.
162  */
163 static const char *SCClassConfGetConfFilename(const DetectEngineCtx *de_ctx)
164 {
165  const char *log_filename = NULL;
166 
167  if (de_ctx != NULL && strlen(de_ctx->config_prefix) > 0) {
168  char config_value[256];
169  snprintf(config_value, sizeof(config_value),
170  "%s.classification-file", de_ctx->config_prefix);
171 
172  /* try loading prefix setting, fall back to global if that
173  * fails. */
174  if (ConfGet(config_value, &log_filename) != 1) {
175  if (ConfGet("classification-file", &log_filename) != 1) {
176  log_filename = (char *)SC_CLASS_CONF_DEF_CONF_FILEPATH;
177  }
178  }
179  } else {
180  if (ConfGet("classification-file", &log_filename) != 1) {
181  log_filename = (char *)SC_CLASS_CONF_DEF_CONF_FILEPATH;
182  }
183  }
184 
185  return log_filename;
186 }
187 
188 /**
189  * \brief Releases resources used by the Classification Config API.
190  */
191 static void SCClassConfDeInitLocalResources(DetectEngineCtx *de_ctx, FILE *fd)
192 {
193  if (fd != NULL) {
194  fclose(fd);
195  fd = NULL;
196  }
197 }
198 
199 /**
200  * \brief Releases resources used by the Classification Config API.
201  */
203 {
204  if (de_ctx->class_conf_ht != NULL)
205  HashTableFree(de_ctx->class_conf_ht);
206 
207  de_ctx->class_conf_ht = NULL;
208 
209  return;
210 }
211 
212 /**
213  * \brief Converts a string to lowercase.
214  *
215  * \param str Pointer to the string to be converted.
216  */
217 static char *SCClassConfStringToLowercase(const char *str)
218 {
219  char *new_str = NULL;
220  char *temp_str = NULL;
221 
222  if ( (new_str = SCStrdup(str)) == NULL) {
223  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
224  return NULL;
225  }
226 
227  temp_str = new_str;
228  while (*temp_str != '\0') {
229  *temp_str = tolower((unsigned char)*temp_str);
230  temp_str++;
231  }
232 
233  return new_str;
234 }
235 
236 /**
237  * \brief Parses a line from the classification file and adds it to Classtype
238  * hash table in DetectEngineCtx, i.e. DetectEngineCtx->class_conf_ht.
239  *
240  * \param rawstr Pointer to the string to be parsed.
241  * \param index Relative index of the string to be parsed.
242  * \param de_ctx Pointer to the Detection Engine Context.
243  *
244  * \retval 0 On success.
245  * \retval -1 On failure.
246  */
247 static int SCClassConfAddClasstype(char *rawstr, uint8_t index, DetectEngineCtx *de_ctx)
248 {
249  char ct_name[64];
250  char ct_desc[512];
251  char ct_priority_str[16];
252  int ct_priority = 0;
253  uint8_t ct_id = index;
254 
255  SCClassConfClasstype *ct_new = NULL;
256  SCClassConfClasstype *ct_lookup = NULL;
257 
258 #define MAX_SUBSTRINGS 30
259  int ret = 0;
260  int ov[MAX_SUBSTRINGS];
261 
262  ret = pcre_exec(regex, regex_study, rawstr, strlen(rawstr), 0, 0, ov, 30);
263  if (ret < 0) {
264  SCLogError(SC_ERR_INVALID_SIGNATURE, "Invalid Classtype in "
265  "classification.config file");
266  goto error;
267  }
268 
269  /* retrieve the classtype name */
270  ret = pcre_copy_substring((char *)rawstr, ov, 30, 1, ct_name, sizeof(ct_name));
271  if (ret < 0) {
272  SCLogInfo("pcre_copy_substring() failed");
273  goto error;
274  }
275 
276  /* retrieve the classtype description */
277  ret = pcre_copy_substring((char *)rawstr, ov, 30, 2, ct_desc, sizeof(ct_desc));
278  if (ret < 0) {
279  SCLogInfo("pcre_copy_substring() failed");
280  goto error;
281  }
282 
283  /* retrieve the classtype priority */
284  ret = pcre_copy_substring((char *)rawstr, ov, 30, 3, ct_priority_str, sizeof(ct_priority_str));
285  if (ret < 0) {
286  SCLogInfo("pcre_copy_substring() failed");
287  goto error;
288  }
289  if (strlen(ct_priority_str) == 0) {
290  goto error;
291  }
292 
293  ct_priority = atoi(ct_priority_str);
294 
295  /* Create a new instance of the parsed Classtype string */
296  ct_new = SCClassConfAllocClasstype(ct_id, ct_name, ct_desc, ct_priority);
297  if (ct_new == NULL)
298  goto error;
299 
300  /* Check if the Classtype is present in the HashTable. In case it's present
301  * ignore it, as it is a duplicate. If not present, add it to the table */
302  ct_lookup = HashTableLookup(de_ctx->class_conf_ht, ct_new, 0);
303  if (ct_lookup == NULL) {
304  if (HashTableAdd(de_ctx->class_conf_ht, ct_new, 0) < 0)
305  SCLogDebug("HashTable Add failed");
306  } else {
307  SCLogDebug("Duplicate classtype found inside classification.config");
308  if (ct_new->classtype_desc) SCFree(ct_new->classtype_desc);
309  if (ct_new->classtype) SCFree(ct_new->classtype);
310  SCFree(ct_new);
311  }
312 
313  return 0;
314 
315  error:
316  return -1;
317 }
318 
319 /**
320  * \brief Checks if a string is a comment or a blank line.
321  *
322  * Comments lines are lines of the following format -
323  * "# This is a comment string" or
324  * " # This is a comment string".
325  *
326  * \param line String that has to be checked
327  *
328  * \retval 1 On the argument string being a comment or blank line
329  * \retval 0 Otherwise
330  */
331 static int SCClassConfIsLineBlankOrComment(char *line)
332 {
333  while (*line != '\0') {
334  /* we have a comment */
335  if (*line == '#')
336  return 1;
337 
338  /* this line is neither a comment line, nor a blank line */
339  if (!isspace((unsigned char)*line))
340  return 0;
341 
342  line++;
343  }
344 
345  /* we have a blank line */
346  return 1;
347 }
348 
349 /**
350  * \brief Parses the Classification Config file and updates the
351  * DetectionEngineCtx->class_conf_ht with the Classtype information.
352  *
353  * \param de_ctx Pointer to the Detection Engine Context.
354  */
355 static void SCClassConfParseFile(DetectEngineCtx *de_ctx, FILE *fd)
356 {
357  char line[1024];
358  uint8_t i = 1;
359 
360  while (fgets(line, sizeof(line), fd) != NULL) {
361  if (SCClassConfIsLineBlankOrComment(line))
362  continue;
363 
364  SCClassConfAddClasstype(line, i, de_ctx);
365  i++;
366  }
367 
368 #ifdef UNITTESTS
369  SCLogInfo("Added \"%d\" classification types from the classification file",
370  de_ctx->class_conf_ht->count);
371 #endif
372 
373  return;
374 }
375 
376 /**
377  * \brief Returns a new SCClassConfClasstype instance. The classtype string
378  * is converted into lowercase, before being assigned to the instance.
379  *
380  * \param classtype Pointer to the classification type.
381  * \param classtype_desc Pointer to the classification type description.
382  * \param priority Holds the priority for the classification type.
383  *
384  * \retval ct Pointer to the new instance of SCClassConfClasstype on success;
385  * NULL on failure.
386  */
388  const char *classtype,
389  const char *classtype_desc,
390  int priority)
391 {
392  SCClassConfClasstype *ct = NULL;
393 
394  if (classtype == NULL)
395  return NULL;
396 
397  if ( (ct = SCMalloc(sizeof(SCClassConfClasstype))) == NULL)
398  return NULL;
399  memset(ct, 0, sizeof(SCClassConfClasstype));
400 
401  if ( (ct->classtype = SCClassConfStringToLowercase(classtype)) == NULL) {
402  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
403 
405  return NULL;
406  }
407 
408  if (classtype_desc != NULL &&
409  (ct->classtype_desc = SCStrdup(classtype_desc)) == NULL) {
410  SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory");
411 
413  return NULL;
414  }
415 
416  ct->classtype_id = classtype_id;
417  ct->priority = priority;
418 
419  return ct;
420 }
421 
422 /**
423  * \brief Frees a SCClassConfClasstype instance
424  *
425  * \param Pointer to the SCClassConfClasstype instance that has to be freed
426  */
428 {
429  if (ct != NULL) {
430  if (ct->classtype != NULL)
431  SCFree(ct->classtype);
432 
433  if (ct->classtype_desc != NULL)
434  SCFree(ct->classtype_desc);
435 
436  SCFree(ct);
437  }
438 
439  return;
440 }
441 
442 /**
443  * \brief Hashing function to be used to hash the Classtype name. Would be
444  * supplied as an argument to the HashTableInit function for
445  * DetectEngineCtx->class_conf_ht.
446  *
447  * \param ht Pointer to the HashTable.
448  * \param data Pointer to the data to be hashed. In this case, the data
449  * would be a pointer to a SCClassConfClasstype instance.
450  * \param datalen Not used by this function.
451  */
452 uint32_t SCClassConfClasstypeHashFunc(HashTable *ht, void *data, uint16_t datalen)
453 {
455  uint32_t hash = 0;
456  int i = 0;
457 
458  int len = strlen(ct->classtype);
459 
460  for (i = 0; i < len; i++)
461  hash += tolower((unsigned char)(ct->classtype)[i]);
462 
463  hash = hash % ht->array_size;
464 
465  return hash;
466 }
467 
468 /**
469  * \brief Used to compare two Classtypes that have been stored in the HashTable.
470  * This function is supplied as an argument to the HashTableInit function
471  * for DetectionEngineCtx->class_conf_ct.
472  *
473  * \param data1 Pointer to the first SCClassConfClasstype to be compared.
474  * \param len1 Not used by this function.
475  * \param data2 Pointer to the second SCClassConfClasstype to be compared.
476  * \param len2 Not used by this function.
477  *
478  * \retval 1 On data1 and data2 being equal.
479  * \retval 0 On data1 and data2 not being equal.
480  */
481 char SCClassConfClasstypeHashCompareFunc(void *data1, uint16_t datalen1,
482  void *data2, uint16_t datalen2)
483 {
486  int len1 = 0;
487  int len2 = 0;
488 
489  if (ct1 == NULL || ct2 == NULL)
490  return 0;
491 
492  if (ct1->classtype == NULL || ct2->classtype == NULL)
493  return 0;
494 
495  len1 = strlen(ct1->classtype);
496  len2 = strlen(ct2->classtype);
497 
498  if (len1 == len2 && memcmp(ct1->classtype, ct2->classtype, len1) == 0) {
499  SCLogDebug("Match found inside Classification-Config hash function");
500  return 1;
501  }
502 
503  return 0;
504 }
505 
506 /**
507  * \brief Used to free the Classification Config Hash Data that was stored in
508  * DetectEngineCtx->class_conf_ht Hashtable.
509  *
510  * \param ch Pointer to the data that has to be freed.
511  */
513 {
515 
516  return;
517 }
518 
519 /**
520  * \brief Loads the Classtype info from the classification.config file.
521  *
522  * The classification.config file contains the different classtypes,
523  * that can be used to label Signatures. Each line of the file should
524  * have the following format -
525  * classtype_name, classtype_description, priority
526  * None of the above parameters should hold a quote inside the file.
527  *
528  * \param de_ctx Pointer to the Detection Engine Context that should be updated
529  * with Classtype information.
530  */
532 {
533  fd = SCClassConfInitContextAndLocalResources(de_ctx, fd);
534  if (fd == NULL) {
535 #ifdef UNITTESTS
536  if (RunmodeIsUnittests() && fd == NULL) {
537  return;
538  }
539 #endif
540  SCLogError(SC_ERR_OPENING_FILE, "please check the \"classification-file\" "
541  "option in your suricata.yaml file");
542  return;
543  }
544 
545  SCClassConfParseFile(de_ctx, fd);
546  SCClassConfDeInitLocalResources(de_ctx, fd);
547 
548  return;
549 }
550 
551 /**
552  * \brief Gets the classtype from the corresponding hash table stored
553  * in the Detection Engine Context's class conf ht, given the
554  * classtype name.
555  *
556  * \param ct_name Pointer to the classtype name that has to be looked up.
557  * \param de_ctx Pointer to the Detection Engine Context.
558  *
559  * \retval lookup_ct_info Pointer to the SCClassConfClasstype instance from
560  * the hash table on success; NULL on failure.
561  */
563  DetectEngineCtx *de_ctx)
564 {
565  char name[strlen(ct_name) + 1];
566  size_t s;
567  for (s = 0; s < strlen(ct_name); s++)
568  name[s] = tolower((unsigned char)ct_name[s]);
569  name[s] = '\0';
570 
571  SCClassConfClasstype ct_lookup = {0, name, NULL, 0 };
572  SCClassConfClasstype *lookup_ct_info = HashTableLookup(de_ctx->class_conf_ht,
573  &ct_lookup, 0);
574  return lookup_ct_info;
575 }
576 
577 /*----------------------------------Unittests---------------------------------*/
578 
579 
580 #ifdef UNITTESTS
581 
582 /**
583  * \brief Creates a dummy classification file, with all valid Classtypes, for
584  * testing purposes.
585  *
586  * \file_path Pointer to the file_path for the dummy classification file.
587  */
589 {
590  const char *buffer =
591  "config classification: nothing-wrong,Nothing Wrong With Us,3\n"
592  "config classification: unknown,Unknown are we,3\n"
593  "config classification: bad-unknown,We think it's bad, 2\n";
594 
595  FILE *fd = SCFmemopen((void *)buffer, strlen(buffer), "r");
596  if (fd == NULL)
597  SCLogDebug("Error with SCFmemopen() called by Classifiation Config test code");
598 
599  return fd;
600 }
601 
602 /**
603  * \brief Creates a dummy classification file, with some valid Classtypes and a
604  * couple of invalid Classtypes, for testing purposes.
605  *
606  * \file_path Pointer to the file_path for the dummy classification file.
607  */
609 {
610  const char *buffer =
611  "config classification: not-suspicious,Not Suspicious Traffic,3\n"
612  "onfig classification: unknown,Unknown Traffic,3\n"
613  "config classification: _badunknown,Potentially Bad Traffic, 2\n"
614  "config classification: bamboola1,Unknown Traffic,3\n"
615  "config classification: misc-activity,Misc activity,-1\n"
616  "config classification: policy-violation,Potential Corporate "
617  "config classification: bamboola,Unknown Traffic,3\n";
618 
619  FILE *fd = SCFmemopen((void *)buffer, strlen(buffer), "r");
620  if (fd == NULL)
621  SCLogDebug("Error with SCFmemopen() called by Classifiation Config test code");
622 
623  return fd;
624 }
625 
626 /**
627  * \brief Creates a dummy classification file, with all invalid Classtypes, for
628  * testing purposes.
629  *
630  * \file_path Pointer to the file_path for the dummy classification file.
631  */
633 {
634  const char *buffer =
635  "conig classification: not-suspicious,Not Suspicious Traffic,3\n"
636  "onfig classification: unknown,Unknown Traffic,3\n"
637  "config classification: _badunknown,Potentially Bad Traffic, 2\n"
638  "config classification: misc-activity,Misc activity,-1\n";
639 
640  FILE *fd = SCFmemopen((void *)buffer, strlen(buffer), "r");
641  if (fd == NULL)
642  SCLogDebug("Error with SCFmemopen() called by Classifiation Config test code");
643 
644  return fd;
645 }
646 
647 /**
648  * \test Check that the classification file is loaded and the detection engine
649  * content class_conf_hash_table loaded with the classtype data.
650  */
651 static int SCClassConfTest01(void)
652 {
654  int result = 0;
655 
656  if (de_ctx == NULL)
657  return result;
658 
661 
662  if (de_ctx->class_conf_ht == NULL)
663  return result;
664 
665  result = (de_ctx->class_conf_ht->count == 3);
666  if (result == 0) printf("de_ctx->class_conf_ht->count %u: ", de_ctx->class_conf_ht->count);
667 
668  DetectEngineCtxFree(de_ctx);
669 
670  return result;
671 }
672 
673 /**
674  * \test Check that invalid classtypes present in the classification config file
675  * aren't loaded.
676  */
677 static int SCClassConfTest02(void)
678 {
680  int result = 0;
681 
682  if (de_ctx == NULL)
683  return result;
684 
687 
688  if (de_ctx->class_conf_ht == NULL)
689  return result;
690 
691  result = (de_ctx->class_conf_ht->count == 0);
692 
693  DetectEngineCtxFree(de_ctx);
694 
695  return result;
696 }
697 
698 /**
699  * \test Check that only valid classtypes are loaded into the hash table from
700  * the classfication.config file.
701  */
702 static int SCClassConfTest03(void)
703 {
705  int result = 0;
706 
707  if (de_ctx == NULL)
708  return result;
709 
712 
713  if (de_ctx->class_conf_ht == NULL)
714  return result;
715 
716  result = (de_ctx->class_conf_ht->count == 3);
717 
718  DetectEngineCtxFree(de_ctx);
719 
720  return result;
721 }
722 
723 /**
724  * \test Check if the classtype info from the classification.config file have
725  * been loaded into the hash table.
726  */
727 static int SCClassConfTest04(void)
728 {
730  int result = 1;
731 
732  if (de_ctx == NULL)
733  return 0;
734 
737 
738  if (de_ctx->class_conf_ht == NULL)
739  return 0;
740 
741  result = (de_ctx->class_conf_ht->count == 3);
742 
743  result &= (SCClassConfGetClasstype("unknown", de_ctx) != NULL);
744  result &= (SCClassConfGetClasstype("unKnoWn", de_ctx) != NULL);
745  result &= (SCClassConfGetClasstype("bamboo", de_ctx) == NULL);
746  result &= (SCClassConfGetClasstype("bad-unknown", de_ctx) != NULL);
747  result &= (SCClassConfGetClasstype("BAD-UNKnOWN", de_ctx) != NULL);
748  result &= (SCClassConfGetClasstype("bed-unknown", de_ctx) == NULL);
749 
750  DetectEngineCtxFree(de_ctx);
751 
752  return result;
753 }
754 
755 /**
756  * \test Check if the classtype info from the invalid classification.config file
757  * have not been loaded into the hash table, and cross verify to check
758  * that the hash table contains no classtype data.
759  */
760 static int SCClassConfTest05(void)
761 {
763  int result = 1;
764 
765  if (de_ctx == NULL)
766  return 0;
767 
770 
771  if (de_ctx->class_conf_ht == NULL)
772  return 0;
773 
774  result = (de_ctx->class_conf_ht->count == 0);
775 
776  result &= (SCClassConfGetClasstype("unknown", de_ctx) == NULL);
777  result &= (SCClassConfGetClasstype("unKnoWn", de_ctx) == NULL);
778  result &= (SCClassConfGetClasstype("bamboo", de_ctx) == NULL);
779  result &= (SCClassConfGetClasstype("bad-unknown", de_ctx) == NULL);
780  result &= (SCClassConfGetClasstype("BAD-UNKnOWN", de_ctx) == NULL);
781  result &= (SCClassConfGetClasstype("bed-unknown", de_ctx) == NULL);
782 
783  DetectEngineCtxFree(de_ctx);
784 
785  return result;
786 }
787 
788 /**
789  * \test Check if the classtype info from the classification.config file have
790  * been loaded into the hash table.
791  */
792 static int SCClassConfTest06(void)
793 {
795  int result = 1;
796 
797  if (de_ctx == NULL)
798  return 0;
799 
802 
803  if (de_ctx->class_conf_ht == NULL)
804  return 0;
805 
806  result = (de_ctx->class_conf_ht->count == 3);
807 
808  result &= (SCClassConfGetClasstype("unknown", de_ctx) == NULL);
809  result &= (SCClassConfGetClasstype("not-suspicious", de_ctx) != NULL);
810  result &= (SCClassConfGetClasstype("bamboola1", de_ctx) != NULL);
811  result &= (SCClassConfGetClasstype("bamboola1", de_ctx) != NULL);
812  result &= (SCClassConfGetClasstype("BAMBOolA1", de_ctx) != NULL);
813  result &= (SCClassConfGetClasstype("unkNOwn", de_ctx) == NULL);
814 
815  DetectEngineCtxFree(de_ctx);
816 
817  return result;
818 }
819 
820 #endif /* UNITTESTS */
821 
822 /**
823  * \brief This function registers unit tests for Classification Config API.
824  */
826 {
827 
828 #ifdef UNITTESTS
829 
830  UtRegisterTest("SCClassConfTest01", SCClassConfTest01);
831  UtRegisterTest("SCClassConfTest02", SCClassConfTest02);
832  UtRegisterTest("SCClassConfTest03", SCClassConfTest03);
833  UtRegisterTest("SCClassConfTest04", SCClassConfTest04);
834  UtRegisterTest("SCClassConfTest05", SCClassConfTest05);
835  UtRegisterTest("SCClassConfTest06", SCClassConfTest06);
836 
837 #endif /* UNITTESTS */
838 
839 }
#define SCLogDebug(...)
Definition: util-debug.h:335
int HashTableAdd(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:113
FILE * SCClassConfGenerateInValidDummyClassConfigFD02(void)
Creates a dummy classification file, with some valid Classtypes and a couple of invalid Classtypes...
#define SCFmemopen
Definition: util-fmemopen.h:52
HashTable * class_conf_ht
Definition: detect.h:753
char config_prefix[64]
Definition: detect.h:853
char SCClassConfClasstypeHashCompareFunc(void *data1, uint16_t datalen1, void *data2, uint16_t datalen2)
Used to compare two Classtypes that have been stored in the HashTable. This function is supplied as a...
void SCClassConfRegisterTests(void)
This function registers unit tests for Classification Config API.
void SCClassConfClasstypeHashFree(void *ch)
Used to free the Classification Config Hash Data that was stored in DetectEngineCtx->class_conf_ht Ha...
HashTable * HashTableInit(uint32_t size, uint32_t(*Hash)(struct HashTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hash.c:34
FILE * SCClassConfGenerateInValidDummyClassConfigFD03(void)
Creates a dummy classification file, with all invalid Classtypes, for testing purposes.
#define DETECT_CLASSCONFIG_REGEX
uint32_t array_size
Definition: util-hash.h:37
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
main detection engine ctx
Definition: detect.h:724
#define str(s)
uint32_t count
Definition: util-hash.h:39
void SCClassConfInit(void)
#define SC_CLASS_CONF_DEF_CONF_FILEPATH
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SCClassConfLoadClassficationConfigFile(DetectEngineCtx *de_ctx, FILE *fd)
Loads the Classtype info from the classification.config file.
int RunmodeIsUnittests(void)
Definition: suricata.c:261
#define index
Definition: win32-misc.h:29
#define MAX_SUBSTRINGS
void HashTableFree(HashTable *ht)
Definition: util-hash.c:79
#define SCMalloc(a)
Definition: util-mem.h:166
void * HashTableLookup(HashTable *ht, void *data, uint16_t datalen)
Definition: util-hash.c:193
void SCClassConfDeAllocClasstype(SCClassConfClasstype *ct)
Frees a SCClassConfClasstype instance.
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCFree(a)
Definition: util-mem.h:228
uint32_t SCClassConfClasstypeHashFunc(HashTable *ht, void *data, uint16_t datalen)
Hashing function to be used to hash the Classtype name. Would be supplied as an argument to the HashT...
Container for a Classtype from the Classification.config file.
#define SCStrdup(a)
Definition: util-mem.h:212
SCClassConfClasstype * SCClassConfGetClasstype(const char *ct_name, DetectEngineCtx *de_ctx)
Gets the classtype from the corresponding hash table stored in the Detection Engine Context&#39;s class c...
uint8_t len
void SCClassConfDeinit(void)
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
FILE * SCClassConfGenerateValidDummyClassConfigFD01(void)
Creates a dummy classification file, with all valid Classtypes, for testing purposes.
SCClassConfClasstype * SCClassConfAllocClasstype(uint8_t classtype_id, const char *classtype, const char *classtype_desc, int priority)
Returns a new SCClassConfClasstype instance. The classtype string is converted into lowercase...
void SCClassConfDeInitContext(DetectEngineCtx *de_ctx)
Releases resources used by the Classification Config API.
DetectEngineCtx * DetectEngineCtxInit(void)