Coverage Report

Created: 2026-01-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-http-stat-code.c
Line
Count
Source
1
/* Copyright (C) 2007-2018 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 Gurvinder Singh <gurvindersinghdahiya@gmail.com>
29
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
30
 *
31
 * Implements the http_stat_code keyword
32
 */
33
34
#include "suricata-common.h"
35
#include "threads.h"
36
#include "decode.h"
37
#include "detect.h"
38
39
#include "detect-parse.h"
40
#include "detect-engine.h"
41
#include "detect-content.h"
42
#include "detect-pcre.h"
43
#include "detect-engine-mpm.h"
44
#include "detect-engine-prefilter.h"
45
46
#include "flow.h"
47
#include "flow-var.h"
48
#include "flow-util.h"
49
50
#include "util-debug.h"
51
#include "util-error.h"
52
#include "util-unittest.h"
53
#include "util-unittest-helper.h"
54
#include "util-spm.h"
55
#include "util-print.h"
56
57
#include "app-layer.h"
58
#include "app-layer-parser.h"
59
60
#include "app-layer-htp.h"
61
#include "detect-http-stat-code.h"
62
#include "stream-tcp-private.h"
63
#include "stream-tcp.h"
64
65
static int DetectHttpStatCodeSetup(DetectEngineCtx *, Signature *, const char *);
66
static int DetectHttpStatCodeSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str);
67
#ifdef UNITTESTS
68
static void DetectHttpStatCodeRegisterTests(void);
69
#endif
70
static int g_http_stat_code_buffer_id = 0;
71
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
72
        const DetectEngineTransforms *transforms, Flow *_f,
73
        const uint8_t _flow_flags, void *txv, const int list_id);
74
static InspectionBuffer *GetData2(DetectEngineThreadCtx *det_ctx,
75
        const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
76
        const int list_id);
77
78
/**
79
 * \brief Registration function for keyword: http_stat_code
80
 */
81
void DetectHttpStatCodeRegister (void)
82
73
{
83
    /* http_stat_code content modifier */
84
73
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].name = "http_stat_code";
85
73
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].desc = "content modifier to match only on HTTP stat-code-buffer";
86
73
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].url = "/rules/http-keywords.html#http-stat-code";
87
73
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].Setup = DetectHttpStatCodeSetup;
88
#ifdef UNITTESTS
89
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].RegisterTests = DetectHttpStatCodeRegisterTests;
90
#endif
91
73
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_CONTENT_MODIFIER;
92
73
    sigmatch_table[DETECT_AL_HTTP_STAT_CODE].alternative = DETECT_HTTP_STAT_CODE;
93
94
    /* http.stat_code content modifier */
95
73
    sigmatch_table[DETECT_HTTP_STAT_CODE].name = "http.stat_code";
96
73
    sigmatch_table[DETECT_HTTP_STAT_CODE].desc = "sticky buffer to match only on HTTP stat-code-buffer";
97
73
    sigmatch_table[DETECT_HTTP_STAT_CODE].url = "/rules/http-keywords.html#http-stat-code";
98
73
    sigmatch_table[DETECT_HTTP_STAT_CODE].Setup = DetectHttpStatCodeSetupSticky;
99
73
    sigmatch_table[DETECT_HTTP_STAT_CODE].flags |= SIGMATCH_NOOPT|SIGMATCH_INFO_STICKY_BUFFER;
100
101
73
    DetectAppLayerInspectEngineRegister2("http_stat_code", ALPROTO_HTTP1, SIG_FLAG_TOCLIENT,
102
73
            HTP_RESPONSE_LINE, DetectEngineInspectBufferGeneric, GetData);
103
104
73
    DetectAppLayerMpmRegister2("http_stat_code", SIG_FLAG_TOCLIENT, 4, PrefilterGenericMpmRegister,
105
73
            GetData, ALPROTO_HTTP1, HTP_RESPONSE_LINE);
106
107
73
    DetectAppLayerInspectEngineRegister2("http_stat_code", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT,
108
73
            HTTP2StateDataServer, DetectEngineInspectBufferGeneric, GetData2);
109
110
73
    DetectAppLayerMpmRegister2("http_stat_code", SIG_FLAG_TOCLIENT, 4, PrefilterGenericMpmRegister,
111
73
            GetData2, ALPROTO_HTTP2, HTTP2StateDataServer);
112
113
73
    DetectBufferTypeSetDescriptionByName("http_stat_code",
114
73
            "http response status code");
115
116
73
    g_http_stat_code_buffer_id = DetectBufferTypeGetByName("http_stat_code");
117
73
}
118
119
/**
120
 * \brief this function setups the http_stat_code modifier keyword used in the rule
121
 *
122
 * \param de_ctx   Pointer to the Detection Engine Context
123
 * \param s        Pointer to the Signature to which the current keyword belongs
124
 * \param str      Should hold an empty string always
125
 *
126
 * \retval  0 On success
127
 * \retval -1 On failure
128
 */
129
130
static int DetectHttpStatCodeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg)
131
2.40k
{
132
2.40k
    return DetectEngineContentModifierBufferSetup(
133
2.40k
            de_ctx, s, arg, DETECT_AL_HTTP_STAT_CODE, g_http_stat_code_buffer_id, ALPROTO_HTTP1);
134
2.40k
}
135
136
/**
137
 * \brief this function setup the http.stat_code keyword used in the rule
138
 *
139
 * \param de_ctx   Pointer to the Detection Engine Context
140
 * \param s        Pointer to the Signature to which the current keyword belongs
141
 * \param str      Should hold an empty string always
142
 *
143
 * \retval 0       On success
144
 */
145
static int DetectHttpStatCodeSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str)
146
4.86k
{
147
4.86k
    if (DetectBufferSetActiveList(de_ctx, s, g_http_stat_code_buffer_id) < 0)
148
54
        return -1;
149
4.81k
    if (DetectSignatureSetAppProto(s, ALPROTO_HTTP) < 0)
150
40
        return -1;
151
4.77k
    return 0;
152
4.81k
}
153
154
static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
155
        const DetectEngineTransforms *transforms, Flow *_f,
156
        const uint8_t _flow_flags, void *txv, const int list_id)
157
3.46k
{
158
3.46k
    SCEnter();
159
160
3.46k
    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
161
3.46k
    if (buffer->inspect == NULL) {
162
2.87k
        htp_tx_t *tx = (htp_tx_t *)txv;
163
164
2.87k
        if (tx->response_status == NULL)
165
1.07k
            return NULL;
166
167
1.80k
        const uint32_t data_len = bstr_len(tx->response_status);
168
1.80k
        const uint8_t *data = bstr_ptr(tx->response_status);
169
170
1.80k
        InspectionBufferSetup(det_ctx, list_id, buffer, data, data_len);
171
1.80k
        InspectionBufferApplyTransforms(buffer, transforms);
172
1.80k
    }
173
174
2.39k
    return buffer;
175
3.46k
}
176
177
static InspectionBuffer *GetData2(DetectEngineThreadCtx *det_ctx,
178
        const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
179
        const int list_id)
180
270
{
181
270
    SCEnter();
182
183
270
    InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
184
270
    if (buffer->inspect == NULL) {
185
269
        uint32_t b_len = 0;
186
269
        const uint8_t *b = NULL;
187
188
269
        if (rs_http2_tx_get_status(txv, &b, &b_len) != 1)
189
136
            return NULL;
190
133
        if (b == NULL || b_len == 0)
191
0
            return NULL;
192
193
133
        InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len);
194
133
        InspectionBufferApplyTransforms(buffer, transforms);
195
133
    }
196
197
134
    return buffer;
198
270
}
199
200
#ifdef UNITTESTS
201
#include "tests/detect-http-stat-code.c"
202
#endif /* UNITTESTS */
203
204
/**
205
 * @}
206
 */