Coverage Report

Created: 2026-11-12 06:59

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