]>
Commit | Line | Data |
---|---|---|
9a5c666b | 1 | /* Copyright (C) 2007-2021 Open Information Security Foundation |
ce019275 WM |
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 | ||
60a99915 EL |
18 | /** |
19 | * \ingroup httplayer | |
20 | * | |
21 | * @{ | |
22 | */ | |
23 | ||
24 | ||
ab02ab9e | 25 | /** |
ce019275 | 26 | * \file |
ab02ab9e PR |
27 | * |
28 | * \author Pablo Rincon <pablo.rincon.crespo@gmail.com> | |
ce019275 | 29 | * |
fc46f216 | 30 | * Implements support for http_header keyword. |
ab02ab9e PR |
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-mpm.h" | |
0e4235cc | 41 | #include "detect-engine-state.h" |
2bb0cae0 VJ |
42 | #include "detect-engine-prefilter.h" |
43 | #include "detect-engine-content-inspection.h" | |
ab02ab9e | 44 | #include "detect-content.h" |
c61c68fd | 45 | #include "detect-pcre.h" |
ab02ab9e | 46 | |
ab02ab9e | 47 | #include "util-debug.h" |
70b32f73 | 48 | #include "util-print.h" |
2bb0cae0 | 49 | #include "util-memcmp.h" |
ab02ab9e PR |
50 | |
51 | #include "app-layer.h" | |
429c6388 | 52 | #include "app-layer-parser.h" |
ab02ab9e | 53 | |
ab02ab9e PR |
54 | #include "app-layer-htp.h" |
55 | #include "detect-http-header.h" | |
f2fc5a25 | 56 | #include "detect-http-header-common.h" |
ab02ab9e | 57 | |
ab1200fb | 58 | static int DetectHttpHeaderSetup(DetectEngineCtx *, Signature *, const char *); |
b9bcd4e1 | 59 | #ifdef UNITTESTS |
e7d5e845 | 60 | static void DetectHttpHeaderRegisterTests(void); |
b9bcd4e1 | 61 | #endif |
e7d5e845 | 62 | static int g_http_header_buffer_id = 0; |
f2fc5a25 | 63 | static int g_keyword_thread_id = 0; |
ab02ab9e | 64 | |
f2fc5a25 | 65 | #define BUFFER_SIZE_STEP 1024 |
9a5c666b | 66 | static HttpHeaderThreadDataConfig g_td_config = { BUFFER_SIZE_STEP }; |
2bb0cae0 | 67 | |
9a5c666b VJ |
68 | static uint8_t *GetBufferForTX( |
69 | htp_tx_t *tx, DetectEngineThreadCtx *det_ctx, Flow *f, uint8_t flags, uint32_t *buffer_len) | |
2bb0cae0 | 70 | { |
2bb0cae0 VJ |
71 | *buffer_len = 0; |
72 | ||
f2fc5a25 | 73 | HttpHeaderThreadData *hdr_td = NULL; |
9a5c666b VJ |
74 | HttpHeaderBuffer *buf = |
75 | HttpHeaderGetBufferSpace(det_ctx, f, flags, g_keyword_thread_id, &hdr_td); | |
f2fc5a25 VJ |
76 | if (unlikely(buf == NULL)) { |
77 | return NULL; | |
2bb0cae0 VJ |
78 | } |
79 | ||
80 | htp_table_t *headers; | |
81 | if (flags & STREAM_TOSERVER) { | |
707f0272 PA |
82 | if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, tx, flags) <= |
83 | HTP_REQUEST_HEADERS) | |
f2fc5a25 | 84 | return NULL; |
2bb0cae0 VJ |
85 | headers = tx->request_headers; |
86 | } else { | |
707f0272 PA |
87 | if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, tx, flags) <= |
88 | HTP_RESPONSE_HEADERS) | |
f2fc5a25 | 89 | return NULL; |
2bb0cae0 VJ |
90 | headers = tx->response_headers; |
91 | } | |
92 | if (headers == NULL) | |
f2fc5a25 | 93 | return NULL; |
2bb0cae0 | 94 | |
2bb0cae0 | 95 | size_t i = 0; |
2bb0cae0 VJ |
96 | size_t no_of_headers = htp_table_size(headers); |
97 | for (; i < no_of_headers; i++) { | |
f2fc5a25 | 98 | htp_header_t *h = htp_table_get_index(headers, i, NULL); |
2bb0cae0 VJ |
99 | size_t size1 = bstr_size(h->name); |
100 | size_t size2 = bstr_size(h->value); | |
101 | ||
102 | if (flags & STREAM_TOSERVER) { | |
103 | if (size1 == 6 && | |
104 | SCMemcmpLowercase("cookie", bstr_ptr(h->name), 6) == 0) { | |
105 | continue; | |
106 | } | |
107 | } else { | |
108 | if (size1 == 10 && | |
109 | SCMemcmpLowercase("set-cookie", bstr_ptr(h->name), 10) == 0) { | |
110 | continue; | |
111 | } | |
112 | } | |
113 | ||
f2fc5a25 VJ |
114 | size_t size = size1 + size2 + 4; |
115 | #if 0 | |
116 | if (i + 1 == no_of_headers) | |
117 | size += 2; | |
118 | #endif | |
119 | if (size + buf->len > buf->size) { | |
120 | if (HttpHeaderExpandBuffer(hdr_td, buf, size) != 0) { | |
121 | return NULL; | |
2bb0cae0 | 122 | } |
2bb0cae0 | 123 | } |
2bb0cae0 | 124 | |
f2fc5a25 VJ |
125 | memcpy(buf->buffer + buf->len, bstr_ptr(h->name), bstr_size(h->name)); |
126 | buf->len += bstr_size(h->name); | |
127 | buf->buffer[buf->len++] = ':'; | |
128 | buf->buffer[buf->len++] = ' '; | |
129 | memcpy(buf->buffer + buf->len, bstr_ptr(h->value), bstr_size(h->value)); | |
130 | buf->len += bstr_size(h->value); | |
131 | buf->buffer[buf->len++] = '\r'; | |
132 | buf->buffer[buf->len++] = '\n'; | |
133 | #if 0 // looks like this breaks existing rules | |
134 | if (i + 1 == no_of_headers) { | |
135 | buf->buffer[buf->len++] = '\r'; | |
136 | buf->buffer[buf->len++] = '\n'; | |
137 | } | |
138 | #endif | |
139 | } | |
2bb0cae0 | 140 | |
f2fc5a25 VJ |
141 | *buffer_len = buf->len; |
142 | return buf->buffer; | |
2bb0cae0 VJ |
143 | } |
144 | ||
0b0649d9 PA |
145 | static InspectionBuffer *GetBuffer2ForTX(DetectEngineThreadCtx *det_ctx, |
146 | const DetectEngineTransforms *transforms, Flow *_f, const uint8_t flow_flags, void *txv, | |
147 | const int list_id) | |
148 | { | |
149 | InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); | |
150 | if (buffer->inspect == NULL) { | |
151 | uint32_t b_len = 0; | |
152 | const uint8_t *b = NULL; | |
153 | ||
154 | if (rs_http2_tx_get_headers(txv, flow_flags, &b, &b_len) != 1) | |
155 | return NULL; | |
156 | if (b == NULL || b_len == 0) | |
157 | return NULL; | |
158 | ||
159 | InspectionBufferSetup(det_ctx, list_id, buffer, b, b_len); | |
160 | InspectionBufferApplyTransforms(buffer, transforms); | |
161 | } | |
162 | ||
163 | return buffer; | |
164 | } | |
165 | ||
5e951a8b VJ |
166 | /** \internal |
167 | * \brief custom inspect function to utilize the cached headers | |
ab02ab9e | 168 | */ |
5e951a8b VJ |
169 | static int DetectEngineInspectBufferHttpHeader( |
170 | DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, | |
171 | const DetectEngineAppInspectionEngine *engine, | |
172 | const Signature *s, | |
173 | Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id) | |
ab02ab9e | 174 | { |
2bb0cae0 | 175 | SCEnter(); |
ab02ab9e | 176 | |
5e951a8b VJ |
177 | const int list_id = engine->sm_list; |
178 | InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); | |
179 | if (buffer->inspect == NULL) { | |
180 | SCLogDebug("setting up inspect buffer %d", list_id); | |
7b98c007 | 181 | |
5e951a8b VJ |
182 | /* if prefilter didn't already run, we need to consider transformations */ |
183 | const DetectEngineTransforms *transforms = NULL; | |
184 | if (!engine->mpm) { | |
185 | transforms = engine->v2.transforms; | |
186 | } | |
2bb0cae0 | 187 | |
5e951a8b | 188 | uint32_t rawdata_len = 0; |
9a5c666b | 189 | uint8_t *rawdata = GetBufferForTX(txv, det_ctx, f, flags, &rawdata_len); |
5e951a8b VJ |
190 | if (rawdata_len == 0) { |
191 | SCLogDebug("no data"); | |
192 | goto end; | |
193 | } | |
194 | /* setup buffer and apply transforms */ | |
13cebb18 | 195 | InspectionBufferSetup(det_ctx, list_id, buffer, rawdata, rawdata_len); |
5e951a8b | 196 | InspectionBufferApplyTransforms(buffer, transforms); |
2bb0cae0 | 197 | } |
eb19eb3f | 198 | |
5e951a8b VJ |
199 | const uint32_t data_len = buffer->inspect_len; |
200 | const uint8_t *data = buffer->inspect; | |
201 | const uint64_t offset = buffer->inspect_offset; | |
e7d5e845 | 202 | |
5e951a8b VJ |
203 | det_ctx->discontinue_matching = 0; |
204 | det_ctx->buffer_offset = 0; | |
205 | det_ctx->inspection_recursion_counter = 0; | |
2bb0cae0 | 206 | |
5e951a8b VJ |
207 | /* Inspect all the uricontents fetched on each |
208 | * transaction at the app layer */ | |
32fb7d77 VJ |
209 | int r = DetectEngineContentInspection(de_ctx, det_ctx, s, engine->smd, |
210 | NULL, f, (uint8_t *)data, data_len, offset, | |
211 | DETECT_CI_FLAGS_SINGLE, DETECT_ENGINE_CONTENT_INSPECTION_MODE_STATE); | |
5e951a8b VJ |
212 | SCLogDebug("r = %d", r); |
213 | if (r == 1) { | |
214 | return DETECT_ENGINE_INSPECT_SIG_MATCH; | |
215 | } | |
216 | end: | |
217 | if (flags & STREAM_TOSERVER) { | |
707f0272 PA |
218 | if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, txv, flags) > |
219 | HTP_REQUEST_HEADERS) | |
5e951a8b VJ |
220 | return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; |
221 | } else { | |
707f0272 PA |
222 | if (AppLayerParserGetStateProgress(IPPROTO_TCP, ALPROTO_HTTP1, txv, flags) > |
223 | HTP_RESPONSE_HEADERS) | |
5e951a8b | 224 | return DETECT_ENGINE_INSPECT_SIG_CANT_MATCH; |
2bb0cae0 | 225 | } |
5e951a8b | 226 | return DETECT_ENGINE_INSPECT_SIG_NO_MATCH; |
2bb0cae0 | 227 | } |
15dcac92 | 228 | |
5e951a8b VJ |
229 | typedef struct PrefilterMpmHttpHeaderCtx { |
230 | int list_id; | |
231 | const MpmCtx *mpm_ctx; | |
232 | const DetectEngineTransforms *transforms; | |
233 | } PrefilterMpmHttpHeaderCtx; | |
ab02ab9e | 234 | |
5e951a8b | 235 | /** \brief Generic Mpm prefilter callback |
cda664a8 | 236 | * |
2bb0cae0 VJ |
237 | * \param det_ctx detection engine thread ctx |
238 | * \param p packet to inspect | |
239 | * \param f flow to inspect | |
240 | * \param txv tx to inspect | |
241 | * \param pectx inspection context | |
cda664a8 | 242 | */ |
5e951a8b | 243 | static void PrefilterMpmHttpHeader(DetectEngineThreadCtx *det_ctx, |
2bb0cae0 VJ |
244 | const void *pectx, |
245 | Packet *p, Flow *f, void *txv, | |
246 | const uint64_t idx, const uint8_t flags) | |
cda664a8 | 247 | { |
2bb0cae0 VJ |
248 | SCEnter(); |
249 | ||
5e951a8b VJ |
250 | const PrefilterMpmHttpHeaderCtx *ctx = pectx; |
251 | const MpmCtx *mpm_ctx = ctx->mpm_ctx; | |
252 | SCLogDebug("running on list %d", ctx->list_id); | |
253 | ||
254 | const int list_id = ctx->list_id; | |
255 | InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id); | |
256 | if (buffer->inspect == NULL) { | |
257 | uint32_t rawdata_len = 0; | |
9a5c666b | 258 | uint8_t *rawdata = GetBufferForTX(txv, det_ctx, f, flags, &rawdata_len); |
5e951a8b VJ |
259 | if (rawdata_len == 0) |
260 | return; | |
261 | ||
262 | /* setup buffer and apply transforms */ | |
13cebb18 | 263 | InspectionBufferSetup(det_ctx, list_id, buffer, rawdata, rawdata_len); |
5e951a8b VJ |
264 | InspectionBufferApplyTransforms(buffer, ctx->transforms); |
265 | } | |
2bb0cae0 | 266 | |
5e951a8b VJ |
267 | const uint32_t data_len = buffer->inspect_len; |
268 | const uint8_t *data = buffer->inspect; | |
2bb0cae0 | 269 | |
5e951a8b VJ |
270 | SCLogDebug("mpm'ing buffer:"); |
271 | //PrintRawDataFp(stdout, data, data_len); | |
2bb0cae0 | 272 | |
5e951a8b | 273 | if (data != NULL && data_len >= mpm_ctx->minlen) { |
2bb0cae0 | 274 | (void)mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx, |
5e951a8b | 275 | &det_ctx->mtcu, &det_ctx->pmq, data, data_len); |
2bb0cae0 VJ |
276 | } |
277 | } | |
15dcac92 | 278 | |
5e951a8b | 279 | static void PrefilterMpmHttpTrailer(DetectEngineThreadCtx *det_ctx, |
2bb0cae0 VJ |
280 | const void *pectx, |
281 | Packet *p, Flow *f, void *txv, | |
282 | const uint64_t idx, const uint8_t flags) | |
283 | { | |
284 | SCEnter(); | |
285 | ||
5e951a8b | 286 | htp_tx_t *tx = txv; |
2bb0cae0 VJ |
287 | const HtpTxUserData *htud = (const HtpTxUserData *)htp_tx_get_user_data(tx); |
288 | /* if the request wasn't flagged as having a trailer, we skip */ | |
5e951a8b VJ |
289 | if (htud && ( |
290 | ((flags & STREAM_TOSERVER) && !htud->request_has_trailers) || | |
291 | ((flags & STREAM_TOCLIENT) && !htud->response_has_trailers))) { | |
292 | SCReturn; | |
2bb0cae0 | 293 | } |
5e951a8b VJ |
294 | PrefilterMpmHttpHeader(det_ctx, pectx, p, f, txv, idx, flags); |
295 | SCReturn; | |
296 | } | |
297 | ||
298 | static void PrefilterMpmHttpHeaderFree(void *ptr) | |
299 | { | |
300 | SCFree(ptr); | |
2bb0cae0 | 301 | } |
15dcac92 | 302 | |
5e951a8b VJ |
303 | static int PrefilterMpmHttpHeaderRequestRegister(DetectEngineCtx *de_ctx, |
304 | SigGroupHead *sgh, MpmCtx *mpm_ctx, | |
4dff903b | 305 | const DetectBufferMpmRegistery *mpm_reg, int list_id) |
2bb0cae0 VJ |
306 | { |
307 | SCEnter(); | |
308 | ||
5e951a8b VJ |
309 | /* header */ |
310 | PrefilterMpmHttpHeaderCtx *pectx = SCCalloc(1, sizeof(*pectx)); | |
311 | if (pectx == NULL) | |
312 | return -1; | |
313 | pectx->list_id = list_id; | |
314 | pectx->mpm_ctx = mpm_ctx; | |
4dff903b | 315 | pectx->transforms = &mpm_reg->transforms; |
5e951a8b VJ |
316 | |
317 | int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeader, | |
4dff903b | 318 | mpm_reg->app_v2.alproto, HTP_REQUEST_HEADERS, |
5e951a8b VJ |
319 | pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname); |
320 | if (r != 0) { | |
321 | SCFree(pectx); | |
2bb0cae0 | 322 | return r; |
5e951a8b VJ |
323 | } |
324 | ||
325 | /* trailer */ | |
326 | pectx = SCCalloc(1, sizeof(*pectx)); | |
327 | if (pectx == NULL) | |
328 | return -1; | |
329 | pectx->list_id = list_id; | |
330 | pectx->mpm_ctx = mpm_ctx; | |
4dff903b | 331 | pectx->transforms = &mpm_reg->transforms; |
5e951a8b VJ |
332 | |
333 | r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailer, | |
4dff903b | 334 | mpm_reg->app_v2.alproto, HTP_REQUEST_TRAILER, |
5e951a8b VJ |
335 | pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname); |
336 | if (r != 0) { | |
337 | SCFree(pectx); | |
338 | } | |
339 | return r; | |
2bb0cae0 VJ |
340 | } |
341 | ||
5e951a8b VJ |
342 | static int PrefilterMpmHttpHeaderResponseRegister(DetectEngineCtx *de_ctx, |
343 | SigGroupHead *sgh, MpmCtx *mpm_ctx, | |
4dff903b | 344 | const DetectBufferMpmRegistery *mpm_reg, int list_id) |
2bb0cae0 | 345 | { |
5e951a8b | 346 | SCEnter(); |
2bb0cae0 | 347 | |
5e951a8b VJ |
348 | /* header */ |
349 | PrefilterMpmHttpHeaderCtx *pectx = SCCalloc(1, sizeof(*pectx)); | |
350 | if (pectx == NULL) | |
351 | return -1; | |
352 | pectx->list_id = list_id; | |
353 | pectx->mpm_ctx = mpm_ctx; | |
4dff903b | 354 | pectx->transforms = &mpm_reg->transforms; |
5e951a8b VJ |
355 | |
356 | int r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpHeader, | |
4dff903b | 357 | mpm_reg->app_v2.alproto, HTP_RESPONSE_HEADERS, |
5e951a8b VJ |
358 | pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname); |
359 | if (r != 0) { | |
360 | SCFree(pectx); | |
361 | return r; | |
362 | } | |
2bb0cae0 | 363 | |
5e951a8b VJ |
364 | /* trailer */ |
365 | pectx = SCCalloc(1, sizeof(*pectx)); | |
366 | if (pectx == NULL) | |
367 | return -1; | |
368 | pectx->list_id = list_id; | |
369 | pectx->mpm_ctx = mpm_ctx; | |
4dff903b | 370 | pectx->transforms = &mpm_reg->transforms; |
5e951a8b VJ |
371 | |
372 | r = PrefilterAppendTxEngine(de_ctx, sgh, PrefilterMpmHttpTrailer, | |
4dff903b | 373 | mpm_reg->app_v2.alproto, HTP_RESPONSE_TRAILER, |
5e951a8b VJ |
374 | pectx, PrefilterMpmHttpHeaderFree, mpm_reg->pname); |
375 | if (r != 0) { | |
376 | SCFree(pectx); | |
2bb0cae0 | 377 | } |
5e951a8b | 378 | return r; |
2bb0cae0 VJ |
379 | } |
380 | ||
ab02ab9e PR |
381 | /** |
382 | * \brief The setup function for the http_header keyword for a signature. | |
383 | * | |
384 | * \param de_ctx Pointer to the detection engine context. | |
385 | * \param s Pointer to signature for the current Signature being parsed | |
386 | * from the rules. | |
387 | * \param m Pointer to the head of the SigMatchs for the current rule | |
388 | * being parsed. | |
389 | * \param arg Pointer to the string holding the keyword value. | |
390 | * | |
6648d1fa AS |
391 | * \retval 0 On success. |
392 | * \retval -1 On failure. | |
ab02ab9e | 393 | */ |
ab1200fb | 394 | static int DetectHttpHeaderSetup(DetectEngineCtx *de_ctx, Signature *s, const char *arg) |
ab02ab9e | 395 | { |
707f0272 PA |
396 | return DetectEngineContentModifierBufferSetup( |
397 | de_ctx, s, arg, DETECT_AL_HTTP_HEADER, g_http_header_buffer_id, ALPROTO_HTTP1); | |
ab02ab9e PR |
398 | } |
399 | ||
85697671 VJ |
400 | /** |
401 | * \brief this function setup the http.header keyword used in the rule | |
402 | * | |
403 | * \param de_ctx Pointer to the Detection Engine Context | |
404 | * \param s Pointer to the Signature to which the current keyword belongs | |
405 | * \param str Should hold an empty string always | |
406 | * | |
407 | * \retval 0 On success | |
408 | */ | |
409 | static int DetectHttpHeaderSetupSticky(DetectEngineCtx *de_ctx, Signature *s, const char *str) | |
410 | { | |
411 | if (DetectBufferSetActiveList(s, g_http_header_buffer_id) < 0) | |
412 | return -1; | |
0b0649d9 | 413 | if (DetectSignatureSetAppProto(s, ALPROTO_HTTP) < 0) |
85697671 VJ |
414 | return -1; |
415 | return 0; | |
416 | } | |
417 | ||
2bb0cae0 VJ |
418 | /** |
419 | * \brief Registers the keyword handlers for the "http_header" keyword. | |
420 | */ | |
421 | void DetectHttpHeaderRegister(void) | |
422 | { | |
85697671 | 423 | /* http_header content modifier */ |
2bb0cae0 | 424 | sigmatch_table[DETECT_AL_HTTP_HEADER].name = "http_header"; |
d801c3e5 | 425 | sigmatch_table[DETECT_AL_HTTP_HEADER].desc = "content modifier to match only on the HTTP header-buffer"; |
26bcc975 | 426 | sigmatch_table[DETECT_AL_HTTP_HEADER].url = "/rules/http-keywords.html#http-header-and-http-raw-header"; |
2bb0cae0 | 427 | sigmatch_table[DETECT_AL_HTTP_HEADER].Setup = DetectHttpHeaderSetup; |
b9bcd4e1 | 428 | #ifdef UNITTESTS |
2bb0cae0 | 429 | sigmatch_table[DETECT_AL_HTTP_HEADER].RegisterTests = DetectHttpHeaderRegisterTests; |
b9bcd4e1 | 430 | #endif |
2bb0cae0 | 431 | sigmatch_table[DETECT_AL_HTTP_HEADER].flags |= SIGMATCH_NOOPT ; |
85697671 VJ |
432 | sigmatch_table[DETECT_AL_HTTP_HEADER].flags |= SIGMATCH_INFO_CONTENT_MODIFIER; |
433 | sigmatch_table[DETECT_AL_HTTP_HEADER].alternative = DETECT_HTTP_HEADER; | |
434 | ||
435 | /* http.header sticky buffer */ | |
436 | sigmatch_table[DETECT_HTTP_HEADER].name = "http.header"; | |
d801c3e5 | 437 | sigmatch_table[DETECT_HTTP_HEADER].desc = "sticky buffer to match on the normalized HTTP header-buffer"; |
26bcc975 | 438 | sigmatch_table[DETECT_HTTP_HEADER].url = "/rules/http-keywords.html#http-header-and-http-raw-header"; |
85697671 VJ |
439 | sigmatch_table[DETECT_HTTP_HEADER].Setup = DetectHttpHeaderSetupSticky; |
440 | sigmatch_table[DETECT_HTTP_HEADER].flags |= SIGMATCH_NOOPT; | |
441 | sigmatch_table[DETECT_HTTP_HEADER].flags |= SIGMATCH_INFO_STICKY_BUFFER; | |
2bb0cae0 | 442 | |
707f0272 PA |
443 | DetectAppLayerInspectEngineRegister2("http_header", ALPROTO_HTTP1, SIG_FLAG_TOSERVER, |
444 | HTP_REQUEST_HEADERS, DetectEngineInspectBufferHttpHeader, NULL); | |
5e951a8b | 445 | DetectAppLayerMpmRegister2("http_header", SIG_FLAG_TOSERVER, 2, |
707f0272 | 446 | PrefilterMpmHttpHeaderRequestRegister, NULL, ALPROTO_HTTP1, |
5e951a8b | 447 | 0); /* not used, registered twice: HEADERS/TRAILER */ |
2bb0cae0 | 448 | |
707f0272 PA |
449 | DetectAppLayerInspectEngineRegister2("http_header", ALPROTO_HTTP1, SIG_FLAG_TOCLIENT, |
450 | HTP_RESPONSE_HEADERS, DetectEngineInspectBufferHttpHeader, NULL); | |
5e951a8b | 451 | DetectAppLayerMpmRegister2("http_header", SIG_FLAG_TOCLIENT, 2, |
707f0272 | 452 | PrefilterMpmHttpHeaderResponseRegister, NULL, ALPROTO_HTTP1, |
5e951a8b | 453 | 0); /* not used, registered twice: HEADERS/TRAILER */ |
2bb0cae0 | 454 | |
0b0649d9 PA |
455 | DetectAppLayerInspectEngineRegister2("http_header", ALPROTO_HTTP2, SIG_FLAG_TOSERVER, |
456 | HTTP2StateDataClient, DetectEngineInspectBufferGeneric, GetBuffer2ForTX); | |
457 | DetectAppLayerMpmRegister2("http_header", SIG_FLAG_TOSERVER, 2, PrefilterGenericMpmRegister, | |
458 | GetBuffer2ForTX, ALPROTO_HTTP2, HTTP2StateDataClient); | |
459 | ||
460 | DetectAppLayerInspectEngineRegister2("http_header", ALPROTO_HTTP2, SIG_FLAG_TOCLIENT, | |
461 | HTTP2StateDataServer, DetectEngineInspectBufferGeneric, GetBuffer2ForTX); | |
462 | DetectAppLayerMpmRegister2("http_header", SIG_FLAG_TOCLIENT, 2, PrefilterGenericMpmRegister, | |
463 | GetBuffer2ForTX, ALPROTO_HTTP2, HTTP2StateDataServer); | |
464 | ||
2bb0cae0 VJ |
465 | DetectBufferTypeSetDescriptionByName("http_header", |
466 | "http headers"); | |
467 | ||
2bb0cae0 | 468 | g_http_header_buffer_id = DetectBufferTypeGetByName("http_header"); |
f2fc5a25 VJ |
469 | |
470 | g_keyword_thread_id = DetectRegisterThreadCtxGlobalFuncs("http_header", | |
471 | HttpHeaderThreadDataInit, &g_td_config, HttpHeaderThreadDataFree); | |
2bb0cae0 VJ |
472 | } |
473 | ||
ab02ab9e PR |
474 | /************************************Unittests*********************************/ |
475 | ||
476 | #ifdef UNITTESTS | |
b9bcd4e1 VJ |
477 | #include "tests/detect-http-header.c" |
478 | #endif | |
ab02ab9e | 479 | |
60a99915 EL |
480 | /** |
481 | * @} | |
482 | */ |