• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 22550902417

01 Mar 2026 07:32PM UTC coverage: 68.401% (-5.3%) from 73.687%
22550902417

Pull #14922

github

web-flow
github-actions: bump actions/upload-artifact from 6.0.0 to 7.0.0

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #14922: github-actions: bump actions/upload-artifact from 6.0.0 to 7.0.0

218243 of 319063 relevant lines covered (68.4%)

3284926.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.29
/src/detect-http-raw-header.c
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
 * \ingroup httplayer
20
 *
21
 * @{
22
 */
23

24

25
/**
26
 * \file
27
 *
28
 * \author Pablo Rincon <pablo.rincon.crespo@gmail.com>
29
 *
30
 * Implements support for http_raw_header keyword.
31
 */
32

33
#include "suricata-common.h"
34
#include "threads.h"
35
#include "decode.h"
36

37
#include "detect.h"
38
#include "detect-parse.h"
39
#include "detect-engine.h"
40
#include "detect-engine-buffer.h"
41
#include "detect-engine-mpm.h"
42
#include "detect-engine-prefilter.h"
43
#include "detect-content.h"
44

45
#include "flow.h"
46
#include "flow-var.h"
47
#include "flow-util.h"
48

49
#include "util-debug.h"
50
#include "util-profiling.h"
51

52
#include "app-layer.h"
53
#include "app-layer-parser.h"
54
#include "app-layer-htp.h"
55
#include "detect-http-raw-header.h"
56

57
static int DetectHttpRawHeaderSetup(DetectEngineCtx *, Signature *, const char *);
58
static int DetectHttpRawHeaderSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str);
59
#ifdef UNITTESTS
60
static void DetectHttpRawHeaderRegisterTests(void);
61
#endif
62
static bool DetectHttpRawHeaderValidateCallback(
63
        const Signature *s, const char **sigerror, const DetectBufferType *dbt);
64
static int g_http_raw_header_buffer_id = 0;
65
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
66
        const DetectEngineTransforms *transforms, Flow *_f,
67
        const uint8_t flow_flags, void *txv, const int list_id);
68
static InspectionBuffer *GetData2(DetectEngineThreadCtx *det_ctx,
69
        const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flow_flags, void *txv,
70
        const int list_id);
71

72
static int PrefilterMpmHttpHeaderRawRequestRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
73
        MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id);
74
static int PrefilterMpmHttpHeaderRawResponseRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
75
        MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id);
76

77
/**
78
 * \brief Registers the keyword handlers for the "http_raw_header" keyword.
79
 */
80
void DetectHttpRawHeaderRegister(void)
81
{
37✔
82
    /* http_raw_header content modifier */
83
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].name = "http_raw_header";
37✔
84
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].desc =
37✔
85
            "content modifier to match the raw HTTP header buffer";
37✔
86
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].url =
37✔
87
            "/rules/http-keywords.html#http-header-and-http-raw-header";
37✔
88
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].Setup = DetectHttpRawHeaderSetup;
37✔
89
#ifdef UNITTESTS
3✔
90
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].RegisterTests = DetectHttpRawHeaderRegisterTests;
3✔
91
#endif
3✔
92
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].flags |=
37✔
93
            SIGMATCH_NOOPT | SIGMATCH_INFO_CONTENT_MODIFIER;
37✔
94
    sigmatch_table[DETECT_HTTP_RAW_HEADER_CM].alternative = DETECT_HTTP_RAW_HEADER;
37✔
95

96
    /* http.header.raw sticky buffer */
97
    sigmatch_table[DETECT_HTTP_RAW_HEADER].name = "http.header.raw";
37✔
98
    sigmatch_table[DETECT_HTTP_RAW_HEADER].desc = "sticky buffer to match the raw HTTP header buffer";
37✔
99
    sigmatch_table[DETECT_HTTP_RAW_HEADER].url = "/rules/http-keywords.html#http-header-and-http-raw-header";
37✔
100
    sigmatch_table[DETECT_HTTP_RAW_HEADER].Setup = DetectHttpRawHeaderSetupSticky;
37✔
101
    sigmatch_table[DETECT_HTTP_RAW_HEADER].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
37✔
102

103
    DetectAppLayerInspectEngineRegister("http_raw_header", ALPROTO_HTTP1, SIG_FLAG_TOSERVER,
37✔
104
            HTP_REQUEST_PROGRESS_HEADERS + 1, DetectEngineInspectBufferGeneric, GetData);
37✔
105
    DetectAppLayerInspectEngineRegister("http_raw_header", ALPROTO_HTTP1, SIG_FLAG_TOCLIENT,
37✔
106
            HTP_RESPONSE_PROGRESS_HEADERS + 1, DetectEngineInspectBufferGeneric, GetData);
37✔
107

108
    DetectAppLayerMpmRegister("http_raw_header", SIG_FLAG_TOSERVER, 2,
37✔
109
            PrefilterMpmHttpHeaderRawRequestRegister, NULL, ALPROTO_HTTP1,
37✔
110
            0); /* progress handled in register */
37✔
111
    DetectAppLayerMpmRegister("http_raw_header", SIG_FLAG_TOCLIENT, 2,
37✔
112
            PrefilterMpmHttpHeaderRawResponseRegister, NULL, ALPROTO_HTTP1,
37✔
113
            0); /* progress handled in register */
37✔
114

115
    DetectAppLayerInspectEngineRegister("http_raw_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER,
37✔
116
            HTTP2StateDataClient, DetectEngineInspectBufferGeneric, GetData2);
37✔
117
    DetectAppLayerInspectEngineRegister("http_raw_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
37✔
118
            HTTP2StateDataServer, DetectEngineInspectBufferGeneric, GetData2);
37✔
119

120
    DetectAppLayerMpmRegister("http_raw_header", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister,
37✔
121
            GetData2, ALPROTO_HTTP2, HTTP2StateDataClient);
37✔
122
    DetectAppLayerMpmRegister("http_raw_header", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister,
37✔
123
            GetData2, ALPROTO_HTTP2, HTTP2StateDataServer);
37✔
124

125
    DetectBufferTypeSetDescriptionByName("http_raw_header",
37✔
126
            "raw http headers");
37✔
127

128
    DetectBufferTypeRegisterValidateCallback("http_raw_header",
37✔
129
            DetectHttpRawHeaderValidateCallback);
37✔
130

131
    g_http_raw_header_buffer_id = DetectBufferTypeGetByName("http_raw_header");
37✔
132
}
37✔
133

134
/**
135
 * \brief The setup function for the http_raw_header keyword for a signature.
136
 *
137
 * \param de_ctx Pointer to the detection engine context.
138
 * \param s      Pointer to signature for the current Signature being parsed
139
 *               from the rules.
140
 * \param m      Pointer to the head of the SigMatchs for the current rule
141
 *               being parsed.
142
 * \param arg    Pointer to the string holding the keyword value.
143
 *
144
 * \retval  0 On success.
145
 * \retval -1 On failure.
146
 */
147
int DetectHttpRawHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
148
{
54✔
149
    return DetectEngineContentModifierBufferSetup(
54✔
150
            de_ctx, s, arg, DETECT_HTTP_RAW_HEADER_CM, g_http_raw_header_buffer_id, ALPROTO_HTTP1);
54✔
151
}
54✔
152

153
/**
154
 * \brief this function setup the http.header.raw keyword used in the rule
155
 *
156
 * \param de_ctx   Pointer to the Detection Engine Context
157
 * \param s        Pointer to the Signature to which the current keyword belongs
158
 * \param str      Should hold an empty string always
159
 *
160
 * \retval 0       On success
161
 */
162
static int DetectHttpRawHeaderSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str)
163
{
26✔
164
    if (SCDetectBufferSetActiveList(de_ctx, s, g_http_raw_header_buffer_id) < 0)
26✔
165
        return -1;
×
166
    if (SCDetectSignatureSetAppProto(s, ALPROTO_HTTP) < 0)
26✔
167
        return -1;
1✔
168
    return 0;
25✔
169
}
26✔
170

171
static bool DetectHttpRawHeaderValidateCallback(
172
        const Signature *s, const char **sigerror, const DetectBufferType *dbt)
173
{
66✔
174
    if ((s->flags & (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER)) == (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER)) {
66✔
175
        *sigerror = "http_raw_header signature "
×
176
                "without a flow direction. Use flow:to_server for "
×
177
                "inspecting request headers or flow:to_client for "
×
178
                "inspecting response headers.";
×
179

180
        SCLogError("%s", *sigerror);
×
181
        SCReturnInt(false);
×
182
    }
×
183
    return true;
66✔
184
}
66✔
185

186
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
187
        const DetectEngineTransforms *transforms, Flow *_f,
188
        const uint8_t flow_flags, void *txv, const int list_id)
189
{
4,888✔
190
    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
4,888✔
191
    if (buffer->inspect == NULL) {
4,888✔
192
        htp_tx_t *tx = (htp_tx_t *)txv;
4,621✔
193

194
        HtpTxUserData *tx_ud = htp_tx_get_user_data(tx);
4,621✔
195

196
        const bool ts = ((flow_flags & STREAM_TOSERVER) != 0);
4,621✔
197
        const uint8_t *data = ts ?
4,621✔
198
            tx_ud->request_headers_raw : tx_ud->response_headers_raw;
2,356✔
199
        if (data == NULL)
4,621✔
200
            return NULL;
91✔
201
        const uint32_t data_len = ts ?
4,530✔
202
            tx_ud->request_headers_raw_len : tx_ud->response_headers_raw_len;
2,343✔
203

204
        InspectionBufferSetupAndApplyTransforms(
4,530✔
205
                det_ctx, list_id, buffer, data, data_len, transforms);
4,530✔
206
    }
4,530✔
207

208
    return buffer;
4,797✔
209
}
4,888✔
210

211
static InspectionBuffer *GetData2(DetectEngineThreadCtx *det_ctx,
212
        const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flow_flags, void *txv,
213
        const int list_id)
214
{
357✔
215
    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
357✔
216
    if (buffer->inspect == NULL) {
357✔
217
        uint32_t b_len = 0;
356✔
218
        const uint8_t *b = NULL;
356✔
219

220
        if (SCHttp2TxGetHeadersRaw(txv, flow_flags, &b, &b_len) != 1)
356✔
221
            return NULL;
198✔
222
        if (b == NULL || b_len == 0)
158✔
223
            return NULL;
×
224

225
        InspectionBufferSetupAndApplyTransforms(det_ctx, list_id, buffer, b, b_len, transforms);
158✔
226
    }
158✔
227

228
    return buffer;
159✔
229
}
357✔
230

231
typedef struct PrefilterMpmHttpHeaderRawCtx {
232
    int list_id;
233
    const MpmCtx *mpm_ctx;
234
    const DetectEngineTransforms *transforms;
235
} PrefilterMpmHttpHeaderRawCtx;
236

237
/** \brief Generic Mpm prefilter callback
238
 *
239
 *  \param det_ctx detection engine thread ctx
240
 *  \param p packet to inspect
241
 *  \param f flow to inspect
242
 *  \param txv tx to inspect
243
 *  \param pectx inspection context
244
 */
245
static void PrefilterMpmHttpHeaderRaw(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
246
        Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
247
{
4,855✔
248
    SCEnter();
4,855✔
249

250
    const PrefilterMpmHttpHeaderRawCtx *ctx = pectx;
4,855✔
251
    const MpmCtx *mpm_ctx = ctx->mpm_ctx;
4,855✔
252
    SCLogDebug("running on list %d", ctx->list_id);
4,855✔
253

254
    const int list_id = ctx->list_id;
4,855✔
255

256
    InspectionBuffer *buffer = GetData(det_ctx, ctx->transforms, f,
4,855✔
257
            flags, txv, list_id);
4,855✔
258
    if (buffer == NULL)
4,855✔
259
        return;
91✔
260

261
    const uint32_t data_len = buffer->inspect_len;
4,764✔
262
    const uint8_t *data = buffer->inspect;
4,764✔
263

264
    SCLogDebug("mpm'ing buffer:");
4,764✔
265
    //PrintRawDataFp(stdout, data, data_len);
266

267
    if (data != NULL && data_len >= mpm_ctx->minlen) {
4,764✔
268
        (void)mpm_table[mpm_ctx->mpm_type].Search(
4,612✔
269
                mpm_ctx, &det_ctx->mtc, &det_ctx->pmq, data, data_len);
4,612✔
270
        PREFILTER_PROFILING_ADD_BYTES(det_ctx, data_len);
4,612✔
271
    }
4,612✔
272
}
4,764✔
273

274
static void PrefilterMpmHttpTrailerRaw(DetectEngineThreadCtx *det_ctx, const void *pectx, Packet *p,
275
        Flow *f, void *txv, const uint64_t idx, const AppLayerTxData *_txd, const uint8_t flags)
276
{
4,436✔
277
    SCEnter();
4,436✔
278

279
    htp_tx_t *tx = txv;
4,436✔
280
    const HtpTxUserData *htud = (const HtpTxUserData *)htp_tx_get_user_data(tx);
4,436✔
281
    /* if the request wasn't flagged as having a trailer, we skip */
282
    if (((flags & STREAM_TOSERVER) && !htud->request_has_trailers) ||
4,436✔
283
            ((flags & STREAM_TOCLIENT) && !htud->response_has_trailers)) {
4,436✔
284
        SCReturn;
4,112✔
285
    }
4,112✔
286
    PrefilterMpmHttpHeaderRaw(det_ctx, pectx, p, f, txv, idx, _txd, flags);
324✔
287
    SCReturn;
324✔
288
}
4,436✔
289

290
static void PrefilterMpmHttpHeaderRawFree(void *ptr)
291
{
232✔
292
    SCFree(ptr);
232✔
293
}
232✔
294

295
static int PrefilterMpmHttpHeaderRawRequestRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
296
        MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
297
{
64✔
298
    SCEnter();
64✔
299

300
    /* header */
301
    PrefilterMpmHttpHeaderRawCtx *pectx = SCCalloc(1, sizeof(*pectx));
64✔
302
    if (pectx == NULL)
64✔
303
        return -1;
×
304
    pectx->list_id = list_id;
64✔
305
    pectx->mpm_ctx = mpm_ctx;
64✔
306
    pectx->transforms = &mpm_reg->transforms;
64✔
307

308
    int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeaderRaw, mpm_reg->app_v2.alproto,
64✔
309
            HTP_REQUEST_PROGRESS_HEADERS + 1, pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname);
64✔
310
    if (r != 0) {
64✔
311
        SCFree(pectx);
×
312
        return r;
×
313
    }
×
314

315
    /* trailer */
316
    pectx = SCCalloc(1, sizeof(*pectx));
64✔
317
    if (pectx == NULL)
64✔
318
        return -1;
×
319
    pectx->list_id = list_id;
64✔
320
    pectx->mpm_ctx = mpm_ctx;
64✔
321
    pectx->transforms = &mpm_reg->transforms;
64✔
322

323
    r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailerRaw, mpm_reg->app_v2.alproto,
64✔
324
            HTP_REQUEST_PROGRESS_TRAILER + 1, pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname);
64✔
325
    if (r != 0) {
64✔
326
        SCFree(pectx);
×
327
    }
×
328
    return r;
64✔
329
}
64✔
330

331
static int PrefilterMpmHttpHeaderRawResponseRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
332
        MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
333
{
23✔
334
    SCEnter();
23✔
335

336
    /* header */
337
    PrefilterMpmHttpHeaderRawCtx *pectx = SCCalloc(1, sizeof(*pectx));
23✔
338
    if (pectx == NULL)
23✔
339
        return -1;
×
340
    pectx->list_id = list_id;
23✔
341
    pectx->mpm_ctx = mpm_ctx;
23✔
342
    pectx->transforms = &mpm_reg->transforms;
23✔
343

344
    int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeaderRaw, mpm_reg->app_v2.alproto,
23✔
345
            HTP_RESPONSE_PROGRESS_HEADERS, pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname);
23✔
346
    if (r != 0) {
23✔
347
        SCFree(pectx);
×
348
        return r;
×
349
    }
×
350

351
    /* trailer */
352
    pectx = SCCalloc(1, sizeof(*pectx));
23✔
353
    if (pectx == NULL)
23✔
354
        return -1;
×
355
    pectx->list_id = list_id;
23✔
356
    pectx->mpm_ctx = mpm_ctx;
23✔
357
    pectx->transforms = &mpm_reg->transforms;
23✔
358

359
    r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailerRaw, mpm_reg->app_v2.alproto,
23✔
360
            HTP_RESPONSE_PROGRESS_TRAILER, pectx, PrefilterMpmHttpHeaderRawFree, mpm_reg->pname);
23✔
361
    if (r != 0) {
23✔
362
        SCFree(pectx);
×
363
    }
×
364
    return r;
23✔
365
}
23✔
366

367
/************************************Unittests*********************************/
368

369
#ifdef UNITTESTS
370
#include "tests/detect-http-raw-header.c"
371
#endif
372

373
/**
374
 * @}
375
 */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc