/src/suricata7/src/util-reference-config.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2007-2022 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 | | |
24 | | #include "suricata-common.h" |
25 | | #include "detect.h" |
26 | | #include "detect-engine.h" |
27 | | #include "util-hash.h" |
28 | | |
29 | | #include "util-reference-config.h" |
30 | | #include "conf.h" |
31 | | #include "util-unittest.h" |
32 | | #include "util-error.h" |
33 | | #include "util-debug.h" |
34 | | #include "util-fmemopen.h" |
35 | | |
36 | | /* Regex to parse each line from reference.config file. The first substring |
37 | | * is for the system name and the second for the url */ |
38 | | /*-----------------------------------------------------------system-------------------url----*/ |
39 | 61.8k | #define SC_RCONF_REGEX "^\\s*config\\s+reference\\s*:\\s*([a-zA-Z][a-zA-Z0-9-_]*)\\s+(.+)\\s*$" |
40 | | |
41 | | /* Default path for the reference.conf file */ |
42 | 135k | #define SC_RCONF_DEFAULT_FILE_PATH CONFIG_DIR "/reference.config" |
43 | | |
44 | | /* the hash functions */ |
45 | | uint32_t SCRConfReferenceHashFunc(HashTable *ht, void *data, uint16_t datalen); |
46 | | char SCRConfReferenceHashCompareFunc(void *data1, uint16_t datalen1, |
47 | | void *data2, uint16_t datalen2); |
48 | | void SCRConfReferenceHashFree(void *ch); |
49 | | |
50 | | /* used to get the reference.config file path */ |
51 | | static const char *SCRConfGetConfFilename(const DetectEngineCtx *de_ctx); |
52 | | |
53 | | void SCReferenceConfInit(DetectEngineCtx *de_ctx) |
54 | 61.8k | { |
55 | 61.8k | int en; |
56 | 61.8k | PCRE2_SIZE eo; |
57 | 61.8k | int opts = 0; |
58 | | |
59 | 61.8k | de_ctx->reference_conf_regex = |
60 | 61.8k | pcre2_compile((PCRE2_SPTR8)SC_RCONF_REGEX, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL); |
61 | 61.8k | if (de_ctx->reference_conf_regex == NULL) { |
62 | 0 | PCRE2_UCHAR errbuffer[256]; |
63 | 0 | pcre2_get_error_message(en, errbuffer, sizeof(errbuffer)); |
64 | 0 | SCLogWarning("pcre2 compile of \"%s\" failed at " |
65 | 0 | "offset %d: %s", |
66 | 0 | SC_RCONF_REGEX, (int)eo, errbuffer); |
67 | 0 | return; |
68 | 0 | } |
69 | 61.8k | de_ctx->reference_conf_regex_match = |
70 | 61.8k | pcre2_match_data_create_from_pattern(de_ctx->reference_conf_regex, NULL); |
71 | 61.8k | return; |
72 | 61.8k | } |
73 | | |
74 | | void SCReferenceConfDeinit(DetectEngineCtx *de_ctx) |
75 | 135k | { |
76 | 135k | if (de_ctx->reference_conf_regex != NULL) { |
77 | 135k | pcre2_code_free(de_ctx->reference_conf_regex); |
78 | 135k | de_ctx->reference_conf_regex = NULL; |
79 | 135k | } |
80 | 135k | if (de_ctx->reference_conf_regex_match != NULL) { |
81 | 135k | pcre2_match_data_free(de_ctx->reference_conf_regex_match); |
82 | 135k | de_ctx->reference_conf_regex_match = NULL; |
83 | 135k | } |
84 | 135k | } |
85 | | |
86 | | |
87 | | /** |
88 | | * \brief Inits the context to be used by the Reference Config parsing API. |
89 | | * |
90 | | * This function initializes the hash table to be used by the Detection |
91 | | * Engine Context to hold the data from reference.config file, |
92 | | * obtains the file descriptor to parse the reference.config file, and |
93 | | * inits the regex used to parse the lines from reference.config file. |
94 | | * |
95 | | * \param de_ctx Pointer to the Detection Engine Context. |
96 | | * |
97 | | * \note if file open fails, we leave de_ctx->reference_conf_ht initialized |
98 | | * |
99 | | * \retval 0 On success. |
100 | | * \retval -1 On failure. |
101 | | */ |
102 | | static FILE *SCRConfInitContextAndLocalResources(DetectEngineCtx *de_ctx, FILE *fd) |
103 | 135k | { |
104 | | /* init the hash table to be used by the reference config references */ |
105 | 135k | de_ctx->reference_conf_ht = HashTableInit(128, SCRConfReferenceHashFunc, |
106 | 135k | SCRConfReferenceHashCompareFunc, |
107 | 135k | SCRConfReferenceHashFree); |
108 | 135k | if (de_ctx->reference_conf_ht == NULL) { |
109 | 0 | SCLogError("Error initializing the hash " |
110 | 0 | "table"); |
111 | 0 | return NULL; |
112 | 0 | } |
113 | | |
114 | | /* if it is not NULL, use the file descriptor. The hack so that we can |
115 | | * avoid using a dummy reference file for testing purposes and |
116 | | * instead use an input stream against a buffer containing the |
117 | | * reference strings */ |
118 | 135k | if (fd == NULL) { |
119 | 135k | const char *filename = SCRConfGetConfFilename(de_ctx); |
120 | 135k | if ((fd = fopen(filename, "r")) == NULL) { |
121 | | #ifdef UNITTESTS |
122 | | if (RunmodeIsUnittests()) { |
123 | | return NULL; // silently fail |
124 | | } |
125 | | #endif |
126 | 135k | SCLogError("Error opening file: \"%s\": %s", filename, strerror(errno)); |
127 | 135k | return NULL; |
128 | 135k | } |
129 | 135k | } |
130 | | |
131 | 0 | return fd; |
132 | 135k | } |
133 | | |
134 | | |
135 | | /** |
136 | | * \brief Returns the path for the Reference Config file. We check if we |
137 | | * can retrieve the path from the yaml conf file. If it is not present, |
138 | | * return the default path for the reference.config file which is |
139 | | * "./reference.config". |
140 | | * |
141 | | * \retval log_filename Pointer to a string containing the path for the |
142 | | * reference.config file. |
143 | | */ |
144 | | static const char *SCRConfGetConfFilename(const DetectEngineCtx *de_ctx) |
145 | 135k | { |
146 | 135k | const char *path = NULL; |
147 | | |
148 | 135k | if (de_ctx != NULL && strlen(de_ctx->config_prefix) > 0) { |
149 | 0 | char config_value[256]; |
150 | 0 | snprintf(config_value, sizeof(config_value), |
151 | 0 | "%s.reference-config-file", de_ctx->config_prefix); |
152 | | |
153 | | /* try loading prefix setting, fall back to global if that |
154 | | * fails. */ |
155 | 0 | if (ConfGet(config_value, &path) != 1) { |
156 | 0 | if (ConfGet("reference-config-file", &path) != 1) { |
157 | 0 | return (char *)SC_RCONF_DEFAULT_FILE_PATH; |
158 | 0 | } |
159 | 0 | } |
160 | 135k | } else { |
161 | 135k | if (ConfGet("reference-config-file", &path) != 1) { |
162 | 135k | return (char *)SC_RCONF_DEFAULT_FILE_PATH; |
163 | 135k | } |
164 | 135k | } |
165 | 0 | return path; |
166 | 135k | } |
167 | | |
168 | | /** |
169 | | * \brief Releases local resources used by the Reference Config API. |
170 | | */ |
171 | | static void SCRConfDeInitLocalResources(DetectEngineCtx *de_ctx, FILE *fd) |
172 | 0 | { |
173 | 0 | if (fd != NULL) { |
174 | 0 | fclose(fd); |
175 | 0 | } |
176 | |
|
177 | 0 | return; |
178 | 0 | } |
179 | | |
180 | | /** |
181 | | * \brief Releases de_ctx resources related to Reference Config API. |
182 | | */ |
183 | | void SCRConfDeInitContext(DetectEngineCtx *de_ctx) |
184 | 61.8k | { |
185 | 61.8k | if (de_ctx->reference_conf_ht != NULL) |
186 | 61.8k | HashTableFree(de_ctx->reference_conf_ht); |
187 | | |
188 | 61.8k | de_ctx->reference_conf_ht = NULL; |
189 | | |
190 | 61.8k | return; |
191 | 61.8k | } |
192 | | |
193 | | /** |
194 | | * \brief Converts a string to lowercase. |
195 | | * |
196 | | * \param str Pointer to the string to be converted. |
197 | | */ |
198 | | static char *SCRConfStringToLowercase(const char *str) |
199 | 435k | { |
200 | 435k | char *new_str = NULL; |
201 | 435k | char *temp_str = NULL; |
202 | | |
203 | 435k | if ((new_str = SCStrdup(str)) == NULL) { |
204 | 0 | return NULL; |
205 | 0 | } |
206 | | |
207 | 435k | temp_str = new_str; |
208 | 1.89M | while (*temp_str != '\0') { |
209 | 1.45M | *temp_str = u8_tolower((unsigned char)*temp_str); |
210 | 1.45M | temp_str++; |
211 | 1.45M | } |
212 | | |
213 | 435k | return new_str; |
214 | 435k | } |
215 | | |
216 | | /** |
217 | | * \brief Parses a line from the reference config file and adds it to Reference |
218 | | * Config hash table DetectEngineCtx->reference_conf_ht. |
219 | | * |
220 | | * \param rawstr Pointer to the string to be parsed. |
221 | | * \param de_ctx Pointer to the Detection Engine Context. |
222 | | * |
223 | | * \retval 0 On success. |
224 | | * \retval -1 On failure. |
225 | | */ |
226 | | int SCRConfAddReference(DetectEngineCtx *de_ctx, const char *line) |
227 | 14.6k | { |
228 | 14.6k | char system[REFERENCE_SYSTEM_NAME_MAX]; |
229 | 14.6k | char url[REFERENCE_CONTENT_NAME_MAX]; |
230 | | |
231 | 14.6k | SCRConfReference *ref_new = NULL; |
232 | 14.6k | SCRConfReference *ref_lookup = NULL; |
233 | | |
234 | 14.6k | int ret = 0; |
235 | | |
236 | 14.6k | ret = pcre2_match(de_ctx->reference_conf_regex, (PCRE2_SPTR8)line, strlen(line), 0, 0, |
237 | 14.6k | de_ctx->reference_conf_regex_match, NULL); |
238 | 14.6k | if (ret < 0) { |
239 | 653 | SCLogError("Invalid Reference Config in " |
240 | 653 | "reference.config file"); |
241 | 653 | goto error; |
242 | 653 | } |
243 | | |
244 | | /* retrieve the reference system */ |
245 | 14.0k | size_t copylen = sizeof(system); |
246 | 14.0k | ret = pcre2_substring_copy_bynumber( |
247 | 14.0k | de_ctx->reference_conf_regex_match, 1, (PCRE2_UCHAR8 *)system, ©len); |
248 | 14.0k | if (ret < 0) { |
249 | 0 | SCLogError("pcre2_substring_copy_bynumber() failed"); |
250 | 0 | goto error; |
251 | 0 | } |
252 | | |
253 | | /* retrieve the reference url */ |
254 | 14.0k | copylen = sizeof(url); |
255 | 14.0k | ret = pcre2_substring_copy_bynumber( |
256 | 14.0k | de_ctx->reference_conf_regex_match, 2, (PCRE2_UCHAR8 *)url, ©len); |
257 | 14.0k | if (ret < 0) { |
258 | 0 | SCLogError("pcre2_substring_copy_bynumber() failed"); |
259 | 0 | goto error; |
260 | 0 | } |
261 | | |
262 | | /* Create a new instance of the parsed Reference string */ |
263 | 14.0k | ref_new = SCRConfAllocSCRConfReference(system, url); |
264 | 14.0k | if (ref_new == NULL) |
265 | 0 | goto error; |
266 | | |
267 | | /* Check if the Reference is present in the HashTable. In case it's present |
268 | | * ignore it, as it's a duplicate. If not present, add it to the table */ |
269 | 14.0k | ref_lookup = HashTableLookup(de_ctx->reference_conf_ht, ref_new, 0); |
270 | 14.0k | if (ref_lookup == NULL) { |
271 | 14.0k | if (HashTableAdd(de_ctx->reference_conf_ht, ref_new, 0) < 0) { |
272 | 0 | SCLogDebug("HashTable Add failed"); |
273 | 0 | } |
274 | 14.0k | } else { |
275 | 0 | SCLogDebug("Duplicate reference found inside reference.config"); |
276 | 0 | SCRConfDeAllocSCRConfReference(ref_new); |
277 | 0 | } |
278 | | |
279 | 14.0k | return 0; |
280 | | |
281 | 653 | error: |
282 | 653 | return -1; |
283 | 14.0k | } |
284 | | |
285 | | /** |
286 | | * \brief Checks if a string is a comment or a blank line. |
287 | | * |
288 | | * Comments lines are lines of the following format - |
289 | | * "# This is a comment string" or |
290 | | * " # This is a comment string". |
291 | | * |
292 | | * \param line String that has to be checked. |
293 | | * |
294 | | * \retval 1 On the argument string being a comment or blank line. |
295 | | * \retval 0 Otherwise. |
296 | | */ |
297 | | static int SCRConfIsLineBlankOrComment(char *line) |
298 | 0 | { |
299 | 0 | while (*line != '\0') { |
300 | | /* we have a comment */ |
301 | 0 | if (*line == '#') |
302 | 0 | return 1; |
303 | | |
304 | | /* this line is neither a comment line, nor a blank line */ |
305 | 0 | if (!isspace((unsigned char)*line)) |
306 | 0 | return 0; |
307 | | |
308 | 0 | line++; |
309 | 0 | } |
310 | | |
311 | | /* we have a blank line */ |
312 | 0 | return 1; |
313 | 0 | } |
314 | | |
315 | | /** |
316 | | * \brief Parses the Reference Config file and updates the |
317 | | * DetectionEngineCtx->reference_conf_ht with the Reference information. |
318 | | * |
319 | | * \param de_ctx Pointer to the Detection Engine Context. |
320 | | */ |
321 | | static bool SCRConfParseFile(DetectEngineCtx *de_ctx, FILE *fd) |
322 | 0 | { |
323 | 0 | char line[1024]; |
324 | 0 | int runmode = RunmodeGetCurrent(); |
325 | 0 | bool is_conf_test_mode = runmode == RUNMODE_CONF_TEST; |
326 | 0 | while (fgets(line, sizeof(line), fd) != NULL) { |
327 | 0 | if (SCRConfIsLineBlankOrComment(line)) |
328 | 0 | continue; |
329 | | |
330 | 0 | if (SCRConfAddReference(de_ctx, line) != 0) { |
331 | 0 | if (is_conf_test_mode) { |
332 | 0 | return false; |
333 | 0 | } |
334 | 0 | } |
335 | 0 | } |
336 | | |
337 | | #ifdef UNITTESTS |
338 | | SCLogInfo("Added \"%d\" reference types from the reference.config file", |
339 | | de_ctx->reference_conf_ht->count); |
340 | | #endif /* UNITTESTS */ |
341 | 0 | return true; |
342 | 0 | } |
343 | | |
344 | | /** |
345 | | * \brief Returns a new SCRConfReference instance. The reference string |
346 | | * is converted into lowercase, before being assigned to the instance. |
347 | | * |
348 | | * \param system Pointer to the system. |
349 | | * \param url Pointer to the reference url. |
350 | | * |
351 | | * \retval ref Pointer to the new instance of SCRConfReference. |
352 | | */ |
353 | | SCRConfReference *SCRConfAllocSCRConfReference(const char *system, |
354 | | const char *url) |
355 | 435k | { |
356 | 435k | SCRConfReference *ref = NULL; |
357 | | |
358 | 435k | if (system == NULL) { |
359 | 0 | SCLogError("Invalid arguments. system NULL"); |
360 | 0 | return NULL; |
361 | 0 | } |
362 | | |
363 | 435k | if ((ref = SCMalloc(sizeof(SCRConfReference))) == NULL) { |
364 | 0 | return NULL; |
365 | 0 | } |
366 | 435k | memset(ref, 0, sizeof(SCRConfReference)); |
367 | | |
368 | 435k | if ((ref->system = SCRConfStringToLowercase(system)) == NULL) { |
369 | 0 | SCFree(ref); |
370 | 0 | return NULL; |
371 | 0 | } |
372 | | |
373 | 435k | if (url != NULL && (ref->url = SCStrdup(url)) == NULL) { |
374 | 0 | SCFree(ref->system); |
375 | 0 | SCFree(ref); |
376 | 0 | return NULL; |
377 | 0 | } |
378 | | |
379 | 435k | return ref; |
380 | 435k | } |
381 | | |
382 | | /** |
383 | | * \brief Frees a SCRConfReference instance. |
384 | | * |
385 | | * \param Pointer to the SCRConfReference instance that has to be freed. |
386 | | */ |
387 | | void SCRConfDeAllocSCRConfReference(SCRConfReference *ref) |
388 | 294k | { |
389 | 294k | if (ref != NULL) { |
390 | 294k | if (ref->system != NULL) |
391 | 294k | SCFree(ref->system); |
392 | | |
393 | 294k | if (ref->url != NULL) |
394 | 8.88k | SCFree(ref->url); |
395 | | |
396 | 294k | SCFree(ref); |
397 | 294k | } |
398 | | |
399 | 294k | return; |
400 | 294k | } |
401 | | |
402 | | /** |
403 | | * \brief Hashing function to be used to hash the Reference name. Would be |
404 | | * supplied as an argument to the HashTableInit function for |
405 | | * DetectEngineCtx->reference_conf_ht. |
406 | | * |
407 | | * \param ht Pointer to the HashTable. |
408 | | * \param data Pointer to the data to be hashed. In this case, the data |
409 | | * would be a pointer to a SCRConfReference instance. |
410 | | * \param datalen Not used by this function. |
411 | | */ |
412 | | uint32_t SCRConfReferenceHashFunc(HashTable *ht, void *data, uint16_t datalen) |
413 | 449k | { |
414 | 449k | SCRConfReference *ref = (SCRConfReference *)data; |
415 | 449k | uint32_t hash = 0; |
416 | 449k | int i = 0; |
417 | | |
418 | 449k | int len = strlen(ref->system); |
419 | | |
420 | 1.95M | for (i = 0; i < len; i++) |
421 | 1.51M | hash += u8_tolower((unsigned char)ref->system[i]); |
422 | | |
423 | 449k | hash = hash % ht->array_size; |
424 | | |
425 | 449k | return hash; |
426 | 449k | } |
427 | | |
428 | | /** |
429 | | * \brief Used to compare two References that have been stored in the HashTable. |
430 | | * This function is supplied as an argument to the HashTableInit function |
431 | | * for DetectionEngineCtx->reference_conf_ct. |
432 | | * |
433 | | * \param data1 Pointer to the first SCRConfReference to be compared. |
434 | | * \param len1 Not used by this function. |
435 | | * \param data2 Pointer to the second SCRConfReference to be compared. |
436 | | * \param len2 Not used by this function. |
437 | | * |
438 | | * \retval 1 On data1 and data2 being equal. |
439 | | * \retval 0 On data1 and data2 not being equal. |
440 | | */ |
441 | | char SCRConfReferenceHashCompareFunc(void *data1, uint16_t datalen1, |
442 | | void *data2, uint16_t datalen2) |
443 | 417k | { |
444 | 417k | SCRConfReference *ref1 = (SCRConfReference *)data1; |
445 | 417k | SCRConfReference *ref2 = (SCRConfReference *)data2; |
446 | 417k | int len1 = 0; |
447 | 417k | int len2 = 0; |
448 | | |
449 | 417k | if (ref1 == NULL || ref2 == NULL) |
450 | 0 | return 0; |
451 | | |
452 | 417k | if (ref1->system == NULL || ref2->system == NULL) |
453 | 0 | return 0; |
454 | | |
455 | 417k | len1 = strlen(ref1->system); |
456 | 417k | len2 = strlen(ref2->system); |
457 | | |
458 | 417k | if (len1 == len2 && memcmp(ref1->system, ref2->system, len1) == 0) { |
459 | 406k | SCLogDebug("Match found inside Reference-Config hash function"); |
460 | 406k | return 1; |
461 | 406k | } |
462 | | |
463 | 10.7k | return 0; |
464 | 417k | } |
465 | | |
466 | | /** |
467 | | * \brief Used to free the Reference Config Hash Data that was stored in |
468 | | * DetectEngineCtx->reference_conf_ht Hashtable. |
469 | | * |
470 | | * \param data Pointer to the data that has to be freed. |
471 | | */ |
472 | | void SCRConfReferenceHashFree(void *data) |
473 | 8.88k | { |
474 | 8.88k | SCRConfDeAllocSCRConfReference(data); |
475 | | |
476 | 8.88k | return; |
477 | 8.88k | } |
478 | | |
479 | | /** |
480 | | * \brief Loads the Reference info from the reference.config file. |
481 | | * |
482 | | * The reference.config file contains references that can be used in |
483 | | * Signatures. Each line of the file should have the following format - |
484 | | * config reference: system_name, reference_url. |
485 | | * |
486 | | * \param de_ctx Pointer to the Detection Engine Context that should be updated |
487 | | * with reference information. |
488 | | * |
489 | | * \retval 0 On success. |
490 | | * \retval -1 On failure. |
491 | | */ |
492 | | int SCRConfLoadReferenceConfigFile(DetectEngineCtx *de_ctx, FILE *fd) |
493 | 135k | { |
494 | 135k | fd = SCRConfInitContextAndLocalResources(de_ctx, fd); |
495 | 135k | if (fd == NULL) { |
496 | | #ifdef UNITTESTS |
497 | | if (RunmodeIsUnittests()) { |
498 | | return -1; |
499 | | } |
500 | | #endif |
501 | 135k | SCLogError("please check the \"reference-config-file\" " |
502 | 135k | "option in your suricata.yaml file"); |
503 | 135k | return -1; |
504 | 135k | } |
505 | | |
506 | 0 | bool rc = SCRConfParseFile(de_ctx, fd); |
507 | 0 | SCRConfDeInitLocalResources(de_ctx, fd); |
508 | |
|
509 | 0 | return rc ? 0 : -1; |
510 | 135k | } |
511 | | |
512 | | /** |
513 | | * \brief Gets the reference config from the corresponding hash table stored |
514 | | * in the Detection Engine Context's reference conf ht, given the |
515 | | * reference name. |
516 | | * |
517 | | * \param ct_name Pointer to the reference name that has to be looked up. |
518 | | * \param de_ctx Pointer to the Detection Engine Context. |
519 | | * |
520 | | * \retval lookup_rconf_info Pointer to the SCRConfReference instance from |
521 | | * the hash table on success; NULL on failure. |
522 | | */ |
523 | | SCRConfReference *SCRConfGetReference(const char *rconf_name, |
524 | | DetectEngineCtx *de_ctx) |
525 | 421k | { |
526 | 421k | SCRConfReference *ref_conf = SCRConfAllocSCRConfReference(rconf_name, NULL); |
527 | 421k | if (ref_conf == NULL) |
528 | 0 | return NULL; |
529 | 421k | SCRConfReference *lookup_ref_conf = HashTableLookup(de_ctx->reference_conf_ht, |
530 | 421k | ref_conf, 0); |
531 | | |
532 | 421k | SCRConfDeAllocSCRConfReference(ref_conf); |
533 | 421k | return lookup_ref_conf; |
534 | 421k | } |
535 | | |
536 | | /*----------------------------------Unittests---------------------------------*/ |
537 | | |
538 | | |
539 | | #ifdef UNITTESTS |
540 | | |
541 | | /** |
542 | | * \brief Creates a dummy reference config, with all valid references, for |
543 | | * testing purposes. |
544 | | */ |
545 | | FILE *SCRConfGenerateValidDummyReferenceConfigFD01(void) |
546 | | { |
547 | | const char *buffer = |
548 | | "config reference: one http://www.one.com\n" |
549 | | "config reference: two http://www.two.com\n" |
550 | | "config reference: three http://www.three.com\n" |
551 | | "config reference: one http://www.one.com\n" |
552 | | "config reference: three http://www.three.com\n"; |
553 | | |
554 | | FILE *fd = SCFmemopen((void *)buffer, strlen(buffer), "r"); |
555 | | if (fd == NULL) |
556 | | SCLogDebug("Error with SCFmemopen() called by Reference Config test code"); |
557 | | |
558 | | return fd; |
559 | | } |
560 | | |
561 | | /** |
562 | | * \brief Creates a dummy reference config, with some valid references and a |
563 | | * couple of invalid references, for testing purposes. |
564 | | */ |
565 | | FILE *SCRConfGenerateInvalidDummyReferenceConfigFD02(void) |
566 | | { |
567 | | const char *buffer = |
568 | | "config reference: one http://www.one.com\n" |
569 | | "config_ reference: two http://www.two.com\n" |
570 | | "config reference_: three http://www.three.com\n" |
571 | | "config reference: four\n" |
572 | | "config reference five http://www.five.com\n"; |
573 | | |
574 | | FILE *fd = SCFmemopen((void *)buffer, strlen(buffer), "r"); |
575 | | if (fd == NULL) |
576 | | SCLogDebug("Error with SCFmemopen() called by Reference Config test code"); |
577 | | |
578 | | return fd; |
579 | | } |
580 | | |
581 | | /** |
582 | | * \brief Creates a dummy reference config, with all invalid references, for |
583 | | * testing purposes. |
584 | | */ |
585 | | FILE *SCRConfGenerateInvalidDummyReferenceConfigFD03(void) |
586 | | { |
587 | | const char *buffer = |
588 | | "config reference one http://www.one.com\n" |
589 | | "config_ reference: two http://www.two.com\n" |
590 | | "config reference_: three http://www.three.com\n" |
591 | | "config reference: four\n"; |
592 | | |
593 | | FILE *fd = SCFmemopen((void *)buffer, strlen(buffer), "r"); |
594 | | if (fd == NULL) |
595 | | SCLogDebug("Error with SCFmemopen() called by Reference Config test code"); |
596 | | |
597 | | return fd; |
598 | | } |
599 | | |
600 | | /** |
601 | | * \test Check that the reference file is loaded and the detection engine |
602 | | * content reference_conf_ht loaded with the reference data. |
603 | | */ |
604 | | static int SCRConfTest01(void) |
605 | | { |
606 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
607 | | int result = 0; |
608 | | |
609 | | if (de_ctx == NULL) |
610 | | return result; |
611 | | |
612 | | FILE *fd = SCRConfGenerateValidDummyReferenceConfigFD01(); |
613 | | SCRConfLoadReferenceConfigFile(de_ctx, fd); |
614 | | |
615 | | if (de_ctx->reference_conf_ht == NULL) |
616 | | goto end; |
617 | | |
618 | | result = (de_ctx->reference_conf_ht->count == 3); |
619 | | if (result == 0) |
620 | | printf("FAILED: de_ctx->reference_conf_ht->count %u: ", de_ctx->reference_conf_ht->count); |
621 | | |
622 | | end: |
623 | | if (de_ctx != NULL) |
624 | | DetectEngineCtxFree(de_ctx); |
625 | | return result; |
626 | | } |
627 | | |
628 | | /** |
629 | | * \test Check that invalid references present in the reference.config file |
630 | | * aren't loaded. |
631 | | */ |
632 | | static int SCRConfTest02(void) |
633 | | { |
634 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
635 | | int result = 0; |
636 | | |
637 | | if (de_ctx == NULL) |
638 | | return result; |
639 | | |
640 | | FILE *fd = SCRConfGenerateInvalidDummyReferenceConfigFD03(); |
641 | | SCRConfLoadReferenceConfigFile(de_ctx, fd); |
642 | | |
643 | | if (de_ctx->reference_conf_ht == NULL) |
644 | | goto end; |
645 | | |
646 | | result = (de_ctx->reference_conf_ht->count == 0); |
647 | | |
648 | | |
649 | | end: |
650 | | if (de_ctx != NULL) |
651 | | DetectEngineCtxFree(de_ctx); |
652 | | return result; |
653 | | } |
654 | | |
655 | | /** |
656 | | * \test Check that only valid references are loaded into the hash table from |
657 | | * the reference.config file. |
658 | | */ |
659 | | static int SCRConfTest03(void) |
660 | | { |
661 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
662 | | int result = 0; |
663 | | |
664 | | if (de_ctx == NULL) |
665 | | return result; |
666 | | |
667 | | FILE *fd = SCRConfGenerateInvalidDummyReferenceConfigFD02(); |
668 | | SCRConfLoadReferenceConfigFile(de_ctx, fd); |
669 | | |
670 | | if (de_ctx->reference_conf_ht == NULL) |
671 | | goto end; |
672 | | |
673 | | result = (de_ctx->reference_conf_ht->count == 1); |
674 | | |
675 | | end: |
676 | | if (de_ctx != NULL) |
677 | | DetectEngineCtxFree(de_ctx); |
678 | | return result; |
679 | | } |
680 | | |
681 | | /** |
682 | | * \test Check if the reference info from the reference.config file have |
683 | | * been loaded into the hash table. |
684 | | */ |
685 | | static int SCRConfTest04(void) |
686 | | { |
687 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
688 | | int result = 1; |
689 | | |
690 | | if (de_ctx == NULL) |
691 | | return 0; |
692 | | |
693 | | FILE *fd = SCRConfGenerateValidDummyReferenceConfigFD01(); |
694 | | SCRConfLoadReferenceConfigFile(de_ctx, fd); |
695 | | |
696 | | if (de_ctx->reference_conf_ht == NULL) |
697 | | goto end; |
698 | | |
699 | | result = (de_ctx->reference_conf_ht->count == 3); |
700 | | |
701 | | result &= (SCRConfGetReference("one", de_ctx) != NULL); |
702 | | result &= (SCRConfGetReference("two", de_ctx) != NULL); |
703 | | result &= (SCRConfGetReference("three", de_ctx) != NULL); |
704 | | result &= (SCRConfGetReference("four", de_ctx) == NULL); |
705 | | |
706 | | end: |
707 | | if (de_ctx != NULL) |
708 | | DetectEngineCtxFree(de_ctx); |
709 | | return result; |
710 | | } |
711 | | |
712 | | /** |
713 | | * \test Check if the reference info from the invalid reference.config file |
714 | | * have not been loaded into the hash table, and cross verify to check |
715 | | * that the hash table contains no reference data. |
716 | | */ |
717 | | static int SCRConfTest05(void) |
718 | | { |
719 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
720 | | int result = 1; |
721 | | |
722 | | if (de_ctx == NULL) |
723 | | return 0; |
724 | | |
725 | | FILE *fd = SCRConfGenerateInvalidDummyReferenceConfigFD03(); |
726 | | SCRConfLoadReferenceConfigFile(de_ctx, fd); |
727 | | |
728 | | if (de_ctx->reference_conf_ht == NULL) |
729 | | goto end; |
730 | | |
731 | | result = (de_ctx->reference_conf_ht->count == 0); |
732 | | |
733 | | result &= (SCRConfGetReference("one", de_ctx) == NULL); |
734 | | result &= (SCRConfGetReference("two", de_ctx) == NULL); |
735 | | result &= (SCRConfGetReference("three", de_ctx) == NULL); |
736 | | result &= (SCRConfGetReference("four", de_ctx) == NULL); |
737 | | result &= (SCRConfGetReference("five", de_ctx) == NULL); |
738 | | |
739 | | end: |
740 | | if (de_ctx != NULL) |
741 | | DetectEngineCtxFree(de_ctx); |
742 | | return result; |
743 | | } |
744 | | |
745 | | /** |
746 | | * \test Check if the reference info from the reference.config file have |
747 | | * been loaded into the hash table. |
748 | | */ |
749 | | static int SCRConfTest06(void) |
750 | | { |
751 | | DetectEngineCtx *de_ctx = DetectEngineCtxInit(); |
752 | | int result = 1; |
753 | | |
754 | | if (de_ctx == NULL) |
755 | | return 0; |
756 | | |
757 | | FILE *fd = SCRConfGenerateInvalidDummyReferenceConfigFD02(); |
758 | | SCRConfLoadReferenceConfigFile(de_ctx, fd); |
759 | | |
760 | | if (de_ctx->reference_conf_ht == NULL) |
761 | | goto end; |
762 | | |
763 | | result = (de_ctx->reference_conf_ht->count == 1); |
764 | | |
765 | | result &= (SCRConfGetReference("one", de_ctx) != NULL); |
766 | | result &= (SCRConfGetReference("two", de_ctx) == NULL); |
767 | | result &= (SCRConfGetReference("three", de_ctx) == NULL); |
768 | | result &= (SCRConfGetReference("four", de_ctx) == NULL); |
769 | | result &= (SCRConfGetReference("five", de_ctx) == NULL); |
770 | | |
771 | | end: |
772 | | if (de_ctx != NULL) |
773 | | DetectEngineCtxFree(de_ctx); |
774 | | return result; |
775 | | } |
776 | | |
777 | | #endif /* UNITTESTS */ |
778 | | |
779 | | /** |
780 | | * \brief This function registers unit tests for Reference Config API. |
781 | | */ |
782 | | void SCRConfRegisterTests(void) |
783 | 0 | { |
784 | |
|
785 | | #ifdef UNITTESTS |
786 | | UtRegisterTest("SCRConfTest01", SCRConfTest01); |
787 | | UtRegisterTest("SCRConfTest02", SCRConfTest02); |
788 | | UtRegisterTest("SCRConfTest03", SCRConfTest03); |
789 | | UtRegisterTest("SCRConfTest04", SCRConfTest04); |
790 | | UtRegisterTest("SCRConfTest05", SCRConfTest05); |
791 | | UtRegisterTest("SCRConfTest06", SCRConfTest06); |
792 | | #endif /* UNITTESTS */ |
793 | |
|
794 | 0 | return; |
795 | 0 | } |