Coverage Report

Created: 2025-07-23 07:29

/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, &copylen);
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, &copylen);
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
}