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