Coverage Report

Created: 2026-06-30 07:20

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
75
{
35
75
    sigmatch_table[DETECT_BASE64_DATA].name = "base64_data";
36
75
    sigmatch_table[DETECT_BASE64_DATA].desc =
37
75
        "Content match base64 decoded data.";
38
75
    sigmatch_table[DETECT_BASE64_DATA].url =
39
75
        "/rules/base64-keywords.html#base64-data";
40
75
    sigmatch_table[DETECT_BASE64_DATA].Setup = DetectBase64DataSetup;
41
#ifdef UNITTESTS
42
    sigmatch_table[DETECT_BASE64_DATA].RegisterTests =
43
        DetectBase64DataRegisterTests;
44
#endif
45
75
    sigmatch_table[DETECT_BASE64_DATA].flags |= SIGMATCH_NOOPT;
46
75
}
47
48
static int DetectBase64DataSetup(DetectEngineCtx *de_ctx, Signature *s,
49
    const char *str)
50
7.56k
{
51
7.56k
    SigMatch *pm = NULL;
52
53
    /* Check for a preceding base64_decode. */
54
7.56k
    pm = DetectGetLastSMFromLists(s, DETECT_BASE64_DECODE, -1);
55
7.56k
    if (pm == NULL) {
56
456
        SCLogError("\"base64_data\" keyword seen without preceding base64_decode.");
57
456
        return -1;
58
456
    }
59
60
7.10k
    s->init_data->list = DETECT_SM_LIST_BASE64_DATA;
61
7.10k
    return 0;
62
7.56k
}
63
64
int DetectBase64DataDoMatch(DetectEngineCtx *de_ctx,
65
    DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f)
66
101
{
67
101
    if (det_ctx->base64_decoded_len) {
68
101
        det_ctx->buffer_offset = 0;
69
101
        return DetectEngineContentInspection(de_ctx, det_ctx, s,
70
101
            s->sm_arrays[DETECT_SM_LIST_BASE64_DATA], NULL, f, det_ctx->base64_decoded,
71
101
            det_ctx->base64_decoded_len, 0, DETECT_CI_FLAGS_SINGLE,
72
101
            DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE);
73
101
    }
74
75
0
    return 0;
76
101
}
77
78
#ifdef UNITTESTS
79
80
static int g_file_data_buffer_id = 0;
81
82
static int DetectBase64DataSetupTest01(void)
83
{
84
    DetectEngineCtx *de_ctx = NULL;
85
    SigMatch *sm;
86
    int retval = 0;
87
88
    de_ctx = DetectEngineCtxInit();
89
    if (de_ctx == NULL) {
90
        goto end;
91
    }
92
93
    de_ctx->flags |= DE_QUIET;
94
    de_ctx->sig_list = SigInit(de_ctx,
95
        "alert smtp any any -> any any (msg:\"DetectBase64DataSetupTest\"; "
96
        "base64_decode; base64_data; content:\"content\"; sid:1; rev:1;)");
97
    if (de_ctx->sig_list == NULL) {
98
        printf("SigInit failed: ");
99
        goto end;
100
    }
101
102
    sm = de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_PMATCH];
103
    if (sm == NULL) {
104
        printf("DETECT_SM_LIST_PMATCH should not be NULL: ");
105
        goto end;
106
    }
107
    if (sm->type != DETECT_BASE64_DECODE) {
108
        printf("sm->type should be DETECT_BASE64_DECODE: ");
109
        goto end;
110
    }
111
112
    if (de_ctx->sig_list->init_data->smlists[DETECT_SM_LIST_BASE64_DATA] == NULL) {
113
        printf("DETECT_SM_LIST_BASE64_DATA should not be NULL: ");
114
       goto end;
115
    }
116
117
    retval = 1;
118
end:
119
    if (de_ctx != NULL) {
120
        SigGroupCleanup(de_ctx);
121
        SigCleanSignatures(de_ctx);
122
        DetectEngineCtxFree(de_ctx);
123
    }
124
    return retval;
125
}
126
127
/**
128
 * \test Test that the list can be changed to post-detection lists
129
 *     after the base64 keyword.
130
 */
131
static int DetectBase64DataSetupTest04(void)
132
{
133
    DetectEngineCtx *de_ctx = NULL;
134
    int retval = 0;
135
136
    de_ctx = DetectEngineCtxInit();
137
    if (de_ctx == NULL) {
138
        goto end;
139
    }
140
141
    de_ctx->flags |= DE_QUIET;
142
    de_ctx->sig_list = SigInit(de_ctx,
143
        "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;)");
144
    if (de_ctx->sig_list == NULL) {
145
        printf("SigInit failed: ");
146
        goto end;
147
    }
148
149
    retval = 1;
150
end:
151
    if (de_ctx != NULL) {
152
        SigGroupCleanup(de_ctx);
153
        SigCleanSignatures(de_ctx);
154
        DetectEngineCtxFree(de_ctx);
155
    }
156
    return retval;
157
}
158
159
static void DetectBase64DataRegisterTests(void)
160
{
161
    g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
162
163
    UtRegisterTest("DetectBase64DataSetupTest01", DetectBase64DataSetupTest01);
164
    UtRegisterTest("DetectBase64DataSetupTest04", DetectBase64DataSetupTest04);
165
}
166
#endif /* UNITTESTS */