Coverage Report

Created: 2025-11-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-base64-data.c
Line
Count
Source
1
/* Copyright (C) 2015 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
#include "suricata-common.h"
19
#include "detect.h"
20
#include "detect-engine.h"
21
#include "detect-engine-content-inspection.h"
22
#include "detect-parse.h"
23
#include "detect-base64-data.h"
24
#include "detect-engine-build.h"
25
26
#include "util-unittest.h"
27
28
static int DetectBase64DataSetup(DetectEngineCtx *, Signature *, const char *);
29
#ifdef UNITTESTS
30
static void DetectBase64DataRegisterTests(void);
31
#endif
32
33
void DetectBase64DataRegister(void)
34
73
{
35
73
    sigmatch_table[DETECT_BASE64_DATA].name = "base64_data";
36
73
    sigmatch_table[DETECT_BASE64_DATA].desc =
37
73
        "Content match base64 decoded data.";
38
73
    sigmatch_table[DETECT_BASE64_DATA].url =
39
73
        "/rules/base64-keywords.html#base64-data";
40
73
    sigmatch_table[DETECT_BASE64_DATA].Setup = DetectBase64DataSetup;
41
#ifdef UNITTESTS
42
    sigmatch_table[DETECT_BASE64_DATA].RegisterTests =
43
        DetectBase64DataRegisterTests;
44
#endif
45
73
    sigmatch_table[DETECT_BASE64_DATA].flags |= SIGMATCH_NOOPT;
46
73
}
47
48
static int DetectBase64DataSetup(DetectEngineCtx *de_ctx, Signature *s,
49
    const char *str)
50
6.51k
{
51
6.51k
    SigMatch *pm = NULL;
52
53
    /* Check for a preceding base64_decode. */
54
6.51k
    pm = DetectGetLastSMFromLists(s, DETECT_BASE64_DECODE, -1);
55
6.51k
    if (pm == NULL) {
56
326
        SCLogError("\"base64_data\" keyword seen without preceding base64_decode.");
57
326
        return -1;
58
326
    }
59
60
6.18k
    s->init_data->list = DETECT_SM_LIST_BASE64_DATA;
61
6.18k
    return 0;
62
6.51k
}
63
64
int DetectBase64DataDoMatch(DetectEngineCtx *de_ctx,
65
    DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f)
66
35
{
67
35
    if (det_ctx->base64_decoded_len) {
68
35
        return DetectEngineContentInspection(de_ctx, det_ctx, s,
69
35
            s->sm_arrays[DETECT_SM_LIST_BASE64_DATA], NULL, f, det_ctx->base64_decoded,
70
35
            det_ctx->base64_decoded_len, 0, DETECT_CI_FLAGS_SINGLE,
71
35
            DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
72
35
    }
73
74
0
    return 0;
75
35
}
76
77
#ifdef UNITTESTS
78
79
static int g_file_data_buffer_id = 0;
80
81
static int DetectBase64DataSetupTest01(void)
82
{
83
    DetectEngineCtx *de_ctx = NULL;
84
    SigMatch *sm;
85
    int retval = 0;
86
87
    de_ctx = DetectEngineCtxInit();
88
    if (de_ctx == NULL) {
89
        goto end;
90
    }
91
92
    de_ctx->flags |= DE_QUIET;
93
    de_ctx->sig_list = SigInit(de_ctx,
94
        "alert smtp any any -> any any (msg:\"DetectBase64DataSetupTest\"; "
95
        "base64_decode; base64_data; content:\"content\"; sid:1; rev:1;)");
96
    if (de_ctx->sig_list == NULL) {
97
        printf("SigInit failed: ");
98
        goto end;
99
    }
100
101
    sm = de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH];
102
    if (sm == NULL) {
103
        printf("DETECT_SM_LIST_PMATCH should not be NULL: ");
104
        goto end;
105
    }
106
    if (sm->type != DETECT_BASE64_DECODE) {
107
        printf("sm->type should be DETECT_BASE64_DECODE: ");
108
        goto end;
109
    }
110
111
    if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_BASE64_DATA] == NULL) {
112
        printf("DETECT_SM_LIST_BASE64_DATA should not be NULL: ");
113
       goto end;
114
    }
115
116
    retval = 1;
117
end:
118
    if (de_ctx != NULL) {
119
        SigGroupCleanup(de_ctx);
120
        SigCleanSignatures(de_ctx);
121
        DetectEngineCtxFree(de_ctx);
122
    }
123
    return retval;
124
}
125
126
/**
127
 * \test Test that the list can be changed to post-detection lists
128
 *     after the base64 keyword.
129
 */
130
static int DetectBase64DataSetupTest04(void)
131
{
132
    DetectEngineCtx *de_ctx = NULL;
133
    int retval = 0;
134
135
    de_ctx = DetectEngineCtxInit();
136
    if (de_ctx == NULL) {
137
        goto end;
138
    }
139
140
    de_ctx->flags |= DE_QUIET;
141
    de_ctx->sig_list = SigInit(de_ctx,
142
        "alert tcp any any -> any any (msg:\"some b64thing\"; flow:established,from_server; file_data; content:\"sometext\"; fast_pattern; base64_decode:relative; base64_data; content:\"foobar\"; nocase; tag:session,120,seconds; sid:1111111; rev:1;)");
143
    if (de_ctx->sig_list == NULL) {
144
        printf("SigInit failed: ");
145
        goto end;
146
    }
147
148
    retval = 1;
149
end:
150
    if (de_ctx != NULL) {
151
        SigGroupCleanup(de_ctx);
152
        SigCleanSignatures(de_ctx);
153
        DetectEngineCtxFree(de_ctx);
154
    }
155
    return retval;
156
}
157
158
static void DetectBase64DataRegisterTests(void)
159
{
160
    g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
161
162
    UtRegisterTest("DetectBase64DataSetupTest01", DetectBase64DataSetupTest01);
163
    UtRegisterTest("DetectBase64DataSetupTest04", DetectBase64DataSetupTest04);
164
}
165
#endif /* UNITTESTS */